-
Notifications
You must be signed in to change notification settings - Fork 21
/
userImporter.js
158 lines (148 loc) · 5.75 KB
/
userImporter.js
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
150
151
152
153
154
155
156
157
158
const db = require('../db');
const knex = require('../db/connection');
const { TABLES } = require('../db/constants');
const email = require('../lib/email'); // eslint-disable-line
const ADDED = 0;
const UPDATED = 1;
const NOT_CHANGED = 2;
class UserImporter {
getRoleId(roleName) {
if (roleName === 'admin') {
return this.adminRoleId;
}
return this.staffRoleId;
}
userFromRow(row, adminUser) {
return {
email: row.email.toLowerCase(),
name: row.name,
role_id: this.getRoleId(row.role_name),
agency_id: this.agencies[row.agency_name].id,
tenant_id: adminUser.tenant_id,
};
}
checkRow(row, rowIndex) {
const ret = [];
const rowNumStr = `Row: ${rowIndex + 2}, `;
if (!row.email) {
ret.push(`${rowNumStr}email: Missing email`);
}
const validRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
if (!row.email.match(validRegex)) {
ret.push(`${rowNumStr}email: Incorrect format: ${row.email}`);
}
if (this.users[row.email]) {
// TO eventually DO: remove this error to allow updating users.
// Must also change front end UI to show # users updated and # users not changed.
ret.push(`${rowNumStr}email: User already exists: ${row.email}`);
}
if (!row.name) {
ret.push(`${rowNumStr}name: Missing name`);
}
if (!row.role_name) {
ret.push(`${rowNumStr}role_name: Missing role`);
}
if ((row.role_name !== 'admin' && row.role_name !== 'staff')) {
ret.push(`${rowNumStr}Role: Unknown role_name: ${row.role_name}, must be 'admin' or 'staff'`);
}
if (!row.agency_name) {
ret.push(`${rowNumStr}Agency: missing Agency`);
}
if (!this.agencies[row.agency_name]) {
ret.push(`${rowNumStr}agency_name: Unknown Agency: ${row.agency_name}`);
}
return ret;
}
static async syncUser(user) {
await knex(TABLES.users)
.where({ email: user.email })
.update({
...user,
});
}
async handleRow(row, adminUser, domain) {
const newUser = this.userFromRow(row, adminUser);
const existingUser = this.users[row.email];
if (existingUser) {
if ((existingUser.name === row.name)
&& (existingUser.role_id === this.getRoleId(row.role_name))
&& (existingUser.agency_id === this.agencies[row.agency_name].id)
&& (existingUser.tenant_id === adminUser.tenant_id)) {
return NOT_CHANGED;
}
// Shouldn't get here until we enable the update functionality. See existing user check in checkRow().
await UserImporter.syncUser(newUser);
return UPDATED;
}
await db.createUser(newUser);
await email.sendWelcomeEmail(newUser.email, domain);
return ADDED;
}
// Currently only used for testing purposes. We can add an API and UX for this at a later date.
static async export(adminUser) {
const users = await db.getUsers(adminUser.tenant_id);
const usersForExport = [];
// eslint-disable-next-line no-restricted-syntax
for (const user of users) {
usersForExport.push({
email: user.email,
name: user.name,
role_name: user.role_name,
agency_name: user.agency_name,
});
}
return usersForExport;
}
async import(user, rowsList, domain) {
const retVal = {
status: {
users: {
added: 0,
updated: 0,
notChanged: 0,
errored: 0,
},
errors: [],
},
};
try {
const roles = await knex('roles').select('*');
this.adminRoleId = roles.find((role) => role.name === 'admin').id;
this.staffRoleId = roles.find((role) => role.name === 'staff').id;
const agenciesArray = await db.getTenantAgencies(user.tenant_id);
this.agencies = {};
// eslint-disable-next-line no-restricted-syntax
for (const agency of agenciesArray) {
this.agencies[agency.name] = agency;
}
const usersArray = await db.getUsers(user.tenant_id);
this.users = {};
// eslint-disable-next-line no-restricted-syntax
for (const existingUser of usersArray) {
this.users[existingUser.email] = existingUser;
}
for (let rowIndex = 0; rowIndex < rowsList.length; rowIndex += 1) {
const theErrors = this.checkRow(rowsList[rowIndex], rowIndex);
if (theErrors.length > 0) {
retVal.status.users.errored += 1;
retVal.status.errors.push(...theErrors);
} else {
// eslint-disable-next-line no-await-in-loop
const theStatus = await this.handleRow(rowsList[rowIndex], user, domain);
if (theStatus === ADDED) {
retVal.status.users.added += 1;
} else if (theStatus === UPDATED) {
retVal.status.users.updated += 1;
} else if (theStatus === NOT_CHANGED) {
retVal.status.users.notChanged += 1;
}
}
}
} catch (e) {
console.log(e.toString());
retVal.status.errors.push(e.toString());
}
return retVal;
}
}
module.exports = UserImporter;