Skip to content

Commit

Permalink
Endorsement Groups
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhollmann committed Mar 15, 2024
1 parent 62e3b62 commit c5590b8
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 131 deletions.
27 changes: 0 additions & 27 deletions db/migrations/20221115171254-create-endorsement-groups-table.js

This file was deleted.

29 changes: 29 additions & 0 deletions db/migrations/20221115171254-create-endorsement-groups-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { QueryInterface } from "sequelize";

import { DataType } from "sequelize-typescript";

export const ENDORSEMENT_GROUPS_TABLE_NAME = "endorsement_groups";

export const ENDORSEMENT_GROUPS_TABLE_ATTRIBUTES = {
id: {
type: DataType.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: {
type: DataType.STRING(70),
allowNull: false,
},
createdAt: DataType.DATE,
updatedAt: DataType.DATE,
};

export default {
async up(queryInterface: QueryInterface) {
await queryInterface.createTable(ENDORSEMENT_GROUPS_TABLE_NAME, ENDORSEMENT_GROUPS_TABLE_ATTRIBUTES);
},

async down(queryInterface: QueryInterface) {
await queryInterface.dropTable(ENDORSEMENT_GROUPS_TABLE_NAME);
},
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { QueryInterface } from "sequelize";

const { DataType } = require("sequelize-typescript");

const DataModelAttributes = {
export const ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_NAME = "endorsement_groups_belong_to_users";
export const ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_ATTRIBUTES = {
id: {
type: DataType.INTEGER,
primaryKey: true,
Expand Down Expand Up @@ -52,14 +55,12 @@ const DataModelAttributes = {
updatedAt: DataType.DATE,
};

module.exports = {
async up(queryInterface) {
await queryInterface.createTable("endorsement_groups_belong_to_users", DataModelAttributes);
export default {
async up(queryInterface: QueryInterface) {
await queryInterface.createTable(ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_NAME, ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_ATTRIBUTES);
},

async down(queryInterface) {
await queryInterface.dropTable("endorsement_groups_belong_to_users");
async down(queryInterface: QueryInterface) {
await queryInterface.dropTable(ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_NAME);
},

DataModelAttributes,
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { HttpStatusCode } from "axios";
import { TrainingStation } from "../../models/TrainingStation";
import { EndorsementGroupsBelongsToUsers } from "../../models/through/EndorsementGroupsBelongsToUsers";
import { User } from "../../models/User";
import Validator, { ValidationTypeEnum } from "../../utility/Validator";

/**
* Returns all Endorsement groups that are mentorable by the current user
Expand Down Expand Up @@ -158,8 +159,6 @@ async function updateByID(request: Request, response: Response, next: NextFuncti
try {
const params = request.params as { id: string };
const body = request.body as { name: string };
EndorsementGroupValidator.validateGetByIDRequest(params);
EndorsementGroupValidator.validateUpdateRequest(body);

let endorsementGroup = await EndorsementGroup.findByPk(params.id);

Expand Down Expand Up @@ -319,6 +318,10 @@ async function createEndorsementGroup(request: Request, response: Response, next
try {
const body = request.body as { name: string; training_station_ids: number[] };
EndorsementGroupValidator.validateCreateRequest(body);
Validator.validate(body, {
name: [ValidationTypeEnum.NON_NULL],
training_station_ids: [ValidationTypeEnum.IS_ARRAY, ValidationTypeEnum.VALID_JSON],
});

const endorsementGroup = await EndorsementGroup.create({
name: body.name,
Expand Down
41 changes: 27 additions & 14 deletions src/controllers/mentor-group/MentorGroupAdminController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MentorGroup } from "../../models/MentorGroup";
import { UserBelongToMentorGroups } from "../../models/through/UserBelongToMentorGroups";
import { User } from "../../models/User";
import { HttpStatusCode } from "axios";
import _MentorGroupAdminValidator from "./_MentorGroupAdminValidator";
//import _MentorGroupAdminValidator from "./_MentorGroupAdminValidator";
import { MentorGroupsBelongToEndorsementGroups } from "../../models/through/MentorGroupsBelongToEndorsementGroups";
import Validator, { ValidationTypeEnum } from "../../utility/Validator";

Expand All @@ -22,17 +22,23 @@ type UserInMentorGroupT = {
*/
async function create(request: Request, response: Response, next: NextFunction) {
try {
const body = request.body as { name: string; users: any; fir?: "edww" | "edgg" | "edmm" | "" };
const body = request.body as { name: string; users: any; fir: "edww" | "edgg" | "edmm" | "none" };

Validator.validate(body, {
name: [ValidationTypeEnum.NON_NULL],
//fir: [ValidationTypeEnum.NON_NULL],
fir: [
ValidationTypeEnum.NON_NULL,
{
option: ValidationTypeEnum.IN_ARRAY,
value: ["none", "edgg", "edww", "edmm"],
},
],
users: [ValidationTypeEnum.NON_NULL, ValidationTypeEnum.VALID_JSON],
});

const mentorGroup = await MentorGroup.create({
name: body.name,
fir: body.fir == "" ? null : body.fir,
fir: body.fir == "none" ? null : body.fir,
});

if (mentorGroup == null) {
Expand Down Expand Up @@ -117,13 +123,9 @@ async function getByID(request: Request, response: Response) {
const user: User = response.locals.user;
const params = request.params;

// const validation = ValidationHelper.validate([
// {
// name: "id",
// validationObject: params.mentor_group_id,
// toValidate: [{ val: ValidationOptions.NON_NULL }, { val: ValidationOptions.NUMBER }],
// },
// ]);
Validator.validate(params, {
mentor_group_id: [ValidationTypeEnum.NON_NULL, ValidationTypeEnum.NUMBER],
});

if (!(await user.isMentorGroupAdmin(Number(params.mentor_group_id)))) {
response.sendStatus(HttpStatusCode.Forbidden);
Expand Down Expand Up @@ -253,7 +255,12 @@ async function addMember(request: Request, response: Response) {
can_manage_course: boolean;
};

const validation = _MentorGroupAdminValidator.validateAddUser(body);
Validator.validate(body, {
user_id: [ValidationTypeEnum.NON_NULL],
mentor_group_id: [ValidationTypeEnum.NON_NULL],
group_admin: [ValidationTypeEnum.NON_NULL],
can_manage_course: [ValidationTypeEnum.NON_NULL],
});

if (!(await user.isMentorGroupAdmin(Number(body.mentor_group_id)))) {
response.sendStatus(HttpStatusCode.Forbidden);
Expand Down Expand Up @@ -286,7 +293,10 @@ async function removeMember(request: Request, response: Response) {
const user: User = response.locals.user;
const body = request.body as { mentor_group_id: number; user_id: number };

const validation = _MentorGroupAdminValidator.validateRemoveUser(body);
Validator.validate(body, {
mentor_group_id: [ValidationTypeEnum.NON_NULL],
user_id: [ValidationTypeEnum.NON_NULL],
});

try {
await UserBelongToMentorGroups.destroy({
Expand All @@ -306,7 +316,10 @@ async function removeMember(request: Request, response: Response) {
async function getEndorsementGroupsByID(request: Request, response: Response, next: NextFunction) {
try {
const params = request.params as { mentor_group_id: string };
// TODO: Validate

Validator.validate(params, {
mentor_group_id: [ValidationTypeEnum.NON_NULL],
});

const mentorGroup = await MentorGroup.findOne({
where: {
Expand Down
25 changes: 5 additions & 20 deletions src/models/EndorsementGroup.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Model, InferAttributes, CreationOptional, InferCreationAttributes, NonAttribute, Association } from "sequelize";
import { DataType } from "sequelize-typescript";
import { sequelize } from "../core/Sequelize";
import { User } from "./User";
import { TrainingStation } from "./TrainingStation";
import { ENDORSEMENT_GROUPS_TABLE_ATTRIBUTES, ENDORSEMENT_GROUPS_TABLE_NAME } from "../../db/migrations/20221115171254-create-endorsement-groups-table";

export class EndorsementGroup extends Model<InferAttributes<EndorsementGroup>, InferCreationAttributes<EndorsementGroup>> {
//
Expand All @@ -29,22 +29,7 @@ export class EndorsementGroup extends Model<InferAttributes<EndorsementGroup>, I
};
}

EndorsementGroup.init(
{
id: {
type: DataType.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: {
type: DataType.STRING(70),
allowNull: false,
},
createdAt: DataType.DATE,
updatedAt: DataType.DATE,
},
{
tableName: "endorsement_groups",
sequelize: sequelize,
}
);
EndorsementGroup.init(ENDORSEMENT_GROUPS_TABLE_ATTRIBUTES, {
tableName: ENDORSEMENT_GROUPS_TABLE_NAME,
sequelize: sequelize,
});
66 changes: 8 additions & 58 deletions src/models/through/EndorsementGroupsBelongsToUsers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Association, CreationOptional, ForeignKey, InferAttributes, InferCreationAttributes, Model, NonAttribute } from "sequelize";
import { DataType } from "sequelize-typescript";
import { sequelize } from "../../core/Sequelize";
import { UserSolo } from "../UserSolo";
import { User } from "../User";
import { EndorsementGroup } from "../EndorsementGroup";
import {
ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_ATTRIBUTES,
ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_NAME,
} from "../../../db/migrations/20221115171255-create-endorsement-groups-belongto-users-table";

export class EndorsementGroupsBelongsToUsers extends Model<
InferAttributes<EndorsementGroupsBelongsToUsers>,
Expand Down Expand Up @@ -36,60 +39,7 @@ export class EndorsementGroupsBelongsToUsers extends Model<
};
}

EndorsementGroupsBelongsToUsers.init(
{
id: {
type: DataType.INTEGER,
primaryKey: true,
autoIncrement: true,
},
endorsement_group_id: {
type: DataType.INTEGER,
allowNull: false,
references: {
model: "endorsement_groups",
key: "id",
},
onUpdate: "cascade",
onDelete: "cascade",
},
user_id: {
type: DataType.INTEGER,
allowNull: false,
references: {
model: "users",
key: "id",
},
onUpdate: "cascade",
onDelete: "cascade",
},
created_by: {
type: DataType.INTEGER,
allowNull: true,
references: {
model: "users",
key: "id",
},
onUpdate: "cascade",
onDelete: "set null",
},
solo_id: {
type: DataType.INTEGER,
allowNull: true,
references: {
model: "user_solos",
key: "id",
},
onUpdate: "cascade",
onDelete: "set null",
// The solo is only ever deleted IFF a rating change has taken place.
// Therefore, we can just set it null to indicate that the solo is over.
},
createdAt: DataType.DATE,
updatedAt: DataType.DATE,
},
{
tableName: "endorsement_groups_belong_to_users",
sequelize: sequelize,
}
);
EndorsementGroupsBelongsToUsers.init(ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_ATTRIBUTES, {
tableName: ENDORSEMENT_GROUPS_BELONGTO_USERS_TABLE_NAME,
sequelize: sequelize,
});
35 changes: 33 additions & 2 deletions src/utility/Validator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import dayjs from "dayjs";
import { ValidationException } from "../exceptions/ValidationException";

type ValidationRule = Record<string, Array<ValidationTypeEnum | { option: ValidationTypeEnum; value: any } | ((arg0: any) => boolean)>>;
type ValidationRule = Record<
string,
Array<
| ValidationTypeEnum
| {
option: ValidationTypeEnum;
value: any;
}
| ((arg0: any) => boolean)
>
>;

/**
* Supported Validation Options
Expand All @@ -19,6 +29,7 @@ enum ValidationTypeEnum {
VALID_DATE,
ARRAY_LENGTH_GT,
VALID_JSON, // This checks if the data is valid json and assigns the parsed value to the key!
STRING,
}

function validateAndReturn(data: any, validationRules: ValidationRule) {
Expand Down Expand Up @@ -63,6 +74,11 @@ function validate(data: any, validationRules: ValidationRule) {
_validateEntry(data, key, messages, { option: rule });
}

if (typeof rule == "string") {
// Validate ENUM Field (no Value)
_validateEntry(data, key, messages, { option: rule });
}

if (typeof rule == "object") {
// Validate ENUM Field (with Value)
_validateEntry(data, key, messages, { option: rule.option, value: rule.value });
Expand All @@ -83,7 +99,15 @@ function validate(data: any, validationRules: ValidationRule) {
}
}

function _validateEntry(rawData: any, key: string, messages: object[], valOption: { option: ValidationTypeEnum; value?: any }) {
function _validateEntry(
rawData: any,
key: string,
messages: object[],
valOption: {
option: ValidationTypeEnum;
value?: any;
}
) {
function addErrorEntry(message: string) {
messages.push({ code: ValidationTypeEnum[valOption.option], key: key, message: message });
}
Expand Down Expand Up @@ -116,6 +140,13 @@ function _validateEntry(rawData: any, key: string, messages: object[], valOption
}
break;

case ValidationTypeEnum.STRING:
let s = String(data);
if (s.length < 1) {
addErrorEntry(`Parameter is not a / a empty string`);
}
break;

case ValidationTypeEnum.NOT_EQUAL:
let invalid = false;
if (typeof valOption.value == "number" && Number(data) === valOption.value) break;
Expand Down

0 comments on commit c5590b8

Please sign in to comment.