user edit
This commit is contained in:
		| @ -7,11 +7,14 @@ const client = new Client({ | |||||||
| 	url: conf.url, | 	url: conf.url, | ||||||
| }); | }); | ||||||
|  |  | ||||||
| async function getGroups(client){ | async function getGroups(client, member){ | ||||||
| 	try{ | 	try{ | ||||||
|  |  | ||||||
|  | 		let memberFilter = member ? `(member=${member})`: '' | ||||||
|  |  | ||||||
| 		let groups = (await client.search(conf.groupBase, { | 		let groups = (await client.search(conf.groupBase, { | ||||||
| 			scope: 'sub', | 			scope: 'sub', | ||||||
| 			filter: '(&(objectClass=groupOfNames))', | 			filter: `(&(objectClass=groupOfNames)${memberFilter})`, | ||||||
| 			attributes: ['*', 'createTimestamp', 'modifyTimestamp'], | 			attributes: ['*', 'createTimestamp', 'modifyTimestamp'], | ||||||
| 		})).searchEntries; | 		})).searchEntries; | ||||||
|  |  | ||||||
| @ -81,11 +84,11 @@ async function removeMember(client, group, user){ | |||||||
|  |  | ||||||
| var Group = {}; | var Group = {}; | ||||||
|  |  | ||||||
| Group.list = async function(){ | Group.list = async function(member){ | ||||||
| 	try{ | 	try{ | ||||||
| 		await client.bind(conf.bindDN, conf.bindPassword); | 		await client.bind(conf.bindDN, conf.bindPassword); | ||||||
|  |  | ||||||
| 		let groups = await getGroups(client) | 		let groups = await getGroups(client, member) | ||||||
|  |  | ||||||
| 		await client.unbind(); | 		await client.unbind(); | ||||||
|  |  | ||||||
| @ -95,11 +98,11 @@ Group.list = async function(){ | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| Group.listDetail = async function(){ | Group.listDetail = async function(member){ | ||||||
| 	try{ | 	try{ | ||||||
| 		await client.bind(conf.bindDN, conf.bindPassword); | 		await client.bind(conf.bindDN, conf.bindPassword); | ||||||
|  |  | ||||||
| 		let groups = await getGroups(client) | 		let groups = await getGroups(client, member) | ||||||
|  |  | ||||||
| 		await client.unbind(); | 		await client.unbind(); | ||||||
|  |  | ||||||
| @ -207,7 +210,4 @@ Group.remove = async function(){ | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = {Group}; | module.exports = {Group}; | ||||||
|  | |||||||
| @ -12,6 +12,7 @@ const client = new Client({ | |||||||
| }); | }); | ||||||
|  |  | ||||||
| async function addPosixGroup(client, data){ | async function addPosixGroup(client, data){ | ||||||
|  |  | ||||||
|   try{ |   try{ | ||||||
| 	const groups = (await client.search(conf.groupBase, { | 	const groups = (await client.search(conf.groupBase, { | ||||||
| 	  scope: 'sub', | 	  scope: 'sub', | ||||||
| @ -54,7 +55,12 @@ async function addPosixAccount(client, data){ | |||||||
| 		loginShell: data.loginShell, | 		loginShell: data.loginShell, | ||||||
| 		homeDirectory: data.homeDirectory, | 		homeDirectory: data.homeDirectory, | ||||||
| 		userPassword: data.userPassword, | 		userPassword: data.userPassword, | ||||||
|       objectclass: [ 'inetOrgPerson', 'posixAccount', 'top' ] | 		description: data.description || ' ',  | ||||||
|  | 		sudoHost: 'ALL', | ||||||
|  | 		sudoCommand: 'ALL', | ||||||
|  | 		sudoUser: data.uid, | ||||||
|  | 		sshPublicKey: data.sshPublicKey, | ||||||
|  | 		objectclass: ['inetOrgPerson', 'sudoRole', 'ldapPublicKey', 'posixAccount', 'top' ] | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	return data | 	return data | ||||||
| @ -67,6 +73,8 @@ async function addPosixAccount(client, data){ | |||||||
|  |  | ||||||
| async function addLdapUser(client, data){ | async function addLdapUser(client, data){ | ||||||
|  |  | ||||||
|  | 	var group; | ||||||
|  |  | ||||||
|   try{ |   try{ | ||||||
| 	data.uid = `${data.givenName[0]}${data.sn}`; | 	data.uid = `${data.givenName[0]}${data.sn}`; | ||||||
| 	data.cn = data.uid; | 	data.cn = data.uid; | ||||||
| @ -74,12 +82,13 @@ async function addLdapUser(client, data){ | |||||||
| 	data.homeDirectory= `/home/${data.uid}`; | 	data.homeDirectory= `/home/${data.uid}`; | ||||||
| 	data.userPassword = '{MD5}'+crypto.createHash('md5').update(data.userPassword, "binary").digest('base64'); | 	data.userPassword = '{MD5}'+crypto.createHash('md5').update(data.userPassword, "binary").digest('base64'); | ||||||
|  |  | ||||||
|     data = await addPosixGroup(client, data); | 	group = await addPosixGroup(client, data); | ||||||
|     data = await addPosixAccount(client, data); | 	data = await addPosixAccount(client, group); | ||||||
|  |  | ||||||
| 	return data; | 	return data; | ||||||
|  |  | ||||||
|   }catch(error){ |   }catch(error){ | ||||||
|  |   	await deleteLdapDN(client, `cn=${data.uid},${conf.groupBase}`, true); | ||||||
| 	throw error; | 	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){ | const user_parse = function(data){ | ||||||
| 	if(data[conf.userNameAttribute]){ | 	if(data[conf.userNameAttribute]){ | ||||||
| 		data.username = data[conf.userNameAttribute] | 		data.username = data[conf.userNameAttribute] | ||||||
|  | 		data.userPassword = undefined; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return data; | 	return data; | ||||||
| @ -152,7 +171,7 @@ User.listDetail = async function(){ | |||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| User.get = async function(data, value){ | User.get = async function(data, key){ | ||||||
| 	try{ | 	try{ | ||||||
| 		if(typeof data !== 'object'){ | 		if(typeof data !== 'object'){ | ||||||
| 			let uid = data; | 			let uid = data; | ||||||
| @ -160,15 +179,14 @@ User.get = async function(data, value){ | |||||||
| 			data.uid = uid; | 			data.uid = uid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
| 		await client.bind(conf.bindDN, conf.bindPassword); | 		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; | 		data.searchValue = data.searchValue || data.uid; | ||||||
|  |  | ||||||
| 		let filter = `(&${conf.userFilter}(${data.searchKey}=${data.searchValue}))`; | 		let filter = `(&${conf.userFilter}(${data.searchKey}=${data.searchValue}))`; | ||||||
|  |  | ||||||
| 		console.log('get filter', filter) |  | ||||||
|  |  | ||||||
| 		const res = await client.search(conf.userBase, { | 		const res = await client.search(conf.userBase, { | ||||||
| 			scope: 'sub', | 			scope: 'sub', | ||||||
| 			filter: filter, | 			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. | 	// Return true or false if the requested entry exists ignoring error's. | ||||||
| 	try{ | 	try{ | ||||||
| 		await this.get(data); | 		await this.get(data, key); | ||||||
|  |  | ||||||
| 		return true | 		return true | ||||||
| 	}catch(error){ | 	}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){ | User.addByInvite = async function(data){ | ||||||
| 	try{ | 	try{ | ||||||
| 		let token = await InviteToken.get(data.token); | 		let token = await InviteToken.get(data.token); | ||||||
| @ -270,6 +317,11 @@ User.addByInvite = async function(data){ | |||||||
|  |  | ||||||
| User.verifyEmail = async function(data){ | User.verifyEmail = async function(data){ | ||||||
| 	try{ | 	try{ | ||||||
|  |  | ||||||
|  | 		let exists = await this.exists(data.mail, 'mail'); | ||||||
|  |  | ||||||
|  | 		if(exists) throw new Error('EmailInUse'); | ||||||
|  |  | ||||||
| 		let token = await InviteToken.get(data.token); | 		let token = await InviteToken.get(data.token); | ||||||
| 		await token.update({mail: data.mail}) | 		await token.update({mail: data.mail}) | ||||||
| 		await Mail.sendTemplate( | 		await Mail.sendTemplate( | ||||||
| @ -294,8 +346,6 @@ User.passwordReset = async function(url, mail){ | |||||||
| 			searchValue: mail | 			searchValue: mail | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		console.log('user', user) |  | ||||||
|  |  | ||||||
| 		let token = await PasswordResetToken.add(user); | 		let token = await PasswordResetToken.add(user); | ||||||
|  |  | ||||||
| 		await Mail.sendTemplate( | 		await Mail.sendTemplate( | ||||||
|  | |||||||
| @ -86,6 +86,7 @@ app.api = (function(app){ | |||||||
| })(app) | })(app) | ||||||
|  |  | ||||||
| app.auth = (function(app) { | app.auth = (function(app) { | ||||||
|  | 	var user = {} | ||||||
| 	function setToken(token){ | 	function setToken(token){ | ||||||
| 		localStorage.setItem('APIToken', token); | 		localStorage.setItem('APIToken', token); | ||||||
| 	} | 	} | ||||||
| @ -97,6 +98,7 @@ app.auth = (function(app) { | |||||||
| 	function isLoggedIn(callack){ | 	function isLoggedIn(callack){ | ||||||
| 		if(getToken()){ | 		if(getToken()){ | ||||||
| 			return app.api.get('user/me', function(error, data){ | 			return app.api.get('user/me', function(error, data){ | ||||||
|  | 				if(!error) app.auth.user = data; | ||||||
| 				return callack(error, data); | 				return callack(error, data); | ||||||
| 			}); | 			}); | ||||||
| 		}else{ | 		}else{ | ||||||
| @ -153,6 +155,7 @@ app.user = (function(app){ | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function remove(args, callack){ | 	function remove(args, callack){ | ||||||
|  | 		if(!confirm('Delete '+ args.uid+ 'user?')) return false; | ||||||
| 		app.api.delete('user/'+ args.uid, function(error, data){ | 		app.api.delete('user/'+ args.uid, function(error, data){ | ||||||
| 			callack(error, data); | 			callack(error, data); | ||||||
| 		}); | 		}); | ||||||
| @ -298,8 +301,6 @@ app.util = (function(app){ | |||||||
| $.holdReady( true ); | $.holdReady( true ); | ||||||
| if(!location.pathname.includes('/login')){ | if(!location.pathname.includes('/login')){ | ||||||
| 	app.auth.isLoggedIn(function(error, isLoggedIn){ | 	app.auth.isLoggedIn(function(error, isLoggedIn){ | ||||||
| 			console.log('here', error, isLoggedIn) |  | ||||||
|  |  | ||||||
| 		if(error || !isLoggedIn){ | 		if(error || !isLoggedIn){ | ||||||
| 			app.auth.logOut(function(){}) | 			app.auth.logOut(function(){}) | ||||||
| 			location.replace('/login/?redirect='+location.pathname); | 			location.replace('/login/?redirect='+location.pathname); | ||||||
| @ -335,17 +336,17 @@ function formAJAX( btn, del ) { | |||||||
| 	var formData = $form.find( '[name]' ).serializeObject(); // builds query formDataing | 	var formData = $form.find( '[name]' ).serializeObject(); // builds query formDataing | ||||||
| 	var method = $form.attr('method') || 'post'; | 	var method = $form.attr('method') || 'post'; | ||||||
|  |  | ||||||
|  | 	if( !$form.validate()) { | ||||||
|  | 		app.util.actionMessage('Please fix the form errors.', $form, 'danger') | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	app.util.actionMessage(  | 	app.util.actionMessage(  | ||||||
| 		'<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>', | 		'<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>', | ||||||
| 		$form, | 		$form, | ||||||
| 		'info' | 		'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.api[method]($form.attr('action'), formData, function(error, data){ | ||||||
| 		app.util.actionMessage(data.message, $form, error ? 'danger' : 'success'); //re-populate table | 		app.util.actionMessage(data.message, $form, error ? 'danger' : 'success'); //re-populate table | ||||||
| 		if(!error){ | 		if(!error){ | ||||||
|  | |||||||
| @ -142,6 +142,15 @@ $.validateSettings({ | |||||||
| 			if ( reg.test( value ) === false ) { | 			if ( reg.test( value ) === false ) { | ||||||
| 				return "Weak password, Try again"; | 				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{ | 	try{ | ||||||
| 		let sent = await User.passwordReset(`${req.protocol}://${req.hostname}`, req.body.mail); | 		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({ | 		return res.json({ | ||||||
| 			message: 'If the emaill address is in our system, you will receive a message.' | 			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){ | router.get('/', async function(req, res, next){ | ||||||
| 	try{ | 	try{ | ||||||
|  | 		let member = req.query.member ? await User.get(req.query.member) : {} | ||||||
|  |  | ||||||
|  | 		console.log('member', member) | ||||||
|  |  | ||||||
| 		return res.json({ | 		return res.json({ | ||||||
| 			results:  await Group[req.query.detail ? "listDetail" : "list"]() | 			results:  await Group[req.query.detail ? "listDetail" : "list"](member.dn) | ||||||
| 		}); | 		}); | ||||||
| 	}catch(error){ | 	}catch(error){ | ||||||
| 		next(error); | 		next(error); | ||||||
|  | |||||||
| @ -16,6 +16,10 @@ router.get('/users', function(req, res, next) { | |||||||
|   res.render('users', { title: 'Express' }); |   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) { | router.get('/groups', function(req, res, next) { | ||||||
|   res.render('groups', { title: 'Express' }); |   res.render('groups', { title: 'Express' }); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -27,14 +27,28 @@ router.delete('/:uid', async function(req, res, next){ | |||||||
| 	try{ | 	try{ | ||||||
| 		let user = await User.get(req.params.uid); | 		let user = await User.get(req.params.uid); | ||||||
|  |  | ||||||
| 		console.log('delete user', user); |  | ||||||
|  |  | ||||||
| 		return res.json({uid: req.params.uid, results: await user.remove()}) | 		return res.json({uid: req.params.uid, results: await user.remove()}) | ||||||
| 	}catch(error){ | 	}catch(error){ | ||||||
| 		next(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){ | router.get('/me', async function(req, res, next){ | ||||||
| 	try{ | 	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; | module.exports = router; | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| <%- include('top') %> | <%- include('top') %> | ||||||
| <script id="rowTemplate" type="text/html"> | <script id="rowTemplate" type="text/html"> | ||||||
| 	<p> | 	<p> | ||||||
| 	<div class="card"> | 	<div class="card shadow-lg"> | ||||||
| 		<div class="card-header"> | 		<div class="card-header"> | ||||||
| 			<i class="fad fa-users-class"></i> | 			<i class="fad fa-users-class"></i> | ||||||
| 			Group: {{ cn }} | 			Group: {{ cn }} | ||||||
| @ -93,7 +93,7 @@ | |||||||
| </script> | </script> | ||||||
| <div class="row" style="display:none"> | <div class="row" style="display:none"> | ||||||
| 	<div class="col-md-4"> | 	<div class="col-md-4"> | ||||||
| 		<div class="card"> | 		<div class="card shadow-lg"> | ||||||
| 			<div class="card-header"> | 			<div class="card-header"> | ||||||
| 				<i class="fas fa-layer-plus"></i> | 				<i class="fas fa-layer-plus"></i> | ||||||
| 				Add new group | 				Add new group | ||||||
| @ -117,13 +117,12 @@ | |||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div class="col-md-8"> | 	<div class="col-md-8"> | ||||||
| 		<div class="card"> | 		<div class="card shadow-lg"> | ||||||
| 			<div class="card-header"> | 			<div class="card-header"> | ||||||
| 				<i class="fad fa-users-class"></i> | 				<i class="fad fa-users-class"></i> | ||||||
| 				Group list | 				Group list | ||||||
| 			</div> | 			</div> | ||||||
| 			<div class="alert alert-warning actionMessage" style="display:none"> | 			<div class="card-header actionMessage" style="display:none"> | ||||||
| 				<!-- Message after AJAX action is preformed --> |  | ||||||
| 			</div> | 			</div> | ||||||
| 			<div class="card-body"> | 			<div class="card-body"> | ||||||
| 				<div class="" id="tableAJAX"> | 				<div class="" id="tableAJAX"> | ||||||
|  | |||||||
| @ -3,24 +3,54 @@ | |||||||
| 	<h2><i>User Name:</i> <b>{{uid}}</b></h2> | 	<h2><i>User Name:</i> <b>{{uid}}</b></h2> | ||||||
| 	<i>Name:</i> <b>{{givenName}} {{sn}}</b><br /> | 	<i>Name:</i> <b>{{givenName}} {{sn}}</b><br /> | ||||||
| 	<i>Email:</i> <b>{{mail}} </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>Phone:</i> <b>{{mobile}} </b><br /> | ||||||
|  | 	<i>LDAP DN:</i> <b>{{dn}} </b><br /> | ||||||
| 	<i>Home Directory:</i> <b>{{homeDirectory}} </b><br /> | 	<i>Home Directory:</i> <b>{{homeDirectory}} </b><br /> | ||||||
| 	<i>Login Shell:</i> <b>{{loginShell}} </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 User ID:</i> <b>{{uidNumber}} </b><br /> | ||||||
| 	<i>Unix Group ID:</i> <b>{{gidNumber}} </b><br /> | 	<i>Unix Group ID:</i> <b>{{gidNumber}} </b><br /> | ||||||
| <i>LDAP DN:</i> <b>{{dn}} </b><br /> | 	<i>Description:</i><br> | ||||||
| <i>SSH Public Key</i> <b>{{sshPublicKey}}</b><br /> | 	<p> | ||||||
| <i>Joined</i> <b>{{createTimestamp}} </b><br /> | 		{{description}} | ||||||
| <i>Edited</i> <b>{{modifyTimestamp}} </b><br /> | 	</p> | ||||||
| 	<img id="profile_photo" > | 	<img id="profile_photo" > | ||||||
| </script> | </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"> | <script id="paswordResetTemplate" type="text/html"> | ||||||
| 	<h3> | 	<h3> | ||||||
| 		Reset Password for {{uid}} | 		Reset Password for {{uid}} | ||||||
| 	</h3> | 	</h3> | ||||||
| 	<form action="user/{{uid}}/password" method="put" onsubmit="formAJAX(this)"> | 	<form action="user/{{uid}}/password" method="put" onsubmit="formAJAX(this)" class="form-group"> | ||||||
| 		<div class="form-group"> |  | ||||||
| 			<label class="control-label">Password</label> | 			<label class="control-label">Password</label> | ||||||
| 			<div class="input-group mb-3"> | 			<div class="input-group mb-3"> | ||||||
| 				<div class="input-group-prepend"> | 				<div class="input-group-prepend"> | ||||||
| @ -30,7 +60,7 @@ | |||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 		<div class="form-group"> | 		<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 mb-3"> | ||||||
| 				<div class="input-group-prepend"> | 				<div class="input-group-prepend"> | ||||||
| 					<span class="input-group-text" ><i class="fad fa-key"></i></span> | 					<span class="input-group-text" ><i class="fad fa-key"></i></span> | ||||||
| @ -43,10 +73,7 @@ | |||||||
|  |  | ||||||
| </script> | </script> | ||||||
| <script type="text/javascript"> | <script type="text/javascript"> | ||||||
|  | 	var currentUser; | ||||||
| 	function hexToBase64(str) { |  | ||||||
| 		return btoa(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	function getInvite(){ | 	function getInvite(){ | ||||||
| 		app.user.createInvite(function(error, data){ | 		app.user.createInvite(function(error, data){ | ||||||
| @ -54,27 +81,82 @@ | |||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	$(document).ready(function(){ | 	function renderProfile(user){ | ||||||
| 		var profileTemplate = $('#profileTemplate').html(); | 		var profileTemplate = $('#profileTemplate').html(); | ||||||
| 		var paswordResetTemplate = $('#paswordResetTemplate').html();  | 		var paswordResetTemplate = $('#paswordResetTemplate').html();  | ||||||
| 		var $target = $('#tableAJAX'); | 		var $target = $('#userProfile div.card-body'); | ||||||
|  |  | ||||||
| 		$target.html('').hide(); |  | ||||||
| 		app.auth.isLoggedIn(function(error, data){ |  | ||||||
| 			if(error){ |  | ||||||
| 				app.util.actionMessage(data.message || '', $target, error ? 'danger': null); |  | ||||||
| 			}else{ |  | ||||||
| 		// data.photo = unescape(encodeURIComponent(data.jpegPhoto)); | 		// data.photo = unescape(encodeURIComponent(data.jpegPhoto)); | ||||||
| 				data.createTimestamp = moment(data.createTimestamp, "YYYYMMDDHHmmssZ").fromNow(); | 		user.createTimestamp = moment(user.createTimestamp, "YYYYMMDDHHmmssZ").fromNow(); | ||||||
| 				data.modifyTimestamp = moment(data.modifyTimestamp, "YYYYMMDDHHmmssZ").fromNow(); | 		user.modifyTimestamp = moment(user.modifyTimestamp, "YYYYMMDDHHmmssZ").fromNow(); | ||||||
|  |  | ||||||
| 				$target.html(Mustache.render(profileTemplate, data)); | 		$target.html(Mustache.render(profileTemplate, user)); | ||||||
|  |  | ||||||
| 				$('#passwordReset').html(Mustache.render(paswordResetTemplate, data)) | 		$('#passwordReset').html(Mustache.render(paswordResetTemplate, user)) | ||||||
|  | 	}; | ||||||
|  |  | ||||||
| 				$target.fadeIn('slow'); | 	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.utils.actionMessage(data.message, $target, 'danger'); | ||||||
|  | 			}else{ | ||||||
|  | 				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> | </script> | ||||||
| <div class="row" style="display:none"> | <div class="row" style="display:none"> | ||||||
| @ -134,28 +216,6 @@ | |||||||
| 				</ul> | 				</ul> | ||||||
| 			</div> | 			</div> | ||||||
| 		</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="shadow-lg card"> | ||||||
| 			<div class="card-header"> | 			<div class="card-header"> | ||||||
| 				<i class="fad fa-undo-alt"></i> | 				<i class="fad fa-undo-alt"></i> | ||||||
| @ -170,7 +230,78 @@ | |||||||
|  |  | ||||||
| 			</div> | 			</div> | ||||||
| 		</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> | 			</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') %> | <%- include('bottom') %> | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ | |||||||
| </script> | </script> | ||||||
| <div class="row" style="display:none"> | <div class="row" style="display:none"> | ||||||
| 		<div class="col-md-12"> | 		<div class="col-md-12"> | ||||||
| 		<div class="card"> | 		<div class="card shadow-lg"> | ||||||
| 			<div class="card-header"> | 			<div class="card-header"> | ||||||
| 				Add new user | 				Add new user | ||||||
| 			</div> | 			</div> | ||||||
|  | |||||||
| @ -32,11 +32,12 @@ | |||||||
| 				</p> | 				</p> | ||||||
| 				<form action="auth/invite/<%= invite.token %>" onsubmit="formAJAX(this)" evalAJAX="emailSent()"> | 				<form action="auth/invite/<%= invite.token %>" onsubmit="formAJAX(this)" evalAJAX="emailSent()"> | ||||||
| 					<div class="form-group"> | 					<div class="form-group"> | ||||||
|  | 						<label class="control-label">Email</label> | ||||||
| 						<div class="input-group mb-3"> | 						<div class="input-group mb-3"> | ||||||
| 						  <div class="input-group-prepend"> | 						  <div class="input-group-prepend"> | ||||||
| 						    <span class="input-group-text" ><i class="fad fa-at"></i></span> | 						    <span class="input-group-text" ><i class="fad fa-at"></i></span> | ||||||
| 						  </div> | 						  </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> | ||||||
| 					</div> | 					</div> | ||||||
|  |  | ||||||
|  | |||||||
| @ -55,8 +55,6 @@ | |||||||
| 			<div class="card-header actionMessage" style="display:none"> | 			<div class="card-header actionMessage" style="display:none"> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div class="card-body"> | 			<div class="card-body"> | ||||||
| 				<div class="alert alert-warning actionMessage" style="display:none"> |  | ||||||
| 				</div> |  | ||||||
| 				<h3>Coming soon!</h3> | 				<h3>Coming soon!</h3> | ||||||
| 				<p> | 				<p> | ||||||
| 					<ul class="list-group"> | 					<ul class="list-group"> | ||||||
| @ -84,11 +82,12 @@ | |||||||
| 					<input type="hidden" name="redirect" value="<%= redirect %>"> | 					<input type="hidden" name="redirect" value="<%= redirect %>"> | ||||||
|  |  | ||||||
| 					<div class="form-group"> | 					<div class="form-group"> | ||||||
|  | 						<label class="control-label">Email</label> | ||||||
| 						<div class="input-group mb-3"> | 						<div class="input-group mb-3"> | ||||||
| 						  <div class="input-group-prepend"> | 						  <div class="input-group-prepend"> | ||||||
| 						    <span class="input-group-text" ><i class="fad fa-at"></i></span> | 						    <span class="input-group-text" ><i class="fad fa-at"></i></span> | ||||||
| 						  </div> | 						  </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> | ||||||
| 					</div> | 					</div> | ||||||
|  |  | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
| </script> | </script> | ||||||
| <div class="row" style="display:none"> | <div class="row" style="display:none"> | ||||||
| 	<div class="col-md-12"> | 	<div class="col-md-12"> | ||||||
| 		<div class="card"> | 		<div class="card shadow-lg"> | ||||||
| 			<div class="card-header"> | 			<div class="card-header"> | ||||||
| 				Password reset | 				Password reset | ||||||
| 			</div> | 			</div> | ||||||
| @ -24,7 +24,7 @@ | |||||||
| 						</div> | 						</div> | ||||||
| 					</div> | 					</div> | ||||||
| 					<div class="form-group"> | 					<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 mb-3"> | ||||||
| 						  <div class="input-group-prepend"> | 						  <div class="input-group-prepend"> | ||||||
| 						    <span class="input-group-text" ><i class="fad fa-key"></i></span> | 						    <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" /> | 	<input type="hidden" class="form-control" name="delete" value="false" /> | ||||||
| 	<div class="form-group"> | 	<div class="form-group"> | ||||||
| 		<label class="control-label">First name</label> | 		<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" /> | 		<input type="text" class="form-control" name="mail" placeholder="jsmith@gmail.com" validate="email:3" /> | ||||||
| 	</div> | 	</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"> | 	<div class="form-group"> | ||||||
| 		<label class="control-label">Mobile Phone</label> | 		<label class="control-label">Mobile Phone</label> | ||||||
| 		<input type="text" class="form-control" name="mobile" placeholder="9175551234" validate=":9" /> | 		<input type="text" class="form-control" name="mobile" placeholder="9175551234" validate=":9" /> | ||||||
| @ -28,5 +33,9 @@ | |||||||
| 		<label class="control-label">Again</label> | 		<label class="control-label">Again</label> | ||||||
| 		<input type="password" class="form-control" name="passwordMatch" placeholder="Retype password" validate="eq:userPassword"/> | 		<input type="password" class="form-control" name="passwordMatch" placeholder="Retype password" validate="eq:userPassword"/> | ||||||
| 	</div> | 	</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> | </form> | ||||||
|  | |||||||
| @ -2,21 +2,33 @@ | |||||||
| <script id="rowTemplate" type="text/html"> | <script id="rowTemplate" type="text/html"> | ||||||
| 	<tr action="user/password/{{ username }}" method="put" evalAJAX="$form.trigger('reset')"> | 	<tr action="user/password/{{ username }}" method="put" evalAJAX="$form.trigger('reset')"> | ||||||
| 		<td> | 		<td> | ||||||
| 			{{ uidNumber }}:{{ uid }}	 | 			{{ uidNumber }} | ||||||
| 		</td> | 		</td> | ||||||
| 		<td> | 		<td> | ||||||
| 			{{givenName}} {{sn}} {{mail}} | 			<a href='/users/{{uid}}'>{{ uid }}</a>	 | ||||||
| 		</td> | 		</td> | ||||||
| 		<td> | 		<td> | ||||||
| 			<button type="button" onclick="app.user.remove({uid: '{{uid}}'}, function(){tableAJAX('username {{uid}} delete.')})" class="btn btn-sm btn-danger"> | 			{{givenName}} {{sn}}  | ||||||
| 				Delete | 		</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> | 			</button> | ||||||
| 		</td> | 		</td> | ||||||
| 	</tr> | 	</tr> | ||||||
| </script> | </script> | ||||||
| <script type="text/javascript"> | <script type="text/javascript"> | ||||||
|  |  | ||||||
| 	function tableAJAX(actionMessage){ | 	function renderUsers(actionMessage){ | ||||||
| 		var rowTemplate = $('#rowTemplate').html(); | 		var rowTemplate = $('#rowTemplate').html(); | ||||||
| 		var $target = $('#tableAJAX'); | 		var $target = $('#tableAJAX'); | ||||||
|  |  | ||||||
| @ -38,12 +50,13 @@ | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	$(document).ready(function(){ | 	$(document).ready(function(){ | ||||||
| 		tableAJAX(); //populate the table | 		renderUsers(); //populate the table | ||||||
|  | 		$('form[action="user/"]').attr('evalAJAX', 'renderUsers()') | ||||||
| 	}); | 	}); | ||||||
| </script> | </script> | ||||||
| <div class="row" style="display:none"> | <div class="row" style="display:none"> | ||||||
| 	<div class="col-md-4"> | 	<div class="col-md-4"> | ||||||
| 		<div class="card"> | 		<div class="card shadow-lg"> | ||||||
| 			<div class="card-header"> | 			<div class="card-header"> | ||||||
| 				<i class="fas fa-user-plus"></i> | 				<i class="fas fa-user-plus"></i> | ||||||
| 				Add new user | 				Add new user | ||||||
| @ -55,7 +68,7 @@ | |||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<div class="col-md-8"> | 	<div class="col-md-8"> | ||||||
| 		<div class="card"> | 		<div class="card shadow-lg"> | ||||||
| 			<div class="card-header"> | 			<div class="card-header"> | ||||||
| 				<i class="fad fa-th-list"></i> | 				<i class="fad fa-th-list"></i> | ||||||
| 				User List | 				User List | ||||||
| @ -65,9 +78,13 @@ | |||||||
| 				<div class="table-responsive"> | 				<div class="table-responsive"> | ||||||
| 					<table class="table"> | 					<table class="table"> | ||||||
| 						<thead> | 						<thead> | ||||||
|  | 							<th>id</th> | ||||||
|  | 							<th>uid</th> | ||||||
| 							<th>Name</th> | 							<th>Name</th> | ||||||
| 							<th>Password</th> | 							<th>eMail</th> | ||||||
| 							<th>Delete</th> | 							<th>Sudo</th> | ||||||
|  | 							<th>key</th> | ||||||
|  | 							<th></th> | ||||||
| 						</thead> | 						</thead> | ||||||
| 						<tbody id="tableAJAX"> | 						<tbody id="tableAJAX"> | ||||||
| 							<!-- ajax loaded table --> | 							<!-- ajax loaded table --> | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user