mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
@@ -39,7 +39,7 @@ const mdl_Users = require('../models/users/users.mdl');
|
||||
const mdl_UserSessions = require('../models/users/user_sessions.mdl');
|
||||
const { checkAccountStatus } = require('../services/accountStatus.service');
|
||||
const { mdl_UserGroups, mdl_UserGroupMembers } = require('../models/users/user_groups.mdl')
|
||||
const { NOGRP_CODE, getDefaultGroupId, enrollDefaultGroup } = require('../utils/defaultGroup.util');
|
||||
const { NOGRP_CODE, getDefaultGroupId, enrollDefaultGroup, switchFromNogrpByCode } = require('../utils/defaultGroup.util');
|
||||
const { generateTokens, verifyRefreshToken, hashToken, shouldRotateRefreshToken } = require('../utils/token.util');
|
||||
const { generateState, generateNonce, generatePKCE, buildAuthUrl, exchangeCode, verifyIdToken } = require('../utils/google_oidc.util');
|
||||
const { generateOTP, getOTPExpiry, isOTPExpired } = require('../utils/otp.util');
|
||||
@@ -366,7 +366,7 @@ exports.resendOTP = async (req, res) => {
|
||||
// ─── System Login ──────────────────────────────────────────────────────────────
|
||||
exports.login = async (req, res) => {
|
||||
try {
|
||||
const { email, password } = req.body;
|
||||
const { email, password, group_code } = req.body;
|
||||
|
||||
const user = await mdl_Users.findOne({ where: { email } });
|
||||
if (!user) return R.error(res, 'Invalid credentials.', 401);
|
||||
@@ -386,7 +386,17 @@ exports.login = async (req, res) => {
|
||||
const match = await bcrypt.compare(password, user.password);
|
||||
if (!match) return R.error(res, 'Invalid credentials.', 401);
|
||||
|
||||
// Password confirmed. If this device already cleared an OTP recently and
|
||||
// Password confirmed the account is genuinely theirs — same bar register
|
||||
// uses before enrolling into a group, so an invite link followed by
|
||||
// "already have an account? sign in" moves a NOGRP user into the group
|
||||
// right here rather than dead-ending on an invite link that only works
|
||||
// for brand-new accounts.
|
||||
if (group_code) {
|
||||
await switchFromNogrpByCode(user.user_id, group_code)
|
||||
.catch(err => console.error('[AUTH] login: Failed to switch NOGRP membership:', err));
|
||||
}
|
||||
|
||||
// If this device already cleared an OTP recently and
|
||||
// its trust window hasn't lapsed or been revoked, skip the OTP gate
|
||||
// entirely — otherwise fall through to the usual fresh-OTP flow. Tokens
|
||||
// are only ever minted via mintSession (called here or from verifyOTP).
|
||||
@@ -431,10 +441,14 @@ exports.googleRedirect = (req, res) => {
|
||||
const state = generateState();
|
||||
const nonce = generateNonce();
|
||||
const { codeVerifier, codeChallenge } = generatePKCE();
|
||||
// Carried through to the callback below — an invite link's group_code has
|
||||
// to survive the round trip to Google and back, so it rides in the same
|
||||
// short-lived signed cookie as state/nonce/codeVerifier.
|
||||
const group_code = typeof req.query.group_code === 'string' ? req.query.group_code.trim() : null;
|
||||
|
||||
// SameSite=Lax is required: the cookie must survive the cross-site redirect
|
||||
// back from Google (top-level GET navigations are allowed under Lax).
|
||||
res.cookie('_oauth', JSON.stringify({ state, nonce, codeVerifier }), {
|
||||
res.cookie('_oauth', JSON.stringify({ state, nonce, codeVerifier, group_code }), {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
@@ -470,7 +484,7 @@ exports.googleCallback = async (req, res) => {
|
||||
return res.redirect(CALLBACK_PAGE);
|
||||
}
|
||||
|
||||
const { state: expectedState, nonce, codeVerifier } = JSON.parse(rawCookie);
|
||||
const { state: expectedState, nonce, codeVerifier, group_code } = JSON.parse(rawCookie);
|
||||
|
||||
if (!state || state !== expectedState) {
|
||||
setGoogleResultCookie(res, { error: 'state_mismatch' });
|
||||
@@ -554,6 +568,14 @@ exports.googleCallback = async (req, res) => {
|
||||
return res.redirect(CALLBACK_PAGE);
|
||||
}
|
||||
|
||||
// Identity is confirmed by Google itself — same bar as a password match on
|
||||
// the system login path — so a NOGRP user (brand-new or returning) riding
|
||||
// in on an invite link gets moved into that group right here.
|
||||
if (group_code) {
|
||||
await switchFromNogrpByCode(user.user_id, group_code)
|
||||
.catch(err => console.error('[AUTH] googleCallback: Failed to switch NOGRP membership:', err));
|
||||
}
|
||||
|
||||
// Every Google sign-in (new or returning account) still has to clear the
|
||||
// same OTP gate as a manual login, unless this device already cleared one
|
||||
// recently and its trust window hasn't lapsed or been revoked — same
|
||||
|
||||
Reference in New Issue
Block a user