Created channel perms schema and api routes.

This commit is contained in:
rainbownapkin 2024-11-23 13:41:48 -05:00
parent 9dbbc4e924
commit 8384e732f3
21 changed files with 250 additions and 20 deletions

View file

@ -0,0 +1,43 @@
/*Canopy - The next generation of stoner streaming software
Copyright (C) 2024 Rainbownapkin and the TTN Community
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
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/>.*/
//NPM Imports
const {mongoose} = require('mongoose');
//This originally belonged to the permissionSchema, but this avoids circular dependencies.
const rankEnum = ["anon", "user", "gold", "bot", "mod", "admin"];
//Since this is intended to be used as a child schema for multiple parent schemas, we won't export it as a model
const channelPermissionSchema = new mongoose.Schema({
manageChannel: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
},
deleteChannel: {
type: mongoose.SchemaTypes.String,
enum: rankEnum,
default: "admin",
required: true
}
});
//Only putting the rank enum out, all other logic should be handled by channelSchema methods to avoid circular dependencies
//Alternatively if things get to big we can make it it's own util.
channelPermissionSchema.statics.rankEnum = rankEnum;
module.exports = channelPermissionSchema;

View file

@ -18,7 +18,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
const {mongoose} = require('mongoose');
//Local Imports
const statSchema = require('./statSchema.js');
const statModel = require('../statSchema.js');
const permissionModel = require('../permissionSchema.js');
const channelPermissionSchema = require('./channelPermissionSchema.js');
const channelSchema = new mongoose.Schema({
id: {
@ -45,10 +47,27 @@ const channelSchema = new mongoose.Schema({
type: mongoose.SchemaTypes.Boolean,
required: true,
default: true
},
},
permissions: {
type: channelPermissionSchema,
default: () => ({})
},
rankList: [{
user: {
type: mongoose.SchemaTypes.ObjectID,
required: true,
ref: "user"
},
rank: {
type: mongoose.SchemaTypes.Boolean,
required: true,
enum: permissionModel.rankEnum
}
}
}]
});
channelSchema.pre('save', async function (next){
if(this.isModified("name")){
if(this.name.match(/^[a-z0-9_\-.]+$/i) == null){
@ -68,7 +87,7 @@ channelSchema.statics.register = async function(channelObj){
if(chanDB){
throw new Error("Channel name already taken!");
}else{
const id = await statSchema.incrementChannelCount();
const id = await statModel.incrementChannelCount();
const newChannel = await this.create((thumbnail ? {id, name, description, thumbnail} : {id, name, description}));
}
}
@ -109,6 +128,46 @@ channelSchema.methods.updateSettings = async function(settingsMap){
return this.settings;
}
channelSchema.methods.updateChannelPerms = async function(permissionsMap){
permissionsMap.forEach((value, key) => {
if(this.permissions[key] == null){
throw new Error("Invalid channel permission.");
}
this.permissions[key] = value;
})
await this.save();
return this.permissions;
}
channelSchema.methods.channelPermCheck = async function(user, perm){
const perms = await permissionSchema.getPerms();
//Set user to anon rank if no rank was found for the given user
if(user == null || user.rank == null){
user ={
rank: "anon"
};
}
//Check if this permission exists
if(this.permissions[perm] != null){
//if so get required rank as a number
requiredRank = permissionModel.rankToNum(this[perm]);
//get the required site-wide rank to override channel perms
requiredOverrideRank = permissionModel.rankToNum(perms.channeOverrides[perm]);
//get user site rank as a number
userRank = user ? permissionModel.rankToNum(user.rank) : 0;
}else{
//if not scream and shout
throw new Error(`Permission check '${perm}' not found!`);
}
}
channelSchema.methods.nuke = async function(confirm){
if(confirm == "" || confirm == null){
throw new Error("Empty Confirmation String!");

View file

@ -17,7 +17,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//NPM Imports
const {mongoose} = require('mongoose');
const rankEnum = ["anon","user", "gold", "bot", "mod", "admin"];
//Local Imports
const channelPermissionSchema = require('./channel/channelPermissionSchema');
//This originally belonged to the permissionSchema, but this avoids circular dependencies.
//We could update all references but quite honestly I that would be uglier, this should have a copy too...
const rankEnum = channelPermissionSchema.statics.rankEnum;
const permissionSchema = new mongoose.Schema({
adminPanel: {
@ -50,6 +55,10 @@ const permissionSchema = new mongoose.Schema({
default: "admin",
required: true
},
channelOverrides: {
type: channelPermissionSchema,
default: () => ({})
},
});
//Statics
@ -108,6 +117,7 @@ permissionSchema.statics.permCheck = async function(user, perm){
}
}
//Middleware for rank checks
permissionSchema.statics.reqPermCheck = function(perm){
return async (req, res, next)=>{