Skip to content

Commit c83c288

Browse files
authored
Merge pull request #579 from codex-team/feat/memberships-to-user
feat(users): move membership data to users model
2 parents dee36aa + e4140b8 commit c83c288

File tree

3 files changed

+83
-56
lines changed

3 files changed

+83
-56
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
require('dotenv').config();
2+
require('process');
3+
const { setup } = require('./setup');
4+
5+
/**
6+
* Method that runs convertor script
7+
*/
8+
async function run() {
9+
const { client, hawkDb } = await setup();
10+
11+
const collections = await hawkDb.listCollections({}, {
12+
authorizedCollections: true,
13+
nameOnly: true,
14+
}).toArray();
15+
16+
let usersMembershipCollectionsToCheck = collections.filter(col => /^membership:/.test(col.name)).map(col => col.name);
17+
18+
console.log(`Found ${usersMembershipCollectionsToCheck.length} users membership collections.`);
19+
20+
const usersDocuments = await hawkDb.collection('users').find({}).toArray();
21+
22+
let i = 1;
23+
24+
for (const collectionName of usersMembershipCollectionsToCheck) {
25+
console.log(`[${i}/${usersMembershipCollectionsToCheck.length}] Processing ${collectionName}`);
26+
27+
const userId = collectionName.split(':')[1];
28+
29+
const userDocument = usersDocuments.find(u => u._id.toString() === userId);
30+
31+
if (!userDocument) {
32+
i++;
33+
continue;
34+
}
35+
36+
const memberships = await hawkDb.collection(collectionName).find({}).toArray();
37+
38+
for (const membership of memberships) {
39+
const workspaceId = membership.workspaceId.toString();
40+
const isPending = membership.isPending || false;
41+
await hawkDb.collection('users').updateOne({ _id: userDocument._id }, { $set: { [`workspaces.${workspaceId}`]: { isPending } } });
42+
}
43+
44+
i++;
45+
}
46+
47+
await client.close();
48+
}
49+
50+
run().catch(err => {
51+
console.error('❌ Script failed:', err);
52+
process.exit(1);
53+
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hawk.api",
3-
"version": "1.2.16",
3+
"version": "1.2.17",
44
"main": "index.ts",
55
"license": "BUSL-1.1",
66
"scripts": {

src/models/user.ts

Lines changed: 29 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,9 @@ export interface TokensPair {
3333
/**
3434
* Membership collection DB implementation
3535
*/
36-
export interface MembershipDBScheme {
37-
/**
38-
* Document id
39-
*/
40-
_id: ObjectId;
41-
42-
/**
43-
* User's workspace id
44-
*/
45-
workspaceId: ObjectId;
46-
47-
/**
48-
* Shows if member is pending
49-
*/
36+
export type MembershipDBScheme = Record<string, {
5037
isPending?: boolean;
51-
}
38+
}>;
5239

5340
/**
5441
* This structure represents how user notifications are stored at the DB (in 'users' collection)
@@ -124,6 +111,11 @@ export default class UserModel extends AbstractModel<UserDBScheme> implements Us
124111
*/
125112
public githubId?: string;
126113

114+
/**
115+
* User's workspaces
116+
*/
117+
public workspaces!: MembershipDBScheme;
118+
127119
/**
128120
* User's original password (this field appears only after registration).
129121
* Using to send password to user after registration
@@ -155,11 +147,6 @@ export default class UserModel extends AbstractModel<UserDBScheme> implements Us
155147
*/
156148
protected collection: Collection<UserDBScheme>;
157149

158-
/**
159-
* Collection of user's workspaces
160-
*/
161-
private membershipCollection: Collection<MembershipDBScheme>;
162-
163150
/**
164151
* Model constructor
165152
* @param modelData - user data
@@ -174,7 +161,6 @@ export default class UserModel extends AbstractModel<UserDBScheme> implements Us
174161

175162
super(modelData);
176163

177-
this.membershipCollection = this.dbConnection.collection('membership:' + this._id);
178164
this.collection = this.dbConnection.collection<UserDBScheme>('users');
179165
}
180166

@@ -339,19 +325,13 @@ export default class UserModel extends AbstractModel<UserDBScheme> implements Us
339325
* @param workspaceId - user's id to add
340326
* @param isPending - if true, mark user's membership as pending
341327
*/
342-
public async addWorkspace(workspaceId: string, isPending = false): Promise<object> {
343-
const doc: OptionalId<MembershipDBScheme> = {
344-
workspaceId: new ObjectId(workspaceId),
345-
};
346-
347-
if (isPending) {
348-
doc.isPending = isPending;
349-
}
350-
351-
const documentId = (await this.membershipCollection.insertOne(doc)).insertedId;
328+
public async addWorkspace(workspaceId: string, isPending = false): Promise<{ workspaceId: string }> {
329+
await this.update(
330+
{ _id: new ObjectId(this._id) },
331+
{ [`workspaces.${workspaceId}`]: { isPending } }
332+
);
352333

353334
return {
354-
id: documentId,
355335
workspaceId,
356336
};
357337
}
@@ -361,9 +341,10 @@ export default class UserModel extends AbstractModel<UserDBScheme> implements Us
361341
* @param workspaceId - id of workspace to remove
362342
*/
363343
public async removeWorkspace(workspaceId: string): Promise<{ workspaceId: string }> {
364-
await this.membershipCollection.deleteOne({
365-
workspaceId: new ObjectId(workspaceId),
366-
});
344+
await this.collection.updateOne(
345+
{ _id: new ObjectId(this._id) },
346+
{ $unset: { [`workspaces.${workspaceId}`]: '' } }
347+
);
367348

368349
return {
369350
workspaceId,
@@ -375,11 +356,9 @@ export default class UserModel extends AbstractModel<UserDBScheme> implements Us
375356
* @param workspaceId - workspace id to confirm
376357
*/
377358
public async confirmMembership(workspaceId: string): Promise<void> {
378-
await this.membershipCollection.updateOne(
379-
{
380-
workspaceId: new ObjectId(workspaceId),
381-
},
382-
{ $unset: { isPending: '' } }
359+
await this.collection.updateOne(
360+
{ _id: new ObjectId(this._id) },
361+
{ $unset: { [`workspaces.${workspaceId}.isPending`]: '' } }
383362
);
384363
}
385364

@@ -389,23 +368,18 @@ export default class UserModel extends AbstractModel<UserDBScheme> implements Us
389368
* @param ids - workspaces id to filter them if there are workspaces that doesn't belong to the user
390369
*/
391370
public async getWorkspacesIds(ids: (string | ObjectId)[] = []): Promise<string[]> {
392-
const idsAsObjectId = ids.map(id => new ObjectId(id));
393-
const searchQuery = ids.length ? {
394-
workspaceId: {
395-
$in: idsAsObjectId,
396-
},
397-
isPending: {
398-
$ne: true,
399-
},
400-
} : {
401-
isPending: {
402-
$ne: true,
403-
},
404-
};
371+
const res = [];
405372

406-
const membershipDocuments = await this.membershipCollection.find(searchQuery).toArray();
373+
for (const id of ids) {
374+
const workspaceId = id.toString();
375+
const workspace = this.workspaces[workspaceId];
376+
377+
if (workspace && workspace.isPending !== true) {
378+
res.push(workspaceId);
379+
}
380+
}
407381

408-
return membershipDocuments.map(doc => doc.workspaceId.toString());
382+
return res;
409383
}
410384

411385
/**

0 commit comments

Comments
 (0)