'use strict'; const router = require('express').Router(); const { OAuthClient } = require('../models/oauth_client'); const permission = require('../utils/permission'); const ADMIN_GROUP = 'app_sso_oauth_admin'; router.get('/', async function(req, res, next) { try { await permission.byGroup(req.user, [ADMIN_GROUP]); return res.json({ results: await OAuthClient.listDetail() }); } catch(error) { next(error); } }); router.post('/', async function(req, res, next) { try { await permission.byGroup(req.user, [ADMIN_GROUP]); req.body.created_by = req.user.uid; // Parse redirect_uris if sent as newline-separated string from the form if (typeof req.body.redirect_uris === 'string') { req.body.redirect_uris = req.body.redirect_uris.split('\n').map(s => s.trim()).filter(Boolean); } // Parse scopes if sent as space-separated string if (typeof req.body.scopes === 'string') { req.body.scopes = req.body.scopes.split(' ').map(s => s.trim()).filter(Boolean); } // Parse allowed_groups if sent as newline-separated string if (typeof req.body.allowed_groups === 'string') { req.body.allowed_groups = req.body.allowed_groups.split('\n').map(s => s.trim()).filter(Boolean); } // jQuery serializeObject sends nested fields as "token_lifetime[access_token]" if (req.body['token_lifetime[access_token]'] || req.body['token_lifetime[refresh_token]']) { req.body.token_lifetime = { access_token: Number(req.body['token_lifetime[access_token]']) || 3600, refresh_token: Number(req.body['token_lifetime[refresh_token]']) || 2592000, }; delete req.body['token_lifetime[access_token]']; delete req.body['token_lifetime[refresh_token]']; } const client = await OAuthClient.add(req.body); const result = client.toJSON ? client.toJSON() : { ...client }; result.client_id = client.client_id || client.id; return res.json({ results: result, client_secret: client._raw_secret, message: `OAuth client '${client.name}' created. Save the client secret — it will not be shown again.`, }); } catch(error) { next(error); } }); router.get('/:client_id', async function(req, res, next) { try { await permission.byGroup(req.user, [ADMIN_GROUP]); return res.json({ results: await OAuthClient.get(req.params.client_id) }); } catch(error) { next(error); } }); router.put('/:client_id', async function(req, res, next) { try { await permission.byGroup(req.user, [ADMIN_GROUP]); const client = await OAuthClient.get(req.params.client_id); if (typeof req.body.redirect_uris === 'string') { req.body.redirect_uris = req.body.redirect_uris.split('\n').map(s => s.trim()).filter(Boolean); } if (typeof req.body.scopes === 'string') { req.body.scopes = req.body.scopes.split(' ').map(s => s.trim()).filter(Boolean); } if (typeof req.body.allowed_groups === 'string') { req.body.allowed_groups = req.body.allowed_groups.split('\n').map(s => s.trim()).filter(Boolean); } return res.json({ results: await client.update(req.body), message: `OAuth client '${client.name}' updated.`, }); } catch(error) { next(error); } }); router.delete('/:client_id', async function(req, res, next) { try { await permission.byGroup(req.user, [ADMIN_GROUP]); const client = await OAuthClient.get(req.params.client_id); await client.delete(); return res.json({ client_id: req.params.client_id, message: `OAuth client '${client.name}' deleted.`, }); } catch(error) { next(error); } }); router.post('/:client_id/rotate', async function(req, res, next) { try { await permission.byGroup(req.user, [ADMIN_GROUP]); const client = await OAuthClient.get(req.params.client_id); const new_secret = await client.rotateSecret(); return res.json({ client_secret: new_secret, message: `Client secret rotated for '${client.name}'. Save it — it will not be shown again.`, }); } catch(error) { next(error); } }); module.exports = router;