add BadgeEditor user role
This commit is contained in:
parent
23a206ce99
commit
ee9f50c87f
6 changed files with 46 additions and 23 deletions
|
@ -105,7 +105,7 @@ export default class AdminController_Auth$Admin extends Controller {
|
||||||
return this.redirectToAction("parties");
|
return this.redirectToAction("parties");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Badges_Get() {
|
public async Badges_Get_Auth$BadgeEditor() {
|
||||||
const adminBadgesViewModel: AdminBadgesViewModel = {
|
const adminBadgesViewModel: AdminBadgesViewModel = {
|
||||||
badges: await BadgeService.LoadAll()
|
badges: await BadgeService.LoadAll()
|
||||||
};
|
};
|
||||||
|
@ -113,7 +113,7 @@ export default class AdminController_Auth$Admin extends Controller {
|
||||||
return this.view(adminBadgesViewModel);
|
return this.view(adminBadgesViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Badge_Get(adminBadgeViewModel: AdminBadgeViewModel) {
|
public async Badge_Get_Auth$BadgeEditor(adminBadgeViewModel: AdminBadgeViewModel) {
|
||||||
const badge = adminBadgeViewModel.id ? await BadgeService.LoadBadge(parseInt(adminBadgeViewModel.id)) : null;
|
const badge = adminBadgeViewModel.id ? await BadgeService.LoadBadge(parseInt(adminBadgeViewModel.id)) : null;
|
||||||
if (typeof(adminBadgeViewModel.id) !== "undefined" && badge) {
|
if (typeof(adminBadgeViewModel.id) !== "undefined" && badge) {
|
||||||
adminBadgeViewModel.name = badge.Name;
|
adminBadgeViewModel.name = badge.Name;
|
||||||
|
@ -130,7 +130,7 @@ export default class AdminController_Auth$Admin extends Controller {
|
||||||
return this.view(adminBadgeViewModel);
|
return this.view(adminBadgeViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Badge_Post(adminBadgeViewModel: AdminBadgeViewModel) {
|
public async Badge_Post_Auth$BadgeEditor(adminBadgeViewModel: AdminBadgeViewModel) {
|
||||||
if (typeof(adminBadgeViewModel.id) === "undefined") {
|
if (typeof(adminBadgeViewModel.id) === "undefined") {
|
||||||
return this.badRequest();
|
return this.badRequest();
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ export default class AdminController_Auth$Admin extends Controller {
|
||||||
return this.redirectToAction("badges");
|
return this.redirectToAction("badges");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async DeleteBadge_Get(adminDeleteBadgeModel: AdminDeleteBadgeModel) {
|
public async DeleteBadge_Get_Auth$BadgeEditor(adminDeleteBadgeModel: AdminDeleteBadgeModel) {
|
||||||
if (typeof(adminDeleteBadgeModel.id) === "undefined" || typeof(adminDeleteBadgeModel.id) !== "string") {
|
if (typeof(adminDeleteBadgeModel.id) === "undefined" || typeof(adminDeleteBadgeModel.id) !== "string") {
|
||||||
return this.badRequest();
|
return this.badRequest();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,14 @@ export default abstract class Controller {
|
||||||
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
|
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
|
||||||
const rawControllerParts = this.constructor.name.split("_");
|
const rawControllerParts = this.constructor.name.split("_");
|
||||||
const controllerName = rawControllerParts.splice(0, 1)[0].replace("Controller", "").toLowerCase();
|
const controllerName = rawControllerParts.splice(0, 1)[0].replace("Controller", "").toLowerCase();
|
||||||
let controllerAuthLevel: UserLevel | undefined;
|
const controllerAuthLevels: Array<UserLevel> = [];
|
||||||
|
const actionAuthLevels: { [ key : string ]: Array<UserLevel> } = {};
|
||||||
|
|
||||||
for (const prop of rawControllerParts) {
|
for (const prop of rawControllerParts) {
|
||||||
if (prop.startsWith("Auth")) {
|
if (prop.startsWith("Auth")) {
|
||||||
const userLevel = prop.split("$")[1];
|
const userLevel = prop.split("$")[1];
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
controllerAuthLevel = UserLevel[userLevel];
|
controllerAuthLevels.push(UserLevel[userLevel]);
|
||||||
Console.printInfo(`Set Auth level requirement for ${this.constructor.name} to ${userLevel}`);
|
Console.printInfo(`Set Auth level requirement for ${this.constructor.name} to ${userLevel}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +33,7 @@ export default abstract class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = method.split("_");
|
const params = method.split("_");
|
||||||
const methodNameRaw = params.splice(0, 1)[0]
|
const methodNameRaw = params.splice(0, 1)[0];
|
||||||
const methodName = methodNameRaw.toLowerCase();
|
const methodName = methodNameRaw.toLowerCase();
|
||||||
const doAuth = !params.includes("AllowAnonymous");
|
const doAuth = !params.includes("AllowAnonymous");
|
||||||
|
|
||||||
|
@ -44,8 +45,25 @@ export default abstract class Controller {
|
||||||
if (doAuth && session === undefined) {
|
if (doAuth && session === undefined) {
|
||||||
return res.redirect(`/account/login?returnTo=${encodeURIComponent(req.url)}`);
|
return res.redirect(`/account/login?returnTo=${encodeURIComponent(req.url)}`);
|
||||||
}
|
}
|
||||||
if (session !== undefined && controllerAuthLevel !== undefined && controllerAuthLevel !== session.userLevel) {
|
const methodAuthCheck = actionAuthLevels[`${controllerName}_${methodName}_${req.method.toLowerCase()}`];
|
||||||
return res.status(403).send("Forbidden");
|
let wasMethodMatch = false;
|
||||||
|
if (methodAuthCheck && session !== undefined) {
|
||||||
|
for (const auth of methodAuthCheck) {
|
||||||
|
if (auth === session.userLevel) {
|
||||||
|
wasMethodMatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!wasMethodMatch && session !== undefined && controllerAuthLevels.length > 0) {
|
||||||
|
let hasLevelMatch = false;
|
||||||
|
for (const level of controllerAuthLevels) {
|
||||||
|
if (level === session.userLevel) {
|
||||||
|
hasLevelMatch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasLevelMatch) {
|
||||||
|
return res.status(403).send("Forbidden");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestCtx = new RequestCtx(req, res, controllerName, methodName, session);
|
const requestCtx = new RequestCtx(req, res, controllerName, methodName, session);
|
||||||
|
@ -53,9 +71,12 @@ export default abstract class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
let funcMethods:Array<string> = [];
|
let funcMethods:Array<string> = [];
|
||||||
|
let thisMethodHttpMethod = "";
|
||||||
for (const param of params) {
|
for (const param of params) {
|
||||||
|
//console.log(param);
|
||||||
if (param === "Get" || param === "Post" || param === "Put") {
|
if (param === "Get" || param === "Post" || param === "Put") {
|
||||||
funcMethods.push(param);
|
funcMethods.push(param);
|
||||||
|
thisMethodHttpMethod = param.toLowerCase();
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}/${methodName === "index" ? "" : methodName}`, requestHandler);
|
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}/${methodName === "index" ? "" : methodName}`, requestHandler);
|
||||||
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}/${methodName === "index" ? "" : methodName}" as ${param}`);
|
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}/${methodName === "index" ? "" : methodName}" as ${param}`);
|
||||||
|
@ -67,6 +88,15 @@ export default abstract class Controller {
|
||||||
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}`, requestHandler);
|
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}`, requestHandler);
|
||||||
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}" as ${param}`);
|
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}" as ${param}`);
|
||||||
}
|
}
|
||||||
|
} else if (param.startsWith("Auth")) {
|
||||||
|
const nameWithMethod = `${controllerName}_${methodName}_${thisMethodHttpMethod}`;
|
||||||
|
const userLevel = param.split("$")[1];
|
||||||
|
if (!(nameWithMethod in actionAuthLevels)) {
|
||||||
|
actionAuthLevels[nameWithMethod] = [];
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
actionAuthLevels[nameWithMethod].push(UserLevel[userLevel]);
|
||||||
|
Console.printInfo(`Set Auth level requirement for ${this.constructor.name}.${method} to ${userLevel}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export enum UserLevel {
|
export enum UserLevel {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
User = 10,
|
User = 10,
|
||||||
|
BadgeEditor = 20,
|
||||||
Admin = 999
|
Admin = 999
|
||||||
}
|
}
|
|
@ -124,7 +124,6 @@ export default class UserService {
|
||||||
await UserPartyRepo.insertUpdate(userParty);
|
await UserPartyRepo.insertUpdate(userParty);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||||
console.log(e);
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +133,6 @@ export default class UserService {
|
||||||
await UserPartyRepo.deactivateAll(currentUserId);
|
await UserPartyRepo.deactivateAll(currentUserId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||||
console.log(e);
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
<select class="form-select" name="userLevel" required>
|
<select class="form-select" name="userLevel" required>
|
||||||
<option value="" disabled <%= userLevel === "0" ? "selected" : "" %>>Please select...</option>
|
<option value="" disabled <%= userLevel === "0" ? "selected" : "" %>>Please select...</option>
|
||||||
<option value="10" <%= userLevel === "10" ? "selected" : "" %>>User</option>
|
<option value="10" <%= userLevel === "10" ? "selected" : "" %>>User</option>
|
||||||
|
<option value="20" <%= userLevel === "20" ? "selected" : "" %>>Badge Editor</option>
|
||||||
<option value="999" <%= userLevel === "999" ? "selected" : "" %>>Admin</option>
|
<option value="999" <%= userLevel === "999" ? "selected" : "" %>>Admin</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -50,16 +51,4 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script>
|
|
||||||
const imageImg = document.querySelector("#imageImg");
|
|
||||||
const imageUrl = document.querySelector("#imageUrl");
|
|
||||||
imageUrl.addEventListener("change", () => {
|
|
||||||
if (imageUrl.value.trim() === ""){
|
|
||||||
imageImg.src = "/img/missing.png";
|
|
||||||
} else {
|
|
||||||
imageImg.src = imageUrl.value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<%- include("../base/footer") %>
|
<%- include("../base/footer") %>
|
|
@ -12,6 +12,11 @@
|
||||||
<a class="btn btn-primary btn-lg me-2" href="/party/create">Create Party</a>
|
<a class="btn btn-primary btn-lg me-2" href="/party/create">Create Party</a>
|
||||||
<a class="btn btn-primary btn-lg" href="/party/join">Join Party</a>
|
<a class="btn btn-primary btn-lg" href="/party/join">Join Party</a>
|
||||||
</div>
|
</div>
|
||||||
|
<% if (user.UserLevel === UserLevel.BadgeEditor) { %>
|
||||||
|
<div class="mt-3">
|
||||||
|
<a class="btn btn-primary btn-lg" href="/admin/badges">Badge Management</a>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
<% if (user.UserLevel === UserLevel.Admin) { %>
|
<% if (user.UserLevel === UserLevel.Admin) { %>
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<a class="btn btn-primary btn-lg" href="/admin">Admin Dashboard</a>
|
<a class="btn btn-primary btn-lg" href="/admin">Admin Dashboard</a>
|
||||||
|
|
Loading…
Reference in a new issue