Migrate web auth from localStorage token pairs to httpOnly cookie sessions (#23642)
This commit is contained in:
@@ -14,6 +14,7 @@ import { RotateSigningKeysCronCommand } from 'src/engine/core-modules/jwt/crons/
|
||||
import { CronTriggerCronCommand } from 'src/engine/core-modules/logic-function/logic-function-trigger/triggers/cron/cron-trigger.cron.command';
|
||||
import { CheckPublicDomainsValidRecordsCronCommand } from 'src/engine/core-modules/public-domain/crons/commands/check-public-domains-valid-records.cron.command';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { UserSessionCleanupCronCommand } from 'src/engine/core-modules/user-session/crons/commands/user-session-cleanup.cron.command';
|
||||
import { CheckCustomDomainValidRecordsCronCommand } from 'src/engine/core-modules/workspace/crons/commands/check-custom-domain-valid-records.cron.command';
|
||||
import { WebhookSubscriptionRenewalCronCommand } from 'src/modules/connected-account/webhook-subscription-manager/crons/commands/webhook-subscription-renewal.cron.command';
|
||||
import { TrashCleanupCronCommand } from 'src/engine/trash-cleanup/commands/trash-cleanup.cron.command';
|
||||
@@ -73,6 +74,7 @@ export class CronRegisterAllCommand extends CommandRunner {
|
||||
private readonly staleRegistrationCleanupCronCommand: StaleRegistrationCleanupCronCommand,
|
||||
private readonly pendingFileCleanupCronCommand: PendingFileCleanupCronCommand,
|
||||
private readonly billingReminderCronCommand: BillingReminderCronCommand,
|
||||
private readonly userSessionCleanupCronCommand: UserSessionCleanupCronCommand,
|
||||
private readonly twentyConfigService: TwentyConfigService,
|
||||
) {
|
||||
super();
|
||||
@@ -207,6 +209,10 @@ export class CronRegisterAllCommand extends CommandRunner {
|
||||
command: this.billingReminderCronCommand,
|
||||
isEnabled: isBillingEnabled,
|
||||
},
|
||||
{
|
||||
name: 'UserSessionCleanup',
|
||||
command: this.userSessionCleanupCronCommand,
|
||||
},
|
||||
];
|
||||
|
||||
let successCount = 0;
|
||||
|
||||
@@ -32,6 +32,7 @@ import { RotateSigningKeysCronCommand } from 'src/engine/core-modules/jwt/crons/
|
||||
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||
import { PublicDomainModule } from 'src/engine/core-modules/public-domain/public-domain.module';
|
||||
import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module';
|
||||
import { UserSessionModule } from 'src/engine/core-modules/user-session/user-session.module';
|
||||
import { UpgradeStatusCommand } from 'src/engine/core-modules/upgrade/commands/upgrade-status.command';
|
||||
import { UpgradeModule } from 'src/engine/core-modules/upgrade/upgrade.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
@@ -99,6 +100,7 @@ import { WorkflowCoreConsistencyModule } from 'src/modules/workflow/workflow-cor
|
||||
WorkspaceVersionModule,
|
||||
UpgradeModule,
|
||||
SecretEncryptionRotationModule,
|
||||
UserSessionModule,
|
||||
],
|
||||
providers: [
|
||||
DataSeedWorkspaceCommand,
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import { type QueryRunner } from 'typeorm';
|
||||
|
||||
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
|
||||
import { type FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
|
||||
|
||||
@RegisteredInstanceCommand('2.27.0', 1785518325511)
|
||||
export class CreateUserSessionCoreTableFastInstanceCommand
|
||||
implements FastInstanceCommand
|
||||
{
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS "core"."userSession" (
|
||||
"id" uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||
"tokenHash" text NOT NULL,
|
||||
"userId" uuid NOT NULL,
|
||||
"workspaceId" uuid,
|
||||
"userWorkspaceId" uuid,
|
||||
"authProvider" text NOT NULL,
|
||||
"isImpersonating" boolean NOT NULL DEFAULT false,
|
||||
"impersonatorUserWorkspaceId" uuid,
|
||||
"impersonatedUserWorkspaceId" uuid,
|
||||
"userAgent" text,
|
||||
"ipAddress" text,
|
||||
"expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"lastActiveAt" TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
"revokedAt" TIMESTAMP WITH TIME ZONE,
|
||||
"revokedReason" text,
|
||||
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
||||
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
||||
CONSTRAINT "PK_userSession_id" PRIMARY KEY ("id"),
|
||||
CONSTRAINT "FK_USER_SESSION_USER_ID" FOREIGN KEY ("userId")
|
||||
REFERENCES "core"."user"("id") ON DELETE CASCADE,
|
||||
CONSTRAINT "FK_USER_SESSION_WORKSPACE_ID" FOREIGN KEY ("workspaceId")
|
||||
REFERENCES "core"."workspace"("id") ON DELETE CASCADE,
|
||||
CONSTRAINT "FK_USER_SESSION_USER_WORKSPACE_ID" FOREIGN KEY ("userWorkspaceId")
|
||||
REFERENCES "core"."userWorkspace"("id") ON DELETE CASCADE
|
||||
)`,
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE UNIQUE INDEX IF NOT EXISTS "IDX_USER_SESSION_TOKEN_HASH_UNIQUE" ON "core"."userSession" ("tokenHash")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_USER_SESSION_USER_ID" ON "core"."userSession" ("userId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_USER_SESSION_WORKSPACE_ID" ON "core"."userSession" ("workspaceId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_USER_SESSION_USER_WORKSPACE_ID" ON "core"."userSession" ("userWorkspaceId")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_USER_SESSION_EXPIRES_AT" ON "core"."userSession" ("expiresAt")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_USER_SESSION_REVOKED_AT" ON "core"."userSession" ("revokedAt")`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS "core"."userSession"`);
|
||||
}
|
||||
}
|
||||
+2
@@ -132,6 +132,7 @@ import { AddChannelWebhookSubscriptionExternalIdIndexesFastInstanceCommand } fro
|
||||
import { AddIsHiddenToAgentMessageFastInstanceCommand } from './2-25/2-25-instance-command-fast-1785230296000-add-is-hidden-to-agent-message';
|
||||
import { AddConnectedAccountHandleProviderIndexFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-26/2-26-instance-command-fast-1785420705255-add-connected-account-handle-provider-index';
|
||||
import { AddOpenRecordInToObjectMetadataFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-27/2-27-instance-command-fast-1785504900000-add-open-record-in-to-object-metadata';
|
||||
import { CreateUserSessionCoreTableFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-27/2-27-instance-command-fast-1785518325511-create-user-session-core-table';
|
||||
|
||||
export const INSTANCE_COMMANDS = [
|
||||
AddViewFieldGroupIdIndexOnViewFieldFastInstanceCommand,
|
||||
@@ -266,4 +267,5 @@ export const INSTANCE_COMMANDS = [
|
||||
AddIsHiddenToAgentMessageFastInstanceCommand,
|
||||
AddConnectedAccountHandleProviderIndexFastInstanceCommand,
|
||||
AddOpenRecordInToObjectMetadataFastInstanceCommand,
|
||||
CreateUserSessionCoreTableFastInstanceCommand,
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user