Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API refactor #98

Merged
merged 11 commits into from
Sep 11, 2024
102 changes: 71 additions & 31 deletions src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ import { Stage } from "./models/stage";
type SequelizeError = { parent: { code: string } };

export type LoginResponse = {
type: "none" | "student" | "educator" | "admin",
result: LoginResult;
user?: User;
id?: number;
success: boolean;
};
Expand All @@ -52,6 +54,13 @@ export type CreateClassResponse = {
class?: object | undefined;
}

export enum UserType {
None = 0, // Not logged in
Student,
Educator,
Admin
}

// Grab any environment variables
// Currently, just the DB password
dotenv.config();
Expand Down Expand Up @@ -107,27 +116,33 @@ async function findEducatorByEmail(email: string): Promise<Educator | null> {
});
}

async function findStudentByEmail(email: string): Promise<Student | null> {
async function _findStudentByEmail(email: string): Promise<Student | null> {
return Student.findOne({
where: { email: { [Op.like] : email } }
});
}

export async function findStudentByUsername(username: string): Promise<Student | null> {
return Student.findOne({
where: { username: username }
where: { username }
});
}

export async function findStudentById(id: number): Promise<Student | null> {
return Student.findOne({
where: { id : id }
where: { id }
});
}

export async function findEducatorById(id: number): Promise<Educator | null> {
return Educator.findOne({
where: { id: id }
where: { id }
});
}

export async function findEducatorByUsername(username: string): Promise<Educator | null> {
return Educator.findOne({
where: { username },
});
}

Expand Down Expand Up @@ -183,11 +198,20 @@ async function educatorVerificationCodeExists(code: string): Promise<boolean> {
return result.length > 0;
}

export async function signUpEducator(firstName: string, lastName: string,
password: string, institution: string | null,
email: string, age: number | null, gender: string): Promise<SignUpResult> {
export interface SignUpEducatorOptions {
first_name: string;
last_name: string;
password: string;
email: string;
username: string;
institution?: string;
age?: number;
gender?: string;
}

export async function signUpEducator(options: SignUpEducatorOptions): Promise<SignUpResult> {

const encryptedPassword = encryptPassword(password);
const encryptedPassword = encryptPassword(options.password);

let validCode;
let verificationCode: string;
Expand All @@ -198,28 +222,31 @@ export async function signUpEducator(firstName: string, lastName: string,

let result = SignUpResult.Ok;
await Educator.create({
first_name: firstName,
last_name: lastName,
...options,
verified: 0,
verification_code: verificationCode,
password: encryptedPassword,
institution: institution,
email: email,
age: age,
gender: gender,
})
.catch(error => {
result = signupResultFromError(error);
});
return result;
}

export async function signUpStudent(username: string,
password: string, institution: string | null,
email: string, age: number, gender: string,
classroomCode: string | null): Promise<SignUpResult> {
export interface SignUpStudentOptions {
username: string;
password: string;
email?: string;
age?: number;
gender?: string;
institution?: string;
classroom_code?: string;
}


export async function signUpStudent(options: SignUpStudentOptions): Promise<SignUpResult> {

const encryptedPassword = encryptPassword(password);
const encryptedPassword = encryptPassword(options.password);

let validCode;
let verificationCode: string;
Expand All @@ -234,19 +261,19 @@ export async function signUpStudent(username: string,
verified: 0,
verification_code: verificationCode,
password: encryptedPassword,
institution: institution,
email: email,
age: age,
gender: gender,
institution: options.institution,
email: options.email,
age: options.age,
gender: options.gender,
})
.catch(error => {
result = signupResultFromError(error);
});

// If the student has a valid classroom code,
// add them to the class
if (student && classroomCode) {
const cls = await findClassByCode(classroomCode);
if (student && options.classroom_code) {
const cls = await findClassByCode(options.classroom_code);
if (cls !== null) {
StudentsClasses.create({
student_id: student.id,
Expand Down Expand Up @@ -293,11 +320,11 @@ export async function addStudentToClass(studentID: number, classID: number): Pro
});
}

async function checkLogin<T extends Model & User>(email: string, password: string, emailFinder: (email: string)
async function checkLogin<T extends Model & User>(identifier: string, password: string, identifierFinder: (identifier: string)
=> Promise<T | null>): Promise<LoginResponse> {

const encryptedPassword = encryptPassword(password);
const user = await emailFinder(email);
const user = await identifierFinder(identifier);
let result: LoginResult;
if (user === null) {
result = LoginResult.EmailNotExist;
Expand All @@ -314,15 +341,28 @@ async function checkLogin<T extends Model & User>(email: string, password: strin
where: { id: user.id }
});
}
return {

let type: LoginResponse["type"] = "none";
if (user instanceof Student) {
type = "student";
} else if (user instanceof Educator) {
type = "educator";
}

const response: LoginResponse = {
result: result,
success: LoginResult.success(result),
type,
id: user?.id ?? 0,
success: LoginResult.success(result)
};
if (user) {
response.user = user;
}
return response;
}

export async function checkStudentLogin(email: string, password: string): Promise<LoginResponse> {
return checkLogin(email, password, findStudentByEmail);
export async function checkStudentLogin(username: string, password: string): Promise<LoginResponse> {
return checkLogin(username, password, findStudentByUsername);
}

export async function checkEducatorLogin(email: string, password: string): Promise<LoginResponse> {
Expand Down
6 changes: 6 additions & 0 deletions src/models/educator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export class Educator extends Model<InferAttributes<Educator>, InferCreationAttr
declare verified: number;
declare verification_code: string;
declare email: string;
declare username: string;
declare first_name: string;
declare last_name: string;
declare password: string;
Expand Down Expand Up @@ -45,6 +46,11 @@ export function initializeEducatorModel(sequelize: Sequelize) {
allowNull: false,
unique: true
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
first_name: {
type: DataTypes.STRING,
allowNull: false,
Expand Down
16 changes: 10 additions & 6 deletions src/models/student.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ export class Student extends Model<InferAttributes<Student>, InferCreationAttrib
declare id: CreationOptional<number>;
declare verified: number;
declare verification_code: string;
declare email: string;
declare email: CreationOptional<string | null>;
declare username: string;
declare password: string;
declare institution: string | null;
declare age: number | null;
declare gender: string | null;
declare institution: CreationOptional<string | null>;
declare age: CreationOptional<number | null>;
declare gender: CreationOptional<string | null>;
declare ip: CreationOptional<string | null>;
declare lat: CreationOptional<string | null>;
declare lon: CreationOptional<string | null>;
Expand Down Expand Up @@ -50,19 +50,23 @@ export function initializeStudentModel(sequelize: Sequelize) {
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
institution: {
type: DataTypes.STRING
type: DataTypes.STRING,
defaultValue: null,
},
age: {
type: DataTypes.TINYINT,
defaultValue: null,
},
gender: {
type: DataTypes.STRING
type: DataTypes.STRING,
defaultValue: null,
},
ip: {
type: DataTypes.STRING
Expand Down
4 changes: 4 additions & 0 deletions src/request_results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export namespace CreateClassResult {
return 200;
}
}

export function success(result: CreateClassResult): boolean {
return result === CreateClassResult.Ok;
}
}

export enum LoginResult {
Expand Down
Loading
Loading