Skip to content

Commit 009bfe0

Browse files
committed
feat: self-service migration of ry members without associated Discord user
1 parent 4c82af4 commit 009bfe0

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

src/database/schemas/userInfo.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const SchemaUserInfo = new Schema({
2222
sparse: true,
2323
type: String
2424
},
25+
migrationKey: String,
2526
handledIn: String,
2627
appliedAt: Date,
2728
status: {

src/routes/membersArea.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ router.use(session({
3636
}
3737
}))
3838

39+
function isValidMigrationQuery(email, migrationKey) {
40+
return (
41+
typeof email === "string" &&
42+
typeof migrationKey === "string" &&
43+
email.length > 0 &&
44+
/^[A-Za-z0-9]{128}$/.test(migrationKey)
45+
)
46+
}
47+
3948
router.post("/authenticate", async (req, res, next) => {
4049
try {
4150
console.log("debug: /authenticate")
@@ -334,6 +343,59 @@ router.get("/logout", async (req, res, next) => {
334343
}
335344
})
336345

346+
router.get("/migrate", async (req, res, next) => {
347+
try {
348+
const { email, migrationKey } = req.query
349+
if (!isValidMigrationQuery(email, migrationKey)) {
350+
return res.status(400).json({ status: "error", message: "invalid query params" })
351+
}
352+
353+
const doc = await database.UserInfo.findOne({
354+
"associationMembership.email": email,
355+
"associationMembership.migrationKey": migrationKey
356+
}, "associationMembership.firstName associationMembership.lastName")
357+
358+
if (!doc) return res.status(404).json({ status: "not_found" })
359+
360+
return res.json({
361+
firstName: doc.associationMembership?.firstName ?? null,
362+
lastName: doc.associationMembership?.lastName ?? null
363+
})
364+
} catch (e) {
365+
next(e)
366+
}
367+
})
368+
369+
router.post("/migrate", requireAuth, async (req, res, next) => {
370+
try {
371+
const { email, migrationKey } = req.query
372+
if (!isValidMigrationQuery(email, migrationKey)) {
373+
return res.status(400).json({ status: "error", message: "invalid query params" })
374+
}
375+
376+
const discordId = req.session.discordId
377+
if (!discordId) return res.status(403).json({ status: "error", message: "unauthenticated" })
378+
379+
// Remove the current document that holds this Discord id
380+
await database.UserInfo.findOneAndDelete({ id: discordId })
381+
382+
// Assign the Discord id to the association member document
383+
const updated = await database.UserInfo.findOneAndUpdate({
384+
"associationMembership.email": email,
385+
"associationMembership.migrationKey": migrationKey
386+
}, {
387+
$set: { id: discordId },
388+
$unset: { "associationMembership.migrationKey": "" }
389+
}, { new: true })
390+
391+
if (!updated) return res.status(404).json({ status: "not_found" })
392+
393+
return res.json({ status: "ok" })
394+
} catch (e) {
395+
next(e)
396+
}
397+
})
398+
337399
router.use((
338400
err, req, res, next
339401
) => {

0 commit comments

Comments
 (0)