mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-17 18:05:42 +02:00
Different social ids for calendar (#10008)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
"0.7.230"
|
||||
"0.7.269"
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"@hcengineering/model-view": "^0.6.0",
|
||||
"@hcengineering/model-setting": "^0.6.0",
|
||||
"@hcengineering/model-workbench": "^0.6.1",
|
||||
"@hcengineering/account-client": "^0.6.0",
|
||||
"@hcengineering/activity": "^0.6.0",
|
||||
"@hcengineering/workbench": "^0.6.16",
|
||||
"@hcengineering/model-preference": "^0.6.0",
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type IntegrationSecret } from '@hcengineering/account-client'
|
||||
import {
|
||||
AccessLevel,
|
||||
type Calendar,
|
||||
@@ -21,10 +22,13 @@ import {
|
||||
type ExternalCalendar,
|
||||
type ReccuringEvent
|
||||
} from '@hcengineering/calendar'
|
||||
import contact, { type SocialIdentity, type SocialIdentityRef } from '@hcengineering/contact'
|
||||
import core, {
|
||||
type AccountUuid,
|
||||
buildSocialIdString,
|
||||
type Doc,
|
||||
DOMAIN_TX,
|
||||
type IntegrationKind,
|
||||
type PersonId,
|
||||
pickPrimarySocialId,
|
||||
type Ref,
|
||||
@@ -50,7 +54,6 @@ import {
|
||||
getSocialKeyByOldAccount
|
||||
} from '@hcengineering/model-core'
|
||||
import setting, { DOMAIN_SETTING, type Integration } from '@hcengineering/setting'
|
||||
import contact, { type SocialIdentityRef, type SocialIdentity } from '@hcengineering/contact'
|
||||
import { DOMAIN_CALENDAR, DOMAIN_EVENT } from '.'
|
||||
import calendar from './plugin'
|
||||
|
||||
@@ -455,6 +458,116 @@ async function migrateTimezone (client: MigrationClient): Promise<void> {
|
||||
)
|
||||
}
|
||||
|
||||
async function moveMigration (client: MigrationClient, secret: IntegrationSecret, socialId: PersonId): Promise<void> {
|
||||
await client.accountClient.deleteIntegrationSecret(secret)
|
||||
const exists = await client.accountClient.listIntegrations({
|
||||
kind: secret.kind,
|
||||
socialId,
|
||||
workspaceUuid: secret.workspaceUuid
|
||||
})
|
||||
if (exists.length === 0) {
|
||||
await client.accountClient.createIntegration({
|
||||
kind: secret.kind,
|
||||
workspaceUuid: secret.workspaceUuid,
|
||||
socialId,
|
||||
data: {
|
||||
email: secret.key
|
||||
}
|
||||
})
|
||||
}
|
||||
await client.accountClient.addIntegrationSecret({
|
||||
...secret,
|
||||
socialId
|
||||
})
|
||||
}
|
||||
|
||||
async function migrateIntegrations (client: MigrationClient): Promise<void> {
|
||||
const secrets = await client.accountClient.listIntegrationsSecrets({
|
||||
kind: 'google-calendar' as IntegrationKind
|
||||
})
|
||||
const map = new Map<PersonId, PersonId | null>()
|
||||
for (const secret of secrets) {
|
||||
try {
|
||||
const exists = map.get(secret.socialId)
|
||||
if (exists == null) continue
|
||||
if (exists !== undefined) {
|
||||
await moveMigration(client, secret, exists)
|
||||
} else {
|
||||
const socials = await client.accountClient.findFullSocialIds([secret.socialId])
|
||||
if (socials.length === 0) continue
|
||||
if (socials[0].type === SocialIdType.GOOGLE && socials[0].value === secret.key) continue
|
||||
const person = socials[0].personUuid
|
||||
|
||||
const target = await client.accountClient.findFullSocialIdBySocialKey(
|
||||
buildSocialIdString({
|
||||
type: SocialIdType.GOOGLE,
|
||||
value: secret.key
|
||||
})
|
||||
)
|
||||
if (target?.personUuid === person) {
|
||||
// Ok, it is the same person, just recreate integration
|
||||
map.set(secret.socialId, target._id)
|
||||
await moveMigration(client, secret, target._id)
|
||||
} else if (target == null) {
|
||||
const newOne = await client.accountClient.addSocialIdToPerson(
|
||||
person,
|
||||
SocialIdType.GOOGLE,
|
||||
secret.key,
|
||||
true,
|
||||
secret.key
|
||||
)
|
||||
map.set(secret.socialId, newOne)
|
||||
await moveMigration(client, secret, newOne)
|
||||
} else {
|
||||
// oh, shit, it's a different person, let's remove it
|
||||
await client.accountClient.deleteIntegrationSecret(secret)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
client.logger.error('Error while migrating integration', { secret, error: err })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function updateCalendarUser (client: MigrationClient): Promise<void> {
|
||||
const calendars = await client.find<ExternalCalendar>(DOMAIN_CALENDAR, {
|
||||
_class: calendar.class.ExternalCalendar
|
||||
})
|
||||
const accs = new Map<string, PersonId>()
|
||||
for (const calendar of calendars) {
|
||||
try {
|
||||
const exists = accs.get(calendar.user)
|
||||
if (exists !== undefined) {
|
||||
await client.update(DOMAIN_CALENDAR, { _id: calendar._id }, { user: exists })
|
||||
continue
|
||||
}
|
||||
const accId = await client.accountClient.findPersonBySocialId(calendar.user)
|
||||
if (accId === undefined) continue
|
||||
const socialId = await client.accountClient.findFullSocialIdBySocialKey(
|
||||
buildSocialIdString({
|
||||
type: SocialIdType.GOOGLE,
|
||||
value: calendar.externalUser
|
||||
})
|
||||
)
|
||||
if (socialId === undefined) {
|
||||
const newOne = await client.accountClient.addSocialIdToPerson(
|
||||
accId,
|
||||
SocialIdType.GOOGLE,
|
||||
calendar.externalUser,
|
||||
true,
|
||||
calendar.externalUser
|
||||
)
|
||||
accs.set(calendar.user, newOne)
|
||||
} else if (socialId.personUuid === accId) {
|
||||
accs.set(calendar.user, socialId._id)
|
||||
await client.update(DOMAIN_CALENDAR, { _id: calendar._id }, { user: accId })
|
||||
}
|
||||
} catch (e) {
|
||||
client.logger.error('Error while updating calendar user', { calendar: calendar._id, error: e })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const calendarOperation: MigrateOperation = {
|
||||
async migrate (client: MigrationClient, mode): Promise<void> {
|
||||
await tryMigrate(mode, client, calendarId, [
|
||||
@@ -528,6 +641,16 @@ export const calendarOperation: MigrateOperation = {
|
||||
state: 'migrate-ev-user-for-deleted',
|
||||
mode: 'upgrade',
|
||||
func: migrateEventUserForDeleted
|
||||
},
|
||||
{
|
||||
state: 'migrate-integrations',
|
||||
mode: 'upgrade',
|
||||
func: migrateIntegrations
|
||||
},
|
||||
{
|
||||
state: 'update-calendar-user',
|
||||
mode: 'upgrade',
|
||||
func: updateCalendarUser
|
||||
}
|
||||
])
|
||||
},
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
q.query(
|
||||
calendar.class.Calendar,
|
||||
{ user: me.primarySocialId, hidden: false, access: { $in: [AccessLevel.Owner, AccessLevel.Writer] } },
|
||||
{ user: { $in: me.socialIds }, hidden: false, access: { $in: [AccessLevel.Owner, AccessLevel.Writer] } },
|
||||
(res) => {
|
||||
calendarsLoaded = true
|
||||
calendars = res
|
||||
|
||||
@@ -10,13 +10,16 @@
|
||||
|
||||
const client = getClient()
|
||||
|
||||
const myAcc = getCurrentAccount()
|
||||
const socialStrings = myAcc.socialIds
|
||||
|
||||
let calendars: Calendar[] = []
|
||||
|
||||
const query = createQuery()
|
||||
query.query(
|
||||
calendar.class.Calendar,
|
||||
{
|
||||
user: getCurrentAccount().primarySocialId
|
||||
user: { $in: socialStrings }
|
||||
},
|
||||
(res) => {
|
||||
calendars = res
|
||||
|
||||
@@ -15,34 +15,33 @@
|
||||
|
||||
import { AccountClient, IntegrationSecret } from '@hcengineering/account-client'
|
||||
import calendar, { calendarIntegrationKind } from '@hcengineering/calendar'
|
||||
import contact, { Employee, getPrimarySocialId, SocialIdentityRef } from '@hcengineering/contact'
|
||||
import contact, { getPrimarySocialId } from '@hcengineering/contact'
|
||||
import core, {
|
||||
AccountUuid,
|
||||
buildSocialIdString,
|
||||
MeasureContext,
|
||||
PersonId,
|
||||
Ref,
|
||||
SocialIdType,
|
||||
TxOperations,
|
||||
WorkspaceUuid
|
||||
} from '@hcengineering/core'
|
||||
import type { IntegrationClient } from '@hcengineering/integration-client'
|
||||
import setting from '@hcengineering/setting'
|
||||
import { Credentials, OAuth2Client } from 'google-auth-library'
|
||||
import { calendar_v3, google } from 'googleapis'
|
||||
import type { IntegrationClient } from '@hcengineering/integration-client'
|
||||
|
||||
import { encode64 } from './base64'
|
||||
import { getClient } from './client'
|
||||
import { setSyncHistory } from './kvsUtils'
|
||||
import { lock } from './mutex'
|
||||
import { IncomingSyncManager } from './sync'
|
||||
import { GoogleEmail, SCOPES, State, Token, User } from './types'
|
||||
import { GoogleEmail, SCOPES, State, Token } from './types'
|
||||
import { addUserByEmail, getGoogleClient, removeIntegrationSecret, removeUserByEmail } from './utils'
|
||||
import { WatchController } from './watch'
|
||||
|
||||
interface AuthResult {
|
||||
success: boolean
|
||||
email: GoogleEmail
|
||||
personId?: PersonId
|
||||
}
|
||||
|
||||
export class AuthController {
|
||||
@@ -54,8 +53,7 @@ export class AuthController {
|
||||
private readonly ctx: MeasureContext,
|
||||
private readonly accountClient: AccountClient,
|
||||
private readonly integrationClient: IntegrationClient,
|
||||
private readonly client: TxOperations,
|
||||
private readonly user: User
|
||||
private readonly user: State
|
||||
) {
|
||||
const res = getGoogleClient()
|
||||
this.googleClient = res.google
|
||||
@@ -73,17 +71,15 @@ export class AuthController {
|
||||
'Create auth controller',
|
||||
{},
|
||||
async () => {
|
||||
const mutex = await lock(`${state.workspace}:${state.userId}`)
|
||||
const mutex = await lock(`${state.workspace}:${state.accountUuid}`)
|
||||
try {
|
||||
const client = await getClient(state.workspace)
|
||||
const txOp = new TxOperations(client, state.userId)
|
||||
const controller = new AuthController(ctx, accountClient, integrationClient, txOp, state)
|
||||
await controller.process(code)
|
||||
const controller = new AuthController(ctx, accountClient, integrationClient, state)
|
||||
await controller.process(code, state)
|
||||
} finally {
|
||||
mutex()
|
||||
}
|
||||
},
|
||||
{ workspace: state.workspace, user: state.userId }
|
||||
{ workspace: state.workspace, user: state.accountUuid }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -102,12 +98,34 @@ export class AuthController {
|
||||
const mutex = await lock(`${workspace}:${userId}`)
|
||||
try {
|
||||
const client = await getClient(workspace)
|
||||
const txOp = new TxOperations(client, core.account.System)
|
||||
const controller = new AuthController(ctx, accountClient, integrationClient, txOp, {
|
||||
userId,
|
||||
workspace
|
||||
const txOp = new TxOperations(client, userId)
|
||||
const integration = await txOp.findOne(setting.class.Integration, {
|
||||
type: calendar.integrationType.Calendar,
|
||||
createdBy: userId,
|
||||
value
|
||||
})
|
||||
await controller.signout(value)
|
||||
if (integration !== undefined) {
|
||||
await txOp.remove(integration)
|
||||
}
|
||||
removeUserByEmail(
|
||||
{
|
||||
workspace,
|
||||
userId
|
||||
},
|
||||
value
|
||||
)
|
||||
const data = {
|
||||
kind: calendarIntegrationKind,
|
||||
workspaceUuid: workspace,
|
||||
key: value,
|
||||
socialId: userId
|
||||
}
|
||||
const secret = await accountClient.getIntegrationSecret(data)
|
||||
if (secret == null) return
|
||||
const token = JSON.parse(secret.secret)
|
||||
await removeIntegrationSecret(ctx, accountClient, data)
|
||||
const watchController = WatchController.get(ctx, accountClient)
|
||||
await watchController.unsubscribe(token)
|
||||
} catch (err) {
|
||||
ctx.error('signout', { workspace, userId, err })
|
||||
} finally {
|
||||
@@ -118,40 +136,21 @@ export class AuthController {
|
||||
)
|
||||
}
|
||||
|
||||
private async signout (value: GoogleEmail): Promise<void> {
|
||||
const integration = await this.client.findOne(setting.class.Integration, {
|
||||
type: calendar.integrationType.Calendar,
|
||||
createdBy: this.user.userId,
|
||||
value
|
||||
})
|
||||
if (integration !== undefined) {
|
||||
await this.client.remove(integration)
|
||||
}
|
||||
removeUserByEmail(this.user, value)
|
||||
const data = {
|
||||
kind: calendarIntegrationKind,
|
||||
workspaceUuid: this.user.workspace,
|
||||
key: value,
|
||||
socialId: this.user.userId
|
||||
}
|
||||
const secret = await this.accountClient.getIntegrationSecret(data)
|
||||
if (secret == null) return
|
||||
const token = JSON.parse(secret.secret)
|
||||
await removeIntegrationSecret(this.ctx, this.accountClient, data)
|
||||
const watchController = WatchController.get(this.ctx, this.accountClient)
|
||||
await watchController.unsubscribe(token)
|
||||
}
|
||||
|
||||
private async process (code: string): Promise<void> {
|
||||
const authRes = await this.authorize(code)
|
||||
await this.setWorkspaceIntegration(authRes)
|
||||
if (authRes.success) {
|
||||
private async process (code: string, state: State): Promise<void> {
|
||||
const authRes = await this.authorize(code, state)
|
||||
if (authRes.success && authRes.personId !== undefined) {
|
||||
const client = await getClient(this.user.workspace)
|
||||
const txOp = new TxOperations(client, authRes.personId)
|
||||
await this.setWorkspaceIntegration(authRes, authRes.personId, txOp)
|
||||
await setSyncHistory(this.user.workspace, Date.now())
|
||||
void IncomingSyncManager.initSync(
|
||||
this.ctx,
|
||||
this.accountClient,
|
||||
this.client,
|
||||
this.user,
|
||||
txOp,
|
||||
{
|
||||
workspace: this.user.workspace,
|
||||
userId: authRes.personId
|
||||
},
|
||||
authRes.email,
|
||||
this.googleClient
|
||||
)
|
||||
@@ -169,7 +168,7 @@ export class AuthController {
|
||||
return this.email
|
||||
}
|
||||
|
||||
private async authorize (code: string): Promise<AuthResult> {
|
||||
private async authorize (code: string, state: State): Promise<AuthResult> {
|
||||
const token = await this.oAuth2Client.getToken(code)
|
||||
this.oAuth2Client.setCredentials(token.tokens)
|
||||
const email = await this.getEmail()
|
||||
@@ -181,34 +180,34 @@ export class AuthController {
|
||||
}
|
||||
}
|
||||
const res = await this.oAuth2Client.refreshAccessToken()
|
||||
await this.createAccIntegrationIfNotExists(email)
|
||||
await this.updateToken(res.credentials, email)
|
||||
const personId = await this.createAccIntegrationIfNotExists(state.accountUuid, email)
|
||||
await this.updateToken(res.credentials, personId, email)
|
||||
|
||||
return { success: true, email }
|
||||
return { success: true, email, personId }
|
||||
}
|
||||
|
||||
private async setWorkspaceIntegration (res: AuthResult): Promise<void> {
|
||||
private async setWorkspaceIntegration (res: AuthResult, personId: PersonId, client: TxOperations): Promise<void> {
|
||||
await this.ctx.with(
|
||||
'Set workspace integration',
|
||||
{},
|
||||
async () => {
|
||||
const integrations = await this.client.findAll(setting.class.Integration, {
|
||||
createdBy: this.user.userId,
|
||||
const integrations = await client.findAll(setting.class.Integration, {
|
||||
createdBy: personId,
|
||||
type: calendar.integrationType.Calendar
|
||||
})
|
||||
|
||||
const updated = integrations.find((p) => p.disabled && p.value === res.email)
|
||||
for (const integration of integrations.filter((p) => p.value === '')) {
|
||||
await this.client.remove(integration)
|
||||
await client.remove(integration)
|
||||
}
|
||||
if (!res.success) {
|
||||
if (updated !== undefined) {
|
||||
await this.client.update(updated, {
|
||||
await client.update(updated, {
|
||||
disabled: true,
|
||||
error: calendar.string.NotAllPermissions
|
||||
})
|
||||
} else {
|
||||
await this.client.createDoc(setting.class.Integration, core.space.Workspace, {
|
||||
await client.createDoc(setting.class.Integration, core.space.Workspace, {
|
||||
type: calendar.integrationType.Calendar,
|
||||
disabled: true,
|
||||
error: calendar.string.NotAllPermissions,
|
||||
@@ -218,49 +217,57 @@ export class AuthController {
|
||||
throw new Error('Not all scopes provided')
|
||||
} else {
|
||||
if (updated !== undefined) {
|
||||
await this.client.update(updated, {
|
||||
await client.update(updated, {
|
||||
disabled: false,
|
||||
error: null
|
||||
})
|
||||
} else {
|
||||
await this.client.createDoc(setting.class.Integration, core.space.Workspace, {
|
||||
await client.createDoc(setting.class.Integration, core.space.Workspace, {
|
||||
type: calendar.integrationType.Calendar,
|
||||
disabled: false,
|
||||
value: res.email
|
||||
})
|
||||
}
|
||||
}
|
||||
await this.addSocialId(res.email)
|
||||
},
|
||||
{
|
||||
user: this.user.userId,
|
||||
user: personId,
|
||||
workspace: this.user.workspace,
|
||||
email: res.email
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private async createAccIntegrationIfNotExists (email: string): Promise<void> {
|
||||
await this.ctx.with(
|
||||
private async createAccIntegrationIfNotExists (accountUuid: AccountUuid, email: string): Promise<PersonId> {
|
||||
return await this.ctx.with(
|
||||
'Create account integration if not exists',
|
||||
{},
|
||||
async () => {
|
||||
const data = { email }
|
||||
const connection = await this.integrationClient.connect(this.user.userId, data)
|
||||
const newSocialId = await this.accountClient.addSocialIdToPerson(
|
||||
accountUuid,
|
||||
SocialIdType.GOOGLE,
|
||||
email,
|
||||
true,
|
||||
email
|
||||
)
|
||||
const connection = await this.integrationClient.connect(newSocialId, data)
|
||||
await this.integrationClient.integrate(connection, this.user.workspace, data)
|
||||
return newSocialId
|
||||
},
|
||||
{ user: this.user.userId }
|
||||
{ accountUuid, email }
|
||||
)
|
||||
}
|
||||
|
||||
private async updateToken (token: Credentials, email: GoogleEmail): Promise<void> {
|
||||
private async updateToken (token: Credentials, personId: PersonId, email: GoogleEmail): Promise<void> {
|
||||
const _token: Token = {
|
||||
...this.user,
|
||||
workspace: this.user.workspace,
|
||||
userId: personId,
|
||||
email,
|
||||
...token
|
||||
}
|
||||
const data: IntegrationSecret = {
|
||||
socialId: this.user.userId,
|
||||
socialId: personId,
|
||||
kind: calendarIntegrationKind,
|
||||
workspaceUuid: this.user.workspace,
|
||||
key: email,
|
||||
@@ -270,31 +277,16 @@ export class AuthController {
|
||||
await this.integrationClient.setSecret(data)
|
||||
addUserByEmail(_token, email)
|
||||
} catch (err) {
|
||||
this.ctx.error('update token error', { workspace: this.user.workspace, user: this.user.userId, err })
|
||||
this.ctx.error('update token error', { workspace: this.user.workspace, email, err })
|
||||
}
|
||||
}
|
||||
|
||||
private async addSocialId (email: GoogleEmail): Promise<void> {
|
||||
const socialString = buildSocialIdString({ type: SocialIdType.GOOGLE, value: email })
|
||||
const exists = await this.accountClient.findFullSocialIdBySocialKey(socialString)
|
||||
if (exists !== undefined) {
|
||||
return
|
||||
}
|
||||
const sID = await this.client.findOne(contact.class.SocialIdentity, {
|
||||
_id: this.user.userId as SocialIdentityRef
|
||||
})
|
||||
if (sID === undefined) return
|
||||
const person = await this.client.findOne(contact.mixin.Employee, { _id: sID.attachedTo as Ref<Employee> })
|
||||
if (person?.personUuid === undefined) return
|
||||
await this.accountClient.addSocialIdToPerson(person.personUuid, SocialIdType.GOOGLE, email, true)
|
||||
}
|
||||
|
||||
static getAuthUrl (redirectURL: string, workspace: WorkspaceUuid, userId: PersonId, token: string): string {
|
||||
static getAuthUrl (redirectURL: string, workspace: WorkspaceUuid, accountUuid: AccountUuid): string {
|
||||
const res = getGoogleClient()
|
||||
const oAuth2Client = res.auth
|
||||
const state: State = {
|
||||
redirectURL,
|
||||
userId,
|
||||
accountUuid,
|
||||
workspace
|
||||
}
|
||||
const authUrl = oAuth2Client.generateAuthUrl({
|
||||
@@ -306,19 +298,48 @@ export class AuthController {
|
||||
return authUrl
|
||||
}
|
||||
|
||||
static async getUserId (account: AccountUuid, workspace: WorkspaceUuid, token: string): Promise<PersonId> {
|
||||
static async getPrimaryUserId (
|
||||
account: AccountUuid,
|
||||
workspace: WorkspaceUuid,
|
||||
token: string,
|
||||
email: GoogleEmail
|
||||
): Promise<PersonId> {
|
||||
const client = await getClient(workspace, token)
|
||||
const person = await client.findOne(contact.class.Person, { personUuid: account })
|
||||
if (person === undefined) {
|
||||
throw new Error('Person not found')
|
||||
}
|
||||
|
||||
const personId = await getPrimarySocialId(client, person._id)
|
||||
const primaryId = await getPrimarySocialId(client, person._id)
|
||||
if (primaryId === undefined) {
|
||||
throw new Error('PrimaryId not found')
|
||||
}
|
||||
|
||||
return primaryId
|
||||
}
|
||||
|
||||
static async getUserId (
|
||||
account: AccountUuid,
|
||||
workspace: WorkspaceUuid,
|
||||
token: string,
|
||||
email: GoogleEmail
|
||||
): Promise<PersonId> {
|
||||
const client = await getClient(workspace, token)
|
||||
const person = await client.findOne(contact.class.Person, { personUuid: account })
|
||||
if (person === undefined) {
|
||||
throw new Error('Person not found')
|
||||
}
|
||||
|
||||
const personId = await client.findOne(contact.class.SocialIdentity, {
|
||||
attachedTo: person._id,
|
||||
type: SocialIdType.GOOGLE,
|
||||
value: email
|
||||
})
|
||||
|
||||
if (personId === undefined) {
|
||||
throw new Error('PersonId not found')
|
||||
}
|
||||
|
||||
return personId
|
||||
return personId._id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { createOpenTelemetryMetricsContext } from '@hcengineering/analytics-service/src'
|
||||
import { calendarIntegrationKind } from '@hcengineering/calendar'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { getIntegrationClient } from '@hcengineering/integration-client'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient, { getAccountClient } from '@hcengineering/server-client'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import serverToken, { decodeToken } from '@hcengineering/server-token'
|
||||
import { calendarIntegrationKind } from '@hcengineering/calendar'
|
||||
import { type IncomingHttpHeaders } from 'http'
|
||||
import { join } from 'path'
|
||||
import { getIntegrationClient } from '@hcengineering/integration-client'
|
||||
|
||||
import { AuthController } from './auth'
|
||||
import { decode64 } from './base64'
|
||||
@@ -93,9 +93,8 @@ export const main = async (): Promise<void> => {
|
||||
}
|
||||
const redirectURL = req.query.redirectURL as string
|
||||
|
||||
const { account, workspace } = decodeToken(token)
|
||||
const userId = await AuthController.getUserId(account, workspace, token)
|
||||
const url = AuthController.getAuthUrl(redirectURL, workspace, userId, token)
|
||||
const { workspace } = decodeToken(token)
|
||||
const url = AuthController.getAuthUrl(redirectURL, workspace, token)
|
||||
res.send(url)
|
||||
} catch (err) {
|
||||
ctx.error('signin error', { message: (err as any).message })
|
||||
@@ -135,7 +134,7 @@ export const main = async (): Promise<void> => {
|
||||
|
||||
const value = req.query.value as GoogleEmail
|
||||
const { account, workspace } = decodeToken(token)
|
||||
const userId = await AuthController.getUserId(account, workspace, token)
|
||||
const userId = await AuthController.getUserId(account, workspace, token, value)
|
||||
await AuthController.signout(ctx, accountClient, integrationClient, userId, workspace, value)
|
||||
} catch (err) {
|
||||
ctx.error('signout', { message: (err as any).message })
|
||||
|
||||
@@ -453,7 +453,7 @@ async function getTokenByEvent (
|
||||
})
|
||||
if (_calendar === undefined) return
|
||||
const res = await accountClient.getIntegrationSecret({
|
||||
socialId: event.user,
|
||||
socialId: _calendar.user,
|
||||
kind: calendarIntegrationKind,
|
||||
workspaceUuid: workspace,
|
||||
key: _calendar.externalUser
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//
|
||||
|
||||
import { RecurringRule } from '@hcengineering/calendar'
|
||||
import type { PersonId, Timestamp, WorkspaceUuid } from '@hcengineering/core'
|
||||
import type { AccountUuid, PersonId, Timestamp, WorkspaceUuid } from '@hcengineering/core'
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
import type { Credentials } from 'google-auth-library'
|
||||
|
||||
@@ -56,8 +56,10 @@ export interface User {
|
||||
workspace: WorkspaceUuid
|
||||
}
|
||||
|
||||
export type State = User & {
|
||||
export interface State {
|
||||
redirectURL: string
|
||||
workspace: WorkspaceUuid
|
||||
accountUuid: AccountUuid
|
||||
}
|
||||
|
||||
export interface AttachedFile {
|
||||
|
||||
Reference in New Issue
Block a user