@@ -12,21 +12,28 @@ const { sequelize } = require("../../../connection");
1212const logger = require ( "../../../logger" ) ;
1313const Config = require ( "../models/config" ) ;
1414const config_template = require ( "../../../templates/config_template" ) ;
15+ const userModel = require ( "../../Users/models/user" ) ;
16+ const User = userModel . User ;
1517
1618// Sanitize user input to prevent XSS in error messages
1719function sanitizeInput ( input ) {
18- if ( typeof input !== 'string' ) return String ( input ) ;
19- return input
20- . replace ( / [ < > ' " & ] / g, function ( match ) {
21- switch ( match ) {
22- case '<' : return '<' ;
23- case '>' : return '>' ;
24- case '"' : return '"' ;
25- case "'" : return ''' ;
26- case '&' : return '&' ;
27- default : return match ;
28- }
29- } ) ;
20+ if ( typeof input !== "string" ) return String ( input ) ;
21+ return input . replace ( / [ < > ' " & ] / g, function ( match ) {
22+ switch ( match ) {
23+ case "<" :
24+ return "<" ;
25+ case ">" :
26+ return ">" ;
27+ case '"' :
28+ return """ ;
29+ case "'" :
30+ return "'" ;
31+ case "&" :
32+ return "&" ;
33+ default :
34+ return match ;
35+ }
36+ } ) ;
3037}
3138
3239const GeneralOptions = require ( "../../GeneralOptions/models/generaloptions" ) ;
4855)
4956 fullAccess = true ;
5057
58+ // Middleware to check if admin user has permission to access specific mission
59+ function checkMissionPermission ( req , res , next ) {
60+ // Determine if this is a long term token request or regular session
61+ let userPermission , userMissions , userId ;
62+
63+ if ( req . isLongTermToken ) {
64+ // Use token creator's permissions for long term tokens
65+ userPermission = req . tokenUserPermission ;
66+ userMissions = req . tokenUserMissions ;
67+ userId = null ; // We don't need to lookup again since we have the data
68+ } else {
69+ // Use session permissions for regular requests
70+ userPermission = req . session . permission ;
71+ userId = req . session . uid ;
72+ userMissions = null ; // Will be looked up from database
73+ }
74+
75+ // SuperAdmins (111) have access to all missions
76+ if ( userPermission === "111" ) {
77+ next ( ) ;
78+ return ;
79+ }
80+
81+ // Regular users (not 110) should not access config endpoints
82+ if ( userPermission !== "110" ) {
83+ res . send ( {
84+ status : "failure" ,
85+ message : "Unauthorized - insufficient permissions."
86+ } ) ;
87+ return ;
88+ }
89+
90+ // For Admins (110), check mission-specific permissions
91+ const mission = req . body . mission || req . query . mission ;
92+ if ( ! mission ) {
93+ next ( ) ; // No mission specified, let other validation handle it
94+ return ;
95+ }
96+
97+ // If we already have missions from token, use them directly
98+ if ( req . isLongTermToken ) {
99+ const managingMissions = userMissions || [ ] ;
100+ if ( managingMissions . includes ( mission ) ) {
101+ next ( ) ;
102+ } else {
103+ res . send ( {
104+ status : "failure" ,
105+ message : `Unauthorized - no permission to access mission: ${ mission } `
106+ } ) ;
107+ }
108+ return ;
109+ }
110+
111+ // For regular session users, get user's missions_managing array from database
112+ User . findOne ( {
113+ where : { id : userId } ,
114+ attributes : [ "missions_managing" ]
115+ } )
116+ . then ( ( user ) => {
117+ if ( ! user ) {
118+ res . send ( {
119+ status : "failure" ,
120+ message : "User not found."
121+ } ) ;
122+ return ;
123+ }
124+
125+ const managingMissions = user . missions_managing || [ ] ;
126+ if ( managingMissions . includes ( mission ) ) {
127+ next ( ) ;
128+ } else {
129+ res . send ( {
130+ status : "failure" ,
131+ message : `Unauthorized - no permission to access mission: ${ mission } `
132+ } ) ;
133+ }
134+ } )
135+ . catch ( ( err ) => {
136+ logger ( "error" , "Failed to check mission permissions." , req . originalUrl , req , err ) ;
137+ res . send ( {
138+ status : "failure" ,
139+ message : "Failed to verify mission permissions."
140+ } ) ;
141+ } ) ;
142+ }
143+
51144function get ( req , res , next , cb ) {
52145 Config . findAll ( {
53146 limit : 1 ,
@@ -109,12 +202,16 @@ function get(req, res, next, cb) {
109202 if ( cb )
110203 cb ( {
111204 status : "failure" ,
112- message : `Mission '${ sanitizeInput ( req . query . mission ) } v${ version } ' not found.` ,
205+ message : `Mission '${ sanitizeInput (
206+ req . query . mission
207+ ) } v${ version } ' not found.`,
113208 } ) ;
114209 else
115210 res . send ( {
116211 status : "failure" ,
117- message : `Mission '${ sanitizeInput ( req . query . mission ) } v${ version } ' not found.` ,
212+ message : `Mission '${ sanitizeInput (
213+ req . query . mission
214+ ) } v${ version } ' not found.`,
118215 } ) ;
119216 return null ;
120217 } ) ;
@@ -258,6 +355,13 @@ function add(req, res, next, cb) {
258355
259356if ( fullAccess )
260357 router . post ( "/add" , function ( req , res , next ) {
358+ if ( req . session . permission !== "111" ) {
359+ res . send ( {
360+ status : "failure" ,
361+ message : "Only SuperAdmins can add new missions." ,
362+ } ) ;
363+ return null ;
364+ }
261365 add ( req , res , next ) ;
262366 } ) ;
263367
@@ -467,7 +571,7 @@ function upsert(req, res, next, cb, info) {
467571}
468572
469573if ( fullAccess )
470- router . post ( "/upsert" , function ( req , res , next ) {
574+ router . post ( "/upsert" , checkMissionPermission , function ( req , res , next ) {
471575 upsert ( req , res , next ) ;
472576 } ) ;
473577
@@ -505,6 +609,46 @@ router.get("/missions", function (req, res, next) {
505609 return null ;
506610} ) ;
507611
612+ // Get current user's mission permissions for the Configure page
613+ router . get ( "/user-permissions" , function ( req , res , next ) {
614+ // SuperAdmins can manage all missions
615+ if ( req . session . permission === "111" ) {
616+ res . send ( {
617+ status : "success" ,
618+ permission : "111" ,
619+ missions_managing : null // null means all missions
620+ } ) ;
621+ return ;
622+ }
623+
624+ // Regular admins get their specific mission list
625+ if ( req . session . permission === "110" ) {
626+ User . findOne ( {
627+ where : { id : req . session . uid } ,
628+ attributes : [ "missions_managing" ]
629+ } )
630+ . then ( ( user ) => {
631+ res . send ( {
632+ status : "success" ,
633+ permission : "110" ,
634+ missions_managing : user ? user . missions_managing || [ ] : [ ]
635+ } ) ;
636+ } )
637+ . catch ( ( err ) => {
638+ logger ( "error" , "Failed to get user permissions." , req . originalUrl , req , err ) ;
639+ res . send ( { status : "failure" , message : "Failed to get user permissions." } ) ;
640+ } ) ;
641+ return ;
642+ }
643+
644+ // Non-admin users
645+ res . send ( {
646+ status : "success" ,
647+ permission : req . session . permission || "000" ,
648+ missions_managing : [ ]
649+ } ) ;
650+ } ) ;
651+
508652if ( fullAccess )
509653 router . get ( "/versions" , function ( req , res , next ) {
510654 Config . findAll ( {
@@ -908,7 +1052,7 @@ function addLayer(req, res, next, cb, forceConfig, caller = "addLayer") {
9081052 ) ;
9091053}
9101054if ( fullAccess )
911- router . post ( "/addLayer" , function ( req , res , next ) {
1055+ router . post ( "/addLayer" , checkMissionPermission , function ( req , res , next ) {
9121056 addLayer ( req , res , next ) ;
9131057 } ) ;
9141058
@@ -917,7 +1061,7 @@ if (fullAccess)
9171061 * /updateLayer
9181062 * Finds the existing layer, merges new layer items, deletes and readds with addLayer.
9191063 */
920- router . post ( "/updateLayer" , function ( req , res , next ) {
1064+ router . post ( "/updateLayer" , checkMissionPermission , function ( req , res , next ) {
9211065 const exampleBody = {
9221066 mission : "{mission_name}" ,
9231067 layerUUID : "{existing_layer_uuid}" ,
@@ -1168,7 +1312,7 @@ if (fullAccess)
11681312 "forceClientUpdate?": true
11691313 }
11701314 */
1171- router . post ( "/removeLayer" , function ( req , res , next ) {
1315+ router . post ( "/removeLayer" , checkMissionPermission , function ( req , res , next ) {
11721316 removeLayer ( req , res , next ) ;
11731317 } ) ;
11741318
@@ -1182,7 +1326,7 @@ if (fullAccess)
11821326 "zoom?": 0
11831327 }
11841328 */
1185- router . post ( "/updateInitialView" , function ( req , res , next ) {
1329+ router . post ( "/updateInitialView" , checkMissionPermission , function ( req , res , next ) {
11861330 const exampleBody = {
11871331 mission : "{mission_name}" ,
11881332 "latitude?" : 0 ,
0 commit comments