diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index a814d7e3b..98f8eefc4 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -716,5 +716,12 @@ "Unknown device": "Unknown device", "No active sessions": "No active sessions", "Session revoked": "Session revoked", - "All other sessions revoked": "All other sessions revoked" + "All other sessions revoked": "All other sessions revoked", + "Last used": "Last used", + "Created": "Created", + "Rename": "Rename", + "Publish": "Publish", + "Security": "Security", + "Enforce SSO": "Enforce SSO", + "Once enforced, members will not be able to login with email and password.": "Once enforced, members will not be able to login with email and password." } diff --git a/apps/server/src/core/auth/auth.controller.ts b/apps/server/src/core/auth/auth.controller.ts index c0997e750..6eab6539d 100644 --- a/apps/server/src/core/auth/auth.controller.ts +++ b/apps/server/src/core/auth/auth.controller.ts @@ -212,6 +212,7 @@ export class AuthController { setAuthCookie(res: FastifyReply, token: string) { res.setCookie('authToken', token, { httpOnly: true, + sameSite: 'lax', path: '/', expires: this.environmentService.getCookieExpiresIn(), secure: this.environmentService.isHttps(), diff --git a/apps/server/src/core/session/session.service.ts b/apps/server/src/core/session/session.service.ts index fa3bbb5f5..513037d15 100644 --- a/apps/server/src/core/session/session.service.ts +++ b/apps/server/src/core/session/session.service.ts @@ -51,7 +51,6 @@ export class SessionService { const mapped = sessions.map((s) => ({ id: s.id, deviceName: s.deviceName, - ipAddress: s.ipAddress, geoLocation: s.geoLocation, lastActiveAt: s.lastActiveAt, createdAt: s.createdAt, diff --git a/apps/server/src/core/workspace/services/workspace.service.ts b/apps/server/src/core/workspace/services/workspace.service.ts index fc187f3f2..c3b6550f5 100644 --- a/apps/server/src/core/workspace/services/workspace.service.ts +++ b/apps/server/src/core/workspace/services/workspace.service.ts @@ -669,13 +669,15 @@ export class WorkspaceService { } } - await this.userRepo.updateUser( - { deactivatedAt: new Date() }, - userId, - workspaceId, - ); - - await this.userSessionRepo.revokeByUserId(userId, workspaceId); + await executeTx(this.db, async (trx) => { + await this.userRepo.updateUser( + { deactivatedAt: new Date() }, + userId, + workspaceId, + trx, + ); + await this.userSessionRepo.revokeByUserId(userId, workspaceId, trx); + }); this.auditService.log({ event: AuditEvent.USER_DEACTIVATED, @@ -789,9 +791,9 @@ export class WorkspaceService { await this.watcherRepo.deleteByUserAndWorkspace(userId, workspaceId, { trx, }); - }); - await this.userSessionRepo.revokeByUserId(userId, workspaceId); + await this.userSessionRepo.revokeByUserId(userId, workspaceId, trx); + }); this.auditService.log({ event: AuditEvent.USER_DELETED, diff --git a/apps/server/src/database/migrations/20260325T120000-user-sessions.ts b/apps/server/src/database/migrations/20260326T121350-user-sessions.ts similarity index 97% rename from apps/server/src/database/migrations/20260325T120000-user-sessions.ts rename to apps/server/src/database/migrations/20260326T121350-user-sessions.ts index 480e4c90c..cd14872c5 100644 --- a/apps/server/src/database/migrations/20260325T120000-user-sessions.ts +++ b/apps/server/src/database/migrations/20260326T121350-user-sessions.ts @@ -20,6 +20,7 @@ export async function up(db: Kysely): Promise { col.notNull().defaultTo(sql`now()`), ) .addColumn('expires_at', 'timestamptz', (col) => col.notNull()) + .addColumn('metadata', 'jsonb') .addColumn('revoked_at', 'timestamptz') .addColumn('created_at', 'timestamptz', (col) => col.notNull().defaultTo(sql`now()`), diff --git a/apps/server/src/database/repos/session/user-session.repo.ts b/apps/server/src/database/repos/session/user-session.repo.ts index 4edc07439..01dedccdc 100644 --- a/apps/server/src/database/repos/session/user-session.repo.ts +++ b/apps/server/src/database/repos/session/user-session.repo.ts @@ -89,8 +89,10 @@ export class UserSessionRepo { async revokeByUserId( userId: string, workspaceId: string, + trx?: KyselyTransaction, ): Promise { - await this.db + const db = dbOrTx(this.db, trx); + await db .updateTable('userSessions') .set({ revokedAt: new Date() }) .where('userId', '=', userId) diff --git a/apps/server/src/database/types/db.d.ts b/apps/server/src/database/types/db.d.ts index 776e7248a..fe4d5a13a 100644 --- a/apps/server/src/database/types/db.d.ts +++ b/apps/server/src/database/types/db.d.ts @@ -437,6 +437,7 @@ export interface UserSessions { userAgent: string | null; ipAddress: string | null; geoLocation: string | null; + metadata: Json | null; lastActiveAt: Generated; expiresAt: Timestamp; revokedAt: Timestamp | null; diff --git a/apps/server/src/ee b/apps/server/src/ee index ebf891554..759e10970 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit ebf891554c031ad72d2b2bdbb09018436b3079c3 +Subproject commit 759e10970832579d39358c2a35286f2142cc0417