Skip to content

Refactor permission management#2090

Open
rteas wants to merge 4 commits intohackforla:developmentfrom
rteas:refactor-permission-management
Open

Refactor permission management#2090
rteas wants to merge 4 commits intohackforla:developmentfrom
rteas:refactor-permission-management

Conversation

@rteas
Copy link
Member

@rteas rteas commented Feb 24, 2026

Fixes
#1861
#2066
#2068
#2072
#2075

What changes did you make and why did you make them ?

  • Refactored middleware/backend to use refresh tokens and json web tokens (jwts) - see auth.middleware.js, user.routes.js
  • Refactored frontend code to utilize most frontend code jwt via authContext.jsx
  • Both middle/back/front rely on the single source of truth (auth) in the shared folder with the following files: roles.js and authorizationUtils.js
No visuals, but website runs using access tokens (JWTS) 15m usage and Refresh Tokens (allowing users extended sessions up to 30 days without needing to relog into the application). Logging out will delete the refresh token and require users to re-login.

…via authcontext. AuthZ code builds on shared/roles and shared/authorizationUtils for a single source of truth for roles/accessLevels
…dmin(), hasMinimumRole(), or hasAnyRole() to showcase flexibility/options, also and adding comments to code
@rteas rteas requested review from geolunalg and trillium February 24, 2026 01:21
@JackHaeg
Copy link
Member

Note - once this PR is merged, hold off on rebuilding DEV until check-in for logged in users is enabled [add issue link here]. Otherwise, we may run into an issue where most users remain logged in and cannot check in without first logging back out of VRMS

@JackHaeg
Copy link
Member

@rteas mentioned that Project manager permissions are still handled the same way as before (standard user who is associated with a project = project manager). @rteas may create a new issue that creates a new UAL of "Project Manager" to follow the middleware refactor for other UALs (admin, superadmin, users, and project managers). Requires front end changes. Also, users assigned to an existing project will need to be promoted to "project manager" UAL in database.

'c0d7d0716e4cecffe9dcc77ff90476d98f5aace08ea40f5516bd982b06401021191f0f24cd6759f7d8ca41b64f68d0b3ad19417453bddfd1dbe8fcb197245079',
CUSTOM_REQUEST_HEADER: process.env.CUSTOM_REQUEST_HEADER,
TOKEN_EXPIRATION_SEC: 900,
// 15 minutes
Copy link
Member

Choose a reason for hiding this comment

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

what is the difference between these two ACCESS_TOKEN_EXPIRATION, and ACCESS_TOKEN_EXPIRATION_MS?

// Utility functions

function generateAccessToken(user, auth_origin) {
return jwt.sign(
Copy link
Member

Choose a reason for hiding this comment

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

Why is there no experation time on the signature of the access token?


// Load in all of our node modules. Their uses are explained below as they are called.
const express = require('express');
// const cron = require('node-cron');
Copy link
Member

Choose a reason for hiding this comment

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

Why are these commented out?

// WORKERS
const runOpenCheckinWorker = require('./workers/openCheckins');
runOpenCheckinWorker(cron, fetch);
// const runOpenCheckinWorker = require('./workers/openCheckins')(cron, fetch);
Copy link
Member

Choose a reason for hiding this comment

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

Why are these commected out?

@@ -1,8 +1,10 @@
/*eslint-disable */
module.exports = {
SECRET:
Copy link
Member

Choose a reason for hiding this comment

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

This should not be part of the code, this should be as the name implies a secret. This should be a env var.

module.exports = {
SECRET:
'c0d7d0716e4cecffe9dcc77ff90476d98f5aace08ea40f5516bd982b06401021191f0f24cd6759f7d8ca41b64f68d0b3ad19417453bddfd1dbe8fcb197245079',
CUSTOM_REQUEST_HEADER: process.env.CUSTOM_REQUEST_HEADER,
Copy link
Member

Choose a reason for hiding this comment

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

Calling an env variable like this, if the var does not exist will cause a silent failure returning undefined.

const crypto = require('crypto');
const AuthUtils = require('../../shared/authorizationUtils');

const SECRET_KEY = process.env.JWT_SECRET;
Copy link
Member

Choose a reason for hiding this comment

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

We should avoid calling these blindly, they will silently fail if they do not exist.

},
);
})
token = jwt.sign({ id: user.id, role: user.accessLevel, auth_origin }, CONFIG_AUTH.SECRET, {
Copy link
Member

Choose a reason for hiding this comment

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

On these test why are you not using the function in code to sign the token for the test?

},
);
})
token = jwt.sign({ id: user.id, role: user.accessLevel, auth_origin }, CONFIG_AUTH.SECRET, {
Copy link
Member

Choose a reason for hiding this comment

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

Same comment here, why is the funtion in code to sign the token for tests?

},
);
})
token = jwt.sign({ id: user.id, role: user.accessLevel, auth_origin }, CONFIG_AUTH.SECRET, {
Copy link
Member

Choose a reason for hiding this comment

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

What is token for?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants