diff --git a/src/app.js b/src/app.js index d1866a85b..676355071 100644 --- a/src/app.js +++ b/src/app.js @@ -42,6 +42,15 @@ const { deleteNarrative, } = endpoints.sources; +const { + getGroupLogo, + putGroupLogo, + deleteGroupLogo, + getGroupOverview, + putGroupOverview, + deleteGroupOverview, +} = endpoints.groups; + const { CoreSource, CoreStagingSource, @@ -305,6 +314,18 @@ app.routeAsync("/groups/:groupName") app.use("/groups/:groupName/settings", endpoints.groups.setGroup(req => req.params.groupName)); +app.routeAsync("/groups/:groupName/settings/logo") + .getAsync(getGroupLogo) + .putAsync(putGroupLogo) + .deleteAsync(deleteGroupLogo) +; + +app.routeAsync("/groups/:groupName/settings/overview") + .getAsync(getGroupOverview) + .putAsync(putGroupOverview) + .deleteAsync(deleteGroupOverview) +; + app.route("/groups/:groupName/settings/*") .all(() => { throw new NotFound(); }); diff --git a/src/endpoints/groups.js b/src/endpoints/groups.js index a5f106c38..463122713 100644 --- a/src/endpoints/groups.js +++ b/src/endpoints/groups.js @@ -1,5 +1,7 @@ import * as authz from "../authz/index.js"; import { Group } from "../groups.js"; +import {contentTypesProvided, contentTypesConsumed} from "../negotiate.js"; +import {deleteByUrls, proxyFromUpstream, proxyToUpstream} from "../upstream.js"; const setGroup = (nameExtractor) => (req, res, next) => { @@ -12,6 +14,147 @@ const setGroup = (nameExtractor) => (req, res, next) => { }; +/* Group customizations + */ + + +/* Group logo + */ + + +/* GET + */ +const getGroupLogo = contentTypesProvided([ + ["image/png", sendGroupLogo], +]); + + +/* PUT + */ +const putGroupLogo = contentTypesConsumed([ + ["image/png", receiveGroupLogo], +]); + + +/* DELETE + */ +const deleteGroupLogo = async (req, res) => { + authz.assertAuthorized(req.user, authz.actions.Write, req.context.group); + + const method = "DELETE"; + const url = await req.context.group.source.urlFor("group-logo.png", method); + await deleteByUrls([url]); + + return res.status(204).end(); +}; + + +/* Group overview + */ + + +/* GET + */ +const getGroupOverview = contentTypesProvided([ + ["text/markdown", sendGroupOverview], + ["text/plain", sendGroupOverview], +]); + + +/* PUT + */ +const putGroupOverview = contentTypesConsumed([ + ["text/markdown", receiveGroupOverview], +]); + + +/* DELETE + */ +const deleteGroupOverview = async (req, res) => { + authz.assertAuthorized(req.user, authz.actions.Write, req.context.group); + + const method = "DELETE"; + const url = await req.context.group.source.urlFor("group-overview.md", method); + await deleteByUrls([url]); + + return res.status(204).end(); +}; + + +/** + * An Express endpoint that sends a group overview determined by the request. + * + * @param {express.request} req - Express-style request instance + * @param {express.response} res - Express-style response instance + * @returns {expressEndpointAsync} + */ +async function sendGroupOverview(req, res) { + authz.assertAuthorized(req.user, authz.actions.Read, req.context.group); + + return await proxyFromUpstream(req, res, + await req.context.group.source.urlFor("group-overview.md"), + "text/markdown" + ); +} + + +/** + * An Express endpoint that receives a group overview determined by the request. + * + * @param {express.request} req - Express-style request instance + * @param {express.response} res - Express-style response instance + * @returns {expressEndpointAsync} + */ +async function receiveGroupOverview(req, res) { + authz.assertAuthorized(req.user, authz.actions.Write, req.context.group); + + return await proxyToUpstream(req, res, + async (method, headers) => await req.context.group.source.urlFor("group-overview.md", method, headers), + "text/markdown" + ); +} + + +/** + * An Express endpoint that sends a group logo determined by the request. + * + * @param {express.request} req - Express-style request instance + * @param {express.response} res - Express-style response instance + * @returns {expressEndpointAsync} + */ +async function sendGroupLogo(req, res) { + authz.assertAuthorized(req.user, authz.actions.Read, req.context.group); + + return await proxyFromUpstream(req, res, + await req.context.group.source.urlFor("group-logo.png"), + "image/png" + ); +} + + +/** + * An Express endpoint that receives a group logo determined by the request. + * + * @param {express.request} req - Express-style request instance + * @param {express.response} res - Express-style response instance + * @returns {expressEndpointAsync} + */ +async function receiveGroupLogo(req, res) { + authz.assertAuthorized(req.user, authz.actions.Write, req.context.group); + + return await proxyToUpstream(req, res, + async (method, headers) => await req.context.group.source.urlFor("group-logo.png", method, headers), + "image/png" + ); +} + + export { setGroup, + getGroupLogo, + putGroupLogo, + deleteGroupLogo, + getGroupOverview, + putGroupOverview, + deleteGroupOverview, };