separate `canUpdateWorkOrders` permission

pull/11/head
Dan Gowans 2025-04-24 09:36:44 -04:00
parent a167ef4a16
commit 38c1288856
27 changed files with 161 additions and 48 deletions

View File

@ -19,6 +19,7 @@ export declare const configDefaultValues: {
'session.secret': string; 'session.secret': string;
'users.canLogin': string[]; 'users.canLogin': string[];
'users.canUpdate': string[]; 'users.canUpdate': string[];
'users.canUpdateWorkOrders': string[];
'users.isAdmin': string[]; 'users.isAdmin': string[];
'users.testing': string[]; 'users.testing': string[];
'aliases.externalReceiptNumber': string; 'aliases.externalReceiptNumber': string;

View File

@ -18,6 +18,7 @@ export const configDefaultValues = {
'session.secret': 'cityssm/sunrise', 'session.secret': 'cityssm/sunrise',
'users.canLogin': ['administrator'], 'users.canLogin': ['administrator'],
'users.canUpdate': [], 'users.canUpdate': [],
'users.canUpdateWorkOrders': [],
'users.isAdmin': ['administrator'], 'users.isAdmin': ['administrator'],
'users.testing': [], 'users.testing': [],
'aliases.externalReceiptNumber': 'External Receipt Number', 'aliases.externalReceiptNumber': 'External Receipt Number',

View File

@ -32,6 +32,7 @@ export const configDefaultValues = {
'users.canLogin': ['administrator'], 'users.canLogin': ['administrator'],
'users.canUpdate': [] as string[], 'users.canUpdate': [] as string[],
'users.canUpdateWorkOrders': [] as string[],
'users.isAdmin': ['administrator'], 'users.isAdmin': ['administrator'],
'users.testing': [] as string[], 'users.testing': [] as string[],

View File

@ -383,6 +383,7 @@ const initializingUser = {
userProperties: { userProperties: {
apiKey: '', apiKey: '',
canUpdate: true, canUpdate: true,
canUpdateWorkOrders: true,
isAdmin: true isAdmin: true
} }
}; };

View File

@ -440,6 +440,7 @@ const initializingUser: User = {
userProperties: { userProperties: {
apiKey: '', apiKey: '',
canUpdate: true, canUpdate: true,
canUpdateWorkOrders: true,
isAdmin: true isAdmin: true
} }
} }

View File

@ -4,3 +4,5 @@ export declare function adminPostHandler(request: Request, response: Response, n
export declare function apiGetHandler(request: Request, response: Response, next: NextFunction): Promise<void>; export declare function apiGetHandler(request: Request, response: Response, next: NextFunction): Promise<void>;
export declare function updateGetHandler(request: Request, response: Response, next: NextFunction): void; export declare function updateGetHandler(request: Request, response: Response, next: NextFunction): void;
export declare function updatePostHandler(request: Request, response: Response, next: NextFunction): void; export declare function updatePostHandler(request: Request, response: Response, next: NextFunction): void;
export declare function updateWorkOrdersGetHandler(request: Request, response: Response, next: NextFunction): void;
export declare function updateWorkOrdersPostHandler(request: Request, response: Response, next: NextFunction): void;

View File

@ -1,5 +1,5 @@
import { getConfigProperty } from '../helpers/config.helpers.js'; import { getConfigProperty } from '../helpers/config.helpers.js';
import { apiKeyIsValid, userCanUpdate, userIsAdmin } from '../helpers/functions.user.js'; import { apiKeyIsValid, userCanUpdate, userCanUpdateWorkOrders, userIsAdmin } from '../helpers/functions.user.js';
const urlPrefix = getConfigProperty('reverseProxy.urlPrefix'); const urlPrefix = getConfigProperty('reverseProxy.urlPrefix');
const forbiddenStatus = 403; const forbiddenStatus = 403;
const forbiddenJSON = { const forbiddenJSON = {
@ -43,3 +43,17 @@ export function updatePostHandler(request, response, next) {
} }
response.status(forbiddenStatus).json(forbiddenJSON); response.status(forbiddenStatus).json(forbiddenJSON);
} }
export function updateWorkOrdersGetHandler(request, response, next) {
if (userCanUpdateWorkOrders(request)) {
next();
return;
}
response.redirect(forbiddenRedirectURL);
}
export function updateWorkOrdersPostHandler(request, response, next) {
if (userCanUpdateWorkOrders(request)) {
next();
return;
}
response.status(forbiddenStatus).json(forbiddenJSON);
}

View File

@ -4,6 +4,7 @@ import { getConfigProperty } from '../helpers/config.helpers.js'
import { import {
apiKeyIsValid, apiKeyIsValid,
userCanUpdate, userCanUpdate,
userCanUpdateWorkOrders,
userIsAdmin userIsAdmin
} from '../helpers/functions.user.js' } from '../helpers/functions.user.js'
@ -81,3 +82,29 @@ export function updatePostHandler(
response.status(forbiddenStatus).json(forbiddenJSON) response.status(forbiddenStatus).json(forbiddenJSON)
} }
export function updateWorkOrdersGetHandler(
request: Request,
response: Response,
next: NextFunction
): void {
if (userCanUpdateWorkOrders(request)) {
next()
return
}
response.redirect(forbiddenRedirectURL)
}
export function updateWorkOrdersPostHandler(
request: Request,
response: Response,
next: NextFunction
): void {
if (userCanUpdateWorkOrders(request)) {
next()
return
}
response.status(forbiddenStatus).json(forbiddenJSON)
}

View File

@ -10,4 +10,5 @@ export interface UserRequest {
} }
export declare function apiKeyIsValid(request: APIRequest): Promise<boolean>; export declare function apiKeyIsValid(request: APIRequest): Promise<boolean>;
export declare function userCanUpdate(request: UserRequest): boolean; export declare function userCanUpdate(request: UserRequest): boolean;
export declare function userCanUpdateWorkOrders(request: UserRequest): boolean;
export declare function userIsAdmin(request: UserRequest): boolean; export declare function userIsAdmin(request: UserRequest): boolean;

View File

@ -14,6 +14,9 @@ export async function apiKeyIsValid(request) {
export function userCanUpdate(request) { export function userCanUpdate(request) {
return request.session?.user?.userProperties?.canUpdate ?? false; return request.session?.user?.userProperties?.canUpdate ?? false;
} }
export function userCanUpdateWorkOrders(request) {
return request.session?.user?.userProperties?.canUpdateWorkOrders ?? false;
}
export function userIsAdmin(request) { export function userIsAdmin(request) {
return request.session?.user?.userProperties?.isAdmin ?? false; return request.session?.user?.userProperties?.isAdmin ?? false;
} }

View File

@ -35,6 +35,10 @@ export function userCanUpdate(request: UserRequest): boolean {
return request.session?.user?.userProperties?.canUpdate ?? false return request.session?.user?.userProperties?.canUpdate ?? false
} }
export function userCanUpdateWorkOrders(request: UserRequest): boolean {
return request.session?.user?.userProperties?.canUpdateWorkOrders ?? false
}
export function userIsAdmin(request: UserRequest): boolean { export function userIsAdmin(request: UserRequest): boolean {
return request.session?.user?.userProperties?.isAdmin ?? false return request.session?.user?.userProperties?.isAdmin ?? false
} }

View File

@ -46,12 +46,14 @@ async function postHandler(request, response) {
const canLogin = getConfigProperty('users.canLogin').some((currentUserName) => userNameLowerCase === currentUserName.toLowerCase()); const canLogin = getConfigProperty('users.canLogin').some((currentUserName) => userNameLowerCase === currentUserName.toLowerCase());
if (canLogin) { if (canLogin) {
const canUpdate = getConfigProperty('users.canUpdate').some((currentUserName) => userNameLowerCase === currentUserName.toLowerCase()); const canUpdate = getConfigProperty('users.canUpdate').some((currentUserName) => userNameLowerCase === currentUserName.toLowerCase());
const canUpdateWorkOrders = getConfigProperty('users.canUpdateWorkOrders').some((currentUserName) => userNameLowerCase === currentUserName.toLowerCase());
const isAdmin = getConfigProperty('users.isAdmin').some((currentUserName) => userNameLowerCase === currentUserName.toLowerCase()); const isAdmin = getConfigProperty('users.isAdmin').some((currentUserName) => userNameLowerCase === currentUserName.toLowerCase());
const apiKey = await getApiKey(userNameLowerCase); const apiKey = await getApiKey(userNameLowerCase);
userObject = { userObject = {
userName: userNameLowerCase, userName: userNameLowerCase,
userProperties: { userProperties: {
canUpdate, canUpdate,
canUpdateWorkOrders,
isAdmin, isAdmin,
apiKey apiKey
} }

View File

@ -86,6 +86,10 @@ async function postHandler(
(currentUserName) => userNameLowerCase === currentUserName.toLowerCase() (currentUserName) => userNameLowerCase === currentUserName.toLowerCase()
) )
const canUpdateWorkOrders = getConfigProperty('users.canUpdateWorkOrders').some(
(currentUserName) => userNameLowerCase === currentUserName.toLowerCase()
)
const isAdmin = getConfigProperty('users.isAdmin').some( const isAdmin = getConfigProperty('users.isAdmin').some(
(currentUserName) => userNameLowerCase === currentUserName.toLowerCase() (currentUserName) => userNameLowerCase === currentUserName.toLowerCase()
) )
@ -96,7 +100,9 @@ async function postHandler(
userName: userNameLowerCase, userName: userNameLowerCase,
userProperties: { userProperties: {
canUpdate, canUpdate,
canUpdateWorkOrders,
isAdmin, isAdmin,
apiKey apiKey
} }
} }

View File

@ -1,5 +1,5 @@
import { Router } from 'express'; import { Router } from 'express';
import { updateGetHandler, updatePostHandler } from '../handlers/permissions.js'; import { updateWorkOrdersGetHandler, updateWorkOrdersPostHandler } from '../handlers/permissions.js';
import handler_edit from '../handlers/workOrders-get/edit.js'; import handler_edit from '../handlers/workOrders-get/edit.js';
import handler_milestoneCalendar from '../handlers/workOrders-get/milestoneCalendar.js'; import handler_milestoneCalendar from '../handlers/workOrders-get/milestoneCalendar.js';
import handler_new from '../handlers/workOrders-get/new.js'; import handler_new from '../handlers/workOrders-get/new.js';
@ -36,30 +36,30 @@ router.post('/doGetWorkOrderMilestones', handler_doGetWorkOrderMilestones);
// Outlook Integration // Outlook Integration
router.get('/outlook', handler_outlook); router.get('/outlook', handler_outlook);
// New // New
router.get('/new', updateGetHandler, handler_new); router.get('/new', updateWorkOrdersGetHandler, handler_new);
router.post('/doCreateWorkOrder', updatePostHandler, handler_doCreateWorkOrder); router.post('/doCreateWorkOrder', updateWorkOrdersPostHandler, handler_doCreateWorkOrder);
// View // View
router.get('/:workOrderId', handler_view); router.get('/:workOrderId', handler_view);
router.post('/doReopenWorkOrder', updatePostHandler, handler_doReopenWorkOrder); router.post('/doReopenWorkOrder', updateWorkOrdersPostHandler, handler_doReopenWorkOrder);
// Edit // Edit
router.get('/:workOrderId/edit', updateGetHandler, handler_edit); router.get('/:workOrderId/edit', updateWorkOrdersGetHandler, handler_edit);
router.post('/doUpdateWorkOrder', updatePostHandler, handler_doUpdateWorkOrder); router.post('/doUpdateWorkOrder', updateWorkOrdersPostHandler, handler_doUpdateWorkOrder);
router.post('/doCloseWorkOrder', updatePostHandler, handler_doCloseWorkOrder); router.post('/doCloseWorkOrder', updateWorkOrdersPostHandler, handler_doCloseWorkOrder);
router.post('/doDeleteWorkOrder', updatePostHandler, handler_doDeleteWorkOrder); router.post('/doDeleteWorkOrder', updateWorkOrdersPostHandler, handler_doDeleteWorkOrder);
// Burial Site Contract // Burial Site Contract
router.post('/doAddWorkOrderContract', updatePostHandler, handler_doAddWorkOrderContract); router.post('/doAddWorkOrderContract', updateWorkOrdersPostHandler, handler_doAddWorkOrderContract);
router.post('/doDeleteWorkOrderContract', updatePostHandler, handler_doDeleteWorkOrderContract); router.post('/doDeleteWorkOrderContract', updateWorkOrdersPostHandler, handler_doDeleteWorkOrderContract);
router.post('/doAddWorkOrderBurialSite', updatePostHandler, handler_doAddWorkOrderBurialSite); router.post('/doAddWorkOrderBurialSite', updateWorkOrdersPostHandler, handler_doAddWorkOrderBurialSite);
router.post('/doUpdateBurialSiteStatus', updatePostHandler, handler_doUpdateBurialSiteStatus); router.post('/doUpdateBurialSiteStatus', updateWorkOrdersPostHandler, handler_doUpdateBurialSiteStatus);
router.post('/doDeleteWorkOrderBurialSite', updatePostHandler, handler_doDeleteWorkOrderBurialSite); router.post('/doDeleteWorkOrderBurialSite', updateWorkOrdersPostHandler, handler_doDeleteWorkOrderBurialSite);
// Comments // Comments
router.post('/doAddWorkOrderComment', updatePostHandler, handler_doAddWorkOrderComment); router.post('/doAddWorkOrderComment', updateWorkOrdersPostHandler, handler_doAddWorkOrderComment);
router.post('/doUpdateWorkOrderComment', updatePostHandler, handler_doUpdateWorkOrderComment); router.post('/doUpdateWorkOrderComment', updateWorkOrdersPostHandler, handler_doUpdateWorkOrderComment);
router.post('/doDeleteWorkOrderComment', updatePostHandler, handler_doDeleteWorkOrderComment); router.post('/doDeleteWorkOrderComment', updateWorkOrdersPostHandler, handler_doDeleteWorkOrderComment);
// Milestones // Milestones
router.post('/doAddWorkOrderMilestone', updatePostHandler, handler_doAddWorkOrderMilestone); router.post('/doAddWorkOrderMilestone', updateWorkOrdersPostHandler, handler_doAddWorkOrderMilestone);
router.post('/doUpdateWorkOrderMilestone', updatePostHandler, handler_doUpdateWorkOrderMilestone); router.post('/doUpdateWorkOrderMilestone', updateWorkOrdersPostHandler, handler_doUpdateWorkOrderMilestone);
router.post('/doCompleteWorkOrderMilestone', updatePostHandler, handler_doCompleteWorkOrderMilestone); router.post('/doCompleteWorkOrderMilestone', updateWorkOrdersPostHandler, handler_doCompleteWorkOrderMilestone);
router.post('/doReopenWorkOrderMilestone', updatePostHandler, handler_doReopenWorkOrderMilestone); router.post('/doReopenWorkOrderMilestone', updateWorkOrdersPostHandler, handler_doReopenWorkOrderMilestone);
router.post('/doDeleteWorkOrderMilestone', updatePostHandler, handler_doDeleteWorkOrderMilestone); router.post('/doDeleteWorkOrderMilestone', updateWorkOrdersPostHandler, handler_doDeleteWorkOrderMilestone);
export default router; export default router;

View File

@ -1,6 +1,9 @@
import { Router } from 'express' import { Router } from 'express'
import { updateGetHandler, updatePostHandler } from '../handlers/permissions.js' import {
updateWorkOrdersGetHandler,
updateWorkOrdersPostHandler
} from '../handlers/permissions.js'
import handler_edit from '../handlers/workOrders-get/edit.js' import handler_edit from '../handlers/workOrders-get/edit.js'
import handler_milestoneCalendar from '../handlers/workOrders-get/milestoneCalendar.js' import handler_milestoneCalendar from '../handlers/workOrders-get/milestoneCalendar.js'
import handler_new from '../handlers/workOrders-get/new.js' import handler_new from '../handlers/workOrders-get/new.js'
@ -48,47 +51,75 @@ router.get('/outlook', handler_outlook)
// New // New
router.get('/new', updateGetHandler, handler_new) router.get('/new', updateWorkOrdersGetHandler, handler_new)
router.post('/doCreateWorkOrder', updatePostHandler, handler_doCreateWorkOrder) router.post(
'/doCreateWorkOrder',
updateWorkOrdersPostHandler,
handler_doCreateWorkOrder
)
// View // View
router.get('/:workOrderId', handler_view) router.get('/:workOrderId', handler_view)
router.post('/doReopenWorkOrder', updatePostHandler, handler_doReopenWorkOrder) router.post(
'/doReopenWorkOrder',
updateWorkOrdersPostHandler,
handler_doReopenWorkOrder
)
// Edit // Edit
router.get('/:workOrderId/edit', updateGetHandler, handler_edit) router.get('/:workOrderId/edit', updateWorkOrdersGetHandler, handler_edit)
router.post('/doUpdateWorkOrder', updatePostHandler, handler_doUpdateWorkOrder) router.post(
'/doUpdateWorkOrder',
updateWorkOrdersPostHandler,
handler_doUpdateWorkOrder
)
router.post('/doCloseWorkOrder', updatePostHandler, handler_doCloseWorkOrder) router.post(
'/doCloseWorkOrder',
updateWorkOrdersPostHandler,
handler_doCloseWorkOrder
)
router.post('/doDeleteWorkOrder', updatePostHandler, handler_doDeleteWorkOrder) router.post(
'/doDeleteWorkOrder',
updateWorkOrdersPostHandler,
handler_doDeleteWorkOrder
)
// Burial Site Contract // Burial Site Contract
router.post( router.post(
'/doAddWorkOrderContract', '/doAddWorkOrderContract',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doAddWorkOrderContract handler_doAddWorkOrderContract
) )
router.post( router.post(
'/doDeleteWorkOrderContract', '/doDeleteWorkOrderContract',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doDeleteWorkOrderContract handler_doDeleteWorkOrderContract
) )
router.post('/doAddWorkOrderBurialSite', updatePostHandler, handler_doAddWorkOrderBurialSite) router.post(
'/doAddWorkOrderBurialSite',
updateWorkOrdersPostHandler,
handler_doAddWorkOrderBurialSite
)
router.post('/doUpdateBurialSiteStatus', updatePostHandler, handler_doUpdateBurialSiteStatus) router.post(
'/doUpdateBurialSiteStatus',
updateWorkOrdersPostHandler,
handler_doUpdateBurialSiteStatus
)
router.post( router.post(
'/doDeleteWorkOrderBurialSite', '/doDeleteWorkOrderBurialSite',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doDeleteWorkOrderBurialSite handler_doDeleteWorkOrderBurialSite
) )
@ -96,19 +127,19 @@ router.post(
router.post( router.post(
'/doAddWorkOrderComment', '/doAddWorkOrderComment',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doAddWorkOrderComment handler_doAddWorkOrderComment
) )
router.post( router.post(
'/doUpdateWorkOrderComment', '/doUpdateWorkOrderComment',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doUpdateWorkOrderComment handler_doUpdateWorkOrderComment
) )
router.post( router.post(
'/doDeleteWorkOrderComment', '/doDeleteWorkOrderComment',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doDeleteWorkOrderComment handler_doDeleteWorkOrderComment
) )
@ -116,31 +147,31 @@ router.post(
router.post( router.post(
'/doAddWorkOrderMilestone', '/doAddWorkOrderMilestone',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doAddWorkOrderMilestone handler_doAddWorkOrderMilestone
) )
router.post( router.post(
'/doUpdateWorkOrderMilestone', '/doUpdateWorkOrderMilestone',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doUpdateWorkOrderMilestone handler_doUpdateWorkOrderMilestone
) )
router.post( router.post(
'/doCompleteWorkOrderMilestone', '/doCompleteWorkOrderMilestone',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doCompleteWorkOrderMilestone handler_doCompleteWorkOrderMilestone
) )
router.post( router.post(
'/doReopenWorkOrderMilestone', '/doReopenWorkOrderMilestone',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doReopenWorkOrderMilestone handler_doReopenWorkOrderMilestone
) )
router.post( router.post(
'/doDeleteWorkOrderMilestone', '/doDeleteWorkOrderMilestone',
updatePostHandler, updateWorkOrdersPostHandler,
handler_doDeleteWorkOrderMilestone handler_doDeleteWorkOrderMilestone
) )

View File

@ -33,6 +33,7 @@ const user = {
userName: 'import.unix', userName: 'import.unix',
userProperties: { userProperties: {
canUpdate: true, canUpdate: true,
canUpdateWorkOrders: true,
isAdmin: false, isAdmin: false,
apiKey: '' apiKey: ''
} }

View File

@ -56,6 +56,7 @@ const user: User = {
userName: 'import.unix', userName: 'import.unix',
userProperties: { userProperties: {
canUpdate: true, canUpdate: true,
canUpdateWorkOrders: true,
isAdmin: false, isAdmin: false,
apiKey: '' apiKey: ''

View File

@ -204,6 +204,7 @@ await describe('functions.user', async () => {
userName: '*test', userName: '*test',
userProperties: { userProperties: {
canUpdate: false, canUpdate: false,
canUpdateWorkOrders: false,
isAdmin: false, isAdmin: false,
apiKey: '' apiKey: ''
} }
@ -224,6 +225,7 @@ await describe('functions.user', async () => {
userName: '*test', userName: '*test',
userProperties: { userProperties: {
canUpdate: true, canUpdate: true,
canUpdateWorkOrders: true,
isAdmin: false, isAdmin: false,
apiKey: '' apiKey: ''
} }
@ -244,6 +246,7 @@ await describe('functions.user', async () => {
userName: '*test', userName: '*test',
userProperties: { userProperties: {
canUpdate: false, canUpdate: false,
canUpdateWorkOrders: false,
isAdmin: true, isAdmin: true,
apiKey: '' apiKey: ''
} }
@ -264,6 +267,7 @@ await describe('functions.user', async () => {
userName: '*test', userName: '*test',
userProperties: { userProperties: {
canUpdate: true, canUpdate: true,
canUpdateWorkOrders: true,
isAdmin: true, isAdmin: true,
apiKey: '' apiKey: ''
} }

View File

@ -361,7 +361,9 @@ await describe('functions.user', async () => {
userName: '*test', userName: '*test',
userProperties: { userProperties: {
canUpdate: false, canUpdate: false,
canUpdateWorkOrders: false,
isAdmin: false, isAdmin: false,
apiKey: '' apiKey: ''
} }
} }
@ -384,7 +386,9 @@ await describe('functions.user', async () => {
userName: '*test', userName: '*test',
userProperties: { userProperties: {
canUpdate: true, canUpdate: true,
canUpdateWorkOrders: true,
isAdmin: false, isAdmin: false,
apiKey: '' apiKey: ''
} }
} }
@ -407,7 +411,9 @@ await describe('functions.user', async () => {
userName: '*test', userName: '*test',
userProperties: { userProperties: {
canUpdate: false, canUpdate: false,
canUpdateWorkOrders: false,
isAdmin: true, isAdmin: true,
apiKey: '' apiKey: ''
} }
} }
@ -430,7 +436,9 @@ await describe('functions.user', async () => {
userName: '*test', userName: '*test',
userProperties: { userProperties: {
canUpdate: true, canUpdate: true,
canUpdateWorkOrders: true,
isAdmin: true, isAdmin: true,
apiKey: '' apiKey: ''
} }
} }

View File

@ -12,6 +12,7 @@ export interface Config {
testing?: Array<`*${string}`>; testing?: Array<`*${string}`>;
canLogin?: string[]; canLogin?: string[];
canUpdate?: string[]; canUpdate?: string[];
canUpdateWorkOrders?: string[];
isAdmin?: string[]; isAdmin?: string[];
}; };
aliases: { aliases: {

View File

@ -18,6 +18,7 @@ export interface Config {
canLogin?: string[] canLogin?: string[]
canUpdate?: string[] canUpdate?: string[]
canUpdateWorkOrders?: string[]
isAdmin?: string[] isAdmin?: string[]
} }

View File

@ -99,7 +99,7 @@ export interface Cemetery extends Record {
parentCemeteryId?: number | null parentCemeteryId?: number | null
parentCemeteryName?: string | null parentCemeteryName?: string | null
parentCemeteryLatitude?: number | null parentCemeteryLatitude?: number | null
parentCemeteryLongitude?: number | null parentCemeteryLongitude?: number | null
parentCemeterySvg?: string | null parentCemeterySvg?: string | null
@ -461,6 +461,6 @@ export interface WorkOrderMilestoneType extends Record {
export interface WorkOrderType extends Record { export interface WorkOrderType extends Record {
workOrderTypeId: number workOrderTypeId: number
workOrderType?: string workOrderType?: string
orderNumber?: number orderNumber?: number
} }

View File

@ -7,6 +7,7 @@ declare global {
export interface UserProperties { export interface UserProperties {
apiKey: string; apiKey: string;
canUpdate: boolean; canUpdate: boolean;
canUpdateWorkOrders: boolean;
isAdmin: boolean; isAdmin: boolean;
} }
declare module 'express-session' { declare module 'express-session' {

View File

@ -8,6 +8,7 @@ declare global {
export interface UserProperties { export interface UserProperties {
apiKey: string apiKey: string
canUpdate: boolean canUpdate: boolean
canUpdateWorkOrders: boolean
isAdmin: boolean isAdmin: boolean
} }

View File

@ -111,7 +111,7 @@
</div> </div>
</a> </a>
<div class="panel-block is-block"> <div class="panel-block is-block">
<% if (user.userProperties.canUpdate) { %> <% if (user.userProperties.canUpdateWorkOrders) { %>
<a class="button is-fullwidth is-success is-light mb-2" href="<%= urlPrefix %>/workOrders/new"> <a class="button is-fullwidth is-success is-light mb-2" href="<%= urlPrefix %>/workOrders/new">
<span class="icon"> <span class="icon">
<i class="fas fa-plus" aria-hidden="true"></i> <i class="fas fa-plus" aria-hidden="true"></i>

View File

@ -21,7 +21,7 @@
Work Order Search Work Order Search
</h1> </h1>
<% if (user.userProperties.canUpdate) { %> <% if (user.userProperties.canUpdateWorkOrders) { %>
<div class="fixed-container is-fixed-bottom-right mx-4 my-4 has-text-right is-hidden-print"> <div class="fixed-container is-fixed-bottom-right mx-4 my-4 has-text-right is-hidden-print">
<a class="button is-circle is-primary has-tooltip-left" <a class="button is-circle is-primary has-tooltip-left"
data-tooltip="Create a New Work Order" data-tooltip="Create a New Work Order"

View File

@ -80,7 +80,7 @@
</div> </div>
<% } %> <% } %>
<% } %> <% } %>
<% if (user.userProperties.canUpdate) { %> <% if (user.userProperties.canUpdateWorkOrders) { %>
<% if (workOrder.workOrderCloseDate) { %> <% if (workOrder.workOrderCloseDate) { %>
<button class="button is-warning" id="button--reopenWorkOrder" data-work-order-id="<%= workOrder.workOrderId %>" type="button"> <button class="button is-warning" id="button--reopenWorkOrder" data-work-order-id="<%= workOrder.workOrderId %>" type="button">
<span class="icon"><i class="fas fa-undo" aria-hidden="true"></i></span> <span class="icon"><i class="fas fa-undo" aria-hidden="true"></i></span>