diff --git a/nodejs/routes/host.js b/nodejs/routes/host.js index 424b7d4..ccfe75d 100755 --- a/nodejs/routes/host.js +++ b/nodejs/routes/host.js @@ -1,7 +1,10 @@ 'use strict'; const router = require('express').Router(); -const {Host, Domain} = require('../models').models; +const conf = require('@simpleworkjs/conf'); +const {Host, Domain, User} = require('../models').models; +const {LocalGroup} = require('../models/local_group'); +const {Permission} = require('../models/permission'); const authz = require('../middleware/authz'); const {normalizeHostFeatures} = require('../utils/host_features'); const {collectHostFieldErrors} = require('../utils/hostname_validate'); @@ -25,6 +28,31 @@ function hashHostSecrets(body){ } } +// Autocomplete source for the per-host auth allow-lists (SSO users/groups). +// Available to any authenticated host editor (not just global admins). Groups +// are derived from local groups, existing permission group-subjects, and the +// conf.auth admin/role-map groups. +router.get('/auth-suggestions', async function(req, res, next){ + try{ + let users = []; + try{ users = (await User.list()) || []; }catch(error){ /* none */ } + + let groups = new Set(); + try{ for(let g of await LocalGroup.list()) groups.add(g); }catch(error){ /* none */ } + try{ + for(let p of await Permission.listDetail()){ + if(p.subjectType === 'group' && p.subject) groups.add(p.subject); + } + }catch(error){ /* none */ } + for(let g of (conf.auth && conf.auth.adminGroups) || []) groups.add(g); + for(let g of Object.keys((conf.auth && conf.auth.groupRoleMap) || {})) groups.add(g); + + return res.json({users, groups: [...groups].sort()}); + }catch(error){ + return next(error); + } +}); + router.get('/', async function(req, res, next){ try{ let results = await Model[req.query.detail ? "listDetail" : "list"](); diff --git a/nodejs/views/hosts.ejs b/nodejs/views/hosts.ejs index 3953c96..918bbfa 100755 --- a/nodejs/views/hosts.ejs +++ b/nodejs/views/hosts.ejs @@ -98,6 +98,29 @@ bootstrap.Tab.getOrCreateInstance(document.getElementById(id)).show(); } + // Append a picked/typed value to one of the SSO allow-list textareas (deduped). + function allowListAdd(input, name){ + let val = (input.value || '').trim(); + if(!val) return; + let $ta = $('#hostForm textarea[name="' + name + '"]'); + let lines = ($ta.val() || '').split(/\r?\n/).map(s => s.trim()).filter(Boolean); + if(lines.indexOf(val) === -1) lines.push(val); + $ta.val(lines.join('\n')); + input.value = ''; + input.focus(); + } + + // Fill the user/group datalists that back the allow-list autocomplete. + function hostLoadAuthSuggestions(){ + app.api.get('host/auth-suggestions', function(error, data){ + if(error || !data) return; + let $u = $('#hostSsoUsers').empty(); + for(let u of (data.users || [])) $u.append($('