added group owners

This commit is contained in:
2020-12-31 09:53:44 -05:00
parent 2c89d42569
commit cb51fae2f6
4 changed files with 250 additions and 59 deletions
+68
View File
@@ -20,6 +20,7 @@ async function getGroups(client, member){
return groups.map(function(group){ return groups.map(function(group){
if(!Array.isArray(group.member)) group.member = [group.member]; if(!Array.isArray(group.member)) group.member = [group.member];
if(!Array.isArray(group.owner)) group.owner = [group.owner];
return group return group
}); });
}catch(error){ }catch(error){
@@ -81,6 +82,41 @@ async function removeMember(client, group, user){
} }
} }
async function addOwner(client, group, user){
try{
await client.modify(group.dn, [
new Change({
operation: 'add',
modification: new Attribute({
type: 'owner',
values: [user.dn]
})
}),
]);
}catch(error){
// if(error = "TypeOrValueExistsError"){
// console.error('addMember error skipped', error)
// return ;
// }
throw error;
}
}
async function removeOwner(client, group, user){
try{
await client.modify(group.dn, [
new Change({
operation: 'delete',
modification: new Attribute({
type: 'owner',
values: [user.dn]
})}),
]);
}catch(error){
if(error = "TypeOrValueExistsError")return ;
throw error;
}
}
var Group = {}; var Group = {};
@@ -133,6 +169,7 @@ Group.get = async function(data){
await client.unbind(); await client.unbind();
if(!Array.isArray(group.member)) group.member = [group.member]; if(!Array.isArray(group.member)) group.member = [group.member];
if(!Array.isArray(group.owner)) group.owner = [group.owner];
if(group){ if(group){
let obj = Object.create(this); let obj = Object.create(this);
@@ -196,6 +233,37 @@ Group.removeMember = async function(user){
} }
}; };
Group.addOwner = async function(user){
try{
await client.bind(conf.bindDN, conf.bindPassword);
await addOwner(client, this, user);
await client.unbind();
return this;
}catch(error){
throw error;
}
};
Group.removeOwner = async function(user){
try{
await client.bind(conf.bindDN, conf.bindPassword);
await removeOwner(client, this, user);
await client.unbind();
return this;
}catch(error){
throw error;
}
};
Group.remove = async function(){ Group.remove = async function(){
try{ try{
await client.bind(conf.bindDN, conf.bindPassword); await client.bind(conf.bindDN, conf.bindPassword);
+47 -1
View File
@@ -2,7 +2,8 @@
const router = require('express').Router(); const router = require('express').Router();
const {User} = require('../models/user_ldap'); const {User} = require('../models/user_ldap');
const {Group} = require('../models/group_ldap'); const {Group} = require('../models/group_ldap');
const permission = require('../utils/permission');
router.get('/', async function(req, res, next){ router.get('/', async function(req, res, next){
try{ try{
@@ -18,6 +19,9 @@ router.get('/', async function(req, res, next){
router.post('/', async function(req, res, next){ router.post('/', async function(req, res, next){
try{ try{
await permission.byGroup(req.user, ['app_sso_admin']);
req.body.owner = req.user.dn; req.body.owner = req.user.dn;
return res.json({ return res.json({
results: await Group.add(req.body), results: await Group.add(req.body),
@@ -38,8 +42,44 @@ router.get('/:name', async function(req, res, next){
} }
}); });
router.put('/owner/:name/:uid', async function(req, res, next){
try{
// await permission.byGroup(req.user, ['app_sso_admin']);
var group = await Group.get(req.params.name);
var user = await User.get(req.params.uid);
return res.json({
results: group.addOwner(user),
message: `Added owner ${req.params.uid} to ${req.params.name} group.`
});
}catch(error){
next(error);
}
});
router.delete('/owner/:name/:uid', async function(req, res, next){
try{
await permission.byGroup(req.user, ['app_sso_admin']);
var group = await Group.get(req.params.name);
var user = await User.get(req.params.uid);
return res.json({
results: group.removeOwner(user),
message: `Removed Owner ${req.params.uid} from ${req.params.name} group.`
});
}catch(error){
next(error);
}
});
router.put('/:name/:uid', async function(req, res, next){ router.put('/:name/:uid', async function(req, res, next){
try{ try{
// await permission.byGroup(req.user, ['app_sso_admin']);
var group = await Group.get(req.params.name); var group = await Group.get(req.params.name);
var user = await User.get(req.params.uid); var user = await User.get(req.params.uid);
return res.json({ return res.json({
@@ -53,6 +93,9 @@ router.put('/:name/:uid', async function(req, res, next){
router.delete('/:name/:uid', async function(req, res, next){ router.delete('/:name/:uid', async function(req, res, next){
try{ try{
await permission.byGroup(req.user, ['app_sso_admin']);
var group = await Group.get(req.params.name); var group = await Group.get(req.params.name);
var user = await User.get(req.params.uid); var user = await User.get(req.params.uid);
return res.json({ return res.json({
@@ -66,6 +109,9 @@ router.delete('/:name/:uid', async function(req, res, next){
router.delete('/:name', async function(req, res, next){ router.delete('/:name', async function(req, res, next){
try{ try{
await permission.byGroup(req.user, ['app_sso_admin']);
var group = await Group.get(req.params.name); var group = await Group.get(req.params.name);
return res.json({ return res.json({
removed: await group.remove(), removed: await group.remove(),
+134 -51
View File
@@ -1,46 +1,111 @@
<%- include('top') %> <%- include('top') %>
<script id="rowTemplate" type="text/html"> <script id="rowTemplate" type="text/html">
<p> <div id="group-card-{{cn}}" class="card shadow">
<div class="card shadow">
<div class="card-header"> <div class="card-header">
<i class="fad fa-users-class"></i> <h5>
Group: {{ cn }} <i class="fad fa-users-class"></i>
Group: {{ cn }}
</h5>
<ul class="nav nav-tabs card-header-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="group-members-tab-{{cn}}" data-toggle="tab" href="#group-memmbers-{{cn}}" role="tab" aria-controls="member" aria-selected="true">
<i class="fad fa-users"></i>
Members
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="group-admins-tab-{{cn}}" data-toggle="tab" href="#group-admins-{{cn}}" role="tab" aria-controls="admin" aria-selected="false">
<i class="fad fa-users-crown"></i>
Owners
</a>
</li>
<li class="nav-item float-right">
</li>
</ul>
</div> </div>
<div class="card-header actionMessage" style="display:none"></div>
<div class="card-body"> <div class="card-body">
<p> <p>
{{ description }} {{ description }}
</p> </p>
<p> <div class="tab-content" id="myTabContent">
<ul class="list-group"> <div class="tab-pane fade show active" id="group-memmbers-{{cn}}" role="tabpanel" aria-labelledby="member-tab">
{{ #member }} <p>
<li class="list-group-item shadow"> <ul class="list-group">
<i class="fad fa-user"></i> {{ uid }} {{ #member }}
<button type="button" action="group/{{groupCN}}/{{uid}}" method="delete" onclick="formAJAX(this)" evalAJAX="tableAJAX(data.message)" class="btn btn-sm btn-danger float-right"> <li id="group-card-{{cn}}-{{uid}}" class="list-group-item shadow">
<i class="fad fa-user-slash"></i> <i class="fad fa-user"></i> {{ uid }}
<button type="button" action="group/{{groupCN}}/{{uid}}" method="delete" onclick="formAJAX(this)" evalAJAX="addedUser(data.message, '{{groupCN}}', '{{uid}}', $form)" class="btn btn-sm btn-danger float-right">
<i class="fad fa-user-slash"></i>
</button>
</li>
{{ /member }}
</ul>
</p>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="group_add_member" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fad fa-user-plus"></i>
</button> </button>
</li> <div class="dropdown-menu shadow-lg" aria-labelledby="group_add_member">
{{ /member }} {{ #toAdd }}{{#.}}
</ul> <a class="dropdown-item" action="group/{{groupCN}}/{{uid}}" method="put" onclick="formAJAX(this)" evalAJAX="addedUser(data.message, '{{groupCN}}', '{{uid}}', $form);">
</p> <i class="fad fa-user"></i> {{uid}}
</a>
{{/.}}{{ /toAdd }}
</div>
</div>
</div>
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <div class="tab-pane fade" id="group-admins-{{cn}}" role="tabpanel" aria-labelledby="admin-tab">
<i class="fad fa-user-plus"></i> <p>
</button> <ul class="list-group">
<div class="dropdown-menu shadow-lg" aria-labelledby="dropdownMenuButton"> {{ #owner }}
{{ #toAdd }}{{#.}} <li class="list-group-item shadow">
<a class="dropdown-item" action="group/{{groupCN}}/{{uid}}" method="put" onclick="formAJAX(this)" evalAJAX="tableAJAX(data.message)"> <i class="fad fa-user"></i> {{ uid }}
<i class="fad fa-user"></i> {{uid}} <button type="button" action="group/owner/{{groupCN}}/{{uid}}" method="delete" onclick="formAJAX(this)" evalAJAX="addedUser(data.message, '{{groupCN}}', '{{uid}}', $form)" class="btn btn-sm btn-danger float-right">
</a> <i class="fad fa-user-slash"></i>
{{/.}}{{ /toAdd }} </button>
</li>
{{ /owner }}
</ul>
</p>
<div class="dropdown float-left">
<button class="btn btn-secondary dropdown-toggle" type="button" id="group_add_admin" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fad fa-user-crown"></i>
</button>
<div class="dropdown-menu shadow-lg" aria-labelledby="group_add_admin">
{{ #toAddOwner }}{{#.}}
<a class="dropdown-item" action="group/owner/{{groupCN}}/{{uid}}" method="put" onclick="formAJAX(this)" evalAJAX="addedUser(data.message, '{{groupCN}}', '{{uid}}', $form)">
<i class="fad fa-user"></i> {{uid}}
</a>
{{/.}}{{ /toAddOwner }}
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<div class="float-left">
Created: {{createTimestamp}}<br />
Last Mortified: {{modifyTimestamp}}
</div>
<div class="float-right">
<button type="button" onclick="" class="btn btn-warning btn-lg shadow">
<i class="fad fa-edit"></i>
</button>
<button type="button" onclick="app.group.remove({cn: '{{cn}}'}, function(){tableAJAX('Group {{cn}} deleted.')})" class="btn btn-danger btn-lg">
<i class="fad fa-trash"></i>
</button>
</div> </div>
<button type="button" onclick="app.group.remove({cn: '{{cn}}'}, function(){tableAJAX('Group {{cn}} deleted.')})" class="btn btn-danger float-right">
<i class="fad fa-trash"></i>
</button>
</div> </div>
</div> </div>
</p> <br/>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
@@ -50,11 +115,24 @@
app.user.list(function(error, data){ app.user.list(function(error, data){
userlist = data.results; userlist = data.results;
callback() callback()
}) });
} }
function addedUser(message, group, user, $form){
tableAJAX(null, function(){
app.util.actionMessage(message, $("#group-card-"+group), 'success');
function tableAJAX(actionMessage){
$('a[href="#'+$form.closest('.tab-pane').attr('id')+'"]').tab('show');
setTimeout(function(group){
$("body,html").animate({
scrollTop: $("#group-card-" + group).offset().top
}, 0);
}, 400, group);
});
}
function tableAJAX(actionMessage, callback){
var rowTemplate = $('#rowTemplate').html(); var rowTemplate = $('#rowTemplate').html();
var $target = $('#tableAJAX'); var $target = $('#tableAJAX');
@@ -62,25 +140,42 @@
app.util.actionMessage('Refreshing user list...', $target); app.util.actionMessage('Refreshing user list...', $target);
app.group.list(function(error, data){ app.group.list(function(error, data){
$.each( data.results, function(key, value) { var out = ''
$.each(data.results, function(key, value) {
// console.log(value.member)
value.toAdd = userlist.map(function(user){ value.toAdd = userlist.map(function(user){
if(!value.member.includes(user.dn)) return user; if(!value.member.includes(user.dn)) return user;
}) })
value.toAddOwner = userlist.map(function(user){
if(!value.owner.includes(user.dn)) return user;
})
value.member = value.member.map(function(user){ value.member = value.member.map(function(user){
return { return {
dn: user, dn: user,
uid: user.match(/cn=[a-zA-Z0-9\_\-\@\.]+/)[0].replace('cn=', '') uid: user.match(/cn=[a-zA-Z0-9\_\-\@\.]+/)[0].replace('cn=', '')
} }
}) })
value.owner = value.owner.map(function(user){
return {
dn: user,
uid: user.match(/cn=[a-zA-Z0-9\_\-\@\.]+/)[0].replace('cn=', '')
}
})
value.createTimestamp = moment(value.createTimestamp, "YYYYMMDDHHmmssZ").fromNow();
value.modifyTimestamp = moment(value.modifyTimestamp, "YYYYMMDDHHmmssZ").fromNow();
value.groupCN = value.cn; value.groupCN = value.cn;
user_row = Mustache.render(rowTemplate, value); out += Mustache.render(rowTemplate, value);
$target.append(user_row);
}); });
$target.fadeIn('slow'); $target.html(out);
$target.fadeIn('slow', ($.isFunction(callback) ? callback: function(){})());
app.util.actionMessage(actionMessage || '', $target, 'info'); app.util.actionMessage(actionMessage || '', $target, 'info');
@@ -116,19 +211,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-8"> <div class="col-md-8" id="tableAJAX">
<div class="card shadow-lg">
<div class="card-header">
<i class="fad fa-users-class"></i>
Group list
</div>
<div class="card-header actionMessage" style="display:none">
</div>
<div class="card-body">
<div class="" id="tableAJAX">
</div>
</div>
</div>
</div> </div>
</div> </div>
<%- include('bottom') %> <%- include('bottom') %>
+1 -7
View File
@@ -220,7 +220,7 @@
<a href="https://rdp.vm42.us" target="_blank" class="text-dark"> <a href="https://rdp.vm42.us" target="_blank" class="text-dark">
<li class="list-group-item text-dark"> <li class="list-group-item text-dark">
<i class="fad fa-desktop"></i> <i class="fad fa-desktop"></i>
Virtual Desk Top Virtual Desktops
</li> </li>
</a> </a>
<a href="https://pve.admin.vm42.us" target="_blank" class="text-dark"> <a href="https://pve.admin.vm42.us" target="_blank" class="text-dark">
@@ -272,12 +272,6 @@
</button> </button>
</form> </form>
<!-- <button type="button" onclick="app.user.remove({uid: currentUser.uid}, function(){app.util.actionMessage('username {{uid}} delete.', $(this), 'danger')})" class="shadow btn btn-danger btn-lg float-right">
<i class="fad fa-user-slash"></i>
</button> -->
</div> </div>
</div> </div>