user edit
This commit is contained in:
parent
0889832efc
commit
b8f632e644
@ -7,11 +7,14 @@ const client = new Client({
|
||||
url: conf.url,
|
||||
});
|
||||
|
||||
async function getGroups(client){
|
||||
async function getGroups(client, member){
|
||||
try{
|
||||
|
||||
let memberFilter = member ? `(member=${member})`: ''
|
||||
|
||||
let groups = (await client.search(conf.groupBase, {
|
||||
scope: 'sub',
|
||||
filter: '(&(objectClass=groupOfNames))',
|
||||
filter: `(&(objectClass=groupOfNames)${memberFilter})`,
|
||||
attributes: ['*', 'createTimestamp', 'modifyTimestamp'],
|
||||
})).searchEntries;
|
||||
|
||||
@ -81,11 +84,11 @@ async function removeMember(client, group, user){
|
||||
|
||||
var Group = {};
|
||||
|
||||
Group.list = async function(){
|
||||
Group.list = async function(member){
|
||||
try{
|
||||
await client.bind(conf.bindDN, conf.bindPassword);
|
||||
|
||||
let groups = await getGroups(client)
|
||||
let groups = await getGroups(client, member)
|
||||
|
||||
await client.unbind();
|
||||
|
||||
@ -95,11 +98,11 @@ Group.list = async function(){
|
||||
}
|
||||
}
|
||||
|
||||
Group.listDetail = async function(){
|
||||
Group.listDetail = async function(member){
|
||||
try{
|
||||
await client.bind(conf.bindDN, conf.bindPassword);
|
||||
|
||||
let groups = await getGroups(client)
|
||||
let groups = await getGroups(client, member)
|
||||
|
||||
await client.unbind();
|
||||
|
||||
@ -207,7 +210,4 @@ Group.remove = async function(){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = {Group};
|
||||
|
@ -12,75 +12,84 @@ const client = new Client({
|
||||
});
|
||||
|
||||
async function addPosixGroup(client, data){
|
||||
|
||||
try{
|
||||
const groups = (await client.search(conf.groupBase, {
|
||||
scope: 'sub',
|
||||
filter: '(&(objectClass=posixGroup))',
|
||||
})).searchEntries;
|
||||
const groups = (await client.search(conf.groupBase, {
|
||||
scope: 'sub',
|
||||
filter: '(&(objectClass=posixGroup))',
|
||||
})).searchEntries;
|
||||
|
||||
data.gidNumber = (Math.max(...groups.map(i => i.gidNumber))+1)+'';
|
||||
data.gidNumber = (Math.max(...groups.map(i => i.gidNumber))+1)+'';
|
||||
|
||||
await client.add(`cn=${data.cn},${conf.groupBase}`, {
|
||||
cn: data.cn,
|
||||
gidNumber: data.gidNumber,
|
||||
objectclass: [ 'posixGroup', 'top' ]
|
||||
});
|
||||
await client.add(`cn=${data.cn},${conf.groupBase}`, {
|
||||
cn: data.cn,
|
||||
gidNumber: data.gidNumber,
|
||||
objectclass: [ 'posixGroup', 'top' ]
|
||||
});
|
||||
|
||||
return data;
|
||||
return data;
|
||||
|
||||
}catch(error){
|
||||
throw error;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function addPosixAccount(client, data){
|
||||
try{
|
||||
const people = (await client.search(conf.userBase, {
|
||||
scope: 'sub',
|
||||
filter: conf.userFilter,
|
||||
})).searchEntries;
|
||||
const people = (await client.search(conf.userBase, {
|
||||
scope: 'sub',
|
||||
filter: conf.userFilter,
|
||||
})).searchEntries;
|
||||
|
||||
data.uidNumber = (Math.max(...people.map(i => i.uidNumber))+1)+'';
|
||||
data.uidNumber = (Math.max(...people.map(i => i.uidNumber))+1)+'';
|
||||
|
||||
await client.add(`cn=${data.cn},${conf.userBase}`, {
|
||||
cn: data.cn,
|
||||
sn: data.sn,
|
||||
uid: data.uid,
|
||||
uidNumber: data.uidNumber,
|
||||
gidNumber: data.gidNumber,
|
||||
givenName: data.givenName,
|
||||
mail: data.mail,
|
||||
mobile: data.mobile,
|
||||
loginShell: data.loginShell,
|
||||
homeDirectory: data.homeDirectory,
|
||||
userPassword: data.userPassword,
|
||||
objectclass: [ 'inetOrgPerson', 'posixAccount', 'top' ]
|
||||
});
|
||||
await client.add(`cn=${data.cn},${conf.userBase}`, {
|
||||
cn: data.cn,
|
||||
sn: data.sn,
|
||||
uid: data.uid,
|
||||
uidNumber: data.uidNumber,
|
||||
gidNumber: data.gidNumber,
|
||||
givenName: data.givenName,
|
||||
mail: data.mail,
|
||||
mobile: data.mobile,
|
||||
loginShell: data.loginShell,
|
||||
homeDirectory: data.homeDirectory,
|
||||
userPassword: data.userPassword,
|
||||
description: data.description || ' ',
|
||||
sudoHost: 'ALL',
|
||||
sudoCommand: 'ALL',
|
||||
sudoUser: data.uid,
|
||||
sshPublicKey: data.sshPublicKey,
|
||||
objectclass: ['inetOrgPerson', 'sudoRole', 'ldapPublicKey', 'posixAccount', 'top' ]
|
||||
});
|
||||
|
||||
return data
|
||||
return data
|
||||
|
||||
}catch(error){
|
||||
throw error;
|
||||
throw error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function addLdapUser(client, data){
|
||||
|
||||
var group;
|
||||
|
||||
try{
|
||||
data.uid = `${data.givenName[0]}${data.sn}`;
|
||||
data.cn = data.uid;
|
||||
data.loginShell = '/bin/bash';
|
||||
data.homeDirectory= `/home/${data.uid}`;
|
||||
data.userPassword = '{MD5}'+crypto.createHash('md5').update(data.userPassword, "binary").digest('base64');
|
||||
data.uid = `${data.givenName[0]}${data.sn}`;
|
||||
data.cn = data.uid;
|
||||
data.loginShell = '/bin/bash';
|
||||
data.homeDirectory= `/home/${data.uid}`;
|
||||
data.userPassword = '{MD5}'+crypto.createHash('md5').update(data.userPassword, "binary").digest('base64');
|
||||
|
||||
data = await addPosixGroup(client, data);
|
||||
data = await addPosixAccount(client, data);
|
||||
group = await addPosixGroup(client, data);
|
||||
data = await addPosixAccount(client, group);
|
||||
|
||||
return data;
|
||||
return data;
|
||||
|
||||
}catch(error){
|
||||
throw error;
|
||||
await deleteLdapDN(client, `cn=${data.uid},${conf.groupBase}`, true);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,9 +102,19 @@ async function deleteLdapUser(client, data){
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteLdapDN(client, dn, ignoreError){
|
||||
try{
|
||||
client.del(dn)
|
||||
}catch(error){
|
||||
if(!ignoreError) throw error;
|
||||
console.error('ERROR: deleteLdapDN', error)
|
||||
}
|
||||
}
|
||||
|
||||
const user_parse = function(data){
|
||||
if(data[conf.userNameAttribute]){
|
||||
data.username = data[conf.userNameAttribute]
|
||||
data.userPassword = undefined;
|
||||
}
|
||||
|
||||
return data;
|
||||
@ -152,7 +171,7 @@ User.listDetail = async function(){
|
||||
}
|
||||
};
|
||||
|
||||
User.get = async function(data, value){
|
||||
User.get = async function(data, key){
|
||||
try{
|
||||
if(typeof data !== 'object'){
|
||||
let uid = data;
|
||||
@ -160,15 +179,14 @@ User.get = async function(data, value){
|
||||
data.uid = uid;
|
||||
}
|
||||
|
||||
|
||||
await client.bind(conf.bindDN, conf.bindPassword);
|
||||
|
||||
data.searchKey = data.searchKey || conf.userNameAttribute;
|
||||
data.searchKey = data.searchKey || key || conf.userNameAttribute;
|
||||
data.searchValue = data.searchValue || data.uid;
|
||||
|
||||
let filter = `(&${conf.userFilter}(${data.searchKey}=${data.searchValue}))`;
|
||||
|
||||
console.log('get filter', filter)
|
||||
|
||||
const res = await client.search(conf.userBase, {
|
||||
scope: 'sub',
|
||||
filter: filter,
|
||||
@ -196,10 +214,10 @@ User.get = async function(data, value){
|
||||
}
|
||||
};
|
||||
|
||||
User.exists = async function(data){
|
||||
User.exists = async function(data, key){
|
||||
// Return true or false if the requested entry exists ignoring error's.
|
||||
try{
|
||||
await this.get(data);
|
||||
await this.get(data, key);
|
||||
|
||||
return true
|
||||
}catch(error){
|
||||
@ -241,6 +259,35 @@ User.add = async function(data) {
|
||||
}
|
||||
};
|
||||
|
||||
User.update = async function(data){
|
||||
try{
|
||||
let editableFeilds = ['mobile', 'sshPublicKey', 'description'];
|
||||
|
||||
await client.bind(conf.bindDN, conf.bindPassword);
|
||||
|
||||
for(let field of editableFeilds){
|
||||
if(data[field]){
|
||||
await client.modify(this.dn, [
|
||||
new Change({
|
||||
operation: 'replace',
|
||||
modification: new Attribute({
|
||||
type: field,
|
||||
values: [data[field]]
|
||||
})
|
||||
}),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
await client.unbind()
|
||||
|
||||
return this;
|
||||
|
||||
}catch(error){
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
User.addByInvite = async function(data){
|
||||
try{
|
||||
let token = await InviteToken.get(data.token);
|
||||
@ -270,6 +317,11 @@ User.addByInvite = async function(data){
|
||||
|
||||
User.verifyEmail = async function(data){
|
||||
try{
|
||||
|
||||
let exists = await this.exists(data.mail, 'mail');
|
||||
|
||||
if(exists) throw new Error('EmailInUse');
|
||||
|
||||
let token = await InviteToken.get(data.token);
|
||||
await token.update({mail: data.mail})
|
||||
await Mail.sendTemplate(
|
||||
@ -294,8 +346,6 @@ User.passwordReset = async function(url, mail){
|
||||
searchValue: mail
|
||||
});
|
||||
|
||||
console.log('user', user)
|
||||
|
||||
let token = await PasswordResetToken.add(user);
|
||||
|
||||
await Mail.sendTemplate(
|
||||
@ -338,11 +388,11 @@ User.setPassword = async function(data){
|
||||
|
||||
await client.modify(this.dn, [
|
||||
new Change({
|
||||
operation: 'replace',
|
||||
modification: new Attribute({
|
||||
type: 'userPassword',
|
||||
values: ['{MD5}'+crypto.createHash('md5').update(data.userPassword, "binary").digest('base64')]
|
||||
})}),
|
||||
operation: 'replace',
|
||||
modification: new Attribute({
|
||||
type: 'userPassword',
|
||||
values: ['{MD5}'+crypto.createHash('md5').update(data.userPassword, "binary").digest('base64')]
|
||||
})}),
|
||||
]);
|
||||
|
||||
await client.unbind();
|
||||
|
@ -86,6 +86,7 @@ app.api = (function(app){
|
||||
})(app)
|
||||
|
||||
app.auth = (function(app) {
|
||||
var user = {}
|
||||
function setToken(token){
|
||||
localStorage.setItem('APIToken', token);
|
||||
}
|
||||
@ -97,6 +98,7 @@ app.auth = (function(app) {
|
||||
function isLoggedIn(callack){
|
||||
if(getToken()){
|
||||
return app.api.get('user/me', function(error, data){
|
||||
if(!error) app.auth.user = data;
|
||||
return callack(error, data);
|
||||
});
|
||||
}else{
|
||||
@ -153,6 +155,7 @@ app.user = (function(app){
|
||||
}
|
||||
|
||||
function remove(args, callack){
|
||||
if(!confirm('Delete '+ args.uid+ 'user?')) return false;
|
||||
app.api.delete('user/'+ args.uid, function(error, data){
|
||||
callack(error, data);
|
||||
});
|
||||
@ -298,8 +301,6 @@ app.util = (function(app){
|
||||
$.holdReady( true );
|
||||
if(!location.pathname.includes('/login')){
|
||||
app.auth.isLoggedIn(function(error, isLoggedIn){
|
||||
console.log('here', error, isLoggedIn)
|
||||
|
||||
if(error || !isLoggedIn){
|
||||
app.auth.logOut(function(){})
|
||||
location.replace('/login/?redirect='+location.pathname);
|
||||
@ -335,17 +336,17 @@ function formAJAX( btn, del ) {
|
||||
var formData = $form.find( '[name]' ).serializeObject(); // builds query formDataing
|
||||
var method = $form.attr('method') || 'post';
|
||||
|
||||
if( !$form.validate()) {
|
||||
app.util.actionMessage('Please fix the form errors.', $form, 'danger')
|
||||
return false;
|
||||
}
|
||||
|
||||
app.util.actionMessage(
|
||||
'<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>',
|
||||
$form,
|
||||
'info'
|
||||
);
|
||||
|
||||
if( !$form.validate()) {
|
||||
app.util.actionMessage('Please fix the form errors.', $form, 'danger')
|
||||
return false;
|
||||
}
|
||||
|
||||
app.api[method]($form.attr('action'), formData, function(error, data){
|
||||
app.util.actionMessage(data.message, $form, error ? 'danger' : 'success'); //re-populate table
|
||||
if(!error){
|
||||
|
@ -142,6 +142,15 @@ $.validateSettings({
|
||||
if ( reg.test( value ) === false ) {
|
||||
return "Weak password, Try again";
|
||||
}
|
||||
}
|
||||
},
|
||||
email: function( value ){
|
||||
|
||||
//validated email address
|
||||
//more testing
|
||||
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
|
||||
if( !pattern.test( value ) ){
|
||||
return 'Invalid';
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
@ -35,7 +35,7 @@ router.post('/resetpassword', async function(req, res, next){
|
||||
try{
|
||||
let sent = await User.passwordReset(`${req.protocol}://${req.hostname}`, req.body.mail);
|
||||
|
||||
console.info('resetpassword for', req.body.mail, sent)
|
||||
console.info('resetpassword for', req.body.mail, 'sent')
|
||||
|
||||
return res.json({
|
||||
message: 'If the emaill address is in our system, you will receive a message.'
|
||||
|
@ -6,8 +6,12 @@ const {Group} = require('../models/group_ldap');
|
||||
|
||||
router.get('/', async function(req, res, next){
|
||||
try{
|
||||
let member = req.query.member ? await User.get(req.query.member) : {}
|
||||
|
||||
console.log('member', member)
|
||||
|
||||
return res.json({
|
||||
results: await Group[req.query.detail ? "listDetail" : "list"]()
|
||||
results: await Group[req.query.detail ? "listDetail" : "list"](member.dn)
|
||||
});
|
||||
}catch(error){
|
||||
next(error);
|
||||
|
@ -16,6 +16,10 @@ router.get('/users', function(req, res, next) {
|
||||
res.render('users', { title: 'Express' });
|
||||
});
|
||||
|
||||
router.get('/users/:uid', function(req, res, next) {
|
||||
res.render('home', { title: 'Express' });
|
||||
});
|
||||
|
||||
router.get('/groups', function(req, res, next) {
|
||||
res.render('groups', { title: 'Express' });
|
||||
});
|
||||
|
@ -27,14 +27,28 @@ router.delete('/:uid', async function(req, res, next){
|
||||
try{
|
||||
let user = await User.get(req.params.uid);
|
||||
|
||||
console.log('delete user', user);
|
||||
|
||||
return res.json({uid: req.params.uid, results: await user.remove()})
|
||||
}catch(error){
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/:uid', async function(req, res, next){
|
||||
try{
|
||||
let user = await User.get(req.params.uid);
|
||||
|
||||
// console.log('update user', user);
|
||||
|
||||
return res.json({
|
||||
results: await user.update(req.body),
|
||||
message: `Updated ${req.params.uid} user`
|
||||
|
||||
});
|
||||
}catch(error){
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/me', async function(req, res, next){
|
||||
try{
|
||||
|
||||
@ -91,4 +105,14 @@ router.post('/key', async function(req, res, next){
|
||||
|
||||
});
|
||||
|
||||
router.get('/:uid', async function(req, res, next){
|
||||
try{
|
||||
return res.json({
|
||||
results: await User.get(req.params.uid),
|
||||
});
|
||||
}catch(error){
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<%- include('top') %>
|
||||
<script id="rowTemplate" type="text/html">
|
||||
<p>
|
||||
<div class="card">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-users-class"></i>
|
||||
Group: {{ cn }}
|
||||
@ -93,7 +93,7 @@
|
||||
</script>
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-layer-plus"></i>
|
||||
Add new group
|
||||
@ -117,13 +117,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-users-class"></i>
|
||||
Group list
|
||||
</div>
|
||||
<div class="alert alert-warning actionMessage" style="display:none">
|
||||
<!-- Message after AJAX action is preformed -->
|
||||
<div class="card-header actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="" id="tableAJAX">
|
||||
|
@ -1,40 +1,70 @@
|
||||
<%- include('top') %>
|
||||
<script id="profileTemplate" type="text/html">
|
||||
<h2><i>User Name:</i> <b>{{uid}}</b></h2>
|
||||
<i>Name:</i> <b>{{givenName}} {{sn}}</b><br />
|
||||
<i>Email:</i> <b>{{mail}} </b><br />
|
||||
<i>Phone:</i> <b>{{mobile}} </b><br />
|
||||
<i>Home Directory:</i> <b>{{homeDirectory}} </b><br />
|
||||
<i>Login Shell:</i> <b>{{loginShell}} </b><br />
|
||||
<i>Unix User ID:</i> <b>{{uidNumber}} </b><br />
|
||||
<i>Unix Group ID:</i> <b>{{gidNumber}} </b><br />
|
||||
<i>LDAP DN:</i> <b>{{dn}} </b><br />
|
||||
<i>SSH Public Key</i> <b>{{sshPublicKey}}</b><br />
|
||||
<i>Joined</i> <b>{{createTimestamp}} </b><br />
|
||||
<i>Edited</i> <b>{{modifyTimestamp}} </b><br />
|
||||
<img id="profile_photo" >
|
||||
<h2><i>User Name:</i> <b>{{uid}}</b></h2>
|
||||
<i>Name:</i> <b>{{givenName}} {{sn}}</b><br />
|
||||
<i>Email:</i> <b>{{mail}} </b><br />
|
||||
<i>Joined:</i> <b>{{createTimestamp}} </b>, <i>Edited:</i> <b>{{modifyTimestamp}} </b><br />
|
||||
<i>Phone:</i> <b>{{mobile}} </b><br />
|
||||
<i>LDAP DN:</i> <b>{{dn}} </b><br />
|
||||
<i>Home Directory:</i> <b>{{homeDirectory}} </b><br />
|
||||
<i>Login Shell:</i> <b>{{loginShell}} </b><br />
|
||||
<i>SSH Public Key:</i> <b>{{sshPublicKey}}</b><br />
|
||||
<i>Unix User ID:</i> <b>{{uidNumber}} </b><br />
|
||||
<i>Unix Group ID:</i> <b>{{gidNumber}} </b><br />
|
||||
<i>Description:</i><br>
|
||||
<p>
|
||||
{{description}}
|
||||
</p>
|
||||
<img id="profile_photo" >
|
||||
</script>
|
||||
|
||||
<script id="groupRowTemplate" type="text/html">
|
||||
<tr>
|
||||
<td>{{cn}}</td>
|
||||
<td>{{description}}</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script id="userEditTemplate" type="text/html">
|
||||
<h3>Editing {{uid}}</h3>
|
||||
<form action="user/{{uid}}" method="put" onsubmit="formAJAX(this)" evalAJAX="editUserSeccess()">
|
||||
<div class="form-group">
|
||||
<label class="control-label">SSH Public Key</label>
|
||||
<input type="text" class="form-control" name="sshPublicKey" placeholder="ssh-rsa AAAAB3NzaC1yc2EAAAADAQ..." value="{{sshPublicKey}}" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Mobile Phone</label>
|
||||
<input type="text" class="form-control" name="mobile" placeholder="9175551234" validate=":9" value="{{mobile}}" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label">User Description (Optional)</label>
|
||||
<textarea class="form-control" name="description" placeholder="Admin group for gitea app">{{description}}</textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-dark btn-warning">Change</button>
|
||||
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<script id="paswordResetTemplate" type="text/html">
|
||||
<h3>
|
||||
Reset Password for {{uid}}
|
||||
</h3>
|
||||
<form action="user/{{uid}}/password" method="put" onsubmit="formAJAX(this)">
|
||||
<div class="form-group">
|
||||
<form action="user/{{uid}}/password" method="put" onsubmit="formAJAX(this)" class="form-group">
|
||||
<label class="control-label">Password</label>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" ><i class="fad fa-key"></i></span>
|
||||
</div>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" ><i class="fad fa-key"></i></span>
|
||||
</div>
|
||||
<input type="password" name="userPassword" class="form-control" placeholder="hunter123!" validate=":3" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label">Agian</label>
|
||||
<label class="control-label">Again</label>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" ><i class="fad fa-key"></i></span>
|
||||
</div>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" ><i class="fad fa-key"></i></span>
|
||||
</div>
|
||||
<input type="password" name="password" class="form-control" placeholder="hunter123!" validate="eq:userPassword" />
|
||||
</div>
|
||||
</div>
|
||||
@ -43,10 +73,7 @@
|
||||
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function hexToBase64(str) {
|
||||
return btoa(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" ")));
|
||||
}
|
||||
var currentUser;
|
||||
|
||||
function getInvite(){
|
||||
app.user.createInvite(function(error, data){
|
||||
@ -54,27 +81,82 @@
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
function renderProfile(user){
|
||||
var profileTemplate = $('#profileTemplate').html();
|
||||
var paswordResetTemplate = $('#paswordResetTemplate').html();
|
||||
var $target = $('#tableAJAX');
|
||||
var $target = $('#userProfile div.card-body');
|
||||
|
||||
$target.html('').hide();
|
||||
app.auth.isLoggedIn(function(error, data){
|
||||
// data.photo = unescape(encodeURIComponent(data.jpegPhoto));
|
||||
user.createTimestamp = moment(user.createTimestamp, "YYYYMMDDHHmmssZ").fromNow();
|
||||
user.modifyTimestamp = moment(user.modifyTimestamp, "YYYYMMDDHHmmssZ").fromNow();
|
||||
|
||||
$target.html(Mustache.render(profileTemplate, user));
|
||||
|
||||
$('#passwordReset').html(Mustache.render(paswordResetTemplate, user))
|
||||
};
|
||||
|
||||
function renderUserGroups(user){
|
||||
app.api.get('group/?detail=true&member='+user.uid, function(error, data){
|
||||
var groupRowTemplate = $('#groupRowTemplate').html();
|
||||
var $target = $('#mygroups');
|
||||
|
||||
$target.html('')
|
||||
if(error){
|
||||
app.util.actionMessage(data.message || '', $target, error ? 'danger': null);
|
||||
app.utils.actionMessage(data.message, $target, 'danger');
|
||||
}else{
|
||||
// data.photo = unescape(encodeURIComponent(data.jpegPhoto));
|
||||
data.createTimestamp = moment(data.createTimestamp, "YYYYMMDDHHmmssZ").fromNow();
|
||||
data.modifyTimestamp = moment(data.modifyTimestamp, "YYYYMMDDHHmmssZ").fromNow();
|
||||
|
||||
$target.html(Mustache.render(profileTemplate, data));
|
||||
|
||||
$('#passwordReset').html(Mustache.render(paswordResetTemplate, data))
|
||||
|
||||
$target.fadeIn('slow');
|
||||
for(var group of data.results){
|
||||
$target.append(Mustache.render(groupRowTemplate, group));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function determinUser(callback){
|
||||
if(location.pathname.includes('/users/')){
|
||||
var uid = location.pathname.replace('/users/', '');
|
||||
|
||||
app.api.get('user/'+uid, function(err, res){
|
||||
callback(res.results)
|
||||
})
|
||||
}else{
|
||||
callback(app.auth.user)
|
||||
}
|
||||
}
|
||||
|
||||
function editUser(){
|
||||
determinUser(function(user){
|
||||
var $profileCard = $('#userProfile');
|
||||
var $editCard = $('#editProfile');
|
||||
var userEditTemplate = $('#userEditTemplate').html()
|
||||
|
||||
$editCard.find('.card-body').html(Mustache.render(userEditTemplate, user))
|
||||
|
||||
$profileCard.slideUp();
|
||||
$editCard.slideDown();
|
||||
});
|
||||
}
|
||||
|
||||
function editUserSeccess(){
|
||||
console.log('edit done')
|
||||
$('#editProfile').slideUp();
|
||||
determinUser(function(user){
|
||||
currentUser = user;
|
||||
app.auth.user = user;
|
||||
renderProfile(user);
|
||||
renderUserGroups(user);
|
||||
$('#userProfile').slideDown();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
determinUser(function(user){
|
||||
currentUser = user;
|
||||
renderProfile(user);
|
||||
renderUserGroups(user);
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<div class="row" style="display:none">
|
||||
@ -134,28 +216,6 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="shadow-lg card card-default mb-8">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-id-card"></i>
|
||||
Profile
|
||||
<div class="hover-effect float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body" style="padding-bottom:0">
|
||||
<div class="alert alert-warning actionMessage" style="display:none">
|
||||
<!-- Message after AJAX action is preformed -->
|
||||
</div>
|
||||
<div id="tableAJAX" style="display:none">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="shadow-lg card">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-undo-alt"></i>
|
||||
@ -170,7 +230,78 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div id="userProfile" class="shadow-lg card card-default mb-8">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-id-card"></i>
|
||||
Profile
|
||||
<div class="hover-effect float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- User profile inserted by JS -->
|
||||
</div>
|
||||
<div class=card-footer>
|
||||
<button type="button" onclick="editUser()" class="btn btn-warning btn-lg">
|
||||
<i class="fad fa-user-edit"></i>
|
||||
</button>
|
||||
<button type="button" onclick="app.user.remove({uid: currentUser.uid}, function(){app.util.actionMessage('username {{uid}} delete.', $(this), 'danger')})" class="btn btn-danger btn-lg float-right">
|
||||
<i class="fad fa-user-slash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editProfile" class="shadow-lg card card-default mb-8" style="display:none">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-id-card"></i>
|
||||
Edit Profile
|
||||
<div class="hover-effect float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="tableAJAX">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<div class="shadow-lg card card-default mb-8">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-id-card"></i>
|
||||
My groups
|
||||
<div class="hover-effect float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body" style="padding-bottom:0">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th>
|
||||
Name
|
||||
</th>
|
||||
<th>
|
||||
Description
|
||||
</th>
|
||||
</thead>
|
||||
<tbody id="mygroups">
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
<%- include('bottom') %>
|
||||
|
@ -11,7 +11,7 @@
|
||||
</script>
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
Add new user
|
||||
</div>
|
||||
|
@ -32,11 +32,12 @@
|
||||
</p>
|
||||
<form action="auth/invite/<%= invite.token %>" onsubmit="formAJAX(this)" evalAJAX="emailSent()">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Email</label>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" ><i class="fad fa-at"></i></span>
|
||||
</div>
|
||||
<input type="email" name="mail" class="form-control" placeholder="jsmith@gmail.com" required />
|
||||
<input type="email" name="mail" class="form-control" placeholder="jsmith@gmail.com" validate="email:3" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -55,8 +55,6 @@
|
||||
<div class="card-header actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="alert alert-warning actionMessage" style="display:none">
|
||||
</div>
|
||||
<h3>Coming soon!</h3>
|
||||
<p>
|
||||
<ul class="list-group">
|
||||
@ -84,11 +82,12 @@
|
||||
<input type="hidden" name="redirect" value="<%= redirect %>">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Email</label>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" ><i class="fad fa-at"></i></span>
|
||||
</div>
|
||||
<input type="email" name="mail" class="form-control" placeholder="jsmith@gmail.com" required />
|
||||
<input type="email" name="mail" class="form-control" placeholder="jsmith@gmail.com" validate="email:3" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
</script>
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
Password reset
|
||||
</div>
|
||||
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label">Agian</label>
|
||||
<label class="control-label">Again</label>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" ><i class="fad fa-key"></i></span>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<form action="user/" method="post">
|
||||
<form action="user/" method="post" onsubmit="formAJAX(this)">
|
||||
<input type="hidden" class="form-control" name="delete" value="false" />
|
||||
<div class="form-group">
|
||||
<label class="control-label">First name</label>
|
||||
@ -15,6 +15,11 @@
|
||||
<input type="text" class="form-control" name="mail" placeholder="jsmith@gmail.com" validate="email:3" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">SSH Public Key</label>
|
||||
<input type="text" class="form-control" name="sshPublicKey" placeholder="ssh-rsa AAAAB3NzaC1yc2EAAAADAQ..." />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Mobile Phone</label>
|
||||
<input type="text" class="form-control" name="mobile" placeholder="9175551234" validate=":9" />
|
||||
@ -28,5 +33,9 @@
|
||||
<label class="control-label">Again</label>
|
||||
<input type="password" class="form-control" name="passwordMatch" placeholder="Retype password" validate="eq:userPassword"/>
|
||||
</div>
|
||||
<button type="button" onclick="formAJAX(this)" class="btn btn-outline-dark">Add</button>
|
||||
<div class="form-group">
|
||||
<label class="control-label">User Description (Optional)</label>
|
||||
<textarea class="form-control" name="description" placeholder="Admin group for gitea app"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-dark">Add</button>
|
||||
</form>
|
||||
|
@ -2,21 +2,33 @@
|
||||
<script id="rowTemplate" type="text/html">
|
||||
<tr action="user/password/{{ username }}" method="put" evalAJAX="$form.trigger('reset')">
|
||||
<td>
|
||||
{{ uidNumber }}:{{ uid }}
|
||||
{{ uidNumber }}
|
||||
</td>
|
||||
<td>
|
||||
{{givenName}} {{sn}} {{mail}}
|
||||
<a href='/users/{{uid}}'>{{ uid }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onclick="app.user.remove({uid: '{{uid}}'}, function(){tableAJAX('username {{uid}} delete.')})" class="btn btn-sm btn-danger">
|
||||
Delete
|
||||
{{givenName}} {{sn}}
|
||||
</td>
|
||||
<td>
|
||||
{{mail}}
|
||||
</td>
|
||||
<td>
|
||||
{{#sudoUser}}<i class="fad fa-check-square"></i>{{/sudoUser}}
|
||||
</td>
|
||||
<td>
|
||||
{{#sshPublicKey}}<i class="fad fa-check-square"></i>{{/sshPublicKey}}
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onclick="app.user.remove({uid: '{{uid}}'}, function(){renderUsers('username {{uid}} delete.')})" class="btn btn-sm btn-danger">
|
||||
<i class="fad fa-user-slash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function tableAJAX(actionMessage){
|
||||
function renderUsers(actionMessage){
|
||||
var rowTemplate = $('#rowTemplate').html();
|
||||
var $target = $('#tableAJAX');
|
||||
|
||||
@ -38,12 +50,13 @@
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
tableAJAX(); //populate the table
|
||||
renderUsers(); //populate the table
|
||||
$('form[action="user/"]').attr('evalAJAX', 'renderUsers()')
|
||||
});
|
||||
</script>
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-user-plus"></i>
|
||||
Add new user
|
||||
@ -55,7 +68,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-th-list"></i>
|
||||
User List
|
||||
@ -65,9 +78,13 @@
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th>id</th>
|
||||
<th>uid</th>
|
||||
<th>Name</th>
|
||||
<th>Password</th>
|
||||
<th>Delete</th>
|
||||
<th>eMail</th>
|
||||
<th>Sudo</th>
|
||||
<th>key</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody id="tableAJAX">
|
||||
<!-- ajax loaded table -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user