Skip to content

Commit

Permalink
Donor and admin (#220)
Browse files Browse the repository at this point in the history
* Start of Admin Panel

User Search
New House

* Removed Homes

* user search and admin api made

* pulling user info for admin

* Chat history by user

* Final Chat history by user

* WIP donor role assignments

* Auto stash before merge of "donor-admin" and "CybertownRevival/master"

* Auto stash before merge of "donor-admin" and "CybertownRevival/master"

* Setting Donor Levels

* Review Submission

* Quick Fixes

* Fixes as Requested

* Minor Donor Fix

When going from donor to None, had to refresh before showing change, now shows on submitting.
  • Loading branch information
smile0711 authored Feb 6, 2024
1 parent b60b55d commit 776f180
Show file tree
Hide file tree
Showing 73 changed files with 29,994 additions and 15,529 deletions.
43 changes: 43 additions & 0 deletions api/db/migrations/20240102165858_add_ban_table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {knex, Knex} from 'knex';

const COLLATE = 'utf8mb4_unicode_ci';
function applyCommon(table: Knex.CreateTableBuilder) {
table.collate(COLLATE);
table.increments('id').primary();
table.timestamps(false, true);
}

export async function up(knex: Knex): Promise<void> {
if (!await knex.schema.hasTable('ban')){
await knex.schema.createTable('ban', (table) => {
console.log('Creating ban table');
applyCommon(table);

table.integer('status')
.defaultTo(1);

table.integer('ban_member_id')
.notNullable();

table.date('end_date')
.notNullable();

table.enu('type', ['jail', 'full'])
.defaultTo('jail')
.notNullable();

table.integer('assigner_member_id')
.notNullable();

table.text('reason').notNullable();
});
}
}


export async function down(knex: Knex): Promise<void> {
if (await knex.schema.hasTable('ban')){
await knex.schema.dropTable('ban');
}
}

9 changes: 9 additions & 0 deletions api/db/seed/06-donor.roles.seed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Knex } from 'knex';

const donorData = require('./../seed_data/donor_data.json');

export async function seed(knex: Knex): Promise<void> {
console.log('Seeding donor data');

await knex('role').insert(donorData);
}
22 changes: 22 additions & 0 deletions api/db/seed_data/donor_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"name": "Supporter",
"income_xp": 0,
"income_cc": 0
},
{
"name": "Advocate",
"income_xp": 0,
"income_cc": 0
},
{
"name": "Devotee",
"income_xp": 0,
"income_cc": 0
},
{
"name": "Champion",
"income_xp": 0,
"income_cc": 0
}
]
2 changes: 2 additions & 0 deletions api/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import express from 'express';
import { Request, Response } from 'express';
import morgan from 'morgan';
import {
adminRoutes,
avatarRoutes,
memberRoutes,
messageRoutes,
Expand Down Expand Up @@ -51,6 +52,7 @@ app.use('/api/colony', colonyRoutes);
app.use('/api/block', blockRoutes);
app.use('/api/home', homeRoutes);
app.use('/api/messageboard', messageboardRoutes);
app.use('/api/admin', adminRoutes);
app.use('/api/inbox', inboxRoutes);

app.use((request, response, next) => {
Expand Down
151 changes: 151 additions & 0 deletions api/src/controllers/admin.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import {Request, Response} from 'express';
import { Container } from 'typedi';

import { AdminService, MemberService } from '../services';

class AdminController {
constructor(private adminService: AdminService, private memberService: MemberService) {}

public async addBan(request: Request, response: Response): Promise<any> {
const session = this.memberService.decryptSession(request, response);
if (!session) return;
const admin = await this.memberService.canAdmin(session.id);
if (admin) {
try {
await this.adminService.addBan(
request.body.ban_member_id,
request.body.time_frame,
request.body.type,
session.id,
request.body.reason,
);
response.status(200).json({message: 'Ban added successfully'});
} catch (error) {
console.log(error);
response.status(400).json({error});
}
} else {
response.status(403).json({message: 'Access Denied'});
}
}

public async addDonor(request: Request, response: Response): Promise<void>{
const session = this.memberService.decryptSession(request, response);
if (!session) return;
const accessLevel = await this.memberService.getAccessLevel(session.id);
if (accessLevel === 'admin') {
try {
await this.adminService.addDonor(
request.body.member_id,
request.body.level,
);
response.status(200).json({message: 'Donor added successfully'});
} catch (e) {
console.log(e);
response.status(400).json({error: 'Error adding donor'});
}
} else {
response.status(403).json({error: 'Access Denied'});
}
}

public async getBanHistory(request: Request, response: Response): Promise<any> {
const session = this.memberService.decryptSession(request, response);
if (!session) return;
const admin = await this.memberService.canAdmin(session.id);
if (admin) {
try {
const banHistory = await this.adminService
.getBanHistory(Number(request.query.ban_member_id.toString()));
response.status(200).json({banHistory});
} catch (error) {
console.log(error);
response.status(400).json({error});
}
} else {
response.status(403).json({message: 'Access Denied'});
}
}

public async deleteBan(request: Request, response: Response): Promise<void> {
const session = this.memberService.decryptSession(request, response);
if (!session) return;
const admin = await this.memberService.canAdmin(session.id);
if (admin) {
try {
const banId = Number(request.body.banId);
const reason = request.body.banReason;
const deleteBy = await this.memberService.getMemberInfoPublic(session.id);
const updateReason = `${reason} (Deleted by ${deleteBy.username})`;
await this.adminService.deleteBan(banId, updateReason);
response.status(200).json({message: 'Ban deleted successfully'});
} catch (error) {
console.log(error);
response.status(400).json({error});
}
} else {
response.status(403).json({message: 'Access Denied'});
}
}

public async getDonor(request: Request, response: Response): Promise<string> {
const session = this.memberService.decryptSession(request, response);
if (!session) return;
const accessLevel = await this.memberService.getAccessLevel(session.id);
if (accessLevel === 'admin') {
const currentLevel = await this
.adminService
.getDonor(Number(request.query.memberId));
response.status(200).json({donorLevel: currentLevel});
} else {
response.status(403).json({error: 'Access Denied'});
}
}

public async searchUsers(request: Request, response: Response): Promise<any> {
const session = this.memberService.decryptSession(request, response);
if (!session) return;
const admin = await this.memberService.canAdmin(session.id);
if (admin) {
try {
const results = await this.adminService.searchUsers(
request.query.search.toString(),
Number.parseInt(request.query.limit.toString()),
Number.parseInt(request.query.offset.toString()),
);
response.status(200).json({results});
} catch (error) {
console.log(error);
response.status(400).json({error});
}
} else {
response.status(403).json({message: 'Access Denied'});
}
}

public async searchUserChat(request: Request, response: Response): Promise<any> {
const session = this.memberService.decryptSession(request, response);
if (!session) return;
const admin = await this.memberService.canAdmin(session.id);
if (admin) {
try {
const results = await this.adminService.searchUserChat(
request.query.search.toString(),
Number.parseInt(request.query.user.toString()),
Number.parseInt(request.query.limit.toString()),
Number.parseInt(request.query.offset.toString()),
);
response.status(200).json({results});
} catch (error) {
console.log(error);
response.status(400).json({error});
}
} else {
response.status(403).json({message: 'Access Denied'});
}
}
}

const adminService = Container.get(AdminService);
const memberService = Container.get(MemberService);
export const adminController = new AdminController(adminService, memberService);
1 change: 1 addition & 0 deletions api/src/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './admin.controller';
export * from './avatar.controller';
export * from './block.controller';
export * from './colony.controller';
Expand Down
32 changes: 25 additions & 7 deletions api/src/controllers/member.controller.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import * as _ from 'lodash';
import bcrypt from 'bcrypt';
import { Request, Response } from 'express';
import {Request, Response} from 'express';
import { Container } from 'typedi';
import validator from 'validator';

import { db, knex } from '../db';
import { sendPasswordResetEmail, sendPasswordResetUnknownEmail } from '../libs';
import { MemberService, HomeService } from '../services';
import { SessionInfo } from 'session-info.interface';
Expand All @@ -29,6 +28,24 @@ class MemberController {
*/
constructor(private memberService: MemberService, private homeService: HomeService) {}

public async getAdminLevel(request: Request, response: Response): Promise<object> {
const session = this.memberService.decryptSession(request, response);
if (!session) return;
const accessLevel = await this.memberService.getAccessLevel(session.id);
response.status(200).json({accessLevel});
}

public async getDonorLevel(request: Request, response: Response): Promise<string>{
const session = this.memberService.decryptSession(request, response);
if (!session) return;
try {
const donorLevel = await this.memberService.getDonorLevel(session.id);
response.status(200).json(donorLevel);
} catch (e) {
response.status(400).json({error: 'Something went wrong try to get donor level.'});
}
}

/**
* Controller method for providing member information
* @route /api/member/info
Expand All @@ -40,7 +57,7 @@ class MemberController {
let memberInfo;

if (typeof request.params.id !== 'undefined') {
if (await memberService.isAdmin(session.id)) {
if (await this.memberService.canAdmin(session.id)) {
memberInfo = await this.memberService.getMemberInfoAdmin(parseInt(request.params.id));
} else if (parseInt(request.params.id) === session.id) {
memberInfo = await this.memberService.getMemberInfo(parseInt(request.params.id));
Expand Down Expand Up @@ -191,17 +208,18 @@ class MemberController {
if (session) {
// refresh client token with latest from database
const token = await this.memberService.getMemberToken(session.id);
const status = await this.memberService.isBanned(session.id);
if (status !== 0) {
this.memberService.maybeGiveDailyCredits(session.id);
const {banned, banInfo} = await this.memberService.isBanned(session.id);
if (!banned) {
await this.memberService.maybeGiveDailyCredits(session.id);
const homeInfo = await this.homeService.getHome(session.id);
session.hasHome = !!homeInfo;
}
response.status(200).json({
message: 'success',
token,
user: session,
status: status,
banned: banned,
banInfo: banInfo,
});
} else {
throw new Error('Invalid or missing token');
Expand Down
42 changes: 41 additions & 1 deletion api/src/controllers/message.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class MessageController {
return;
}

if(parseInt(request.params.placeId) <= 0) {
if(Number.parseInt(request.params.placeId) <= 0) {
response.status(400).json({
error: 'placeId is required.',
});
Expand Down Expand Up @@ -86,6 +86,46 @@ class MessageController {
}
}
}

/** delete a message from the chat **/
public async deleteMessage(request: Request, response: Response): Promise<void> {
const { apitoken } = request.headers;
const session = this.memberService.decodeMemberToken(<string> apitoken);
if(!session) {
response.status(400).json({
error: 'Invalid or missing token.',
});
return;
}

const messageId = Number.parseInt(request.params.messageid);

if(messageId <= 0) {
response.status(400).json({
error: 'messageId is required.',
});
return;
}

try {
// Check if the member has permission to delete the message
const admin = await this.memberService.canAdmin(session.id);
if (!admin) {
response.status(403).json({
error: 'You do not have permission to delete this message.',
});
return;
}

await this.messageService.deleteMessage(messageId);
response.status(200).json({ success: true });
} catch (error) {
console.error(error);
response.status(400).json({
error: 'A problem occurred while trying to delete the message.',
});
}
}

/** Provides an ordered list of messages for the given place */
public async getResults(request: Request, response: Response): Promise<void> {
Expand Down
Loading

0 comments on commit 776f180

Please sign in to comment.