Skip to content

Commit 3443f32

Browse files
committed
RI-6154 updates in cloud session
1 parent 99c923c commit 3443f32

20 files changed

+190
-28
lines changed

redisinsight/api/config/ormconfig.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { CloudDatabaseDetailsEntity } from 'src/modules/cloud/database/entities/
2121
import { CloudCapiKeyEntity } from 'src/modules/cloud/capi-key/entity/cloud-capi-key.entity';
2222
import { RdiEntity } from 'src/modules/rdi/entities/rdi.entity';
2323
import { AiQueryMessageEntity } from 'src/modules/ai/query/entities/ai-query.message.entity';
24+
import { CloudSessionEntity } from 'src/modules/cloud/session/entities/cloud.session.entity';
2425
import migrations from '../migration';
2526
import * as config from '../src/utils/config';
2627

@@ -52,6 +53,7 @@ const ormConfig = {
5253
CloudCapiKeyEntity,
5354
RdiEntity,
5455
AiQueryMessageEntity,
56+
CloudSessionEntity,
5557
],
5658
migrations,
5759
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { MigrationInterface, QueryRunner } from "typeorm";
2+
3+
export class CloudSession1729024196797 implements MigrationInterface {
4+
name = 'CloudSession1729024196797'
5+
6+
public async up(queryRunner: QueryRunner): Promise<void> {
7+
await queryRunner.query(`CREATE TABLE "cloud_session" ("id" integer PRIMARY KEY NOT NULL, "data" varchar, "encryption" varchar)`);
8+
}
9+
10+
public async down(queryRunner: QueryRunner): Promise<void> {
11+
await queryRunner.query(`DROP TABLE "cloud_session"`);
12+
}
13+
14+
}

redisinsight/api/migration/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { AiHistory1713515657364 } from './1713515657364-ai-history';
4242
import { AiHistorySteps1714501203616 } from './1714501203616-ai-history-steps';
4343
import { Rdi1716370509836 } from './1716370509836-rdi';
4444
import { AiHistory1718260230164 } from './1718260230164-ai-history';
45+
import { CloudSession1729024196797 } from './1729024196797-cloud-session';
4546

4647
export default [
4748
initialMigration1614164490968,
@@ -88,4 +89,5 @@ export default [
8889
AiHistorySteps1714501203616,
8990
Rdi1716370509836,
9091
AiHistory1718260230164,
92+
CloudSession1729024196797,
9193
];

redisinsight/api/src/modules/cloud/auth/cloud-auth.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { CloudAuthController } from 'src/modules/cloud/auth/cloud-auth.controlle
88
import { CloudAuthAnalytics } from 'src/modules/cloud/auth/cloud-auth.analytics';
99

1010
@Module({
11-
imports: [CloudSessionModule],
11+
imports: [CloudSessionModule.register()],
1212
providers: [
1313
GoogleIdpCloudAuthStrategy,
1414
GithubIdpCloudAuthStrategy,

redisinsight/api/src/modules/cloud/auth/cloud-auth.service.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import { CloudSsoFeatureStrategy } from 'src/modules/cloud/cloud-sso.feature.fla
4141
import { CloudApiUnauthorizedException } from 'src/modules/cloud/common/exceptions';
4242
import { SsoIdpCloudAuthStrategy } from 'src/modules/cloud/auth/auth-strategy/sso-idp.cloud.auth-strategy';
4343
import {
44-
CloudOauthSsoUnsupportedEmailException
44+
CloudOauthSsoUnsupportedEmailException,
4545
} from 'src/modules/cloud/auth/exceptions/cloud-oauth.sso-unsupported-email.exception';
4646

4747
const mockedAxios = axios as jest.Mocked<typeof axios>;
@@ -255,7 +255,9 @@ describe('CloudAuthService', () => {
255255
error: 'access_denied',
256256
error_description: 'Some required properties are missing: email and lastName',
257257
},
258-
)).rejects.toThrow(new CloudOauthMissedRequiredDataException('Some required properties are missing: email and lastName'));
258+
)).rejects.toThrow(
259+
new CloudOauthMissedRequiredDataException('Some required properties are missing: email and lastName'),
260+
);
259261
});
260262
it('should throw an error if request not found', async () => {
261263
expect(service['authRequests'].size).toEqual(1);

redisinsight/api/src/modules/cloud/auth/cloud-auth.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@ export class CloudAuthService {
200200
private async revokeRefreshToken(sessionMetadata: SessionMetadata): Promise<void> {
201201
try {
202202
const session = await this.sessionService.getSession(sessionMetadata.sessionId);
203-
204203
if (!session?.refreshToken) {
205204
return;
206205
}
@@ -270,6 +269,7 @@ export class CloudAuthService {
270269
await this.sessionService.updateSessionData(sessionMetadata.sessionId, {
271270
accessToken: data.access_token,
272271
refreshToken: data.refresh_token,
272+
idpType,
273273
csrf: null,
274274
apiSessionId: null,
275275
});

redisinsight/api/src/modules/cloud/capi-key/cloud-capi-key.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { CloudCapiKeyAnalytics } from 'src/modules/cloud/capi-key/cloud-capi-key
1111
@Module({
1212
imports: [
1313
CloudUserModule,
14-
CloudSessionModule,
14+
CloudSessionModule.register(),
1515
],
1616
controllers: [CloudCapiKeyController],
1717
providers: [
Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
1-
import { Module } from '@nestjs/common';
1+
import { Module, Type } from '@nestjs/common';
22
import { CloudSessionService } from 'src/modules/cloud/session/cloud-session.service';
3+
import { CloudSessionRepository } from './repositories/cloud.session.repository';
4+
import { LocalCloudSessionRepository } from './repositories/local.cloud.session.repository';
35

4-
@Module({
5-
providers: [CloudSessionService],
6-
exports: [CloudSessionService],
7-
})
8-
export class CloudSessionModule {}
6+
@Module({})
7+
export class CloudSessionModule {
8+
static register(
9+
cloudSessionRepository: Type<CloudSessionRepository> = LocalCloudSessionRepository,
10+
) {
11+
return {
12+
module: CloudSessionModule,
13+
providers: [
14+
CloudSessionService,
15+
{
16+
provide: CloudSessionRepository,
17+
useClass: cloudSessionRepository,
18+
},
19+
],
20+
exports: [CloudSessionService],
21+
};
22+
}
23+
}

redisinsight/api/src/modules/cloud/session/cloud-session.service.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,71 @@ import { SessionService } from 'src/modules/session/session.service';
33
import { CloudSession } from 'src/modules/cloud/session/models/cloud-session';
44
import { classToPlain, plainToClass } from 'class-transformer';
55
import { TransformGroup } from 'src/common/constants';
6+
import { CloudSessionRepository } from './repositories/cloud.session.repository';
67

78
@Injectable()
89
export class CloudSessionService {
910
constructor(
1011
private readonly sessionService: SessionService,
12+
private readonly cloudSessionRepository: CloudSessionRepository,
1113
) {}
1214

1315
async getSession(id: string): Promise<CloudSession> {
1416
const session = await this.sessionService.getSession(id);
15-
return session?.data?.cloud || null;
17+
const cloud = session?.data?.cloud;
18+
if (!cloud?.refreshToken) {
19+
try {
20+
const cloudSessionData = await this.cloudSessionRepository.get();
21+
if (cloudSessionData?.data) {
22+
const { data } = cloudSessionData;
23+
24+
return {
25+
...cloud,
26+
refreshToken: data.refreshToken,
27+
idpType: data.idpType,
28+
};
29+
}
30+
} catch (e) {
31+
// ignore
32+
}
33+
}
34+
return cloud;
1635
}
1736

1837
async updateSessionData(id: string, cloud: any): Promise<CloudSession> {
1938
const session = await this.getSession(id);
2039

21-
return (await this.sessionService.updateSessionData(id, {
40+
const cloudSession = (await this.sessionService.updateSessionData(id, {
2241
cloud: plainToClass(CloudSession, {
2342
...classToPlain(session, { groups: [TransformGroup.Secure] }),
2443
...classToPlain(cloud, { groups: [TransformGroup.Secure] }),
2544
}, { groups: [TransformGroup.Secure] }),
2645
}))?.data?.cloud || null;
46+
47+
if (cloudSession && cloud?.refreshToken && cloud?.idpType) {
48+
try {
49+
this.cloudSessionRepository.save({
50+
data: {
51+
refreshToken: cloud.refreshToken,
52+
idpType: cloud.idpType,
53+
},
54+
});
55+
} catch (e) {
56+
// ignore
57+
}
58+
}
59+
60+
return cloudSession;
2761
}
2862

2963
async deleteSessionData(id: string): Promise<void> {
3064
await this.sessionService.updateSessionData(id, { cloud: null });
65+
66+
try {
67+
await this.cloudSessionRepository.save({ data: null });
68+
} catch (e) {
69+
// ignore
70+
}
3171
}
3272

3373
async invalidateApiSession(id: string): Promise<void> {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Expose } from 'class-transformer';
2+
import { DataAsJsonString } from 'src/common/decorators';
3+
import { Column, Entity } from 'typeorm';
4+
5+
@Entity('cloud_session')
6+
export class CloudSessionEntity {
7+
@Column({ nullable: false, primary: true })
8+
@Expose()
9+
id: number;
10+
11+
@Column({ nullable: true })
12+
@DataAsJsonString()
13+
@Expose()
14+
data: string;
15+
16+
@Column({ nullable: true })
17+
encryption: string;
18+
}

0 commit comments

Comments
 (0)