Cleaned adminPanel and started adding User mgmt

This commit is contained in:
rainbownapkin 2024-11-17 11:47:03 -05:00
parent cde60bb78d
commit 064109556c
11 changed files with 153 additions and 54 deletions

View file

@ -16,15 +16,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//Config //Config
const config = require('../../config.json'); const config = require('../../config.json');
const userModel = require('../schemas/userSchema');
const channelModel = require('../schemas/channelSchema'); const channelModel = require('../schemas/channelSchema');
const {exceptionHandler} = require("../utils/loggerUtils");
//register page functions //register page functions
module.exports.get = async function(req, res){ module.exports.get = async function(req, res){
try{ try{
const chanGuide = await channelModel.getChannelList(true); const chanGuide = await channelModel.getChannelList(true);
return res.render('adminPanel', {instance: config.instanceName, user: req.session.user, chanGuide: chanGuide}); const userList = await userModel.getUserList(true);
return res.render('adminPanel', {instance: config.instanceName, user: req.session.user, chanGuide: chanGuide, userList: userList});
}catch(err){ }catch(err){
res.status(500); return exceptionHandler(res,err);
return res.send("Error indexing channels!");
} }
} }

View file

@ -38,7 +38,7 @@ const channelSchema = new mongoose.Schema({
thumbnail: { thumbnail: {
type: mongoose.SchemaTypes.String, type: mongoose.SchemaTypes.String,
required: true, required: true,
default: "img/johnny.png" default: "/img/johnny.png"
}, },
settings: { settings: {
hidden: { hidden: {

View file

@ -59,7 +59,7 @@ const userSchema = new mongoose.Schema({
img: { img: {
type: mongoose.SchemaTypes.String, type: mongoose.SchemaTypes.String,
required: true, required: true,
default: "img/johnny.png" default: "/img/johnny.png"
}, },
bio: { bio: {
type: mongoose.SchemaTypes.String, type: mongoose.SchemaTypes.String,
@ -167,6 +167,40 @@ userSchema.methods.getAuthenticatedSessions = async function(){
} }
userSchema.statics.getUserList = async function(fullList = false){
var userList = [];
//Get all of our users
const users = await this.find({});
//Return empty if we don't find nuthin'
if(users == null){
return [];
}
//For each user
users.forEach((user)=>{
//create a user object with limited properties (safe for public consumption)
var userObj = {
id: user.id,
name: user.user,
img: user.img,
date: user.date
}
//Put together a spicier version for admins when told so (permission checks should happen before this is called)
if(fullList){
userObj.rank = user.rank,
userObj.email = user.email
}
//Add user object to list
userList.push(userObj);
});
//return the userlist
return userList;
}
//note: if you gotta call this from a request authenticated by it's user, make sure to kill that session first! //note: if you gotta call this from a request authenticated by it's user, make sure to kill that session first!
userSchema.methods.killAllSessions = async function(){ userSchema.methods.killAllSessions = async function(){
//get authenticated sessions //get authenticated sessions

View file

@ -27,7 +27,7 @@ module.exports.accountValidator = {
email: (field = 'email') => body(field).optional().isEmail().normalizeEmail(), email: (field = 'email') => body(field).optional().isEmail().normalizeEmail(),
img: (field = 'img') => body(field).optional().isURL({require_tld: false}).trim(), img: (field = 'img') => body(field).optional().isURL({require_tld: false, require_host: false}).trim(),
signature: (field = 'signature') => body(field).optional().escape().trim().isLength({min: 1, max: 150}), signature: (field = 'signature') => body(field).optional().escape().trim().isLength({min: 1, max: 150}),

View file

@ -22,39 +22,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.-->
</head> </head>
<body> <body>
<%- include('partial/navbar', {user}); %> <%- include('partial/navbar', {user}); %>
<div id="admin-channel-list-div" class="admin-channel-list"> <%- include('partial/adminPanel/channelList', {chanGuide}) %>
<h3>Channel List:</h3> <%- include('partial/adminPanel/userList', {userList}) %>
<table id="admin-channel-list-table" class="admin-channel-list">
<tr id="admin-channel-list-entry-title" class="admin-channel-list-entry">
<td id="admin-channel-list-entry-img-title" class="admin-channel-list-entry admin-channel-list-entry-title admin-channel-list-entry-item admin-channel-list-entry-img-row">
<h3>Img</h3>
</td>
<td id="admin-channel-list-entry-name-title" class="admin-channel-list-entry admin-channel-list-entry-title admin-channel-list-entry-item admin-channel-list-entry-name-row">
<h3>Name</h3>
</td>
<td id="admin-channel-list-entry-description-title" class="admin-channel-list-entry admin-channel-list-entry-title admin-channel-list-entry-item">
<h3>Description</h3>
</td>
</tr>
<% chanGuide.forEach((channel) => { %>
<tr id="admin-channel-list-entry-<%- channel.name %>" class="admin-channel-list-entry">
<td id="admin-channel-list-entry-img-<%- channel.name %>" class="admin-channel-list-entry admin-channel-list-entry-item admin-channel-list-entry-img-row">
<a href="/c/<%- channel.name %>" class="admin-channel-list-entry admin-channel-list-entry-item">
<img id="admin-channel-list-entry-img-<%- channel.name %>" class="admin-channel-list-entry admin-channel-list-entry-item" src="<%- channel.thumbnail %>">
</a>
</td>
<td id="admin-channel-list-entry-name-<%- channel.name %>" class="admin-channel-list-entry admin-channel-list-entry-item admin-channel-list-entry-name-row">
<a href="/c/<%- channel.name %>" class="admin-channel-list-entry admin-channel-list-entry-item">
<%- channel.name %>
</a>
</td>
<td id="admin-channel-list-entry-description-<%- channel.name %>" class="admin-channel-list-entry admin-channel-list-entry-item">
<p><%- channel.description %></p>
</td>
</tr>
<% }); %>
</table>
</div>
</body> </body>
<footer> <footer>
<%- include('partial/scripts', {user}); %> <%- include('partial/scripts', {user}); %>

View file

@ -0,0 +1,33 @@
<div id="admin-channel-list-div" class="admin-list-div">
<h3>Channel List:</h3>
<table id="admin-channel-list-table" class="admin-list-table">
<tr id="admin-channel-list-entry-title" class="admin-list-entry">
<td id="admin-channel-list-entry-img-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-img-title">
<h3>Img</h3>
</td>
<td id="admin-channel-list-entry-name-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-not-first-row">
<h3>Name</h3>
</td>
<td id="admin-channel-list-entry-description-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-not-first-row">
<h3>Description</h3>
</td>
</tr>
<% chanGuide.forEach((channel) => { %>
<tr id="admin-channel-list-entry-<%- channel.name %>" class="admin-list-entry">
<td id="admin-channel-list-entry-img-<%- channel.name %>" class="admin-list-entry admin-list-entry-item">
<a href="/c/<%- channel.name %>" class="admin-list-entry admin-list-entry-item">
<img id="admin-channel-list-entry-img-<%- channel.name %>" class="admin-list-entry admin-list-entry-item" src="<%- channel.thumbnail %>">
</a>
</td>
<td id="admin-channel-list-entry-name-<%- channel.name %>" class="admin-list-entry admin-list-entry-item admin-list-entry-not-first-row">
<a href="/c/<%- channel.name %>" class="admin-list-entry admin-list-entry-item">
<%- channel.name %>
</a>
</td>
<td id="admin-channel-list-entry-description-<%- channel.name %>" class="admin-list-entry admin-list-entry-large admin-list-entry-item admin-list-entry-not-first-row">
<%- channel.description %>
</td>
</tr>
<% }); %>
</table>
</div>

View file

@ -0,0 +1,53 @@
<div id="admin-user-list-div" class="admin-list-div">
<h3>User List:</h3>
<table id="admin-user-list-table" class="admin-list-table">
<tr id="admin-user-list-entry-title" class="admin-list-entry">
<td id="admin-user-list-entry-img-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-img-title">
<h3>Img</h3>
</td>
<td id="admin-user-list-entry-id-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-not-first-row">
<h3>ID</h3>
</td>
<td id="admin-user-list-entry-name-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-not-first-row">
<h3>Name</h3>
</td>
<td id="admin-user-list-entry-rank-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-not-first-row">
<h3>Rank</h3>
</td>
<td id="admin-user-list-entry-rank-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-not-first-row">
<h3>E-Mail</h3>
</td>
<td id="admin-user-list-entry-rank-title" class="admin-list-entry admin-list-entry-title admin-list-entry-item admin-list-entry-not-first-row">
<h3>Sign-Up Date</h3>
</td>
</tr>
<% userList.forEach((user) => { %>
<tr id="admin-user-list-entry-<%- user.name %>" class="admin-list-entry">
<td id="admin-user-list-entry-img-<%- user.name %>" class="admin-list-entry admin-list-entry-item">
<a href="/profile/<%- user.name %>" class="admin-list-entry admin-list-entry-item">
<img id="admin-user-list-entry-img-<%- user.name %>" class="admin-list-entry admin-list-entry-item" src="<%- user.img %>">
</a>
</td>
<td id="admin-user-list-entry-id-<%- user.name %>" class="admin-list-entry admin-list-entry-item admin-list-entry-not-first-row">
<a href="/profile/<%- user.name %>" class="admin-list-entry admin-list-entry-item">
<%- user.id %>
</a>
</td>
<td id="admin-user-list-entry-name-<%- user.name %>" class="admin-list-entry admin-list-entry-item admin-list-entry-not-first-row">
<a href="/profile/<%- user.name %>" class="admin-list-entry admin-list-entry-item">
<%- user.name %>
</a>
</td>
<td id="admin-user-list-entry-rank-<%- user.name %>" class="admin-list-entry admin-list-entry-item admin-list-entry-not-first-row">
<%- user.rank %>
</td>
<td id="admin-user-list-entry-email-<%- user.name %>" class="admin-list-entry admin-list-entry-item admin-list-entry-not-first-row">
<%- user.email ? user.email : "N/A" %>
</td>
<td id="admin-user-list-entry-date-<%- user.name %>" class="admin-list-entry admin-list-entry-item admin-list-entry-not-first-row">
<%- user.date %>
</td>
</tr>
<% }); %>
</table>
</div>

View file

@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.-->
<p class="navbar-item" id="instance-title"><a href="/" class="navbar-item"><%= instance %></a></p> <p class="navbar-item" id="instance-title"><a href="/" class="navbar-item"><%= instance %></a></p>
<span class="navbar-item" id="right-controls"> <span class="navbar-item" id="right-controls">
<% if(user){ %> <% if(user){ %>
<p class="navbar-item">Welcome, <a class="navbar-item" href="/profile"><%= user.user %></a> - <a href="/adminPanel" title="Admin Panel" class="bi bi-server navbar-item"></a> <a class="navbar-item" href="javascript:" id="logout-button">logout</a></p> <p class="navbar-item">Welcome, <a class="navbar-item" href="/profile"><%= user.user %></a> - <% if(user.rank == "admin"){ %><a href="/adminPanel" title="Admin Panel" class="bi bi-server navbar-item"></a> <% } %><a class="navbar-item" href="javascript:" id="logout-button">logout</a></p>
<% }else{ %> <% }else{ %>
<input class="navbar-item login-prompt" id="username-prompt" placeholder="username"> <input class="navbar-item login-prompt" id="username-prompt" placeholder="username">
<input class="navbar-item login-prompt" id="password-prompt" placeholder="password" type="password"> <input class="navbar-item login-prompt" id="password-prompt" placeholder="password" type="password">

View file

@ -14,34 +14,41 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
#admin-channel-list-div{ .admin-list-div{
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin: 0 30%; margin: 0 30%;
} }
#admin-channel-list-table{ .admin-list-table{
border-spacing: 0px; border-spacing: 0px;
} }
td.admin-channel-list-entry{ td.admin-list-entry{
padding: 0 1em; padding: 0.3em 1em;
} }
.admin-list-entry{
.admin-channel-list-entry-title{
text-align: center; text-align: center;
} }
.admin-channel-list-entry-img-row{ .admin-list-entry-large{
text-align: left;
}
.admin-list-entry-img-title{
width: 1.5em; width: 1.5em;
} }
img.admin-channel-list-entry-item{ img.admin-list-entry-item{
height: 2em; height: 2em;
} }
.admin-channel-list-entry-name-row{ #admin-channel-list-entry-name-title{
width: 15%; width: 15%;
} }
#admin-user-list-entry-id-title{
width: 2em;
}

View file

@ -134,24 +134,24 @@ a#account-settings-delete-link{
color: var(--accent0-warning); color: var(--accent0-warning);
} }
#admin-channel-list-table{ .admin-list-table{
background-color: var(--bg1); background-color: var(--bg1);
color: var(--accent1); color: var(--accent1);
} }
tr.admin-channel-list-entry{ tr.admin-list-entry{
box-shadow: var(--accent1) 0px 1em 1px -1em, var(--accent1) 0px -1em 1px -1em; box-shadow: var(--accent1) 0px 1em 1px -1em, var(--accent1) 0px -1em 1px -1em;
} }
td.admin-channel-list-entry-name-row{ td.admin-list-entry-not-first-row{
box-shadow: var(--accent1) 1em 0px 1px -1em, var(--accent1) -1em 0px 1px -1em; box-shadow: var(--accent1) 1em 0px 1px -1em, var(--accent1) -1em 0px 1px -1em;
} }
a.admin-channel-list-entry-item{ a.admin-list-entry-item{
color: var(--accent1); color: var(--accent1);
} }
a:hover.admin-channel-list-entry-item{ a:hover.admin-list-entry-item{
color: var(--accent1-alt0); color: var(--accent1-alt0);
} }

View file

@ -76,6 +76,7 @@ class profileEditPrompt{
} }
this.finish(); this.finish();
}else if(event.key == "Escape" || event.key == "Enter"){ }else if(event.key == "Escape" || event.key == "Enter"){
console.log(response);
this.finish(); this.finish();
} }
} }