Skip to content

Commit

Permalink
Merge pull request #83 from cuappdev/kidus/reportmodel
Browse files Browse the repository at this point in the history
Start a report model
  • Loading branch information
akmatchev authored Apr 18, 2024
2 parents 6ebf41a + ed1d4b7 commit 4ff09b9
Show file tree
Hide file tree
Showing 19 changed files with 822 additions and 155 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"multer": "1.4.5-lts.1",
"node-fetch": "^2.6.1",
"pg": "^8.7.1",
"pug": "^3.0.2",
"reflect-metadata": "^0.1.13",
"routing-controllers": "0.10.2",
"string-similarity": "^4.0.4",
Expand Down
72 changes: 72 additions & 0 deletions src/api/controllers/ReportController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Body, CurrentUser, JsonController, Get, Post, Delete, Params} from "routing-controllers";
import { UserModel } from "../../models/UserModel";
import { ReportService } from "../../services/ReportService";
import { ReportPostRequest, ReportProfileRequest, ReportMessageRequest } from "../../types/ApiRequests";
import { GetReportResponse, GetReportsResponse } from "../../types/ApiResponses";
import { ReportModel } from "../../models/ReportModel";
import { report } from "process";
import { UuidParam } from "../validators/GenericRequests";

@JsonController("report/")
export class ReportController {
private reportService: ReportService;

constructor(reportService: ReportService) {
this.reportService = reportService;
}

@Get("admin/all/")
async getAllReports(@CurrentUser() user: UserModel): Promise<GetReportsResponse> {
return { reports: await this.reportService.getAllReports(user) };
}

@Get("admin/post/")
async getAllPostReports(@CurrentUser() user: UserModel): Promise<GetReportsResponse> {
return { reports: await this.reportService.getAllPostReports(user) };
}

@Get("admin/profile/")
async getAllProfileReports(@CurrentUser() user: UserModel): Promise<GetReportsResponse> {
return { reports: await this.reportService.getAllProfileReports(user) };
}

@Get("admin/message/")
async getAllMessageReports(@CurrentUser() user: UserModel): Promise<GetReportsResponse> {
return { reports: await this.reportService.getAllMessageReports(user) };
}

@Get("id/:id/")
async getReportById(@CurrentUser() user: UserModel, @Params() params: UuidParam): Promise<GetReportResponse> {
return { report: await this.reportService.getReportById(user, params) };
}

@Get("reporter/id/:id/")
async getReportsByReporter(@CurrentUser() user: UserModel, @Params() params: UuidParam): Promise<GetReportsResponse> {
return { reports: await this.reportService.getReportsByReporter(user, params) };
}

@Post("post/")
async reportPost(@Body() reportPostRequest: ReportPostRequest, @CurrentUser() user: UserModel): Promise<ReportModel> {
return this.reportService.reportPost(user, reportPostRequest);
}

@Post("profile/")
async reportProfile(@Body() reportProfileRequest: ReportProfileRequest, @CurrentUser() user: UserModel): Promise<ReportModel> {
return this.reportService.reportProfile(user,reportProfileRequest);
}

@Post("message/")
async reportMessage(@Body() reportMessageRequest: ReportMessageRequest, @CurrentUser() user: UserModel): Promise<ReportModel> {
return this.reportService.reportMessage(user, reportMessageRequest);
}

@Post("resolve/reportId/:id/")
async resolveReport(@CurrentUser() user: UserModel,@Params() params: UuidParam): Promise<ReportModel> {
return this.reportService.resolveReport(user, params);
}

@Delete("delete/:id/")
async deleteReport(@CurrentUser() user: UserModel, @Params() params: UuidParam): Promise<ReportModel> {
return this.reportService.deleteReport(user, params);
}
}
2 changes: 2 additions & 0 deletions src/api/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { RequestController } from './RequestController';
import { UserController } from './UserController';
import { UserReviewController } from './UserReviewController';
import { NotifController } from './NotifController'
import { ReportController } from './ReportController';

export const controllers = [
AuthController,
Expand All @@ -14,6 +15,7 @@ export const controllers = [
NotifController,
PostController,
RequestController,
ReportController,
UserController,
UserReviewController,
];
40 changes: 39 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ import 'reflect-metadata';

import dotenv from 'dotenv';
import { createExpressServer, ForbiddenError, useContainer as routingUseContainer } from 'routing-controllers';
import { getManager, useContainer } from 'typeorm';
import { EntityManager, getManager, useContainer } from 'typeorm';
import { Container } from 'typeorm-typedi-extensions';

import { controllers } from './api/controllers';
import { middlewares } from './api/middlewares';
import { UserModel } from './models/UserModel';
import { UserSessionModel } from './models/UserSessionModel';
import { ReportPostRequest, ReportProfileRequest, ReportMessageRequest } from './types';
import { GetReportsResponse, Report } from './types/ApiResponses';
import { ReportController } from './api/controllers/ReportController';
import resellConnection from './utils/DB';
import { ReportService } from './services/ReportService';
import { ReportRepository } from './repositories/ReportRepository';
import { reportToString } from './utils/Requests';
import { CurrentUserChecker } from 'routing-controllers/types/CurrentUserChecker';

dotenv.config();


async function main() {
routingUseContainer(Container);
useContainer(Container);
Expand Down Expand Up @@ -54,6 +62,36 @@ async function main() {
},
defaultErrorHandler: false,
});

const entityManager = getManager();
const reportService = new ReportService(entityManager);
const reportController = new ReportController(reportService);

app.set('view engine', 'pug')

app.get('/api/reports/admin/', async (req: any, res: any) => {
const userCheck = async (action: any) => {
const accessToken = action.headers["authorization"];
const manager = getManager();
const session = await manager.findOne(UserSessionModel, { accessToken: accessToken });
if (session && session.expiresAt.getTime() > Date.now()) {
const userId = session.userId;
const user = await manager.findOne(UserModel, { id: userId }, { relations: ["posts", "saved", "sessions", "feedbacks", "requests"] });
if (!user || !user.admin) throw new ForbiddenError("User unauthorized");
return user;
}
throw new ForbiddenError("User unauthorized");
}
const user = await userCheck(req);
user.admin = true;
const postReports = await reportController.getAllPostReports(user);
const profileReports = await reportController.getAllProfileReports(user);
const messageReports = await reportController.getAllMessageReports(user);
res.render('admin', {
postReports: reportToString(postReports),
profileReports: reportToString(profileReports),
messageReports: reportToString(messageReports) });
});

const host = process.env.HOST ?? 'localhost';
const port = +(process.env.PORT ?? 3000);
Expand Down
28 changes: 28 additions & 0 deletions src/migrations/1713308449994-addreports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {MigrationInterface, QueryRunner} from "typeorm";

export class addreports1713308449994 implements MigrationInterface {
name = 'addreports1713308449994'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "Message" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "content" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "sender" uuid, "receiver" uuid, CONSTRAINT "PK_7dd6398f0d1dcaf73df342fa325" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE TABLE "Report" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "reason" character varying NOT NULL, "type" character varying NOT NULL, "resolved" boolean NOT NULL, "created" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "reporter_id" uuid, "reported_id" uuid, "post_id" uuid, "message_id" uuid, CONSTRAINT "PK_9dbb4c593be9832c28a5793e258" PRIMARY KEY ("id"))`);
await queryRunner.query(`ALTER TABLE "Message" ADD CONSTRAINT "FK_e2dae4735204f29947d6c42a615" FOREIGN KEY ("sender") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "Message" ADD CONSTRAINT "FK_8cc2e2f4ee9cdf7e5d9c70c5809" FOREIGN KEY ("receiver") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "Report" ADD CONSTRAINT "FK_6c3af08f1d45614f3b2f7e1b407" FOREIGN KEY ("reporter_id") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "Report" ADD CONSTRAINT "FK_0dd9a57f65a4b09cdae63735b13" FOREIGN KEY ("reported_id") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "Report" ADD CONSTRAINT "FK_244bde34d749985aa27e551c110" FOREIGN KEY ("post_id") REFERENCES "Post"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "Report" ADD CONSTRAINT "FK_b0ecf30cfa1f4908dec8d19547c" FOREIGN KEY ("message_id") REFERENCES "Message"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "Report" DROP CONSTRAINT "FK_b0ecf30cfa1f4908dec8d19547c"`);
await queryRunner.query(`ALTER TABLE "Report" DROP CONSTRAINT "FK_244bde34d749985aa27e551c110"`);
await queryRunner.query(`ALTER TABLE "Report" DROP CONSTRAINT "FK_0dd9a57f65a4b09cdae63735b13"`);
await queryRunner.query(`ALTER TABLE "Report" DROP CONSTRAINT "FK_6c3af08f1d45614f3b2f7e1b407"`);
await queryRunner.query(`ALTER TABLE "Message" DROP CONSTRAINT "FK_8cc2e2f4ee9cdf7e5d9c70c5809"`);
await queryRunner.query(`ALTER TABLE "Message" DROP CONSTRAINT "FK_e2dae4735204f29947d6c42a615"`);
await queryRunner.query(`DROP TABLE "Report"`);
await queryRunner.query(`DROP TABLE "Message"`);
}

}
30 changes: 30 additions & 0 deletions src/migrations/1713320015776-UpdateMessageModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {MigrationInterface, QueryRunner} from "typeorm";

export class UpdateMessageModel1713320015776 implements MigrationInterface {
name = 'UpdateMessageModel1713320015776'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "Message" DROP CONSTRAINT "FK_e2dae4735204f29947d6c42a615"`);
await queryRunner.query(`ALTER TABLE "Message" DROP CONSTRAINT "FK_8cc2e2f4ee9cdf7e5d9c70c5809"`);
await queryRunner.query(`ALTER TABLE "Message" DROP COLUMN "timestamp"`);
await queryRunner.query(`ALTER TABLE "Message" DROP COLUMN "sender"`);
await queryRunner.query(`ALTER TABLE "Message" DROP COLUMN "receiver"`);
await queryRunner.query(`ALTER TABLE "Message" DROP COLUMN "content"`);
await queryRunner.query(`ALTER TABLE "Report" DROP CONSTRAINT "FK_b0ecf30cfa1f4908dec8d19547c"`);
await queryRunner.query(`ALTER TABLE "Message" ALTER COLUMN "id" DROP DEFAULT`);
await queryRunner.query(`ALTER TABLE "Report" ADD CONSTRAINT "FK_b0ecf30cfa1f4908dec8d19547c" FOREIGN KEY ("message_id") REFERENCES "Message"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "Report" DROP CONSTRAINT "FK_b0ecf30cfa1f4908dec8d19547c"`);
await queryRunner.query(`ALTER TABLE "Message" ALTER COLUMN "id" SET DEFAULT uuid_generate_v4()`);
await queryRunner.query(`ALTER TABLE "Report" ADD CONSTRAINT "FK_b0ecf30cfa1f4908dec8d19547c" FOREIGN KEY ("message_id") REFERENCES "Message"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "Message" ADD "content" character varying NOT NULL`);
await queryRunner.query(`ALTER TABLE "Message" ADD "receiver" uuid NOT NULL`);
await queryRunner.query(`ALTER TABLE "Message" ADD "sender" uuid NOT NULL`);
await queryRunner.query(`ALTER TABLE "Message" ADD "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()`);
await queryRunner.query(`ALTER TABLE "Message" ADD CONSTRAINT "FK_8cc2e2f4ee9cdf7e5d9c70c5809" FOREIGN KEY ("receiver") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "Message" ADD CONSTRAINT "FK_e2dae4735204f29947d6c42a615" FOREIGN KEY ("sender") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
}

}
22 changes: 22 additions & 0 deletions src/models/MessageModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
PrimaryColumn
} from "typeorm";
import { Uuid } from "../types";
import { UserModel } from "./UserModel";
import { ReportModel } from "./ReportModel";

@Entity("Message")
export class MessageModel {
@PrimaryColumn("uuid")
id: Uuid;

@OneToMany(() => ReportModel, (report) => report.message)
reports: ReportModel[];
}
55 changes: 23 additions & 32 deletions src/models/PostModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import {
JoinTable,
ManyToMany,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
} from 'typeorm';
} from "typeorm";
import { Post, Uuid } from "../types";
import { RequestModel } from "./RequestModel";
import { UserModel } from "./UserModel";
import { ReportModel } from "./ReportModel";

import { Post, Uuid } from '../types';
import { RequestModel } from './RequestModel';
import { UserModel } from './UserModel';

@Entity('Post')
@Entity("Post")
export class PostModel {

@PrimaryGeneratedColumn('uuid')
@PrimaryGeneratedColumn("uuid")
id: Uuid;

@Column()
Expand All @@ -37,47 +37,38 @@ export class PostModel {
@Column("text", { array: true })
images: string[];

@CreateDateColumn({ type: 'timestamptz' })
@CreateDateColumn({ type: "timestamptz" })
created: Date;

@Column(({ nullable: true }))
@Column({ nullable: true })
location: string;

@Column({ default: false })
archive: boolean;

@ManyToOne(() => UserModel, user => user.posts)
@JoinColumn({ name: 'user' })
@ManyToOne(() => UserModel, (user) => user.posts)
@JoinColumn({ name: "user" })
user: UserModel;

@ManyToMany(() => UserModel, user => user.saved)
@ManyToMany(() => UserModel, (user) => user.saved)
@JoinTable({
name: "user_saved_posts",
joinColumn: {
name: "saved",
referencedColumnName: "id"
},
inverseJoinColumn: {
name: "savers",
referencedColumnName: "id"
}
joinColumn: { name: "saved", referencedColumnName: "id" },
inverseJoinColumn: { name: "savers", referencedColumnName: "id" },
})
savers: UserModel[];

@ManyToMany(() => RequestModel, request => request.matches)
@ManyToMany(() => RequestModel, (request) => request.matches)
@JoinTable({
name: "request_matches_posts",
joinColumn: {
name: "matches",
referencedColumnName: "id"
},
inverseJoinColumn: {
name: "matched",
referencedColumnName: "id"
}
joinColumn: { name: "matches", referencedColumnName: "id" },
inverseJoinColumn: { name: "matched", referencedColumnName: "id" },
})
matched: RequestModel[];

@OneToMany(() => ReportModel, (report) => report.post)
public reports: ReportModel[];

public getPostInfo(): Post {
return {
id: this.id,
Expand All @@ -91,8 +82,8 @@ export class PostModel {
location: this.location,
archive: this.archive,
user: this.user.getUserProfile(),
savers: this.savers?.map(user => user.getUserProfile()),
matched: this.matched?.map(request => request.getRequestInfo()),
savers: this.savers?.map((user) => user.getUserProfile()),
matched: this.matched?.map((request) => request.getRequestInfo()),
};
}
}
52 changes: 52 additions & 0 deletions src/models/ReportModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
import { Uuid } from "../types";
import { UserModel } from "./UserModel";
import { PostModel } from "./PostModel";
import { MessageModel } from "./MessageModel";
import { Report } from "../types";

@Entity("Report")
export class ReportModel {
@PrimaryGeneratedColumn("uuid")
id: Uuid;

@ManyToOne(() => UserModel, (user) => user.reports)
reporter: UserModel;

@ManyToOne(() => UserModel, (user) => user.reportedBy)
reported: UserModel;

@ManyToOne(() => PostModel, (post) => post.reports, { nullable: true })
post?: PostModel;

@ManyToOne(() => MessageModel, (message) => message.reports, {
nullable: true,
})
message?: MessageModel;

@Column({nullable: false})
reason: string;

@Column({nullable: false})
type: "post" | "profile" | "message";

@Column()
resolved: boolean;

@CreateDateColumn({ type: "timestamptz" })
created: Date;

public getReportInfo(): Report {
return {
id: this.id,
reporter: this.reporter,
reported: this.reported,
post: this.post,
message: this.message,
reason: this.reason,
type: this.type,
resolved: this.resolved,
created: this.created,
};
}
}
Loading

0 comments on commit 4ff09b9

Please sign in to comment.