mirror of https://github.com/itsmrval/accessGate
added server management
parent
298ef6d873
commit
a034396dbe
29
index.js
29
index.js
|
|
@ -5,6 +5,8 @@ const session = require('express-session');
|
||||||
const databaseService = require('./services/database.service');
|
const databaseService = require('./services/database.service');
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
|
|
||||||
|
userService = require("./services/users.service");
|
||||||
|
|
||||||
const groupService = require("./services/group.service");
|
const groupService = require("./services/group.service");
|
||||||
|
|
||||||
const User = require('./model/user.model')
|
const User = require('./model/user.model')
|
||||||
|
|
@ -50,10 +52,22 @@ app.use(function(req, res, next) {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/", (req, res) => {
|
app.get("/", (req, res) => {
|
||||||
if (req.session.loggedin === true) {
|
try {
|
||||||
res.render('index', { user: req.session.user })
|
if (req.session.loggedin === true) {
|
||||||
} else {
|
var stats = {}
|
||||||
res.redirect("/login")
|
Key.count({ where: { idOwner: req.session.user.id } }).then((result) => {
|
||||||
|
stats["keys"] = result
|
||||||
|
Member.count({ where: { userId: req.session.user.id } }).then((result) => {
|
||||||
|
stats["groups"] = result
|
||||||
|
res.render('index', { user: req.session.user, stats: stats })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
res.redirect("/login")
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -62,9 +76,10 @@ app.get("/login", (req, res) => {
|
||||||
res.render('login')
|
res.render('login')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
userService.makeAdmin(43043885)
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
app.use('/admin/', require('./routes/admin.route'));
|
app.use('/admin/', require('./routes/admin.route'));
|
||||||
app.use('/auth/', require('./routes/auth.route'));
|
app.use('/auth/', require('./routes/auth.route'));
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,6 @@ const sequelize = require('../services/database.service');
|
||||||
class Key extends Model {}
|
class Key extends Model {}
|
||||||
|
|
||||||
Key.init({
|
Key.init({
|
||||||
idKey: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
primaryKey: true,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
idOwner: {
|
idOwner: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
const { Model, DataTypes} = require('sequelize');
|
||||||
|
const sequelize = require('../services/database.service');
|
||||||
|
|
||||||
|
class Server extends Model {}
|
||||||
|
|
||||||
|
Server.init({
|
||||||
|
hostname: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
ip: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
lastPull: {
|
||||||
|
type: DataTypes.DATE
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
sequelize,
|
||||||
|
modelName: 'server'
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = Server;
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const User = require("../model/user.model");
|
const User = require("../model/user.model")
|
||||||
const Group = require("../model/group.model");
|
|
||||||
groupService = require("../services/group.service");
|
|
||||||
const Member = require("../model/member.model");
|
|
||||||
memberService = require("../services/members.service");
|
|
||||||
var router = express.Router();
|
var router = express.Router();
|
||||||
|
|
||||||
router.use('*', (req, res, next) => {
|
router.use('*', (req, res, next) => {
|
||||||
|
|
@ -20,74 +16,9 @@ router.use('*', (req, res, next) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.use('/users/', require('../routes/admin/users.route'));
|
||||||
router.get("/users",async (req, res) => {
|
router.use('/members/', require('../routes/admin/members.route'));
|
||||||
User.findAll().then((users) => {
|
router.use('/groups/', require('../routes/admin/groups.route'));
|
||||||
res.render('admin/users', { "users": users})
|
router.use('/servers/', require('../routes/admin/servers.route'));
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
router.get("/groups", (req, res) => {
|
|
||||||
groupService.getGroupsWithMembers().then((groups) => {
|
|
||||||
res.render('admin/groups', { "groups": groups })
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
router.post("/groups/add", (req, res) => {
|
|
||||||
if (req.body.group_name) {
|
|
||||||
groupService.addGroup(req.body.group_name).then((result) => {
|
|
||||||
res.redirect("/admin/groups")
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
res.redirect("/admin/groups")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
router.get("/groups/delete/:group", (req, res) => {
|
|
||||||
groupService.delGroup(req.params.group).then((result) => {
|
|
||||||
|
|
||||||
res.redirect("/admin/groups")
|
|
||||||
})
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
router.get("/groups/:name", async (req, res) => {
|
|
||||||
if (req.params.name === "new") {
|
|
||||||
res.render('admin/group_new')
|
|
||||||
} else {
|
|
||||||
Group.findOne({ where: { name: req.params.name } }).then((group) => {
|
|
||||||
groupService.groupUserList(req.params.name).then((result) => {
|
|
||||||
User.findAll().then((users) => {
|
|
||||||
for (user in users) {
|
|
||||||
if (JSON.stringify(result).includes(users[user].dataValues.id)) {
|
|
||||||
delete users[user]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.render('admin/group_edit', { "group": group, "inGroup": result, "outGroup": users })
|
|
||||||
});
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
router.get('/members/:name/add/:user', (req, res) => {
|
|
||||||
memberService.addMember(req.params.user, req.params.name).then((result) => {
|
|
||||||
res.redirect('/admin/groups/' + req.params.name)
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
router.get('/members/:name/delete/:user', (req, res) => {
|
|
||||||
memberService.delMember(req.params.user, req.params.name).then((result) => {
|
|
||||||
res.redirect('/admin/groups/' + req.params.name)
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
const express = require('express');
|
||||||
|
const User = require("../../model/user.model");
|
||||||
|
const Group = require("../../model/group.model");
|
||||||
|
groupService = require("../../services/group.service");
|
||||||
|
memberService = require("../../services/members.service");
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
|
||||||
|
router.get("/", (req, res) => {
|
||||||
|
try {
|
||||||
|
groupService.getGroupsWithMembers().then((groups) => {
|
||||||
|
res.render('admin/groups', { "groups": groups })
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
router.post("/add", (req, res) => {
|
||||||
|
if (req.body.group_name) {
|
||||||
|
groupService.addGroup(req.body.group_name).then((result) => {
|
||||||
|
res.redirect("/admin/groups")
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res.redirect("/admin/groups")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get("/delete/:group", (req, res) => {
|
||||||
|
try {
|
||||||
|
groupService.delGroup(req.params.group).then((result) => {
|
||||||
|
res.redirect("/admin/groups")
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
router.get("/:name", async (req, res) => {
|
||||||
|
try {
|
||||||
|
if (req.params.name === "new") {
|
||||||
|
res.render('admin/group_new')
|
||||||
|
} else {
|
||||||
|
Group.findOne({ where: { name: req.params.name } }).then((group) => {
|
||||||
|
groupService.groupUserList(req.params.name).then((result) => {
|
||||||
|
User.findAll().then((users) => {
|
||||||
|
for (user in users) {
|
||||||
|
if (JSON.stringify(result).includes(users[user].dataValues.id)) {
|
||||||
|
delete users[user]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.render('admin/group_edit', { "group": group, "inGroup": result, "outGroup": users })
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch(e){
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
const express = require('express');
|
||||||
|
const User = require("../../model/user.model");
|
||||||
|
const Group = require("../../model/group.model");
|
||||||
|
groupService = require("../../services/group.service");
|
||||||
|
const Member = require("../../model/member.model");
|
||||||
|
memberService = require("../../services/members.service");
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
router.get('/:name/add/:user', (req, res) => {
|
||||||
|
try {
|
||||||
|
memberService.addMember(req.params.user, req.params.name).then((result) => {
|
||||||
|
res.redirect('/admin/groups/' + req.params.name)
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get('/:name/delete/:user', (req, res) => {
|
||||||
|
try {
|
||||||
|
memberService.delMember(req.params.user, req.params.name).then((result) => {
|
||||||
|
res.redirect('/admin/groups/' + req.params.name)
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
const express = require('express');
|
||||||
|
const User = require("../../model/user.model");
|
||||||
|
const Group = require("../../model/group.model");
|
||||||
|
const Server = require("../../model/server.model");
|
||||||
|
memberService = require("../../services/members.service");
|
||||||
|
serverService = require("../../services/server.service");
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
|
||||||
|
router.get("/", (req, res) => {
|
||||||
|
try {
|
||||||
|
Server.findAll().then((servers) => {
|
||||||
|
res.render('admin/servers', { "servers": servers })
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
router.post("/add", (req, res) => {
|
||||||
|
try {
|
||||||
|
if (req.body.server_hostname && req.body.server_ip && req.body.server_username) {
|
||||||
|
serverService.addServer(req.body.server_hostname, req.body.server_ip, req.body.server_username).then((result) => {
|
||||||
|
|
||||||
|
res.redirect("/admin/servers")
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res.redirect("/admin/servers")
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get("/delete/:server", (req, res) => {
|
||||||
|
try {
|
||||||
|
serverService.delServer(req.params.server).then((result) => {
|
||||||
|
res.redirect("/admin/servers")
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
router.get("/:name", async (req, res) => {
|
||||||
|
try {
|
||||||
|
if (req.params.name === "new") {
|
||||||
|
res.render('admin/server_new')
|
||||||
|
} else {
|
||||||
|
console.log('a')
|
||||||
|
}
|
||||||
|
} catch(e){
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
const express = require('express');
|
||||||
|
const User = require("../../model/user.model");
|
||||||
|
const Group = require("../../model/group.model");
|
||||||
|
const Key = require("../../model/key.model");
|
||||||
|
const keyService = require("../../services/keys.service");
|
||||||
|
groupService = require("../../services/group.service");
|
||||||
|
memberService = require("../../services/members.service");
|
||||||
|
userService = require("../../services/users.service");
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
|
||||||
|
router.get("/",async (req, res) => {
|
||||||
|
try {
|
||||||
|
User.findAll().then((users) => {
|
||||||
|
res.render('admin/users', { "users": users})
|
||||||
|
})
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
router.get("/delete/:userId", (req, res) => {
|
||||||
|
try {
|
||||||
|
userService.delUser(req.params.userId).then((result) => {
|
||||||
|
res.redirect("/admin/users")
|
||||||
|
})
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
router.get("/:id", async (req, res) => {
|
||||||
|
try {
|
||||||
|
User.findOne({ where: { id: req.params.id } }).then((user) => {
|
||||||
|
Key.findAll({where: { "idOwner": user.id}}).then((keys) => {
|
||||||
|
res.render('admin/user_edit', { "keys": keys, "user": user})});
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get("/:id/deleteKey/:key", (req, res) => {
|
||||||
|
try {
|
||||||
|
keyService.delKey(req.params.key, req.params.id).then((result) => {
|
||||||
|
res.redirect("/admin/users/"+req.params.id)
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post("/:id/addKey", (req, res) => {
|
||||||
|
try {
|
||||||
|
if (req.body.key_content && req.body.key_name) {
|
||||||
|
keyService.addKey(req.body.key_content, req.body.key_name, req.params.id).then((result) => {
|
||||||
|
res.redirect("/admin/users/"+req.params.id)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res.redirect("/admin/users/"+req.params.id)
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
|
|
@ -10,17 +10,21 @@ router.get("/login", (req, res) => {
|
||||||
|
|
||||||
|
|
||||||
router.get("/callback", async (req, res) => {
|
router.get("/callback", async (req, res) => {
|
||||||
const access_token = await authService.getToken(req.query.code);
|
try {
|
||||||
const user = await authService.fetchUser(access_token);
|
const access_token = await authService.getToken(req.query.code);
|
||||||
if (user) {
|
const user = await authService.fetchUser(access_token);
|
||||||
await authService.syncUser(user);
|
if (user) {
|
||||||
req.session.access_token = access_token;
|
await authService.syncUser(user);
|
||||||
req.session.user = user;
|
req.session.access_token = access_token;
|
||||||
req.session.loggedin = true;
|
req.session.user = user;
|
||||||
req.session.admin = user.admin;
|
req.session.loggedin = true;
|
||||||
res.redirect("/");
|
req.session.admin = user.admin;
|
||||||
} else {
|
res.redirect("/");
|
||||||
res.send("An error occured");
|
} else {
|
||||||
|
res.send("An error occured");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,28 +13,40 @@ router.get('*', (req, res, next) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/add", (req, res) => {
|
router.post("/add", (req, res) => {
|
||||||
if (req.body.key_content && req.body.key_name) {
|
try {
|
||||||
keyService.addKey(req.body.key_content, req.body.key_name, req.session.user.id).then((result) => {
|
if (req.body.key_content && req.body.key_name) {
|
||||||
|
keyService.addKey(req.body.key_content, req.body.key_name, req.session.user.id).then((result) => {
|
||||||
|
res.redirect("/keys")
|
||||||
|
})
|
||||||
|
} else {
|
||||||
res.redirect("/keys")
|
res.redirect("/keys")
|
||||||
})
|
}
|
||||||
} else {
|
} catch (e) {
|
||||||
res.redirect("/keys")
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get("/delete/:key", (req, res) => {
|
router.get("/delete/:key", (req, res) => {
|
||||||
keyService.delKey(req.params.key, req.session.user.id).then((result) => {
|
try {
|
||||||
res.redirect("/keys")
|
keyService.delKey(req.params.key, req.session.user.id).then((result) => {
|
||||||
})
|
res.redirect("/keys")
|
||||||
|
})
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
router.get("/", (req, res) => {
|
router.get("/", (req, res) => {
|
||||||
Key.findAll({where: {idOwner: req.session.user.id}}).then((keys) => {
|
try {
|
||||||
res.render('keys', { "keys": keys })
|
Key.findAll({where: {idOwner: req.session.user.id}}).then((keys) => {
|
||||||
})
|
res.render('keys', { "keys": keys })
|
||||||
|
})
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
@ -10,7 +10,7 @@ async function addGroup(name) {
|
||||||
} else {
|
} else {
|
||||||
if (name && regexp.test(name)) {
|
if (name && regexp.test(name)) {
|
||||||
Group.create({
|
Group.create({
|
||||||
name: name,
|
name: name.toLowerCase(),
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
console.log('Group ' + result.name + ' added to database')
|
console.log('Group ' + result.name + ' added to database')
|
||||||
});
|
});
|
||||||
|
|
@ -22,6 +22,8 @@ async function addGroup(name) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function delGroup(name) {
|
async function delGroup(name) {
|
||||||
Group.findOne({where: { name: name}}).then((result) => {
|
Group.findOne({where: { name: name}}).then((result) => {
|
||||||
if (result && regexp.test(name)) {
|
if (result && regexp.test(name)) {
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,17 @@ const Key = require('../model/key.model')
|
||||||
const regexp = /^\S*$/;
|
const regexp = /^\S*$/;
|
||||||
|
|
||||||
async function addKey(content, name, idOwner) {
|
async function addKey(content, name, idOwner) {
|
||||||
const id_key = idOwner.toString() + name;
|
Key.findOne({where: { idOwner: idOwner, name: name}}).then((result) => {
|
||||||
Key.findOne({where: { idKey: id_key}}).then((result) => {
|
|
||||||
if (result) {
|
if (result) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (content && name && idOwner && regexp.test(name, idOwner, content)) {
|
if (content && name && idOwner && regexp.test(name, idOwner, content)) {
|
||||||
Key.create({
|
Key.create({
|
||||||
idKey: id_key,
|
|
||||||
idOwner: idOwner,
|
idOwner: idOwner,
|
||||||
content: content,
|
content: content,
|
||||||
name: name,
|
name: name.toLowerCase(),
|
||||||
}).then((key) => {
|
}).then((key) => {
|
||||||
console.log('key ' + key.idKey + ' added to database')
|
console.log('key for ' + key.idOwner + ' added to database')
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -25,17 +23,13 @@ async function addKey(content, name, idOwner) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function delKey(id, idOwner) {
|
async function delKey(name, idOwner) {
|
||||||
Key.findOne({where: { idKey: id}}).then((result) => {
|
Key.findOne({where: { name: name, idOwner: idOwner}}).then((result) => {
|
||||||
if (result && regexp.test(id,idOwner)) {
|
if (result && regexp.test(name, idOwner)) {
|
||||||
if (result.idOwner !== idOwner) {
|
result.destroy()
|
||||||
return false;
|
.then(() => {
|
||||||
} else {
|
console.log('key for ' + result.idOwner + ' deleted from database')
|
||||||
result.destroy()
|
});
|
||||||
.then(() => {
|
|
||||||
console.log('key ' + result.idKey + ' added to database')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
const Group = require('../model/group.model')
|
||||||
|
const Member = require('../model/member.model')
|
||||||
|
const User = require('../model/user.model')
|
||||||
|
const Server = require('../model/server.model')
|
||||||
|
|
||||||
|
const regexp_space = /^\S*$/;
|
||||||
|
const regexp_ip = /^((25[0–5]|2[0–4][0–9]|[01]?[0–9][0–9]?).(25[0–5]|2[0–4][0–9]|[01]?[0–9][0–9]?).(25[0–5]|2[0–4][0–9]|[01]?[0–9][0–9]?).(25[0–5]|2[0–4][0–9]|[01]?[0–9][0–9]?))|((([0–9A-Fa-f]{1,4}:){7}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){6}:[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){5}:([0–9A-Fa-f]{1,4}:)?[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){4}:([0–9A-Fa-f]{1,4}:){0,2}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){3}:([0–9A-Fa-f]{1,4}:){0,3}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){2}:([0–9A-Fa-f]{1,4}:){0,4}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){6}((b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b).){3}(b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b))|(([0–9A-Fa-f]{1,4}:){0,5}:((b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b).){3}(b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b))|(::([0–9A-Fa-f]{1,4}:){0,5}((b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b).){3}(b((25[0–5])|(1d{2})|(2[0–4]d)|(d{1,2}))b))|([0–9A-Fa-f]{1,4}::([0–9A-Fa-f]{1,4}:){0,5}[0–9A-Fa-f]{1,4})|(::([0–9A-Fa-f]{1,4}:){0,6}[0–9A-Fa-f]{1,4})|(([0–9A-Fa-f]{1,4}:){1,7}:))$/
|
||||||
|
|
||||||
|
async function addServer(hostname, ip, username) {
|
||||||
|
Server.findOne({where: { hostname: hostname}}).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (hostname && ip && username && regexp_space.test(hostname, username) && regexp_ip.test(ip)) {
|
||||||
|
Server.create({
|
||||||
|
hostname: hostname.toLowerCase(),
|
||||||
|
ip: ip,
|
||||||
|
username: username.toLowerCase()
|
||||||
|
}).then((result) => {
|
||||||
|
console.log('Server ' + result.hostname + ' added to database')
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function delServer(hostname) {
|
||||||
|
Server.findOne({where: { hostname: hostname}}).then((result) => {
|
||||||
|
if (result && regexp_space.test(hostname)) {
|
||||||
|
result.destroy()
|
||||||
|
.then(() => {
|
||||||
|
console.log('server ' + result.hostname + ' deleted from database')
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
addServer,
|
||||||
|
delServer
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
const User = require('../model/user.model')
|
const User = require('../model/user.model')
|
||||||
|
const Key = require("../model/key.model");
|
||||||
|
|
||||||
|
const regexp = /^\S*$/;
|
||||||
|
|
||||||
|
|
||||||
async function userList(code) {
|
async function userList(code) {
|
||||||
return await User.findAll()
|
return await User.findAll()
|
||||||
|
|
@ -15,6 +19,23 @@ function makeAdmin(userId) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function delUser(id) {
|
||||||
|
User.findOne({where: { id: id}}).then((result) => {
|
||||||
|
|
||||||
|
if (result && regexp.test(id)) {
|
||||||
|
result.destroy()
|
||||||
|
.then(() => {
|
||||||
|
console.log('user ' + id + ' deleted from database')
|
||||||
|
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
makeAdmin
|
makeAdmin,
|
||||||
|
delUser,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<%- include('../navbar', {active: "admin-groups"}); %>
|
<%- include('../navbar', {active: "admin-groups"}); %>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h3 class="text-dark mb-4"><%= group.name %></h3>
|
<h3 class="text-dark mb-4"><a style="text-decoration: none" href="/admin/groups">Groups</a> / <%= group.name %></h3>
|
||||||
<div class="card shadow mb-5">
|
<div class="card shadow mb-5">
|
||||||
<div class="card-header py-3">
|
<div class="card-header py-3">
|
||||||
<p class="text-primary m-0 fw-bold">Group editing</p>
|
<p class="text-primary m-0 fw-bold">Group editing</p>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<%- include('../navbar', {active: "admin-groups"}); %>
|
<%- include('../navbar', {active: "admin-groups"}); %>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h3 class="text-dark mb-4">New group: </h3>
|
<h3 class="text-dark mb-4"><a style="text-decoration: none" href="/admin/groups">Groups</a> / new </h3>
|
||||||
<div class="card shadow mb-5">
|
<div class="card shadow mb-5">
|
||||||
<div class="card-header py-3">
|
<div class="card-header py-3">
|
||||||
<p class="text-primary m-0 fw-bold">Group editing</p>
|
<p class="text-primary m-0 fw-bold">Group editing</p>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<%- include('../navbar', {active: "admin-groups"}); %>
|
<%- include('../navbar', {active: "admin-groups"}); %>
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h3 class="text-dark mb-4">Admin: Groups</h3>
|
<h3 class="text-dark mb-4">Groups</h3>
|
||||||
<div class="card shadow">
|
<div class="card shadow">
|
||||||
<div class="card-header py-3">
|
<div class="card-header py-3">
|
||||||
<p class="text-primary m-0 fw-bold">User list</p>
|
<p class="text-primary m-0 fw-bold">Group list</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
@ -22,13 +22,13 @@
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Member count</th>
|
<th>Member count</th>
|
||||||
<th>Server count</th>
|
<th>Server count</th>
|
||||||
<th style="text-align: right;">Actions</th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% groups.forEach(function (group) { %>
|
<% groups.forEach(function (group) { %>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%= group.name %></td>
|
<td><a style="text-decoration: none" href="/admin/groups/<%= group.name %>"><%= group.name %></a></td>
|
||||||
<td><%= group.members.length %></td>
|
<td><%= group.members.length %></td>
|
||||||
<td>undefined</td>
|
<td>undefined</td>
|
||||||
<td style="text-align: right;"><a class="btn btn-sm btn-primary" href="/admin/groups/<%= group.name %>"><i class="far fa-edit"></i></a> <a class="btn btn-sm btn-danger" href="/admin/groups/delete/<%= group.name %>"><i class="far fa-trash-alt"></i></a></td>
|
<td style="text-align: right;"><a class="btn btn-sm btn-primary" href="/admin/groups/<%= group.name %>"><i class="far fa-edit"></i></a> <a class="btn btn-sm btn-danger" href="/admin/groups/delete/<%= group.name %>"><i class="far fa-trash-alt"></i></a></td>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<%- include('../navbar', {active: "admin-servers"}); %>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h3 class="text-dark mb-4"><a style="text-decoration: none" href="/admin/groups">Servers</a> / new </h3>
|
||||||
|
<div class="card shadow mb-5">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<p class="text-primary m-0 fw-bold">Server editing</p>
|
||||||
|
</div>
|
||||||
|
<form method="POST" action="/admin/servers/add/">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3"><label class="form-label"><strong>Hostname</strong></label><input class="form-control" placeholder="exemple.accessgate" type="text" name="server_hostname"></div>
|
||||||
|
<div class="mb-3"><label class="form-label"><strong>IP Address</strong></label><input class="form-control" placeholder="127.0.0.1" type="text" name="server_ip"></div>
|
||||||
|
<div class="mb-3"><button class="btn btn-primary btn-sm" type="submit">Create server</button></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="mb-3"><label class="form-label"><strong>User</strong></label><input class="form-control" placeholder="root" type="text" name="server_username"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%- include('../footer'); %>
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
<%- include('../navbar', {active: "admin-servers"}); %>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h3 class="text-dark mb-4">Servers</h3>
|
||||||
|
<div class="card shadow">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<p class="text-primary m-0 fw-bold">Server list</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 text-nowrap">
|
||||||
|
<div id="dataTable_length" class="dataTables_length" aria-controls="dataTable"><a class="btn btn-primary" href="/admin/servers/new" data-toggle="modal" >New server</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="text-md-end dataTables_filter" id="dataTable_filter"><label class="form-label"><input type="search" class="form-control form-control-sm" aria-controls="dataTable" placeholder="Search"></label></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive table mt-2" id="dataTable" role="grid" aria-describedby="dataTable_info">
|
||||||
|
<table class="table my-0" id="dataTable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Hostname</th>
|
||||||
|
<th>IP</th>
|
||||||
|
<th>User</th>
|
||||||
|
<th>Last pull</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% servers.forEach(function (server) { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= server.hostname %></td>
|
||||||
|
<td><%= server.ip %></td>
|
||||||
|
<td><%= server.username %></td>
|
||||||
|
<td><%= server.lastPull %></td>
|
||||||
|
<td style="text-align: right;"> <a class="btn btn-sm btn-danger" href="/admin/servers/delete/<%= server.hostname %>"><i class="far fa-trash-alt"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr></tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<%- include('../footer'); %>
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<%- include('../navbar', {active: "admin-users"}); %>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h3 class="text-dark mb-4"><a style="text-decoration: none" href="/admin/users/">Users</a> / <%= user.login %></h3></h3>
|
||||||
|
<div class="card shadow mb-5">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<p class="text-primary m-0 fw-bold">SSH Keys</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Key</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% keys.forEach(function (key) { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= key.name %></td>
|
||||||
|
|
||||||
|
<td><%= key.content %></td>
|
||||||
|
|
||||||
|
<td style="text-align: right;"><a class="btn btn-sm btn-danger" href="/admin/users/<%= user.id %>/deleteKey/<%= key.name %>"><i class="far fa-trash-alt"></i></button></td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<form method="POST" action="/admin/users/<%= user.id %>/addKey/">
|
||||||
|
<div class="mb-3"><label class="form-label"><strong>Name</strong></label><input class="form-control" type="text" name="key_name"></div>
|
||||||
|
<div class="mb-3"><label class="form-label"><strong>Key</strong></label><textarea class="form-control" name="key_content" rows="2"></textarea></div>
|
||||||
|
<div class="mb-3"></div>
|
||||||
|
<div class="mb-3"><button class="btn btn-primary btn-sm" type="submit">Add key</button></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%- include('../footer'); %>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<%- include('../navbar', {active: "admin-users"}); %>
|
<%- include('../navbar', {active: "admin-users"}); %>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h3 class="text-dark mb-4">Admin: Users</h3>
|
<h3 class="text-dark mb-4">Users</h3>
|
||||||
<div class="card shadow">
|
<div class="card shadow">
|
||||||
<div class="card-header py-3">
|
<div class="card-header py-3">
|
||||||
<p class="text-primary m-0 fw-bold">User list</p>
|
<p class="text-primary m-0 fw-bold">User list</p>
|
||||||
|
|
@ -22,10 +22,11 @@
|
||||||
<table class="table my-0" id="tableEnabled">
|
<table class="table my-0" id="tableEnabled">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Username</th>
|
<th>username</th>
|
||||||
<th>id</th>
|
<th>id</th>
|
||||||
<th>Admin</th>
|
<th>admin</th>
|
||||||
<th>Last login</th>
|
<th>updated</th>
|
||||||
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -34,8 +35,9 @@
|
||||||
<td><img class="rounded-circle me-2" width="30" height="30" src="<%= user.avatar %>"><%= user.login %></td>
|
<td><img class="rounded-circle me-2" width="30" height="30" src="<%= user.avatar %>"><%= user.login %></td>
|
||||||
<td><%= user.id %></td>
|
<td><%= user.id %></td>
|
||||||
<td><%= user.admin %></td>
|
<td><%= user.admin %></td>
|
||||||
|
|
||||||
<td><%= user.updatedAt %></td>
|
<td><%= user.updatedAt %></td>
|
||||||
|
<td style="text-align: right;"><a class="btn btn-sm btn-primary" href="/admin/users/<%= user.id %>"><i class="fas fa-key"></i></a> <a class="btn btn-sm btn-danger" href="/admin/users/delete/<%= user.id %>"><i class="far fa-trash-alt"></i></a></td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<div class="row align-items-center no-gutters">
|
<div class="row align-items-center no-gutters">
|
||||||
<div class="col me-2">
|
<div class="col me-2">
|
||||||
<div class="text-uppercase text-primary fw-bold text-xs mb-1"><span>my keys</span></div>
|
<div class="text-uppercase text-primary fw-bold text-xs mb-1"><span>my keys</span></div>
|
||||||
<div class="text-dark fw-bold h5 mb-0"><span>1</span></div>
|
<div class="text-dark fw-bold h5 mb-0"><span><%= stats.keys %></span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto"><i class="fas fa-key fa-2x text-gray-300"></i></div>
|
<div class="col-auto"><i class="fas fa-key fa-2x text-gray-300"></i></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<div class="row align-items-center no-gutters">
|
<div class="row align-items-center no-gutters">
|
||||||
<div class="col me-2">
|
<div class="col me-2">
|
||||||
<div class="text-uppercase text-success fw-bold text-xs mb-1"><span>my authorized servers</span></div>
|
<div class="text-uppercase text-success fw-bold text-xs mb-1"><span>my authorized servers</span></div>
|
||||||
<div class="text-dark fw-bold h5 mb-0"><span>5</span></div>
|
<div class="text-dark fw-bold h5 mb-0"><span>undefined</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto"><i class="fas fa-hdd fa-2x text-gray-300"></i></div>
|
<div class="col-auto"><i class="fas fa-hdd fa-2x text-gray-300"></i></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
<div class="text-uppercase text-info fw-bold text-xs mb-1"><span>my groups</span></div>
|
<div class="text-uppercase text-info fw-bold text-xs mb-1"><span>my groups</span></div>
|
||||||
<div class="row g-0 align-items-center">
|
<div class="row g-0 align-items-center">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<div class="text-dark fw-bold h5 mb-0 me-3"><span>2</span></div>
|
<div class="text-dark fw-bold h5 mb-0 me-3"><span><%= stats.groups %></span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
<div class="row align-items-center no-gutters">
|
<div class="row align-items-center no-gutters">
|
||||||
<div class="col me-2">
|
<div class="col me-2">
|
||||||
<div class="text-uppercase text-warning fw-bold text-xs mb-1"><span>Pending requests</span></div>
|
<div class="text-uppercase text-warning fw-bold text-xs mb-1"><span>Pending requests</span></div>
|
||||||
<div class="text-dark fw-bold h5 mb-0"><span>18</span></div>
|
<div class="text-dark fw-bold h5 mb-0"><span>0</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto"><i class="fas fa-comments fa-2x text-gray-300"></i></div>
|
<div class="col-auto"><i class="fas fa-comments fa-2x text-gray-300"></i></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,6 @@
|
||||||
<%- include('navbar', {active: "keys"}); %>
|
<%- include('navbar', {active: "keys"}); %>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h3 class="text-dark mb-4">Keys management</h3>
|
<h3 class="text-dark mb-4"><a style="text-decoration: none" href="/">Dashboard</a> / keys</h3></h3>
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col-lg-8">
|
|
||||||
<div class="row mb-3 d-none">
|
|
||||||
<div class="col">
|
|
||||||
<div class="card text-white bg-primary shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<div class="col">
|
|
||||||
<p class="m-0">Peformance</p>
|
|
||||||
<p class="m-0"><strong>65.2%</strong></p>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto"><i class="fas fa-rocket fa-2x"></i></div>
|
|
||||||
</div>
|
|
||||||
<p class="text-white-50 small m-0"><i class="fas fa-arrow-up"></i> 5% since last month</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="card text-white bg-success shadow">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<div class="col">
|
|
||||||
<p class="m-0">Peformance</p>
|
|
||||||
<p class="m-0"><strong>65.2%</strong></p>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto"><i class="fas fa-rocket fa-2x"></i></div>
|
|
||||||
</div>
|
|
||||||
<p class="text-white-50 small m-0"><i class="fas fa-arrow-up"></i> 5% since last month</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card shadow mb-5">
|
<div class="card shadow mb-5">
|
||||||
<div class="card-header py-3">
|
<div class="card-header py-3">
|
||||||
<p class="text-primary m-0 fw-bold">SSH Keys</p>
|
<p class="text-primary m-0 fw-bold">SSH Keys</p>
|
||||||
|
|
@ -58,7 +24,7 @@
|
||||||
|
|
||||||
<td><%= key.content %></td>
|
<td><%= key.content %></td>
|
||||||
|
|
||||||
<td style="text-align: right;"><a class="btn btn-sm btn-danger" href="/keys/delete/<%= key.idKey %>"><i class="far fa-trash-alt"></i></button></td>
|
<td style="text-align: right;"><a class="btn btn-sm btn-danger" href="/keys/delete/<%= key.name %>"><i class="far fa-trash-alt"></i></button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue