firt
This commit is contained in:
3
nodejs/views/bottom.ejs
Executable file
3
nodejs/views/bottom.ejs
Executable file
@ -0,0 +1,3 @@
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
25
nodejs/views/email_templates/reset_link.js
Normal file
25
nodejs/views/email_templates/reset_link.js
Normal file
@ -0,0 +1,25 @@
|
||||
module.exports = {
|
||||
subject: 'Password reset for Theta 42 account',
|
||||
message: `
|
||||
<h2> Theta 42 account</h2>
|
||||
|
||||
<p>
|
||||
Hello {{ user.givenName }},
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You have asked to reset the password for user name <b>{{ user.uid }}</b> . Please
|
||||
click the link below to complete this request. If this was done in errror,
|
||||
please ignore this email.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{{ link }}
|
||||
</p>
|
||||
|
||||
</p>
|
||||
Thank you,<br />
|
||||
Theta 42
|
||||
</p>
|
||||
`
|
||||
};
|
24
nodejs/views/email_templates/validate_link.js
Normal file
24
nodejs/views/email_templates/validate_link.js
Normal file
@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
subject: 'Validate email for Theta 42 account',
|
||||
message: `
|
||||
<h2> Theta 42 account</h2>
|
||||
|
||||
<p>
|
||||
Welcome,
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We need to verify the provided email address in order to continue. Please
|
||||
follow the link below to verify this email address:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{{ link }}
|
||||
</p>
|
||||
|
||||
</p>
|
||||
Thank you,<br />
|
||||
Theta 42
|
||||
</p>
|
||||
`
|
||||
};
|
34
nodejs/views/email_templates/welcome.js
Normal file
34
nodejs/views/email_templates/welcome.js
Normal file
@ -0,0 +1,34 @@
|
||||
module.exports = {
|
||||
subject: 'Welcome to Theta 42!',
|
||||
message: `
|
||||
<p>
|
||||
Welcome {{user.givenName}},
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Your new Theta 42 Single sign-on account is ready to use. Here is some
|
||||
information to get you started.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Your username is <b>{{user.uid}}</b>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can manage your account at https://sso.theta42.com
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You account is ready to be used now, test it by SSHing into the Theta 42
|
||||
jump host \`ssh {{user.uid}}@718it.biz\`
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The SSO service is still in beta, so please report any bugs you may find!
|
||||
You will be notified of new features and services as they become available.
|
||||
</p>
|
||||
Thank you,<br />
|
||||
Theta 42
|
||||
</p>
|
||||
`
|
||||
};
|
217
nodejs/views/groups.ejs
Normal file
217
nodejs/views/groups.ejs
Normal file
@ -0,0 +1,217 @@
|
||||
<%- include('top') %>
|
||||
<script id="rowTemplate" type="text/html">
|
||||
<div id="group-card-{{cn}}" class="card shadow">
|
||||
<div class="card-header">
|
||||
<h5>
|
||||
<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 class="card-header actionMessage" style="display:none"></div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
{{ description }}
|
||||
</p>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="group-memmbers-{{cn}}" role="tabpanel" aria-labelledby="member-tab">
|
||||
<p>
|
||||
<ul class="list-group">
|
||||
{{ #member }}
|
||||
<li id="group-card-{{cn}}-{{uid}}" class="list-group-item shadow">
|
||||
<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>
|
||||
<div class="dropdown-menu shadow-lg" aria-labelledby="group_add_member">
|
||||
{{ #toAdd }}{{#.}}
|
||||
<a class="dropdown-item" action="group/{{groupCN}}/{{uid}}" method="put" onclick="formAJAX(this)" evalAJAX="addedUser(data.message, '{{groupCN}}', '{{uid}}', $form);">
|
||||
<i class="fad fa-user"></i> {{uid}}
|
||||
</a>
|
||||
{{/.}}{{ /toAdd }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="group-admins-{{cn}}" role="tabpanel" aria-labelledby="admin-tab">
|
||||
<p>
|
||||
<ul class="list-group">
|
||||
{{ #owner }}
|
||||
<li class="list-group-item shadow">
|
||||
<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">
|
||||
<i class="fad fa-user-slash"></i>
|
||||
</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>
|
||||
</div>
|
||||
<br/>
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var userlist;
|
||||
|
||||
function getUserList(callback){
|
||||
app.user.list(function(error, data){
|
||||
userlist = data.results;
|
||||
callback()
|
||||
});
|
||||
}
|
||||
|
||||
function addedUser(message, group, user, $form){
|
||||
tableAJAX(null, function(){
|
||||
app.util.actionMessage(message, $("#group-card-"+group), 'success');
|
||||
|
||||
|
||||
$('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 $target = $('#tableAJAX');
|
||||
|
||||
$target.html('').hide();
|
||||
app.util.actionMessage('Refreshing user list...', $target);
|
||||
|
||||
app.group.list(function(error, data){
|
||||
var out = ''
|
||||
$.each(data.results, function(key, value) {
|
||||
|
||||
value.toAdd = userlist.map(function(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){
|
||||
return {
|
||||
dn: user,
|
||||
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;
|
||||
out += Mustache.render(rowTemplate, value);
|
||||
});
|
||||
|
||||
$target.html(out);
|
||||
|
||||
$target.fadeIn('slow', ($.isFunction(callback) ? callback: function(){})());
|
||||
|
||||
app.util.actionMessage(actionMessage || '', $target, 'info');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
getUserList(tableAJAX);
|
||||
});
|
||||
</script>
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-4">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-layer-plus"></i>
|
||||
Add new group
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none"></div>
|
||||
<div class="card-body">
|
||||
<form action="group/" method="post" onsubmit="formAJAX(this)" evalAJAX="tableAJAX('')">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Name</label>
|
||||
<input type="text" class="form-control shadow" name="name" placeholder="app_gitea_admin" validate=":3" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Description</label>
|
||||
<textarea class="form-control shadow" name="description" placeholder="Admin group for gitea app" validate=":3"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-outline-dark">Add</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8" id="tableAJAX">
|
||||
</div>
|
||||
</div>
|
||||
<%- include('bottom') %>
|
337
nodejs/views/home.ejs
Normal file
337
nodejs/views/home.ejs
Normal file
@ -0,0 +1,337 @@
|
||||
<%- include('top') %>
|
||||
<script id="profileTemplate" type="text/html">
|
||||
<div class="card-body profile-body-{{uid}}">
|
||||
<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>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" /> -->
|
||||
</div>
|
||||
<div class="card-footer profile-body-{{uid}}">
|
||||
<div class="float-left">
|
||||
<i>Joined:</i> <b>{{createTimestamp}} </b> <br/>
|
||||
<i>Edited:</i> <b>{{modifyTimestamp}} </b>
|
||||
</div>
|
||||
<div class="float-right">
|
||||
<button type="button" onclick="editUser()" class="btn btn-warning btn shadow ">
|
||||
<i class="fad fa-user-edit"></i>
|
||||
</button>
|
||||
<button type="submit" class="btn btn btn-danger" action="user/{{uid}}" method="delete" onsubmit="formAJAX(this)" evalAJAX="window.location.href = '/users'">
|
||||
<i class="fad fa-user-slash"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</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(data.message)">
|
||||
<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)" class="form-group">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Password</label>
|
||||
<div class="input-group mb-3 shadow">
|
||||
<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">Again</label>
|
||||
<div class="input-group mb-3 shadow">
|
||||
<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>
|
||||
<button type="submit" class="btn btn-outline-secondary shadow">Change</button>
|
||||
</form>
|
||||
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
var currentUser;
|
||||
|
||||
function getInvite(){
|
||||
app.user.createInvite(function(error, data){
|
||||
$('#invite_token').html(location.origin+"/login/invite/"+data.token);
|
||||
});
|
||||
}
|
||||
|
||||
function renderProfile(user, message){
|
||||
var profileTemplate = $('#profileTemplate').html();
|
||||
var paswordResetTemplate = $('#paswordResetTemplate').html();
|
||||
var $target = $('#userProfile div.actionMessage');
|
||||
|
||||
$('.profile-body-'+user.uid).remove();
|
||||
|
||||
app.util.actionMessage(message, $target, 'success')
|
||||
|
||||
// data.photo = unescape(encodeURIComponent(data.jpegPhoto));
|
||||
user.createTimestamp = moment(user.createTimestamp, "YYYYMMDDHHmmssZ").fromNow();
|
||||
user.modifyTimestamp = moment(user.modifyTimestamp, "YYYYMMDDHHmmssZ").fromNow();
|
||||
|
||||
$target.after(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, '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(message){
|
||||
console.log('edit done')
|
||||
$('#editProfile').slideUp();
|
||||
app.auth.isLoggedIn(function(){
|
||||
determinUser(function(user){
|
||||
currentUser = user;
|
||||
app.auth.user = user;
|
||||
renderProfile(user, message);
|
||||
renderUserGroups(user);
|
||||
$('#userProfile').slideDown();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
determinUser(function(user){
|
||||
currentUser = user;
|
||||
renderProfile(user);
|
||||
renderUserGroups(user);
|
||||
$('#username').text(user.uid);
|
||||
$('form[action="user/{{uid}}"]').attr('action', 'user/'+user.uid)
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<style type="text/css">
|
||||
.services-list i{
|
||||
padding-right: .5em;
|
||||
}
|
||||
</style>
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-4">
|
||||
<div class="shadow-lg card mb-3 card-default">
|
||||
<div class="card-header shadow">
|
||||
<i class="fas fa-user-plus"></i>
|
||||
Invite User
|
||||
<div class="float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header shadow actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<button onclick="getInvite(this)" class="btn btn-outline-dark shadow">New Invite Token</button>
|
||||
<div>
|
||||
<b id="invite_token"></b>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="shadow-lg card mb-3 card-default">
|
||||
<div class="card-header shadow">
|
||||
<div class="float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
<i class="fad fa-th-list"></i>
|
||||
Services
|
||||
</div>
|
||||
<div class="card-header shadow actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="list-group text-dark services-list">
|
||||
<li class="list-group-item text-dark">
|
||||
<i class="fad fa-terminal"></i>
|
||||
SSH <b id="username"></b>@718it.biz:22
|
||||
</li>
|
||||
<a href="https://emby.718it.biz/" target="_blank" class="text-dark">
|
||||
<li class="list-group-item text-dark">
|
||||
<i class="fad fa-film"></i>
|
||||
Emby
|
||||
</li>
|
||||
</a>
|
||||
<a href="https://git.theta42.com" target="_blank" class="text-dark">
|
||||
<li class="list-group-item text-dark">
|
||||
<i class="fab fa-git"></i>
|
||||
Git server
|
||||
</li>
|
||||
</a>
|
||||
<a href="https://rdp.vm42.us" target="_blank" class="text-dark">
|
||||
<li class="list-group-item text-dark">
|
||||
<i class="fad fa-desktop"></i>
|
||||
Virtual Desktops
|
||||
</li>
|
||||
</a>
|
||||
<a href="https://pve.admin.vm42.us" target="_blank" class="text-dark">
|
||||
<li class="list-group-item text-dark">
|
||||
<i class="fad fa-server"></i>
|
||||
Promox (contact wmanlty for access)
|
||||
</li>
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shadow-lg card">
|
||||
<div class="card-header shadow">
|
||||
<i class="fad fa-undo-alt"></i>
|
||||
Password Reset
|
||||
<div class="float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header shadow actionMessage" style="display:none">
|
||||
</div>
|
||||
<div id="passwordReset" class="card-body">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div id="userProfile" class="shadow-lg card card-default mb-8">
|
||||
<div class="card-header shadow">
|
||||
<i class="fad fa-id-card"></i>
|
||||
Profile
|
||||
<div class="float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header shadow actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="profile-body">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editProfile" class="shadow-lg card card-default mb-8" style="display:none">
|
||||
<div class="card-header shadow">
|
||||
<i class="fad fa-id-card"></i>
|
||||
Edit Profile
|
||||
<div class="float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header shadow 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 shadow">
|
||||
<i class="fad fa-id-card"></i>
|
||||
My groups
|
||||
<div class="float-right">
|
||||
<i class="far fa-arrows-v"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-header shadow 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') %>
|
2
nodejs/views/index.ejs
Executable file
2
nodejs/views/index.ejs
Executable file
@ -0,0 +1,2 @@
|
||||
<% include top %>
|
||||
<% include bottom %>
|
39
nodejs/views/invite.ejs
Normal file
39
nodejs/views/invite.ejs
Normal file
@ -0,0 +1,39 @@
|
||||
<%- include('top') %>
|
||||
<script type="text/javascript">
|
||||
function tableAJAX(message){
|
||||
app.util.actionMessage(message);
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
$('form').attr('action', 'auth/invite/<%= invite.token %>/<%= invite.mail_token %>').attr('evalAJAX', 'location.replace("/login");')
|
||||
$('[name="mail"').val('<%= invite.mail %>').prop("disabled", true);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
div.form-group:hover {
|
||||
-ms-transform: scale(1.02);
|
||||
-webkit-transform: scale(1.02);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-12">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
Add new user
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Invited By: <b><%= invite.created_by %></b>, <%= invite.created_on %>
|
||||
</p>
|
||||
<%- include('user_form') %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%- include('bottom') %>
|
59
nodejs/views/invite_email.ejs
Normal file
59
nodejs/views/invite_email.ejs
Normal file
@ -0,0 +1,59 @@
|
||||
<%- include('top') %>
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
var emailSent = function(){
|
||||
$('#email_card .card-body').html("<h1>Thank you!</h1><p>Check your mail</p>")
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
});
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
div.form-group:hover {
|
||||
-ms-transform: scale(1.02);
|
||||
-webkit-transform: scale(1.02);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="row">
|
||||
<div id="email_card" class="card-deck">
|
||||
<div class="shadow-lg card mb-3">
|
||||
<div class="card-header">
|
||||
Validate Email
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Invited By: <b><%= invite.created_by %></b>, <%= invite.created_on %>.
|
||||
</p>
|
||||
<p>
|
||||
Please enter a valid email address. A link will be sent to
|
||||
the supplied address to complete the registration process.
|
||||
</p>
|
||||
<p>
|
||||
The supplied email will also be used as the linked email for
|
||||
the new user.
|
||||
</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" validate="email:3" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-outline-dark"><i class="fad fa-paper-plane"></i> Send It!</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%- include('bottom') %>
|
100
nodejs/views/login.ejs
Executable file
100
nodejs/views/login.ejs
Executable file
@ -0,0 +1,100 @@
|
||||
<%- include('top') %>
|
||||
<script type="text/javascript">
|
||||
|
||||
app.auth.isLoggedIn(function(error, isLoggedIn){
|
||||
if(isLoggedIn){
|
||||
window.location.href = app.util.getUrlParameter('redirect') || '/';
|
||||
}
|
||||
})
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="row">
|
||||
<div class="card-deck">
|
||||
<div class="shadow-lg card mb-3">
|
||||
<div class="card-header shadow">
|
||||
Password Log in
|
||||
</div>
|
||||
<div class="card-header shadow actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="auth/login" onsubmit="formAJAX(this)" evalAJAX="app.auth.setToken(data.token);window.location.href = app.util.getUrlParameter('redirect') || '/';">
|
||||
<input type="hidden" name="redirect" value="<%= redirect %>">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">User name</label>
|
||||
<div class="input-group mb-3 shadow">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" ><i class="fad fa-user"></i></span>
|
||||
</div>
|
||||
<input type="text" name="uid" class="form-control" placeholder="jsmith" validate="user:3" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Password</label>
|
||||
<div class="input-group mb-3 shadow">
|
||||
<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=":3" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-outline-dark"><i class="fad fa-sign-in"></i> Log in</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shadow-lg card border-danger mb-3">
|
||||
<div class="card-header shadow">
|
||||
Social Login
|
||||
</div>
|
||||
<div class="card-header shadow actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h3>Coming soon!</h3>
|
||||
<p>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><i class="fab fa-google"></i> Login with google OATH</li>
|
||||
<li class="list-group-item"><i class="fab fa-github"></i> Login with github OATH</li>
|
||||
<li class="list-group-item"><i class="fab fa-facebook"></i> Login with facebook OATH</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shadow-lg card mb-3">
|
||||
<div class="card-header shadow">
|
||||
Password Reset
|
||||
</div>
|
||||
<div class="card-header shadow actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
Forgot your password? Or your user name? No problem! Just
|
||||
enter you email address below and if you are in our system,
|
||||
we will email with the required information to get back up
|
||||
and running!
|
||||
</p>
|
||||
<form action="auth/resetpassword" onsubmit="formAJAX(this)">
|
||||
<input type="hidden" name="redirect" value="<%= redirect %>">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Email</label>
|
||||
<div class="input-group mb-3 shadow">
|
||||
<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" validate="email:3" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-outline-dark"><i class="fad fa-question"></i> Help me!</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%- include('bottom') %>
|
43
nodejs/views/reset_password.ejs
Normal file
43
nodejs/views/reset_password.ejs
Normal file
@ -0,0 +1,43 @@
|
||||
<%- include('top') %>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
|
||||
});
|
||||
</script>
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-12">
|
||||
<div class="card mb-3 shadow-lg">
|
||||
<div class="card-header">
|
||||
Password reset
|
||||
</div>
|
||||
<div class="card-header shadow actionMessage" style="display:none">
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<form action="auth/resetpassword/<%= token.token%>" method="post" onsubmit="formAJAX(this)">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Password</label>
|
||||
<div class="input-group mb-3 shadow">
|
||||
<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">Again</label>
|
||||
<div class="input-group mb-3 shadow">
|
||||
<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>
|
||||
<button type="submit" class="btn btn-outline-dark">Change</button>
|
||||
</form>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%- include('bottom') %>
|
39
nodejs/views/top.ejs
Executable file
39
nodejs/views/top.ejs
Executable file
@ -0,0 +1,39 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>SSO Manager - Theta 42</title>
|
||||
<!-- CSS are placed here -->
|
||||
<link rel="stylesheet" href="/static/css/bootstrap-4.4.1.min.css">
|
||||
<link rel='stylesheet' href='/static/css/styles.css' />
|
||||
<!-- Scripts are placed here -->
|
||||
<script type="text/javascript" src='/static/js/jquery-3.5.0.min.js'></script>
|
||||
<script type="text/javascript" src="/static/js/popper-1.16.0.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/bootstrap-4.4.1.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/all.min.js"></script>
|
||||
<script type="text/javascript" src='/static/js/mustache.min.js'></script>
|
||||
<script type="text/javascript" src="/static/js/app.js"></script>
|
||||
<script type="text/javascript" src="/static/js/val.js"></script>
|
||||
<script type="text/javascript" src="/static/js/moment.js"></script>
|
||||
|
||||
|
||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<header class="shadow d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
|
||||
<h5 class="hover-effect my-0 mr-md-auto font-weight-normal">SSO Manager - Theta 42</h5>
|
||||
<nav class="my-2 my-md-0 mr-md-3">
|
||||
<a class="text-dark hover-effect" href="/"><i class="fad fa-tachometer-alt-fastest"></i>Home</a>
|
||||
<a class="text-dark hover-effect" href="/users"><i class="fad fa-users"></i>Users</a>
|
||||
<a class="text-dark hover-effect" href="/groups"><i class="fad fa-users-class"></i>Groups</a>
|
||||
</nav>
|
||||
<a class="hover-effect btn btn-outline-primary" onclick="app.auth.logOut(e => window.location.href='/')"><i class="fas fa-sign-out"></i> Log Out</a>
|
||||
|
||||
</header>
|
||||
|
||||
<!-- Container -->
|
||||
<div class="container">
|
41
nodejs/views/user_form.ejs
Normal file
41
nodejs/views/user_form.ejs
Normal file
@ -0,0 +1,41 @@
|
||||
<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>
|
||||
<input type="text" class="form-control shadow" name="givenName" placeholder="John" validate=":3" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Last name</label>
|
||||
<input type="text" class="form-control shadow" name="sn" placeholder="smith" validate=":3" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Email</label>
|
||||
<input type="text" class="form-control shadow" 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 shadow" name="sshPublicKey" placeholder="ssh-rsa AAAAB3NzaC1yc2EAAAADAQ..." />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Mobile Phone</label>
|
||||
<input type="text" class="form-control shadow" name="mobile" placeholder="9175551234" validate=":9" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Password</label>
|
||||
<input type="password" class="form-control shadow" name="userPassword" placeholder="Atleast 5 char. long" validate="password:5"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label">Again</label>
|
||||
<input type="password" class="form-control shadow" name="passwordMatch" placeholder="Retype password" validate="eq:userPassword"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label">User Description (Optional)</label>
|
||||
<textarea class="form-control shadow" name="description" placeholder="Admin group for gitea app"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-dark">Add</button>
|
||||
</form>
|
96
nodejs/views/users.ejs
Executable file
96
nodejs/views/users.ejs
Executable file
@ -0,0 +1,96 @@
|
||||
<%- include('top') %>
|
||||
<script id="rowTemplate" type="text/html">
|
||||
<tr class="" action="user/password/{{ username }}" method="put" evalAJAX="$form.trigger('reset')">
|
||||
<td>
|
||||
{{ uidNumber }}
|
||||
</td>
|
||||
<td>
|
||||
<a href='/users/{{uid}}'>{{ uid }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{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>
|
||||
<form action="user/{{uid}}" method="delete" onsubmit="formAJAX(this)" evalAJAX="renderUsers('Deleted {{uid}}', 'success')">
|
||||
<button type="submit" class="btn btn-sm btn-danger">
|
||||
<i class="fad fa-user-slash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function renderUsers(actionMessage, type){
|
||||
var rowTemplate = $('#rowTemplate').html();
|
||||
var $target = $('#tableAJAX');
|
||||
|
||||
$target.html('').hide();
|
||||
app.util.actionMessage('Refreshing user list...', $target);
|
||||
|
||||
app.user.list(function(error, data){
|
||||
$.each( data.results, function(key, value) {
|
||||
if(value.uidNumber<1500) return;
|
||||
user_row = Mustache.render(rowTemplate, value);
|
||||
$target.append(user_row);
|
||||
});
|
||||
|
||||
$target.fadeIn('slow');
|
||||
|
||||
app.util.actionMessage(actionMessage || '', $target, type || 'info');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
renderUsers(); //populate the table
|
||||
$('form[action="user/"]').attr('evalAJAX', 'renderUsers("User added", "success")')
|
||||
});
|
||||
</script>
|
||||
<div class="row" style="display:none">
|
||||
<div class="col-md-4">
|
||||
<div class="card shadow-lg">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-user-plus"></i>
|
||||
Add new user
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none"></div>
|
||||
<div class="card-body">
|
||||
<%- include('user_form') %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow">
|
||||
<div class="card-header">
|
||||
<i class="fad fa-th-list"></i>
|
||||
User List
|
||||
</div>
|
||||
<div class="card-header actionMessage" style="display:none"></div>
|
||||
<table class="card-body table table-striped" style="margin-bottom:0">
|
||||
<thead>
|
||||
<th>ID</th>
|
||||
<th>User Name</th>
|
||||
<th>Name</th>
|
||||
<th>eMail</th>
|
||||
<th>Sudo</th>
|
||||
<th>Key</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody id="tableAJAX">
|
||||
<!-- ajax loaded table -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%- include('bottom') %>
|
Reference in New Issue
Block a user