chore: send shared vault owner context when creating a shared vault file valet token (#2435)

* chore: send shared vault owner context when creating a shared vault file valet token

* chore: remove unused shared vault upload bytes limit
This commit is contained in:
Karol Sójko
2023-08-21 14:57:54 +02:00
committed by GitHub
parent f2c92d24f3
commit a6029e3ef1
10 changed files with 59 additions and 29 deletions

View File

@@ -0,0 +1,4 @@
export interface HttpRequestOptions {
authentication?: string
headers?: Record<string, string>[]
}

View File

@@ -16,6 +16,7 @@ import { Paths } from '../Server/Auth/Paths'
import { SessionRefreshResponseBody } from '../Response/Auth/SessionRefreshResponseBody' import { SessionRefreshResponseBody } from '../Response/Auth/SessionRefreshResponseBody'
import { FetchRequestHandler } from './FetchRequestHandler' import { FetchRequestHandler } from './FetchRequestHandler'
import { RequestHandlerInterface } from './RequestHandlerInterface' import { RequestHandlerInterface } from './RequestHandlerInterface'
import { HttpRequestOptions } from './HttpRequestOptions'
export class HttpService implements HttpServiceInterface { export class HttpService implements HttpServiceInterface {
private session?: Session | LegacySession private session?: Session | LegacySession
@@ -76,7 +77,7 @@ export class HttpService implements HttpServiceInterface {
} }
} }
async get<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> { async get<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
if (!this.host) { if (!this.host) {
throw new Error('Attempting to make network request before host is set') throw new Error('Attempting to make network request before host is set')
} }
@@ -85,7 +86,7 @@ export class HttpService implements HttpServiceInterface {
url: joinPaths(this.host, path), url: joinPaths(this.host, path),
params, params,
verb: HttpVerb.Get, verb: HttpVerb.Get,
authentication: authentication ?? this.getSessionAccessToken(), authentication: options?.authentication ?? this.getSessionAccessToken(),
}) })
} }
@@ -98,7 +99,7 @@ export class HttpService implements HttpServiceInterface {
}) })
} }
async post<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> { async post<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
if (!this.host) { if (!this.host) {
throw new Error('Attempting to make network request before host is set') throw new Error('Attempting to make network request before host is set')
} }
@@ -107,34 +108,35 @@ export class HttpService implements HttpServiceInterface {
url: joinPaths(this.host, path), url: joinPaths(this.host, path),
params, params,
verb: HttpVerb.Post, verb: HttpVerb.Post,
authentication: authentication ?? this.getSessionAccessToken(), authentication: options?.authentication ?? this.getSessionAccessToken(),
customHeaders: options?.headers,
}) })
} }
async put<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> { async put<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
return this.runHttp({ return this.runHttp({
url: joinPaths(this.host, path), url: joinPaths(this.host, path),
params, params,
verb: HttpVerb.Put, verb: HttpVerb.Put,
authentication: authentication ?? this.getSessionAccessToken(), authentication: options?.authentication ?? this.getSessionAccessToken(),
}) })
} }
async patch<T>(path: string, params: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> { async patch<T>(path: string, params: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
return this.runHttp({ return this.runHttp({
url: joinPaths(this.host, path), url: joinPaths(this.host, path),
params, params,
verb: HttpVerb.Patch, verb: HttpVerb.Patch,
authentication: authentication ?? this.getSessionAccessToken(), authentication: options?.authentication ?? this.getSessionAccessToken(),
}) })
} }
async delete<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> { async delete<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
return this.runHttp({ return this.runHttp({
url: joinPaths(this.host, path), url: joinPaths(this.host, path),
params, params,
verb: HttpVerb.Delete, verb: HttpVerb.Delete,
authentication: authentication ?? this.getSessionAccessToken(), authentication: options?.authentication ?? this.getSessionAccessToken(),
}) })
} }

View File

@@ -1,16 +1,18 @@
import { LegacySession, Session } from '@standardnotes/domain-core' import { LegacySession, Session } from '@standardnotes/domain-core'
import { HttpRequest, HttpRequestParams, HttpResponse, HttpResponseMeta } from '@standardnotes/responses' import { HttpRequest, HttpRequestParams, HttpResponse, HttpResponseMeta } from '@standardnotes/responses'
import { HttpRequestOptions } from './HttpRequestOptions'
export interface HttpServiceInterface { export interface HttpServiceInterface {
setHost(host: string): void setHost(host: string): void
getHost(): string getHost(): string
get<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> get<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
getExternal<T>(url: string, params?: HttpRequestParams): Promise<HttpResponse<T>> getExternal<T>(url: string, params?: HttpRequestParams): Promise<HttpResponse<T>>
post<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> post<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
put<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> put<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
patch<T>(path: string, params: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> patch<T>(path: string, params: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
delete<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> delete<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
runHttp<T>(httpRequest: HttpRequest): Promise<HttpResponse<T>> runHttp<T>(httpRequest: HttpRequest): Promise<HttpResponse<T>>
setSession(session: Session | LegacySession): void setSession(session: Session | LegacySession): void

View File

@@ -1,4 +1,5 @@
export * from './HttpService' export * from './HttpService'
export * from './FetchRequestHandler' export * from './FetchRequestHandler'
export * from './HttpRequestOptions'
export * from './HttpServiceInterface' export * from './HttpServiceInterface'
export * from './XMLHttpRequestState' export * from './XMLHttpRequestState'

View File

@@ -8,4 +8,5 @@ export type CreateSharedVaultValetTokenParams = {
unencryptedFileSize?: number unencryptedFileSize?: number
moveOperationType?: SharedVaultMoveType moveOperationType?: SharedVaultMoveType
sharedVaultToSharedVaultMoveTargetUuid?: string sharedVaultToSharedVaultMoveTargetUuid?: string
sharedVaultOwnerUuid?: string
} }

View File

@@ -25,13 +25,23 @@ export class SharedVaultServer implements SharedVaultServerInterface {
createSharedVaultFileValetToken( createSharedVaultFileValetToken(
params: CreateSharedVaultValetTokenParams, params: CreateSharedVaultValetTokenParams,
): Promise<HttpResponse<CreateSharedVaultValetTokenResponse>> { ): Promise<HttpResponse<CreateSharedVaultValetTokenResponse>> {
return this.httpService.post(SharedVaultsPaths.createSharedVaultFileValetToken(params.sharedVaultUuid), { let headers = undefined
file_uuid: params.fileUuid, if (params.sharedVaultOwnerUuid) {
remote_identifier: params.remoteIdentifier, headers = [{ 'x-shared-vault-owner-context': params.sharedVaultOwnerUuid }]
operation: params.operation, }
unencrypted_file_size: params.unencryptedFileSize, return this.httpService.post(
move_operation_type: params.moveOperationType, SharedVaultsPaths.createSharedVaultFileValetToken(params.sharedVaultUuid),
shared_vault_to_shared_vault_move_target_uuid: params.sharedVaultToSharedVaultMoveTargetUuid, {
}) file_uuid: params.fileUuid,
remote_identifier: params.remoteIdentifier,
operation: params.operation,
unencrypted_file_size: params.unencryptedFileSize,
move_operation_type: params.moveOperationType,
shared_vault_to_shared_vault_move_target_uuid: params.sharedVaultToSharedVaultMoveTargetUuid,
},
{
headers,
},
)
} }
} }

View File

@@ -2,7 +2,6 @@ export interface SharedVaultServerHash {
uuid: string uuid: string
user_uuid: string user_uuid: string
file_upload_bytes_used: number file_upload_bytes_used: number
file_upload_bytes_limit: number
created_at_timestamp: number created_at_timestamp: number
updated_at_timestamp: number updated_at_timestamp: number
} }

View File

@@ -107,6 +107,7 @@ export class FileService extends AbstractService implements FilesClientInterface
unencryptedFileSizeForUpload?: number | undefined unencryptedFileSizeForUpload?: number | undefined
moveOperationType?: SharedVaultMoveType moveOperationType?: SharedVaultMoveType
sharedVaultToSharedVaultMoveTargetUuid?: string sharedVaultToSharedVaultMoveTargetUuid?: string
sharedVaultOwnerUuid?: string
}): Promise<string | ClientDisplayableError> { }): Promise<string | ClientDisplayableError> {
if (params.operation !== ValetTokenOperation.Write && !params.fileUuidRequiredForExistingFiles) { if (params.operation !== ValetTokenOperation.Write && !params.fileUuidRequiredForExistingFiles) {
throw new Error('File UUID is required for for non-write operations') throw new Error('File UUID is required for for non-write operations')
@@ -114,6 +115,7 @@ export class FileService extends AbstractService implements FilesClientInterface
const valetTokenResponse = await this.sharedVault.createSharedVaultFileValetToken({ const valetTokenResponse = await this.sharedVault.createSharedVaultFileValetToken({
sharedVaultUuid: params.sharedVaultUuid, sharedVaultUuid: params.sharedVaultUuid,
sharedVaultOwnerUuid: params.sharedVaultUuid,
fileUuid: params.fileUuidRequiredForExistingFiles, fileUuid: params.fileUuidRequiredForExistingFiles,
remoteIdentifier: params.remoteIdentifier, remoteIdentifier: params.remoteIdentifier,
operation: params.operation, operation: params.operation,
@@ -135,6 +137,7 @@ export class FileService extends AbstractService implements FilesClientInterface
): Promise<void | ClientDisplayableError> { ): Promise<void | ClientDisplayableError> {
const valetTokenResult = await this.createSharedVaultValetToken({ const valetTokenResult = await this.createSharedVaultValetToken({
sharedVaultUuid: file.shared_vault_uuid ? file.shared_vault_uuid : sharedVault.sharing.sharedVaultUuid, sharedVaultUuid: file.shared_vault_uuid ? file.shared_vault_uuid : sharedVault.sharing.sharedVaultUuid,
sharedVaultOwnerUuid: sharedVault.sharing.ownerUserUuid,
remoteIdentifier: file.remoteIdentifier, remoteIdentifier: file.remoteIdentifier,
operation: ValetTokenOperation.Move, operation: ValetTokenOperation.Move,
fileUuidRequiredForExistingFiles: file.uuid, fileUuidRequiredForExistingFiles: file.uuid,
@@ -186,6 +189,7 @@ export class FileService extends AbstractService implements FilesClientInterface
vault && vault.isSharedVaultListing() vault && vault.isSharedVaultListing()
? await this.createSharedVaultValetToken({ ? await this.createSharedVaultValetToken({
sharedVaultUuid: vault.sharing.sharedVaultUuid, sharedVaultUuid: vault.sharing.sharedVaultUuid,
sharedVaultOwnerUuid: vault.sharing.ownerUserUuid,
remoteIdentifier, remoteIdentifier,
operation: ValetTokenOperation.Write, operation: ValetTokenOperation.Write,
unencryptedFileSizeForUpload: sizeInBytes, unencryptedFileSizeForUpload: sizeInBytes,

View File

@@ -13,7 +13,6 @@ describe('SyncLocalVaultsWithRemoteSharedVaults', () => {
uuid: '1-2-3', uuid: '1-2-3',
user_uuid: '2-3-4', user_uuid: '2-3-4',
file_upload_bytes_used: 123, file_upload_bytes_used: 123,
file_upload_bytes_limit: 10000000,
created_at_timestamp: 123, created_at_timestamp: 123,
updated_at_timestamp: 123, updated_at_timestamp: 123,
}] } }) }] } })

View File

@@ -318,7 +318,9 @@ export class LegacyApiService
} }
signOut(): Promise<HttpResponse<SignOutResponse>> { signOut(): Promise<HttpResponse<SignOutResponse>> {
return this.httpService.post<SignOutResponse>(Paths.v1.signOut, undefined, this.getSessionAccessToken()) return this.httpService.post<SignOutResponse>(Paths.v1.signOut, undefined, {
authentication: this.getSessionAccessToken(),
})
} }
async changeCredentials(parameters: { async changeCredentials(parameters: {
@@ -344,7 +346,9 @@ export class LegacyApiService
...parameters.newKeyParams.getPortableValue(), ...parameters.newKeyParams.getPortableValue(),
}) })
const response = await this.httpService.put<ChangeCredentialsResponse>(path, params, this.getSessionAccessToken()) const response = await this.httpService.put<ChangeCredentialsResponse>(path, params, {
authentication: this.getSessionAccessToken(),
})
this.changing = false this.changing = false
@@ -481,7 +485,11 @@ export class LegacyApiService
return preprocessingError return preprocessingError
} }
const path = Paths.v1.sessions const path = Paths.v1.sessions
const response = await this.httpService.get<SessionListResponse>(path, {}, this.getSessionAccessToken()) const response = await this.httpService.get<SessionListResponse>(
path,
{},
{ authentication: this.getSessionAccessToken() },
)
if (isErrorResponse(response)) { if (isErrorResponse(response)) {
this.preprocessAuthenticatedErrorResponse(response) this.preprocessAuthenticatedErrorResponse(response)
@@ -502,7 +510,7 @@ export class LegacyApiService
const response = await this.httpService.delete<SessionListResponse>( const response = await this.httpService.delete<SessionListResponse>(
path, path,
{ uuid: sessionId }, { uuid: sessionId },
this.getSessionAccessToken(), { authentication: this.getSessionAccessToken() },
) )
if (isErrorResponse(response)) { if (isErrorResponse(response)) {