-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathusersFactory.ts
More file actions
149 lines (125 loc) · 3.83 KB
/
usersFactory.ts
File metadata and controls
149 lines (125 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import AbstractModelFactory from './abstactModelFactory';
import UserModel from './user';
import { Collection, Db } from 'mongodb';
import DataLoaders from '../dataLoaders';
import { UserDBScheme } from '@hawk.so/types';
import { Analytics, AnalyticsEventTypes } from '../utils/analytics';
/**
* Users factory to work with User Model
*/
export default class UsersFactory extends AbstractModelFactory<UserDBScheme, UserModel> {
/**
* DataBase collection to work with
*/
protected collection: Collection<UserDBScheme>;
/**
* DataLoaders for fetching data from database
*/
private dataLoaders: DataLoaders;
/**
* Creates user factory instance
* @param dbConnection - connection to DataBase
* @param dataLoaders - dataLoaders for fetching data
*/
constructor(dbConnection: Db, dataLoaders: DataLoaders) {
super(dbConnection, UserModel);
this.collection = dbConnection.collection('users');
this.dataLoaders = dataLoaders;
}
/**
* Finds user by his email
* @param email - user's email
*/
public async findByEmail(email: string): Promise<UserModel | null> {
const userData = await this.dataLoaders.userByEmail.load(email);
if (!userData) {
return null;
}
return new UserModel(userData);
}
/**
* Finds user by its id
* @param id - user id
*/
public async findById(id: string): Promise<UserModel | null> {
const userData = await this.dataLoaders.userById.load(id);
if (!userData) {
return null;
}
return new UserModel(userData);
}
/**
* Creates new user in DB and returns it
* @param email - user email
* @param password - user password
* @param utm - UTM parameters
*/
public async create(email: string, password?: string, utm?: any): Promise<UserModel> {
const generatedPassword = password || (await UserModel.generatePassword());
const hashedPassword = await UserModel.hashPassword(generatedPassword);
const userData: any = {
email,
password: hashedPassword,
notifications: UserModel.generateDefaultNotificationsSettings(email),
};
// Add UTM data if provided
if (utm && Object.keys(utm).length > 0) {
userData.utm = utm;
}
const userId = (await this.collection.insertOne(userData)).insertedId;
const user = new UserModel({
_id: userId,
...userData,
});
user.generatedPassword = generatedPassword;
await Analytics.logEvent({
/* eslint-disable-next-line camelcase */
event_type: AnalyticsEventTypes.NEW_USER_REGISTERED,
/* eslint-disable-next-line camelcase */
user_id: userId.toString(),
time: Date.now(),
});
return user;
}
/**
* Creates new user id DB by GitHub provider
* @param id - GitHub profile id
* @param name - GitHub profile name
* @param image - GitHub profile avatar url
*/
public async createByGithub(
{ id, name, image }: { id: string; name: string; image: string }
): Promise<UserModel> {
if (!id || !name || !image) {
throw new Error('Required parameters are not provided');
}
const userData = {
githubId: id,
name,
image,
};
const userId = (await this.collection.insertOne(userData)).insertedId;
return new UserModel({
_id: userId,
...userData,
});
}
/**
* Get Users by their ids
* @param ids - users ids to fetch
*/
public async findManyByIds(ids: string[]): Promise<UserDBScheme[]> {
return (await this.dataLoaders.userById.loadMany(ids))
.map((data) => !data || data instanceof Error ? null : new UserModel(data))
.filter(Boolean) as UserModel[];
}
/**
* Delete's user by email
*
* @param email - user email
*/
public async deleteByEmail(email: string): Promise<boolean> {
const { result } = await this.collection.deleteOne({ email: email });
return !!result.ok;
}
}