Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor auth roles #195

Merged
merged 1 commit into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ REACT_APP_WATO_FINANCE_BACKEND_URL=http://localhost:5000
4. Set Project support email to your own email
5. Select Save and ensure that the Google Provider has the Enabled Status

### Changing authorization for debugging

1. If you would like to change your authorization for debugging, set `REACT_APP_AUTH_OVERRIDE=ADMIN | TEAM_CAPTAIN | DIRECTOR` in the frontend env, and `AUTH_OVERRIDE=ADMIN | TEAM_CAPTAIN | DIRECTOR` in the backend env.

### Starting the app

To start the frontend, in a different terminal run
Expand Down
13 changes: 5 additions & 8 deletions backend/auth/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,12 @@ const authenticateUser = async (req, res, next) => {
next()
return
}
const { isDirector, isAdmin, isTeamCaptain, isReporter } =
await getAuthRoles(
decodedToken.uid,
decodedToken.email,
reporter_id
)
req.user.isDirector = isDirector
const { isAdmin, isReporter } = await getAuthRoles(
decodedToken.uid,
decodedToken.email,
reporter_id
)
req.user.isAdmin = isAdmin
req.user.isTeamCaptain = isTeamCaptain
req.user.isReporter = isReporter
next()
} catch (err) {
Expand Down
12 changes: 6 additions & 6 deletions backend/controller/fundingitems.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ const createFundingItemController = (req, res) => {
}

const updateFundingItemController = (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to update')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to update')
return
}

Expand All @@ -49,8 +49,8 @@ const updateFundingItemController = (req, res) => {
}

const updateSFLinkFundingItemController = async (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to update')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to update')
return
}

Expand All @@ -68,8 +68,8 @@ const updateSFLinkFundingItemController = async (req, res) => {
}

const deleteFundingItemController = (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to delete')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to delete')
return
}

Expand Down
27 changes: 3 additions & 24 deletions backend/controller/getAuthRoles.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
const { getGoogleGroup } = require('../service/googlegroup.service')
const {
ADMIN_IDENTIFIERS,
TEAM_CAPTAIN_TITLES,
DIRECTOR_TITLES,
} = require('../models/constants')
const { AUTH_ROLES } = require('../models/constants')

const getWATIAMFromEmail = async (email) => {
return email.substring(0, email.indexOf('@'))
Expand All @@ -12,28 +8,11 @@ const getWATIAMFromEmail = async (email) => {
const getAuthRoles = async (user_uid, email, reporter_id) => {
const watiam = await getWATIAMFromEmail(email)
const currentGoogleGroup = await getGoogleGroup(watiam)

let isAdmin, isTeamCaptain, isDirector, isReporter

if (process.env?.AUTH_OVERRIDE) {
const authRoles = process.env?.AUTH_OVERRIDE?.split(',')
isAdmin = authRoles.includes('ADMIN')
isTeamCaptain = authRoles.includes('TEAM_CAPTAIN') || isAdmin
isDirector = authRoles.includes('DIRECTOR') || isTeamCaptain
isReporter = authRoles.includes('REPORTER')
} else {
isAdmin = ADMIN_IDENTIFIERS.includes(watiam)
isTeamCaptain =
isAdmin || TEAM_CAPTAIN_TITLES.includes(currentGoogleGroup.title)
isDirector =
isTeamCaptain || DIRECTOR_TITLES.includes(currentGoogleGroup.title)
isReporter = reporter_id === user_uid
}
const isAdmin = currentGoogleGroup.title === AUTH_ROLES.Administrator
const isReporter = reporter_id === user_uid

return {
isAdmin,
isTeamCaptain,
isDirector,
isReporter,
}
}
Expand Down
23 changes: 8 additions & 15 deletions backend/controller/personalpurchases.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ const createPersonalPurchaseController = (req, res) => {
}

const updatePersonalPurchaseController = (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to update')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to update')
return
}

Expand All @@ -48,8 +48,8 @@ const updatePersonalPurchaseController = (req, res) => {
}

const updateFILinkPersonalPurchaseController = async (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to update')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to update')
return
}
const { fi_link } = req.params
Expand All @@ -66,16 +66,9 @@ const updateFILinkPersonalPurchaseController = async (req, res) => {
}

const updateApprovalsPersonalPurchaseController = async (req, res) => {
const { new_approval_levels, approval_type } = req.body
const canUpdateApproval =
(approval_type === APPROVAL_LEVELS.admin_approval &&
req.user.isAdmin) ||
(approval_type === APPROVAL_LEVELS.team_captain_approval &&
req.user.isTeamCaptain) ||
(approval_type === APPROVAL_LEVELS.director_approval &&
req.user.isDirector)
const { new_approval_levels } = req.body

if (!canUpdateApproval) {
if (!req.user.isAdmin) {
res.status(403).json('Error: Permission Denied')
return
}
Expand All @@ -88,8 +81,8 @@ const updateApprovalsPersonalPurchaseController = async (req, res) => {
}

const deletePersonalPurchaseController = (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to delete')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to delete')
return
}
deletePersonalPurchase(req.params.id)
Expand Down
8 changes: 4 additions & 4 deletions backend/controller/sponsorshipfunds.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ const createSponsorshipFundController = (req, res) => {
}

const updateSponsorshipFundController = (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to update')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to update')
return
}

Expand All @@ -55,8 +55,8 @@ const updateSponsorshipFundController = (req, res) => {
}

const deleteSponsorshipFundController = (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to delete')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to delete')
return
}

Expand Down
25 changes: 9 additions & 16 deletions backend/controller/uwfinancepurchases.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ const createNewUWFinancePurchaseController = (req, res) => {
}

const updateUWFinancePurchaseController = (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to update')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to update')
return
}

Expand All @@ -50,8 +50,8 @@ const updateUWFinancePurchaseController = (req, res) => {
}

const updateFILinkUWFinancePurchaseController = async (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to update')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to update')
return
}

Expand All @@ -69,16 +69,9 @@ const updateFILinkUWFinancePurchaseController = async (req, res) => {
}

const updateApprovalsUWFinancePurchaseController = async (req, res) => {
const { new_approval_levels, approval_type } = req.body
const canUpdateApproval =
(approval_type === APPROVAL_LEVELS.admin_approval &&
req.user.isAdmin) ||
(approval_type === APPROVAL_LEVELS.team_captain_approval &&
req.user.isTeamCaptain) ||
(approval_type === APPROVAL_LEVELS.director_approval &&
req.user.isDirector)

if (!canUpdateApproval) {
const { new_approval_levels } = req.body

if (!req.user.isAdmin) {
res.status(403).json('Error: Permission Denied')
return
}
Expand All @@ -93,8 +86,8 @@ const updateApprovalsUWFinancePurchaseController = async (req, res) => {
}

const deleteUWFinancePurchaseController = (req, res) => {
if (!req.user.isDirector && !req.user.isReporter) {
res.status(403).json('Error: Must be Director+ or reporter to delete')
if (!req.user.isAdmin && !req.user.isReporter) {
res.status(403).json('Error: Must be admin or reporter to delete')
return
}
deleteUWFinancePurchase(req.params.id)
Expand Down
13 changes: 9 additions & 4 deletions backend/emails/emails.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ const getEmailToSection = async (reporter_id, recipients) => {

if (recipients.includes(EMAIL_RECIPIENTS.reporter)) {
const reporter = await getUserByUID(reporter_id)
emailToSet.add(reporter.email)
if (reporter.email) {
emailToSet.add(reporter.email)
}
}

if (recipients.includes(EMAIL_RECIPIENTS.team_captain)) {
Expand All @@ -61,6 +63,7 @@ const getMainMessageHTML = (msg) => `<p>${msg}</p>`

const getPPRTicketInfoHTML = async (ppr) => {
const reporter = await getUserByUID(ppr.reporter_id)
const reporterEmail = reporter.email ? `&lt;${reporter.email}&gt;` : ''
return `
<p>
Ticket Code: ${ppr.code} <br />
Expand All @@ -69,14 +72,15 @@ const getPPRTicketInfoHTML = async (ppr) => {
Purchase URL: ${ppr.purchase_url} <br />
Purchase Justification: ${ppr.purchase_justification} <br />
Status: ${ppr.status} <br />
Reporter: ${reporter.displayName} &lt;${reporter.email}&gt; <br />
Reporter: ${reporter.displayName} ${reporterEmail} <br />
Created: ${new Date(ppr.createdAt).toDateString()}
</p>
`
}

const getUPRTicketInfoHTML = async (upr) => {
const reporter = await getUserByUID(upr.reporter_id)
const reporterEmail = reporter.email ? `&lt;${reporter.email}&gt;` : ''
return `
<p>
Ticket Code: ${upr.code} <br />
Expand All @@ -86,14 +90,15 @@ const getUPRTicketInfoHTML = async (upr) => {
Purchase Instructions: ${upr.purchase_instructions} <br />
Purchase Justification: ${upr.purchase_justification} <br />
Status: ${upr.status} <br />
Reporter: ${reporter.displayName} &lt;${reporter.email}&gt; <br />
Reporter: ${reporter.displayName} ${reporterEmail} <br />
Created: ${new Date(upr.createdAt).toDateString()}
</p>
`
}

const getSFTicketInfoHTML = async (sf) => {
const reporter = await getUserByUID(sf.reporter_id)
const reporterEmail = reporter.email ? `&lt;${reporter.email}&gt;` : ''
return `
<p>
Ticket Code: ${sf.code} <br />
Expand All @@ -111,7 +116,7 @@ const getSFTicketInfoHTML = async (sf) => {
: ``
}
Status: ${sf.status} <br />
Reporter: ${reporter.displayName} &lt;${reporter.email}&gt; <br />
Reporter: ${reporter.displayName} ${reporterEmail} <br />
Created: ${new Date(sf.createdAt).toDateString()} <br />
Claim Deadline: ${new Date(sf.claim_deadline).toDateString()} <br />
</p>
Expand Down
15 changes: 9 additions & 6 deletions backend/models/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,15 @@ const UPR_STATUS = [
const UPR_STATUS_FUNDING_SPENT = ['ORDERED', 'READY_FOR_PICKUP', 'PICKED_UP']

const APPROVAL_LEVELS = Object.freeze({
director_approval: 'director_approval',
team_captain_approval: 'team_captain_approval',
director_approval: 'director_approval', // deprecated
team_captain_approval: 'team_captain_approval', // deprecated
admin_approval: 'admin_approval',
faculty_advisor_approval: 'faculty_advisor_approval',
})

const AUTH_ROLES = Object.freeze({
Member: 'Member',
Administrator: 'Administrator',
})

const EMAIL_RECIPIENTS = Object.freeze({
Expand All @@ -49,8 +55,6 @@ const TICKET_ENDPOINTS = Object.freeze({
})

const ADMIN_IDENTIFIERS = ['drayside', 'v2zheng', 'jw4he', 'william.li']
const TEAM_CAPTAIN_TITLES = ['Team Captain']
const DIRECTOR_TITLES = ['Director']

module.exports = {
ENDOWMENT_FUNDS,
Expand All @@ -61,8 +65,7 @@ module.exports = {
UPR_STATUS_FUNDING_SPENT,
TICKET_ENDPOINTS,
APPROVAL_LEVELS,
AUTH_ROLES,
EMAIL_RECIPIENTS,
ADMIN_IDENTIFIERS,
TEAM_CAPTAIN_TITLES,
DIRECTOR_TITLES,
}
5 changes: 3 additions & 2 deletions backend/models/personalpurchase.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ const PersonalPurchaseSchema = new Schema(
purchase_url: { type: String, required: true },
cost: { type: Number, required: true },
purchase_justification: { type: String, required: true },
director_approval: { type: Boolean, default: false },
team_captain_approval: { type: Boolean, default: false },
director_approval: { type: Boolean, default: false }, // deprecated
team_captain_approval: { type: Boolean, default: false }, // deprecated
admin_approval: { type: Boolean, default: false },
faculty_advisor_approval: { type: Boolean, default: false },
},
{
_id: false,
Expand Down
5 changes: 3 additions & 2 deletions backend/models/uwfinancepurchase.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ const UWFinancePurchaseSchema = new Schema(
cost: { type: Number, required: true },
purchase_justification: { type: String, required: true },
pickup_instruction: { type: String },
director_approval: { type: Boolean, default: false },
team_captain_approval: { type: Boolean, default: false },
director_approval: { type: Boolean, default: false }, // deprecated
team_captain_approval: { type: Boolean, default: false }, // deprecated
admin_approval: { type: Boolean, default: false },
faculty_advisor_approval: { type: Boolean, default: false },
requisition_number: { type: String },
po_number: { type: String },
},
Expand Down
4 changes: 2 additions & 2 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mongoose.connect(uri, {

const connection = mongoose.connection
connection.once('open', () => {
console.log('MongoDB database connection established successfully')
console.log('🛢️ MongoDB database connection established successfully')
Copy link
Collaborator

Choose a reason for hiding this comment

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

🔥

})

const fundingItemsRouter = require('./routes/fundingitems.routes')
Expand All @@ -43,6 +43,6 @@ app.use('/files', filesRouter)
app.use('/comments', commentRouter)

app.listen(port, async () => {
console.log(`Server is running on port: ${port}`)
console.log(`🗄️ Server is running on port: ${port}`)
Copy link
Collaborator

Choose a reason for hiding this comment

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

🔥

await updateGroup()
})
4 changes: 2 additions & 2 deletions backend/service/googlegroup.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const deleteUnrecognizedUsers = async (currentEmails, newEmails) => {
await GoogleGroup.deleteMany({
filter: { email: { $in: emailsToDelete } },
})
console.log('User Cleanup Successful')
console.log('🧹 Clean up users completed')
}

const upsertUsers = async (newUsers) => {
Expand All @@ -41,7 +41,7 @@ const upsertUsers = async (newUsers) => {
})
})
await GoogleGroup.bulkWrite(bulkOps)
console.log('Updating users successful')
console.log('🛠️ Update users completed')
}

const updateGoogleGroups = async (body) => {
Expand Down
Loading
Loading