mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-24 01:07:50 +00:00
fix: use workspace id in collaborator (#6447)
Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
parent
699e553e83
commit
202adb5077
@ -27,11 +27,11 @@ describe('utils', () => {
|
|||||||
|
|
||||||
describe('parseDocumentId', () => {
|
describe('parseDocumentId', () => {
|
||||||
expect(parseDocumentId('ws1://doc1:HEAD' as DocumentId)).toEqual({
|
expect(parseDocumentId('ws1://doc1:HEAD' as DocumentId)).toEqual({
|
||||||
workspaceUrl: 'ws1',
|
workspaceId: 'ws1',
|
||||||
collaborativeDoc: 'doc1:HEAD:HEAD' as CollaborativeDoc
|
collaborativeDoc: 'doc1:HEAD:HEAD' as CollaborativeDoc
|
||||||
})
|
})
|
||||||
expect(parseDocumentId('ws1://doc1:HEAD/doc2:v2' as DocumentId)).toEqual({
|
expect(parseDocumentId('ws1://doc1:HEAD/doc2:v2' as DocumentId)).toEqual({
|
||||||
workspaceUrl: 'ws1',
|
workspaceId: 'ws1',
|
||||||
collaborativeDoc: 'doc1:HEAD:HEAD#doc2:v2:v2' as CollaborativeDoc
|
collaborativeDoc: 'doc1:HEAD:HEAD#doc2:v2:v2' as CollaborativeDoc
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -36,7 +36,7 @@ import { DocumentId, PlatformDocumentId } from './types'
|
|||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export function formatDocumentId (workspaceUrl: string, collaborativeDoc: CollaborativeDoc): DocumentId {
|
export function formatDocumentId (workspaceId: string, collaborativeDoc: CollaborativeDoc): DocumentId {
|
||||||
const path = collaborativeDocUnchain(collaborativeDoc)
|
const path = collaborativeDocUnchain(collaborativeDoc)
|
||||||
.map((p) => {
|
.map((p) => {
|
||||||
const { documentId, versionId } = collaborativeDocParse(p)
|
const { documentId, versionId } = collaborativeDocParse(p)
|
||||||
@ -44,15 +44,15 @@ export function formatDocumentId (workspaceUrl: string, collaborativeDoc: Collab
|
|||||||
})
|
})
|
||||||
.join('/')
|
.join('/')
|
||||||
|
|
||||||
return `${workspaceUrl}://${path}` as DocumentId
|
return `${workspaceId}://${path}` as DocumentId
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export function parseDocumentId (documentId: DocumentId): {
|
export function parseDocumentId (documentId: DocumentId): {
|
||||||
workspaceUrl: string
|
workspaceId: string
|
||||||
collaborativeDoc: CollaborativeDoc
|
collaborativeDoc: CollaborativeDoc
|
||||||
} {
|
} {
|
||||||
const [workspaceUrl, path] = documentId.split('://')
|
const [workspaceId, path] = documentId.split('://')
|
||||||
const segments = path.split('/')
|
const segments = path.split('/')
|
||||||
|
|
||||||
const collaborativeDocs = segments.map((p) => {
|
const collaborativeDocs = segments.map((p) => {
|
||||||
@ -61,7 +61,7 @@ export function parseDocumentId (documentId: DocumentId): {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
workspaceUrl,
|
workspaceId,
|
||||||
collaborativeDoc: collaborativeDocChain(...collaborativeDocs)
|
collaborativeDoc: collaborativeDocChain(...collaborativeDocs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import { PlatformError, Severity, Status, getMetadata } from '@hcengineering/pla
|
|||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
|
||||||
import plugin from './plugin'
|
import plugin from './plugin'
|
||||||
import { decodeTokenPayload } from './utils'
|
|
||||||
|
|
||||||
interface FileUploadError {
|
interface FileUploadError {
|
||||||
key: string
|
key: string
|
||||||
@ -42,8 +41,8 @@ function getFilesUrl (): string {
|
|||||||
return filesUrl.includes('://') ? filesUrl : concatLink(frontUrl, filesUrl)
|
return filesUrl.includes('://') ? filesUrl : concatLink(frontUrl, filesUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentWorkspace (): string {
|
export function getCurrentWorkspaceId (): string {
|
||||||
return decodeTokenPayload(getMetadata(plugin.metadata.Token) ?? '').workspace
|
return getMetadata(plugin.metadata.WorkspaceId) ?? ''
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,7 +58,7 @@ export function generateFileId (): string {
|
|||||||
export function getUploadUrl (): string {
|
export function getUploadUrl (): string {
|
||||||
const template = getMetadata(plugin.metadata.UploadURL) ?? defaultUploadUrl
|
const template = getMetadata(plugin.metadata.UploadURL) ?? defaultUploadUrl
|
||||||
|
|
||||||
return template.replaceAll(':workspace', encodeURIComponent(getCurrentWorkspace()))
|
return template.replaceAll(':workspace', encodeURIComponent(getCurrentWorkspaceId()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,7 +72,7 @@ export function getFileUrl (file: string, filename?: string): string {
|
|||||||
const template = getFilesUrl()
|
const template = getFilesUrl()
|
||||||
return template
|
return template
|
||||||
.replaceAll(':filename', encodeURIComponent(filename ?? file))
|
.replaceAll(':filename', encodeURIComponent(filename ?? file))
|
||||||
.replaceAll(':workspace', encodeURIComponent(getCurrentWorkspace()))
|
.replaceAll(':workspace', encodeURIComponent(getCurrentWorkspaceId()))
|
||||||
.replaceAll(':blobId', encodeURIComponent(file))
|
.replaceAll(':blobId', encodeURIComponent(file))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ export default plugin(presentationId, {
|
|||||||
Token: '' as Metadata<string>,
|
Token: '' as Metadata<string>,
|
||||||
Endpoint: '' as Metadata<string>,
|
Endpoint: '' as Metadata<string>,
|
||||||
Workspace: '' as Metadata<string>,
|
Workspace: '' as Metadata<string>,
|
||||||
|
WorkspaceId: '' as Metadata<string>,
|
||||||
FrontUrl: '' as Asset,
|
FrontUrl: '' as Asset,
|
||||||
PreviewConfig: '' as Metadata<PreviewConfig | undefined>,
|
PreviewConfig: '' as Metadata<PreviewConfig | undefined>,
|
||||||
ClientHook: '' as Metadata<ClientHook>,
|
ClientHook: '' as Metadata<ClientHook>,
|
||||||
|
@ -2,14 +2,14 @@ import type { Blob, Ref } from '@hcengineering/core'
|
|||||||
import { concatLink } from '@hcengineering/core'
|
import { concatLink } from '@hcengineering/core'
|
||||||
import { getMetadata } from '@hcengineering/platform'
|
import { getMetadata } from '@hcengineering/platform'
|
||||||
|
|
||||||
import { getFileUrl, getCurrentWorkspace } from './file'
|
import { getFileUrl, getCurrentWorkspaceId } from './file'
|
||||||
import presentation from './plugin'
|
import presentation from './plugin'
|
||||||
|
|
||||||
export interface PreviewConfig {
|
export interface PreviewConfig {
|
||||||
previewUrl: string
|
previewUrl: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultPreview = (): string => `/files/${getCurrentWorkspace()}?file=:blobId&size=:size`
|
const defaultPreview = (): string => `/files/${getCurrentWorkspaceId()}?file=:blobId&size=:size`
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -58,7 +58,7 @@ function blobToSrcSet (cfg: PreviewConfig, blob: Ref<Blob>, width: number | unde
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = cfg.previewUrl.replaceAll(':workspace', encodeURIComponent(getCurrentWorkspace()))
|
let url = cfg.previewUrl.replaceAll(':workspace', encodeURIComponent(getCurrentWorkspaceId()))
|
||||||
const downloadUrl = getFileUrl(blob)
|
const downloadUrl = getFileUrl(blob)
|
||||||
|
|
||||||
const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin
|
const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin
|
||||||
|
@ -52,6 +52,7 @@ export async function connect (title: string): Promise<Client | undefined> {
|
|||||||
|
|
||||||
setMetadata(presentation.metadata.Token, token)
|
setMetadata(presentation.metadata.Token, token)
|
||||||
setMetadata(presentation.metadata.Workspace, workspaceLoginInfo.workspace)
|
setMetadata(presentation.metadata.Workspace, workspaceLoginInfo.workspace)
|
||||||
|
setMetadata(presentation.metadata.WorkspaceId, workspaceLoginInfo.workspaceId)
|
||||||
setMetadata(presentation.metadata.Endpoint, workspaceLoginInfo.endpoint)
|
setMetadata(presentation.metadata.Endpoint, workspaceLoginInfo.endpoint)
|
||||||
|
|
||||||
if (_token !== token && _client !== undefined) {
|
if (_token !== token && _client !== undefined) {
|
||||||
|
@ -441,6 +441,7 @@ export function navigateToWorkspace (
|
|||||||
}
|
}
|
||||||
setMetadata(presentation.metadata.Token, loginInfo.token)
|
setMetadata(presentation.metadata.Token, loginInfo.token)
|
||||||
setMetadata(presentation.metadata.Workspace, loginInfo.workspace)
|
setMetadata(presentation.metadata.Workspace, loginInfo.workspace)
|
||||||
|
setMetadata(presentation.metadata.WorkspaceId, loginInfo.workspaceId)
|
||||||
setLoginInfo(loginInfo)
|
setLoginInfo(loginInfo)
|
||||||
|
|
||||||
if (navigateUrl !== undefined) {
|
if (navigateUrl !== undefined) {
|
||||||
@ -896,6 +897,7 @@ export async function afterConfirm (clearQuery = false): Promise<void> {
|
|||||||
if (result !== undefined) {
|
if (result !== undefined) {
|
||||||
setMetadata(presentation.metadata.Token, result.token)
|
setMetadata(presentation.metadata.Token, result.token)
|
||||||
setMetadata(presentation.metadata.Workspace, result.workspace)
|
setMetadata(presentation.metadata.Workspace, result.workspace)
|
||||||
|
setMetadata(presentation.metadata.WorkspaceId, result.workspaceId)
|
||||||
setMetadataLocalStorage(login.metadata.LastToken, result.token)
|
setMetadataLocalStorage(login.metadata.LastToken, result.token)
|
||||||
setLoginInfo(result)
|
setLoginInfo(result)
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ export async function connect (title: string): Promise<Client | undefined> {
|
|||||||
token = workspaceLoginInfo.token
|
token = workspaceLoginInfo.token
|
||||||
setMetadataLocalStorage(login.metadata.LoginTokens, tokens)
|
setMetadataLocalStorage(login.metadata.LoginTokens, tokens)
|
||||||
setMetadata(presentation.metadata.Workspace, workspaceLoginInfo.workspace)
|
setMetadata(presentation.metadata.Workspace, workspaceLoginInfo.workspace)
|
||||||
|
setMetadata(presentation.metadata.WorkspaceId, workspaceLoginInfo.workspaceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
setMetadata(presentation.metadata.Token, token)
|
setMetadata(presentation.metadata.Token, token)
|
||||||
@ -354,6 +355,7 @@ function clearMetadata (ws: string): void {
|
|||||||
|
|
||||||
setMetadata(presentation.metadata.Token, null)
|
setMetadata(presentation.metadata.Token, null)
|
||||||
setMetadata(presentation.metadata.Workspace, null)
|
setMetadata(presentation.metadata.Workspace, null)
|
||||||
|
setMetadata(presentation.metadata.WorkspaceId, null)
|
||||||
setMetadataLocalStorage(login.metadata.LastToken, null)
|
setMetadataLocalStorage(login.metadata.LastToken, null)
|
||||||
setMetadataLocalStorage(login.metadata.LoginEndpoint, null)
|
setMetadataLocalStorage(login.metadata.LoginEndpoint, null)
|
||||||
setMetadataLocalStorage(login.metadata.LoginEmail, null)
|
setMetadataLocalStorage(login.metadata.LoginEmail, null)
|
||||||
|
@ -35,19 +35,19 @@ export class AuthenticationExtension implements Extension {
|
|||||||
|
|
||||||
async onAuthenticate (data: onAuthenticatePayload): Promise<Context> {
|
async onAuthenticate (data: onAuthenticatePayload): Promise<Context> {
|
||||||
const ctx = this.configuration.ctx
|
const ctx = this.configuration.ctx
|
||||||
const { workspaceUrl: workspace, collaborativeDoc } = parseDocumentId(data.documentName as DocumentId)
|
const { workspaceId, collaborativeDoc } = parseDocumentId(data.documentName as DocumentId)
|
||||||
|
|
||||||
return await ctx.with('authenticate', { workspace }, async () => {
|
return await ctx.with('authenticate', { workspaceId }, async () => {
|
||||||
const token = decodeToken(data.token)
|
const token = decodeToken(data.token)
|
||||||
|
|
||||||
ctx.info('authenticate', { workspace, mode: token.extra?.mode ?? '' })
|
ctx.info('authenticate', { workspaceId, mode: token.extra?.mode ?? '' })
|
||||||
|
|
||||||
// verify workspace can be accessed with the token
|
// verify workspace can be accessed with the token
|
||||||
const workspaceInfo = await getWorkspaceInfo(data.token)
|
const workspaceInfo = await getWorkspaceInfo(data.token)
|
||||||
|
|
||||||
// verify workspace url in the document matches the token
|
// verify workspace url in the document matches the token
|
||||||
if (workspaceInfo.workspace !== workspace) {
|
if (workspaceInfo.workspace !== workspaceId) {
|
||||||
throw new Error('documentName must include workspace')
|
throw new Error('documentName must include workspace id')
|
||||||
}
|
}
|
||||||
|
|
||||||
data.connection.readOnly = isReadonlyDoc(collaborativeDoc)
|
data.connection.readOnly = isReadonlyDoc(collaborativeDoc)
|
||||||
|
@ -17,7 +17,7 @@ import type { Class, Doc, Domain, Ref } from '@hcengineering/core'
|
|||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export interface DocumentId {
|
export interface DocumentId {
|
||||||
workspaceUrl: string
|
workspaceId: string
|
||||||
documentId: string
|
documentId: string
|
||||||
versionId: string
|
versionId: string
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user