Skip to content

Conversation

@saffiullah200
Copy link
Collaborator

  • Add inactivity email templates (warning, archived, weekly report)
  • Create reactivate-user endpoint for archived accounts
  • Update sign-in endpoints to handle archived users with proper response
  • Reset inactivity tracking flags on successful login
  • Create inactivity-checker helper with functions:
    • sendInactivityWarnings: email users inactive for 1+ year
    • archiveInactiveUsers: archive users 7 days after warning
    • runWeeklyReport: send admin summary email
  • Add cron endpoints for scheduled tasks:
    • POST /cron/inactivity-check (daily)
    • POST /cron/weekly-report (weekly)
  • Protected cron endpoints with CRON_SECRET header
  • Add validation for reactivate-user endpoint

Inactivity workflow:

  1. User inactive for 1 year -> warning email sent
  2. No login within 7 days -> account archived
  3. Archived user can reactivate via /users/reactivate endpoint

- Add inactivity email templates (warning, archived, weekly report)
- Create reactivate-user endpoint for archived accounts
- Update sign-in endpoints to handle archived users with proper response
- Reset inactivity tracking flags on successful login
- Create inactivity-checker helper with functions:
  * sendInactivityWarnings: email users inactive for 1+ year
  * archiveInactiveUsers: archive users 7 days after warning
  * runWeeklyReport: send admin summary email
- Add cron endpoints for scheduled tasks:
  * POST /cron/inactivity-check (daily)
  * POST /cron/weekly-report (weekly)
- Protected cron endpoints with CRON_SECRET header
- Add validation for reactivate-user endpoint

Inactivity workflow:
1. User inactive for 1 year -> warning email sent
2. No login within 7 days -> account archived
3. Archived user can reactivate via /users/reactivate endpoint
Copilot AI review requested due to automatic review settings January 25, 2026 00:33
…llback

- Remove $or condition that used createdAt as fallback
- Only send warning emails to users with recorded lastLogin
- This prevents mass emails to 13k+ existing users
- Inactivity tracking will only apply to users who log in after this feature is deployed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements an inactivity lifecycle for user accounts (warn after 1 year inactive, archive after 7 days), with reactivation support and cron-triggerable endpoints to run the workflow and weekly reporting.

Changes:

  • Added inactivity checking helper (warn, archive, weekly report) plus new email templates for user/admin notifications.
  • Updated sign-in flows (email/password, Google, Facebook) to detect archived users and reset inactivity flags on successful login.
  • Added public reactivation endpoint and cron endpoints protected by a secret header.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
src/routes/users/validations.js Adds request validation for the new reactivation endpoint payload.
src/routes/users/reactivate-user.js Implements archived-account reactivation and issues fresh auth tokens.
src/routes/users/index.js Exposes a public /users/reactivate route.
src/routes/others/index.js Registers cron endpoints at /cron/inactivity-check and /cron/weekly-report.
src/routes/others/inactivity-cron.js Adds cron endpoint handlers gated by a secret header.
src/routes/auth/sign-in.js Allows detecting archived accounts at sign-in; resets inactivity tracking on login.
src/routes/auth/google-sign-in.js Adds archived-account handling and inactivity reset for Google sign-in.
src/routes/auth/facebook-sign-in.js Adds archived-account handling and inactivity reset for Facebook sign-in.
src/helpers/mail-template.js Adds templates for inactivity warning, archived notice, and weekly admin report.
src/helpers/inactivity-checker.js Implements inactivity warning/archive logic and weekly reporting.
.gitignore Ignores .pem files and docs/*.md locally.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 23 to 26
// First check if user exists (including archived users)
user = await User.findOne({ email });
console.log("User", user);
} catch (err) {
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid logging the full user document during sign-in. This can leak sensitive fields (e.g., hashedPassword, emails) into logs. Remove this debug log or log only a non-sensitive identifier if needed.

Copilot uses AI. Check for mistakes.
- Fix textContent email fallback (use displayName instead of user.firstName directly)
- Add reactivatedAt field to User model for accurate reactivation tracking
- Update getReactivatedUsersCount to use reactivatedAt timestamp
- Set reactivatedAt when user reactivates their account
- Fix CRON_SECRET check to fail closed (reject if not configured)
- Remove userId from archived user responses (security/enumeration risk)
- Remove debug console.log from sign-in
BREAKING CHANGE: Reactivation endpoint now requires userId instead of email

Security improvements:
- Reactivation now requires userId (from 403 login response) + currentPassword
- This prevents account takeover - attacker must know original password
- Sign-in endpoints return userId in 403 response for archived users
- Generic "Invalid credentials" errors prevent enumeration

Removed weekly reports:
- Removed sendWeeklyReport() and runWeeklyReportJob() functions
- Removed /cron/weekly-report endpoint
- Only daily inactivity check remains

Updated validation:
- validateReactivateUser now validates userId (24-char ObjectId)
- Requires currentPassword + newPassword fields

Frontend guide updated with new API contract.
- forgotten-password.js: Include archived users in lookup
- reset-password.js: Reset inactivity flags when password is reset
  - Sets lastLogin to reset inactivity timer
  - Sets isArchived to false to reactivate account
  - Clears inactivityEmailSent and inactivityEmailSentAt
  - Sets reactivatedAt if user was archived

This provides an alternative recovery path for:
- Users who forgot their password
- Social login users who need to reactivate archived accounts

Updated frontend guide with new recovery flow documentation.
… endpoint

BREAKING CHANGE: /auth/reactivate-account now requires currentPassword

Removed duplicate endpoint:
- Deleted /users/reactivate endpoint and reactivate-user.js
- Removed validateReactivateUser from users/validations.js

Updated /auth/reactivate-account with security improvements:
- Now requires currentPassword to prove account ownership
- Uses newPassword instead of password for clarity
- Generic "Invalid credentials" error prevents enumeration
- Social login users directed to forgot password flow
- Uses user.save() with model's virtual password setter

Updated frontend guide with correct endpoint path.
@saffiullah200 saffiullah200 merged commit 06c3edf into stage Jan 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants