Skip to content

Commit 1752971

Browse files
author
Romaric Mourgues
authored
🛠 Fix canary 1802 (#1966)
* Fix #1963 * Fix #1964 * Update invite token test
1 parent 473720f commit 1752971

File tree

9 files changed

+70
-24
lines changed

9 files changed

+70
-24
lines changed

twake/backend/node/src/services/console/processing/merge.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,7 @@ export class MergeProcess {
171171
return progress$;
172172
}
173173

174-
private getStreams(
175-
concurrent: number = 1,
176-
): {
174+
private getStreams(concurrent: number = 1): {
177175
// hot companies observable
178176
companies$: Observable<CompanyCreatedStreamObject>;
179177
// hot users observable
@@ -325,6 +323,7 @@ export class MergeProcess {
325323
}),
326324
skipInvite: true,
327325
role,
326+
inviterEmail: "",
328327
},
329328
);
330329

twake/backend/node/src/services/console/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export interface CreateConsoleUser {
4141
password: string;
4242
role: CompanyUserRole;
4343
skipInvite: boolean;
44-
inviterEmail?: string;
44+
inviterEmail: string;
4545
}
4646

4747
export interface CreateInternalUser {

twake/backend/node/src/services/workspaces/api.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,19 @@ export interface WorkspaceServiceAPI
122122
workspaceUserPk: WorkspacePendingUserPrimaryKey,
123123
): Promise<DeleteResult<WorkspacePendingUserPrimaryKey>>;
124124

125-
getInviteToken(companyId: string, workspaceId: string): Promise<WorkspaceInviteTokenObject>;
126-
createInviteToken(companyId: string, workspaceId: string): Promise<WorkspaceInviteTokenObject>;
127-
deleteInviteToken(companyId: string, workspaceId: string): Promise<boolean>;
125+
getInviteToken(
126+
companyId: string,
127+
workspaceId: string,
128+
userId: string,
129+
): Promise<WorkspaceInviteTokenObject>;
130+
createInviteToken(
131+
companyId: string,
132+
workspaceId: string,
133+
userId: string,
134+
): Promise<WorkspaceInviteTokenObject>;
135+
deleteInviteToken(companyId: string, workspaceId: string, userId: string): Promise<boolean>;
128136
getInviteTokenInfo(jwtToken: string): Promise<WorkspaceInviteTokens>;
129137

130-
encodeInviteToken(companyId: string, workspaceId: string, token: string): string;
138+
encodeInviteToken(companyId: string, workspaceId: string, userId: string, token: string): string;
131139
decodeInviteToken(encodedToken: string): InviteTokenObject;
132140
}

twake/backend/node/src/services/workspaces/entities/workspace_invite_tokens.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Column, Entity } from "../../../core/platform/services/database/service
44
export const TYPE = "workspace_invite_tokens";
55

66
@Entity(TYPE, {
7-
primaryKey: [["company_id"], "workspace_id", "invite_token"],
7+
primaryKey: [["company_id"], "workspace_id", "user_id", "invite_token"],
88
type: TYPE,
99
})
1010
export default class WorkspaceInviteTokens {
@@ -14,13 +14,16 @@ export default class WorkspaceInviteTokens {
1414
@Column("workspace_id", "string")
1515
workspace_id: string;
1616

17+
@Column("user_id", "string")
18+
user_id: string;
19+
1720
@Column("invite_token", "string")
1821
invite_token: string;
1922
}
2023

2124
export type WorkspaceInviteTokensPrimaryKey = Pick<
2225
WorkspaceInviteTokens,
23-
"company_id" | "workspace_id" | "invite_token"
26+
"company_id" | "workspace_id" | "user_id" | "invite_token"
2427
>;
2528

2629
export function getInstance(

twake/backend/node/src/services/workspaces/services/workspace/service.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -569,33 +569,39 @@ export class WorkspaceService implements WorkspaceServiceAPI {
569569
async getInviteToken(
570570
companyId: string,
571571
workspaceId: string,
572+
userId: string,
572573
): Promise<WorkspaceInviteTokenObject> {
573-
const pk = { company_id: companyId, workspace_id: workspaceId };
574+
const pk = { company_id: companyId, workspace_id: workspaceId, user_id: userId };
574575
const res = await this.workspaceInviteTokensRepository.findOne(pk);
575576
if (!res) return null;
576577

577578
return {
578-
token: this.encodeInviteToken(companyId, workspaceId, res.invite_token),
579+
token: this.encodeInviteToken(companyId, workspaceId, userId, res.invite_token),
579580
};
580581
}
581582

582583
async createInviteToken(
583584
companyId: string,
584585
workspaceId: string,
586+
userId: string,
585587
): Promise<WorkspaceInviteTokenObject> {
586-
await this.deleteInviteToken(companyId, workspaceId);
588+
await this.deleteInviteToken(companyId, workspaceId, userId);
587589
const token = randomBytes(32).toString("base64");
588-
const pk = { company_id: companyId, workspace_id: workspaceId };
590+
const pk = { company_id: companyId, workspace_id: workspaceId, user_id: userId };
589591
await this.workspaceInviteTokensRepository.save(
590592
getWorkspaceInviteTokensInstance({ ...pk, invite_token: token }),
591593
);
592594
return {
593-
token: this.encodeInviteToken(companyId, workspaceId, token),
595+
token: this.encodeInviteToken(companyId, workspaceId, userId, token),
594596
};
595597
}
596598

597-
async deleteInviteToken(companyId: string, workspaceId: string): Promise<boolean> {
598-
const pk = { company_id: companyId, workspace_id: workspaceId };
599+
async deleteInviteToken(
600+
companyId: string,
601+
workspaceId: string,
602+
userId: string,
603+
): Promise<boolean> {
604+
const pk = { company_id: companyId, workspace_id: workspaceId, user_id: userId };
599605
const currentRecord = await this.workspaceInviteTokensRepository.findOne(pk);
600606
if (!currentRecord) {
601607
return false;
@@ -617,23 +623,31 @@ export class WorkspaceService implements WorkspaceServiceAPI {
617623
const pk: WorkspaceInviteTokensPrimaryKey = {
618624
company_id: tokenInfo.c,
619625
workspace_id: tokenInfo.w,
626+
user_id: tokenInfo.u,
620627
invite_token: tokenInfo.t,
621628
};
622629
return this.workspaceInviteTokensRepository.findOne(pk);
623630
}
624631

625-
public encodeInviteToken(companyId: string, workspaceId: string, token: string) {
632+
public encodeInviteToken(companyId: string, workspaceId: string, userId: string, token: string) {
626633
// Change base64 characters to make them url safe
627634
token = token.replace(/\+/g, ".").replace(/\//g, "_").replace(/=/g, "-");
628-
const encodedToken = `${reduceUUID4(companyId)}-${reduceUUID4(workspaceId)}-${token}`;
635+
const encodedToken = `${reduceUUID4(companyId)}-${reduceUUID4(workspaceId)}-${reduceUUID4(
636+
userId,
637+
)}-${token}`;
629638
return encodedToken;
630639
}
631640

632641
public decodeInviteToken(encodedToken: string): InviteTokenObject | null {
633642
try {
634643
let split = encodedToken.split("-");
635644
//We split on "-" but the token can contain "-" so be careful
636-
let [companyId, workspaceId, token] = [split.shift(), split.shift(), split.join("-")];
645+
let [companyId, workspaceId, userId, token] = [
646+
split.shift(),
647+
split.shift(),
648+
split.shift(),
649+
split.join("-"),
650+
];
637651
if (!token) {
638652
return;
639653
}
@@ -642,6 +656,7 @@ export class WorkspaceService implements WorkspaceServiceAPI {
642656
return {
643657
c: expandUUID4(companyId),
644658
w: expandUUID4(workspaceId),
659+
u: expandUUID4(userId),
645660
t: token,
646661
};
647662
} catch (e) {

twake/backend/node/src/services/workspaces/web/controllers/workspace-invite-tokens.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export class WorkspaceInviteTokensCrudController
4242
const res = await this.services.workspaces.getInviteToken(
4343
context.company_id,
4444
context.workspace_id,
45+
context.user.id,
4546
);
4647

4748
if (!res) {
@@ -62,6 +63,7 @@ export class WorkspaceInviteTokensCrudController
6263
const res = await this.services.workspaces.createInviteToken(
6364
context.company_id,
6465
context.workspace_id,
66+
context.user.id,
6567
);
6668

6769
return {
@@ -84,6 +86,7 @@ export class WorkspaceInviteTokensCrudController
8486
const deleted = await this.services.workspaces.deleteInviteToken(
8587
context.company_id,
8688
context.workspace_id,
89+
context.user.id,
8790
);
8891

8992
if (!deleted) {
@@ -134,6 +137,8 @@ export class WorkspaceInviteTokensCrudController
134137
{ id: userId },
135138
);
136139
if (!companyUser) {
140+
const inviter = await this.services.users.get({ id: entity.user_id });
141+
137142
const createdConsoleUser = await this.services.console
138143
.getClient()
139144
.addUserToCompany(
@@ -151,6 +156,7 @@ export class WorkspaceInviteTokensCrudController
151156
},
152157
role: "member",
153158
skipInvite: true,
159+
inviterEmail: inviter.email_canonical,
154160
},
155161
);
156162
await this.services.console

twake/backend/node/src/services/workspaces/web/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export interface WorkspaceInviteTokenObject {
111111
export interface InviteTokenObject {
112112
c: string;
113113
w: string;
114+
u: string;
114115
t: string;
115116
}
116117

twake/backend/node/test/e2e/workspaces/workspaces.invite-tokens.spec.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ describe("The /workspaces API (invite tokens)", () => {
123123
const userId = testDbService.workspaces[0].users[0].id;
124124
const companyId = testDbService.company.id;
125125

126-
await workspaceServicesAPI.workspaces.createInviteToken(companyId, workspaceId);
126+
await workspaceServicesAPI.workspaces.createInviteToken(companyId, workspaceId, userId);
127127

128128
const jwtToken = await platform.auth.getJWTToken({ sub: userId });
129129

@@ -340,7 +340,7 @@ describe("The /workspaces API (invite tokens)", () => {
340340
const userId = testDbService.workspaces[0].users[0].id;
341341
const companyId = testDbService.company.id;
342342

343-
await workspaceServicesAPI.workspaces.createInviteToken(companyId, workspaceId);
343+
await workspaceServicesAPI.workspaces.createInviteToken(companyId, workspaceId, userId);
344344

345345
const jwtToken = await platform.auth.getJWTToken({ sub: userId });
346346

@@ -403,7 +403,11 @@ describe("The /workspaces API (invite tokens)", () => {
403403
companyId = testDbService.company.id;
404404
workspaceId = testDbService.workspaces[0].workspace.id;
405405
userId = testDbService.workspaces[2].users[0].id;
406-
inviteToken = await workspaceServicesAPI.workspaces.createInviteToken(companyId, workspaceId);
406+
inviteToken = await workspaceServicesAPI.workspaces.createInviteToken(
407+
companyId,
408+
workspaceId,
409+
userId,
410+
);
407411
});
408412
afterAll(shutdown);
409413

twake/frontend/src/app/state/recoil/hooks/channels/usePublicOrPrivateChannels.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,19 @@ export function usePublicOrPrivateChannels(): {
4040
[companyId, workspaceId],
4141
);
4242

43+
//Public channels
4344
useRealtimeRoom<ChannelType[]>(
4445
ChannelsMineAPIClient.websockets(companyId, workspaceId)[0],
45-
'usePublicOrPrivateChannels',
46+
'usePublicOrPrivateChannelsPublic',
47+
(_action, _resource) => {
48+
if (_action === 'saved') refresh();
49+
},
50+
);
51+
52+
//Private channels
53+
useRealtimeRoom<ChannelType[]>(
54+
ChannelsMineAPIClient.websockets(companyId, workspaceId)[1],
55+
'usePublicOrPrivateChannelsPrivate',
4656
(_action, _resource) => {
4757
if (_action === 'saved') refresh();
4858
},

0 commit comments

Comments
 (0)