diff --git a/src/auth/index.ts b/src/auth/index.ts index 7f0d0727..ab59a0f9 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -168,7 +168,7 @@ export class Auth { user: UserSettings; userTeam: TeamsSettings | null; }>( - '/access', + '/auth/login/access', { email: details.email, password: encryptedPasswordHash, @@ -238,7 +238,7 @@ export class Auth { sKey: string; tfa: boolean | null; }>( - '/login', + '/auth/login', { email: email, }, @@ -252,15 +252,22 @@ export class Auth { }); } + /** + * Logout + */ + public logout(token?: Token): Promise { + return this.client.get('/auth/logout', this.headersWithToken(token ?? this.apiSecurity?.token)); + } + /** * Generates a new TwoFactorAuth code */ - public generateTwoFactorAuthQR(): Promise { + public generateTwoFactorAuthQR(token?: Token): Promise { return this.client .get<{ qr: string; code: string; - }>('/tfa', this.headersWithToken(this.apiSecurity?.token)) + }>('/auth/tfa', this.headersWithToken(token ?? this.apiSecurity?.token)) .then((data) => { return { qr: data.qr, @@ -274,8 +281,8 @@ export class Auth { * @param pass * @param code */ - public disableTwoFactorAuth(pass: string, code: string): Promise { - return this.client.delete('/tfa', this.headersWithToken(this.apiSecurity?.token), { + public disableTwoFactorAuth(pass: string, code: string, token?: Token): Promise { + return this.client.delete('/auth/tfa', this.headersWithToken(token ?? this.apiSecurity?.token), { pass: pass, code: code, }); @@ -286,14 +293,14 @@ export class Auth { * @param backupKey * @param code */ - public storeTwoFactorAuthKey(backupKey: string, code: string): Promise { + public storeTwoFactorAuthKey(backupKey: string, code: string, token?: Token): Promise { return this.client.put( - '/tfa', + '/auth/tfa', { key: backupKey, code: code, }, - this.headersWithToken(this.apiSecurity?.token), + this.headersWithToken(token ?? this.apiSecurity?.token), ); } diff --git a/src/workspaces/index.ts b/src/workspaces/index.ts index 8ad2b5cd..fb9b4a02 100644 --- a/src/workspaces/index.ts +++ b/src/workspaces/index.ts @@ -31,6 +31,10 @@ import { UsersAndTeamsAnItemIsShareWidthResponse, WorkspaceUser, WorkspaceUsage, + ItemType, + WorkspaceLogOrderBy, + WorkspaceLogType, + WorkspaceLogResponse, } from './types'; export class Workspaces { @@ -203,7 +207,7 @@ export class Workspaces { public getPersonalTrash( workspaceId: string, - type: 'file' | 'folder', + type: ItemType, offset = 0, limit = 50, ): Promise { @@ -647,7 +651,7 @@ export class Workspaces { itemId, }: { workspaceId: string; - itemType: 'folder' | 'file'; + itemType: ItemType; itemId: string; }): [Promise, RequestCanceler] { const { promise, requestCanceler } = this.client.getCancellable( @@ -661,6 +665,43 @@ export class Workspaces { public getWorkspace(workspaceId: string): Promise { return this.client.get(`workspaces/${workspaceId}`, this.headers()); } + + public getWorkspaceLogs( + workspaceId: string, + limit = 50, + offset = 0, + member?: string, + activity?: WorkspaceLogType[], + lastDays?: number, + summary = true, + orderBy?: WorkspaceLogOrderBy, + ): Promise { + const params = new URLSearchParams(); + + params.append('limit', String(limit)); + params.append('offset', String(offset)); + params.append('summary', String(summary)); + + if (member) { + params.append('member', member); + } + if (activity && activity.length > 0) { + activity.forEach((act, index) => { + params.append(`activity[${index}]`, act); + }); + } + if (lastDays) { + params.append('lastDays', String(lastDays)); + } + if (orderBy) { + params.append('orderBy', String(orderBy)); + } + + return this.client.get( + `workspaces/${workspaceId}/access/logs?${params.toString()}`, + this.headers(), + ); + } } export * from './types'; diff --git a/src/workspaces/types.ts b/src/workspaces/types.ts index 792c19dc..6115bea1 100644 --- a/src/workspaces/types.ts +++ b/src/workspaces/types.ts @@ -317,3 +317,85 @@ export type UsersAndTeamsAnItemIsShareWidthResponse = { export type OrderByOptions = 'views:ASC' | 'views:DESC' | 'createdAt:ASC' | 'createdAt:DESC'; export type GetMemberUsageResponse = { backupsUsage: number; driveUsage: number; spaceLimit: number }; + +export enum WorkspaceLogType { + Login = 'login', + ChangedPassword = 'changed-password', + Logout = 'logout', + ShareFile = 'share-file', + ShareFolder = 'share-folder', + DeleteFile = 'delete-file', + DeleteFolder = 'delete-folder', +} + +export enum WorkspaceLogActionType { + Share = 'share', + Delete = 'delete', + DeleteAll = 'delete-all', +} + +export enum WorkspaceLogPlatform { + Web = 'web', + Mobile = 'mobile', + Desktop = 'desktop', +} + +export interface WorkspaceLogUser { + id: number; + name: string; + lastname: string; + email: string; + username: string; + bridgeUser?: string; + rootFolderId?: number; + uuid: string; + sharedWorkspace?: boolean; + avatar?: string; + lastPasswordChangedAt?: Date; +} + +export interface WorkspaceLog { + id: string; + workspaceId: string; + creator: string; + type: WorkspaceLogType; + platform: WorkspaceLogPlatform; + entityId?: string; + user: WorkspaceLogUser; + workspace: Workspace; + createdAt: Date; + updatedAt: Date; +} + +export interface WorkspaceLogResponse { + id: string; + workspaceId: string; + creator: string; + type: WorkspaceLogType; + platform: WorkspaceLogPlatform; + entityId?: string; + createdAt: Date; + updatedAt: Date; + user: WorkspaceLogUser; + workspace: Workspace; + file?: { + uuid: string; + plainName: string; + folderUuid: string; + type: string; + }; + folder?: { + uuid: string; + plainName: string; + parentId: string; + parentUuid?: string; + }; +} + +export type WorkspaceLogOrderBy = + | 'createdAt:ASC' + | 'createdAt:DESC' + | 'platform:ASC' + | 'platform:DESC' + | 'type:ASC' + | 'type:DESC'; diff --git a/test/auth/index.test.ts b/test/auth/index.test.ts index 03634dfd..28fc0d29 100644 --- a/test/auth/index.test.ts +++ b/test/auth/index.test.ts @@ -1,9 +1,9 @@ -import { Auth, CryptoProvider, Keys, LoginDetails, Password, RegisterDetails, Token } from '../../src'; import sinon from 'sinon'; import { emptyRegisterDetails } from './registerDetails.mother'; import { basicHeaders, headersWithToken } from '../../src/shared/headers'; import { ApiSecurity, AppDetails } from '../../src/shared'; import { HttpClient } from '../../src/shared/http/client'; +import { Auth, CryptoProvider, Keys, LoginDetails, Password, RegisterDetails, Token } from '../../src'; const httpClient = HttpClient.create(''); @@ -290,14 +290,14 @@ describe('# auth service tests', () => { // Assert expect(postStub.firstCall.args).toEqual([ - '/login', + '/auth/login', { email: loginDetails.email, }, headers, ]); expect(postStub.secondCall.args).toEqual([ - '/access', + '/auth/login/access', { email: loginDetails.email, password: 'password-encrypted_salt', @@ -387,7 +387,7 @@ describe('# auth service tests', () => { // Assert expect(postStub.firstCall.args).toEqual([ - '/login', + '/auth/login', { email: email, }, @@ -433,7 +433,7 @@ describe('# auth service tests', () => { const body = await client.generateTwoFactorAuthQR(); // Assert - await expect(callStub.firstCall.args).toEqual(['/tfa', headers]); + await expect(callStub.firstCall.args).toEqual(['/auth/tfa', headers]); expect(body).toEqual({ qr: 'qr', backupKey: 'code', @@ -454,7 +454,7 @@ describe('# auth service tests', () => { // Assert await expect(callStub.firstCall.args).toEqual([ - '/tfa', + '/auth/tfa', headers, { pass: pass, @@ -478,7 +478,7 @@ describe('# auth service tests', () => { // Assert await expect(callStub.firstCall.args).toEqual([ - '/tfa', + '/auth/tfa', { key: backupKey, code: code,