-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Total restructuring inside the /api dir:
- v1 and v2 have their own dirs - I appended a .v2 to all logger definitions for API V2 controllers/services - I removed the obsolete endpoints from V2 - Added the new endpoints: PUT and DELETE /mapconfig/{name} instead of /mapconfig/create/{name} and /mapconfig/delete/{name}. This was already changed in the API spec so we will now conform to that - This is by no means complete (at least I think there's room for improvement). See this as a proposal for future structure inside the Backend dir and please let me know what you think in #1309.
- Loading branch information
Showing
54 changed files
with
2,687 additions
and
16 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import ActiveDirectoryService from "../../services/activedirectory.service"; | ||
import handleStandardResponse from "../../utils/handleStandardResponse"; | ||
import log4js from "log4js"; | ||
|
||
// Create a logger for admin events, those will be saved in a separate log file. | ||
const ael = log4js.getLogger("adminEvent.v2"); | ||
|
||
export class Controller { | ||
availableADGroups(req, res) { | ||
ActiveDirectoryService.getAvailableADGroups().then((data) => | ||
handleStandardResponse(res, data) | ||
); | ||
} | ||
|
||
findCommonADGroupsForUsers(req, res) { | ||
ActiveDirectoryService.findCommonADGroupsForUsers(req.query.users).then( | ||
(data) => handleStandardResponse(res, data) | ||
); | ||
} | ||
|
||
getStore(req, res) { | ||
// Extract the store name from request's path | ||
const store = req.route.path.substring(1); | ||
ActiveDirectoryService.getStore(store).then((data) => { | ||
handleStandardResponse(res, data); | ||
// If data doesn't contain the error property, we're good - print event to admin log | ||
!data.error && | ||
ael.info( | ||
`${res.locals.authUser} viewed contents of AD store "${store}"` | ||
); | ||
}); | ||
} | ||
|
||
flushStores(req, res) { | ||
ActiveDirectoryService.flushStores().then((data) => { | ||
handleStandardResponse(res, data); | ||
// If data doesn't contain the error property, we're good - print event to admin log | ||
!data.error && ael.info(`${res.locals.authUser} flushed all AD stores`); | ||
}); | ||
} | ||
} | ||
|
||
export default new Controller(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import * as express from "express"; | ||
import controller from "./controller"; | ||
import restrictAdmin from "../../middlewares/restrict.admin"; | ||
|
||
export default express | ||
.Router() | ||
.use(restrictAdmin) // We will not allow any of the following routes unless user is admin | ||
.get("/availableadgroups", controller.availableADGroups) | ||
.get("/findcommonadgroupsforusers", controller.findCommonADGroupsForUsers) | ||
.get("/users", controller.getStore) | ||
.get("/groups", controller.getStore) | ||
.get("/groupsPerUser", controller.getStore) | ||
.put("/flushStores", controller.flushStores); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
62 changes: 62 additions & 0 deletions
62
new-backend/server/apis/v2/controllers/informative/controller.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import InformativeService from "../../services/informative.service"; | ||
import log4js from "log4js"; | ||
|
||
// Create a logger for admin events, those will be saved in a separate log file. | ||
const ael = log4js.getLogger("adminEvent.v2"); | ||
|
||
export class Controller { | ||
create(req, res) { | ||
const { documentName, mapName } = JSON.parse(req.body); | ||
InformativeService.create(documentName, mapName).then((r) => { | ||
// FIXME: The buggy admin expects 200 and this string on success, | ||
// but I think that we'd do better with a meaningful JSON response. | ||
if (r && !r.error) { | ||
res.status(200).send("Document created"); | ||
ael.info( | ||
`${res.locals.authUser} created a new document, ${documentName}.json, and connected it to map ${mapName}.json` | ||
); | ||
} else res.status(500).send(r.error.message); | ||
}); | ||
} | ||
|
||
getByName(req, res) { | ||
InformativeService.getByName(req.params.name).then((r) => { | ||
if (r && !r.error) res.json(r); | ||
else { | ||
res | ||
.status(404) | ||
.send(`Document "${req.params.name}" could not be found`); | ||
} | ||
}); | ||
} | ||
|
||
saveByName(req, res) { | ||
InformativeService.saveByName(req.params.name, req.body).then((r) => { | ||
if (r && !r.error) { | ||
res.status(200).send("File saved"); | ||
ael.info( | ||
`${res.locals.authUser} saved document ${req.params.name}.json` | ||
); | ||
} else res.status(500).send(r.error.message); | ||
}); | ||
} | ||
|
||
deleteByName(req, res) { | ||
InformativeService.deleteByName(req.params.name).then((r) => { | ||
if (r && !r.error) { | ||
res.status(200).send("File saved"); | ||
ael.info( | ||
`${res.locals.authUser} deleted document ${req.params.name}.json` | ||
); | ||
} else res.status(500).send(r.error.message); | ||
}); | ||
} | ||
|
||
list(req, res) { | ||
InformativeService.getAvailableDocuments().then((r) => { | ||
if (r && !r.error) res.json(r); | ||
else res.status(500).send(r.error.message); | ||
}); | ||
} | ||
} | ||
export default new Controller(); |
13 changes: 13 additions & 0 deletions
13
new-backend/server/apis/v2/controllers/informative/router.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import * as express from "express"; | ||
import controller from "./controller"; | ||
import restrictAdmin from "../../middlewares/restrict.admin"; | ||
|
||
export default express | ||
.Router() | ||
.get("/load/:name", controller.getByName) | ||
.use(restrictAdmin) // All routes that follow are admin-only! | ||
.put("/create", controller.create) // PUT is correct here, as this operation is idempotent | ||
.delete("/delete/:name", controller.deleteByName) | ||
.get("/list", controller.list) | ||
.get("/list/:name", controller.list) // FIXME: For now, the name paramter is ignored - should list only documents connected to specified map | ||
.put("/save/:name", controller.saveByName); // PUT is correct here, as this operation is idempotent |
129 changes: 129 additions & 0 deletions
129
new-backend/server/apis/v2/controllers/mapconfig/controller.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import ConfigService from "../../services/config.service"; | ||
import InformativeService from "../../services/informative.service"; | ||
import ad from "../../services/activedirectory.service"; | ||
import handleStandardResponse from "../../utils/handleStandardResponse"; | ||
import log4js from "log4js"; | ||
|
||
// Create a logger for admin events, those will be saved in a separate log file. | ||
const ael = log4js.getLogger("adminEvent.v2"); | ||
|
||
export class Controller { | ||
/** | ||
* @summary Get a specific map config using the supplied | ||
* request parameter "map" as map's name. | ||
* | ||
* @param {*} req | ||
* @param {*} res | ||
* @memberof Controller | ||
*/ | ||
byMap(req, res) { | ||
ConfigService.getMapConfig( | ||
req.params.map, | ||
ad.getUserFromRequestHeader(req), | ||
false // 'false' here means that the map config won't be "washed" - this is exactly what we need for this admin request | ||
).then((data) => handleStandardResponse(res, data)); | ||
} | ||
|
||
/** | ||
* @summary Returns a list of all available layers in specified (often human-readable) format. | ||
* | ||
* @description Sometimes it's useful for admins to get a list of a map's contents and make it | ||
* available for users in some format (be it JSON, XML, Excel). This endpoint can be used as-is | ||
* or by implementing a feature in the client UI, so users themselves can request a description | ||
* of a map's contents from e.g. LayerSwitcher. | ||
* @param {*} req | ||
* @param {*} res | ||
* @memberof Controller | ||
*/ | ||
exportMapConfig(req, res) { | ||
ConfigService.exportMapConfig( | ||
req.params.map, | ||
req.params.format, | ||
ad.getUserFromRequestHeader(req) | ||
).then((data) => handleStandardResponse(res, data)); | ||
} | ||
|
||
/** | ||
* @summary Get the contents of the layers database | ||
* | ||
* @param {*} req | ||
* @param {*} res | ||
* @memberof Controller | ||
*/ | ||
layers(req, res) { | ||
ConfigService.getLayersStore( | ||
ad.getUserFromRequestHeader(req), | ||
false // won't "wash" content, which is what we need for admin UI to list the entire layer's store | ||
).then((data) => handleStandardResponse(res, data)); | ||
} | ||
|
||
layersVerify(req, res) { | ||
ConfigService.verifyLayers(ad.getUserFromRequestHeader(req)).then((data) => | ||
handleStandardResponse(res, data) | ||
); | ||
} | ||
|
||
/** | ||
* @summary List all available map configs - used in admin | ||
* | ||
* @param {*} req | ||
* @param {*} res | ||
* @memberof Controller | ||
*/ | ||
list(req, res) { | ||
ConfigService.getAvailableMaps().then((data) => | ||
handleStandardResponse(res, data) | ||
); | ||
} | ||
|
||
listimage(req, res) { | ||
InformativeService.getUploadedFiles("image").then((data) => | ||
handleStandardResponse(res, data) | ||
); | ||
} | ||
|
||
listvideo(req, res) { | ||
InformativeService.getUploadedFiles("video").then((data) => | ||
handleStandardResponse(res, data) | ||
); | ||
} | ||
|
||
listaudio(req, res) { | ||
InformativeService.getUploadedFiles("audio").then((data) => | ||
handleStandardResponse(res, data) | ||
); | ||
} | ||
|
||
createNewMap(req, res) { | ||
ConfigService.createNewMap(req.params.name).then((data) => { | ||
handleStandardResponse(res, data); | ||
!data.error && | ||
ael.info( | ||
`${res.locals.authUser} created a new map config: ${req.params.name}.json` | ||
); | ||
}); | ||
} | ||
|
||
duplicateMap(req, res) { | ||
ConfigService.duplicateMap(req.params.nameFrom, req.params.nameTo).then( | ||
(data) => { | ||
handleStandardResponse(res, data); | ||
!data.error && | ||
ael.info( | ||
`${res.locals.authUser} created a new map config, ${req.params.nameTo}.json, by duplicating ${req.params.nameFrom}.json` | ||
); | ||
} | ||
); | ||
} | ||
|
||
deleteMap(req, res) { | ||
ConfigService.deleteMap(req.params.name).then((data) => { | ||
handleStandardResponse(res, data); | ||
!data.error && | ||
ael.info( | ||
`${res.locals.authUser} deleted map config ${req.params.name}.json` | ||
); | ||
}); | ||
} | ||
} | ||
export default new Controller(); |
22 changes: 22 additions & 0 deletions
22
new-backend/server/apis/v2/controllers/mapconfig/router.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import * as express from "express"; | ||
import controller from "./controller"; | ||
import restrictAdmin from "../../middlewares/restrict.admin"; | ||
|
||
export default express | ||
.Router() | ||
.use(restrictAdmin) // We will not allow any of the following routes unless user is admin | ||
// First we handle _specific_ routes, so we can catch them… | ||
.put("/duplicate/:nameFrom/:nameTo", controller.duplicateMap) | ||
.get("/export/:map/:format", controller.exportMapConfig) // Describe all available layers in a human-readable format | ||
.get("/layers", controller.layers) // Get all layers (from layers.json) | ||
.get("/layers/verify", controller.layersVerify) // Check which Hajk layers actually exist in their respective services | ||
.get("/list", controller.list) // List all available maps | ||
.get("/listimage", controller.listimage) // List all available maps | ||
.get("/listvideo", controller.listvideo) | ||
.get("/listaudio", controller.listaudio) | ||
|
||
// …but if none of the above matched, let's assume the string | ||
// provided is a param that should be used as map config name. | ||
.get("/:map", controller.byMap) // Get specific map config | ||
.put("/:name", controller.createNewMap) | ||
.delete("/:name", controller.deleteMap); |
77 changes: 77 additions & 0 deletions
77
new-backend/server/apis/v2/controllers/settings/controller.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import SettingsService from "../../services/settings.service"; | ||
import handleStandardResponse from "../../utils/handleStandardResponse"; | ||
import log4js from "log4js"; | ||
|
||
// Create a logger for admin events, those will be saved in a separate log file. | ||
const ael = log4js.getLogger("adminEvent.v2"); | ||
|
||
export class Controller { | ||
putSettingsToMapFile(req, res) { | ||
SettingsService.updateMapFile(req.query.mapFile, req.body, req.url).then( | ||
(data) => { | ||
// Can't use handleStandardResponse here because we need to | ||
// output only data.mapConfig on success – not the entire data. | ||
if (data.error) res.status(500).send(data.error.toString()); | ||
else { | ||
// Send response | ||
res.status(200).json(data.mapConfig); | ||
// Log admin action | ||
ael.info(`${res.locals.authUser} saved map ${req.query.mapFile}`); | ||
} | ||
} | ||
); | ||
} | ||
|
||
updateMapTool(req, res) { | ||
SettingsService.updateMapTool( | ||
req.params.map, | ||
req.params.tool, | ||
req.body | ||
).then((data) => { | ||
// Can't use handleStandardResponse here because we need to | ||
// output only data.mapConfig on success – not the entire data. | ||
if (data.error) res.status(500).send(data.error.toString()); | ||
else { | ||
// Send response | ||
res.sendStatus(data); | ||
// Log admin action | ||
ael.info(`${res.locals.authUser} saved map ${req.query.mapFile}`); | ||
} | ||
}); | ||
} | ||
|
||
putLayerOfType(req, res) { | ||
SettingsService.createOrUpdateLayer(req.params.type, req.body).then( | ||
(data) => { | ||
// Can't use handleStandardResponse here because we need to | ||
// output only data.newLayer on success – not the entire data. | ||
if (data.error) res.status(500).send(data.error.toString()); | ||
else { | ||
// r.status will be either 200 (layer updated) or 201 (layer created) | ||
res.status(data.status).json(data.newLayer); | ||
|
||
ael.info( | ||
`${res.locals.authUser} ${ | ||
data.status === 201 ? "added" : "updated" | ||
} ${req.params.type} with id ${data.newLayer.id} ("${ | ||
data.newLayer.caption | ||
}")` | ||
); | ||
} | ||
} | ||
); | ||
} | ||
|
||
deleteLayerFromStore(req, res) { | ||
SettingsService.deleteLayer(req.params.type, req.params.layerId).then( | ||
(data) => { | ||
handleStandardResponse(res, data); | ||
!data.error && | ||
ael.info( | ||
`${res.locals.authUser} deleted ${req.params.type} with id ${req.params.layerId}` | ||
); | ||
} | ||
); | ||
} | ||
} | ||
export default new Controller(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import * as express from "express"; | ||
import controller from "./controller"; | ||
import restrictAdmin from "../../middlewares/restrict.admin"; | ||
|
||
export default express | ||
.Router() | ||
.use(restrictAdmin) // We will not allow any of the following routes unless user is admin | ||
// We use the same controller method to handle these 3 | ||
// PUT requests, as they all write into the same file, | ||
// only different portions of it. | ||
.put("/layermenu", controller.putSettingsToMapFile) | ||
.put("/mapsettings", controller.putSettingsToMapFile) | ||
.put("/toolsettings", controller.putSettingsToMapFile) | ||
.put("/update/:map/:tool", controller.updateMapTool) | ||
.post("/:type", controller.putLayerOfType) // Will add new each time it's called | ||
.put("/:type", controller.putLayerOfType) // Will overwrite existing and the result is idempotent | ||
// Handle layer removal | ||
.delete("/:type/:layerId", controller.deleteLayerFromStore); |
Oops, something went wrong.