session-sync-auth-site 0.5.3 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -88,6 +88,12 @@ setUpSessionSyncAuthRoutes({
88
88
  // typically coincide with `extraUserTableSelectValues` above.
89
89
  }
90
90
  },
91
+ mergeUser: async ({ userId, mergeToUserId }) => { // optional (when absent, merge requests will succeed even though no data is merged for this site)
92
+ // move all of userId's data to mergeToUserId
93
+ },
94
+ deleteUser: async ({ id, email }) => { // optional (when absent, the appropriate rows from users and sessions are deleted)
95
+ // delete all of userId's data, including appropriate rows from users and sessions tables
96
+ },
91
97
  protocol: 'https',
92
98
  paths: {
93
99
  getUser: '/get-user',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "session-sync-auth-site",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "main": "src/index.js",
5
5
  "repository": {
6
6
  "type": "git",
package/src/createUser.js CHANGED
@@ -11,7 +11,7 @@ const createUser = async ({
11
11
  siteId,
12
12
  authDomain,
13
13
  jwtSecret,
14
- protocol=req.sessionSyncAuthProtocol || `https`,
14
+ protocol=(setup || req).sessionSyncAuthProtocol || `https`,
15
15
  } = setup || await req.getSessionSyncAuthSetupInfo()
16
16
 
17
17
  const createUserResult = await fetch(
@@ -8,6 +8,8 @@ const setUpSessionSyncAuthRoutes = ({
8
8
  authDomain,
9
9
  jwtSecret,
10
10
  getSetupInfo, // for multi-tenancy setup; sent req and must return the siteId, authDomain, and jwtSecret
11
+ mergeUser,
12
+ deleteUser,
11
13
  protocol='https',
12
14
  paths: {
13
15
  getUser='/get-user',
@@ -105,13 +107,11 @@ const setUpSessionSyncAuthRoutes = ({
105
107
  sessionTableColNameMap,
106
108
  } = req.sessionSyncAuthSiteOptions
107
109
 
108
- const { users } = jwt.verify(payload, jwtSecret)
110
+ const { users, usersToDelete } = jwt.verify(payload, jwtSecret)
109
111
 
110
- if(!users) throw "Invalid payload. Missing `payload.user`."
111
- if(!(users instanceof Array)) throw "Invalid payload. `payload.users` must be an array."
112
-
113
- const queries = []
114
- const variables = {}
112
+ if(!users && !usersToDelete) throw "Invalid payload. Missing `payload.user`."
113
+ if(users && !(users instanceof Array)) throw "Invalid payload. `payload.users` must be an array."
114
+ if(usersToDelete && !(usersToDelete instanceof Array)) throw "Invalid payload. `payload.usersToDelete` must be an array."
115
115
 
116
116
  const getSnakeCaseOfKeys = (obj, allowedKeys) => {
117
117
  const newObj = {}
@@ -143,91 +143,149 @@ const setUpSessionSyncAuthRoutes = ({
143
143
  })
144
144
  }
145
145
 
146
- users.forEach(user => {
147
- const { id, sessions, createdAt, updatedAt } = user
146
+ if(users) {
148
147
 
149
- if(!id) throw "Invalid payload. Item in `payload.users` missing `id` key."
150
- if(!sessions) throw "Invalid payload. Item in `payload.users` missing `sessions` key."
151
- if(!(sessions instanceof Array)) throw "Invalid payload. `payload.users[].sessions` must be an array."
152
- if(!createdAt) throw "Invalid payload. Item in `payload.users` missing `createdAt` key."
153
- if(!updatedAt) throw "Invalid payload. Item in `payload.users` missing `updatedAt` key."
148
+ const queries = []
149
+ const variables = {}
154
150
 
155
- convertMsTimestampsToDateTimeStrings(user)
151
+ users.forEach(user => {
152
+ const { id, sessions, createdAt, updatedAt } = user
156
153
 
157
- // add/update the user
154
+ if(!id) throw "Invalid payload. Item in `payload.users` missing `id` key."
155
+ if(!sessions) throw "Invalid payload. Item in `payload.users` missing `sessions` key."
156
+ if(!(sessions instanceof Array)) throw "Invalid payload. `payload.users[].sessions` must be an array."
157
+ if(!createdAt) throw "Invalid payload. Item in `payload.users` missing `createdAt` key."
158
+ if(!updatedAt) throw "Invalid payload. Item in `payload.users` missing `updatedAt` key."
158
159
 
159
- variables[`user__${id}`] = getSnakeCaseOfKeys(
160
- user,
161
- [ 'id', 'email', 'name', 'image', 'language', 'gender', 'created_at', 'updated_at' ],
162
- )
160
+ convertMsTimestampsToDateTimeStrings(user)
163
161
 
164
- if(languageColType !== 'IETF') {
165
- variables[`user__${id}`].language = variables[`user__${id}`].language.split('-')[0]
166
- }
162
+ // add/update the user
167
163
 
168
- if(languageColType === '639-1') {
169
- variables[`user__${id}`].language = iso6393To1[variables[`user__${id}`].language] || 'en'
170
- }
164
+ variables[`user__${id}`] = getSnakeCaseOfKeys(
165
+ user,
166
+ [ 'id', 'email', 'name', 'image', 'language', 'gender', 'created_at', 'updated_at' ],
167
+ )
171
168
 
172
- if(extraUserTableValues) {
173
- variables[`user__${id}`] = {
174
- ...extraUserTableValues,
175
- ...variables[`user__${id}`],
169
+ if(languageColType !== 'IETF') {
170
+ variables[`user__${id}`].language = variables[`user__${id}`].language.split('-')[0]
176
171
  }
177
- }
178
172
 
179
- mapKeys(variables[`user__${id}`], 'user')
173
+ if(languageColType === '639-1') {
174
+ variables[`user__${id}`].language = iso6393To1[variables[`user__${id}`].language] || 'en'
175
+ }
180
176
 
181
- queries.push(`
182
- INSERT INTO \`${userTableName}\` SET :user__${id}
183
- ON DUPLICATE KEY UPDATE :user__${id}
184
- `)
177
+ if(extraUserTableValues) {
178
+ variables[`user__${id}`] = {
179
+ ...extraUserTableValues,
180
+ ...variables[`user__${id}`],
181
+ }
182
+ }
185
183
 
186
- // add the sessions
184
+ mapKeys(variables[`user__${id}`], 'user')
187
185
 
188
- sessions.forEach(session => {
189
- const { accessToken, createdAt } = session
186
+ queries.push(`
187
+ INSERT INTO \`${userTableName}\` SET :user__${id}
188
+ ON DUPLICATE KEY UPDATE :user__${id}
189
+ `)
190
190
 
191
- if(!accessToken) throw "Invalid payload. Item in `payload.users[].sessions` missing `accessToken` key."
192
- if(!createdAt) throw "Invalid payload. Item in `payload.users[].sessions` missing `createdAt` key."
191
+ // add the sessions
193
192
 
194
- convertMsTimestampsToDateTimeStrings(session)
193
+ sessions.forEach(session => {
194
+ const { accessToken, createdAt } = session
195
195
 
196
- variables[`session__${accessToken}`] = {
197
- ...getSnakeCaseOfKeys(
198
- session,
199
- [ 'created_at', 'access_token' ],
200
- ),
201
- user_id: id,
202
- }
203
- mapKeys(variables[`session__${accessToken}`], 'session')
196
+ if(!accessToken) throw "Invalid payload. Item in `payload.users[].sessions` missing `accessToken` key."
197
+ if(!createdAt) throw "Invalid payload. Item in `payload.users[].sessions` missing `createdAt` key."
198
+
199
+ convertMsTimestampsToDateTimeStrings(session)
200
+
201
+ variables[`session__${accessToken}`] = {
202
+ ...getSnakeCaseOfKeys(
203
+ session,
204
+ [ 'created_at', 'access_token' ],
205
+ ),
206
+ user_id: id,
207
+ }
208
+ mapKeys(variables[`session__${accessToken}`], 'session')
209
+
210
+ queries.push(`
211
+ INSERT IGNORE INTO \`${sessionTableName}\` SET :session__${accessToken}
212
+ `)
213
+
214
+ })
215
+
216
+ // delete old sessions
217
+
218
+ variables[`userId__${id}`] = id
219
+ variables[`accessTokens__${id}`] = [
220
+ 'dummy_token', // so the SQL is still valid even if there are no sessions
221
+ ...sessions.map(({ accessToken }) => accessToken),
222
+ ]
204
223
 
205
224
  queries.push(`
206
- INSERT IGNORE INTO \`${sessionTableName}\` SET :session__${accessToken}
225
+ DELETE FROM \`${sessionTableName}\`
226
+ WHERE \`${(sessionTableColNameMap.user_id || `user_id`).replace(/`/g, '')}\` = :userId__${id}
227
+ AND \`${(sessionTableColNameMap.access_token || `access_token`).replace(/`/g, '')}\` NOT IN (:accessTokens__${id})
207
228
  `)
208
229
 
209
230
  })
210
231
 
211
- // delete old sessions
232
+ await global.sessionSyncAuthSiteConnection.asyncQuery(
233
+ queries.join(';'),
234
+ variables,
235
+ )
212
236
 
213
- variables[`userId__${id}`] = id
214
- variables[`accessTokens__${id}`] = [
215
- 'dummy_token', // so the SQL is still valid even if there are no sessions
216
- ...sessions.map(({ accessToken }) => accessToken),
217
- ]
237
+ }
218
238
 
219
- queries.push(`
220
- DELETE FROM \`${sessionTableName}\`
221
- WHERE \`${(sessionTableColNameMap.user_id || `user_id`).replace(/`/g, '')}\` = :userId__${id}
222
- AND \`${(sessionTableColNameMap.access_token || `access_token`).replace(/`/g, '')}\` NOT IN (:accessTokens__${id})
223
- `)
239
+ if(usersToDelete) {
240
+
241
+ await Promise.all(usersToDelete.map(async user => {
242
+ const { id, email, mergeToUserId } = user
243
+
244
+ if(!id) throw "Invalid payload. Item in `payload.usersToDelete` missing `id` key."
245
+ if(!email) throw "Invalid payload. Item in `payload.usersToDelete` missing `email` key."
246
+
247
+ const [ user ] = await global.sessionSyncAuthSiteConnection.asyncQuery(
248
+ `
249
+ SELECT email
250
+ FROM \`${userTableName}\`
251
+ WHERE \`${(userTableColNameMap.id || `id`).replace(/`/g, '')}\` = :userId
252
+ `,
253
+ {
254
+ userId: id,
255
+ },
256
+ )
257
+
258
+ if(!user) return // gracefully handle non-existent user
259
+ if(user.email !== email) throw "The `id` and `email` passed in do not coorespond."
260
+
261
+ if(mergeToUserId && mergeUser) {
262
+ await mergeUser({
263
+ id,
264
+ mergeToUserId,
265
+ })
266
+ }
224
267
 
225
- })
268
+ if(deleteUser) {
269
+ await deleteUser({ id })
270
+ } else {
271
+ await global.sessionSyncAuthSiteConnection.asyncQuery(
272
+ `
273
+ DELETE FROM \`${sessionTableName}\`
274
+ WHERE \`${(sessionTableColNameMap.user_id || `user_id`).replace(/`/g, '')}\` = :userId
275
+ ;
276
+
277
+ DELETE FROM \`${userTableName}\`
278
+ WHERE \`${(userTableColNameMap.id || `id`).replace(/`/g, '')}\` = :userId
279
+ `,
280
+ {
281
+ userId: id,
282
+ },
283
+ )
284
+ }
226
285
 
227
- await global.sessionSyncAuthSiteConnection.asyncQuery(
228
- queries.join(';'),
229
- variables,
230
- )
286
+ }))
287
+
288
+ }
231
289
 
232
290
  res.json({ success: true })
233
291