fix: confirm email with code flow

It wasn't working:
- erroneously expected `email` parameter in request
- sqlite compatibility issue
- incorrect branching, fixed with guard clause
This commit is contained in:
KernelDeimos
2025-08-06 14:58:33 -04:00
parent f06abf96b3
commit 7b1fb5d9a6
4 changed files with 38 additions and 34 deletions
+35 -31
View File
@@ -43,15 +43,22 @@ router.post('/confirm-email', auth, express.json(), async (req, res, next)=>{
const db = req.services.get('database').get(DB_WRITE, 'auth');
// Increment & check rate limit
if(kv.incr(`confirm-email|${req.ip}|${req.body.email ?? req.body.username}`) > 10)
if(kv.incr(`confirm-email|${req.ip}|${req.user.email ?? req.user.username}`) > 10)
return res.status(429).send({error: 'Too many requests.'});
// Set expiry for rate limit
kv.expire(`confirm-email|${req.ip}|${req.body.email ?? req.body.username}`, 60 * 10, 'NX')
kv.expire(`confirm-email|${req.ip}|${req.user.email ?? req.user.username}`, 60 * 10, 'NX')
console.log('need to check these', typeof req.body.code, typeof req.user.email_confirm_code, req.body.code, req.user.email_confirm_code);
if(req.body.code !== req.user.email_confirm_code) {
res.send({ email_confirmed: false });
return;
}
// Scenario: email was confirmed on another account already
{
const svc_cleanEmail = req.services.get('clean-email');
const clean_email = svc_cleanEmail.clean(req.body.email);
const clean_email = svc_cleanEmail.clean(req.user.email);
if ( ! await svc_cleanEmail.validate(clean_email) ) {
APIError.create('field_invalid', null, {
@@ -63,7 +70,7 @@ router.post('/confirm-email', auth, express.json(), async (req, res, next)=>{
const rows = await db.read(
`SELECT EXISTS(
SELECT 1 FROM user WHERE (email=? OR clean_email=?) AND email_confirmed=1 AND password IS NOT NULL
) AS email_exists`, [req.body.email, clean_email]);
) AS email_exists`, [req.user.email, clean_email]);
if ( rows[0].email_exists ) {
APIError.create('email_already_in_use').write(res);
return;
@@ -76,37 +83,34 @@ router.post('/confirm-email', auth, express.json(), async (req, res, next)=>{
[req.user.email],
);
if(req.body.code === req.user.email_confirm_code) {
await db.write(
"UPDATE `user` SET `email_confirmed` = 1, `requires_email_confirmation` = 0 WHERE id = ? LIMIT 1",
[req.user.id],
);
const svc_getUser = req.services.get('get-user');
await svc_getUser.get_user({ id: req.user.id, force: true });
// Update user record to say email is confirmed
await db.write(
"UPDATE `user` SET `email_confirmed` = 1, `requires_email_confirmation` = 0 WHERE id = ? LIMIT 1",
[req.user.id],
);
// Invalidate user cache
const svc_getUser = req.services.get('get-user');
await svc_getUser.get_user({ id: req.user.id, force: true });
const svc_event = req.services.get('event');
svc_event.emit('user.email-confirmed', {
user_uid: req.user.uuid,
email: req.user.email,
});
}
// Emit internal event
const svc_event = req.services.get('event');
svc_event.emit('user.email-confirmed', {
user_uid: req.user.uuid,
email: req.user.email,
});
// Build response object
const res_obj = {
email_confirmed: (req.body.code === req.user.email_confirm_code),
original_client_socket_id: req.body.original_client_socket_id,
}
// Send realtime success msg to client
if(req.body.code === req.user.email_confirm_code){
const svc_socketio = req.services.get('socketio');
svc_socketio.send({ room: req.user.id }, 'user.email_confirmed', {
original_client_socket_id: req.body.original_client_socket_id
});
}
// Emit websocket event (TODO: should come from internal event above)
const svc_socketio = req.services.get('socketio');
svc_socketio.send({ room: req.user.id }, 'user.email_confirmed', {
original_client_socket_id: req.body.original_client_socket_id
});
// return results
return res.send(res_obj)
return res.send({
email_confirmed: true,
original_client_socket_id: req.body.original_client_socket_id,
});
})
module.exports = router
+1 -1
View File
@@ -147,7 +147,7 @@ router.post('/save_account', auth, express.json(), async (req, res, next)=>{
// password
await bcrypt.hash(req.body.password, 8),
// email_confirm_code
email_confirm_code,
'' + email_confirm_code,
//email_confirm_token
email_confirm_token,
// referred_by
@@ -46,7 +46,7 @@ router.post('/send-confirm-email', auth, express.json(), async (req, res, next)=
`UPDATE user SET email_confirm_code = ? WHERE id = ?`,
[
// email_confirm_code
email_confirm_code,
'' + email_confirm_code,
// id
req.user.id,
]);
+1 -1
View File
@@ -271,7 +271,7 @@ module.exports = eggspress(['/signup'], {
// referrer
req.body.referrer ?? null,
// email_confirm_code
email_confirm_code,
'' + email_confirm_code,
// email_confirm_token
email_confirm_token,
// free_storage