Skip to content

Commit

Permalink
Merge pull request #35 from uwblueprint/review-access-verification
Browse files Browse the repository at this point in the history
implement isAuthorizedToReview
  • Loading branch information
aaggarwal10 authored Sep 27, 2023
2 parents 403e806 + ea33e5d commit f39737d
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 6 deletions.
2 changes: 2 additions & 0 deletions backend/typescript/graphql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import userResolvers from "./resolvers/userResolvers";
import userType from "./types/userType";
import dashboardType from "./types/dashboardType";
import dashboardResolvers from "./resolvers/dashboardResolvers";
import reviewType from "./types/reviewType";

const query = gql`
type Query {
Expand All @@ -35,6 +36,7 @@ const executableSchema = makeExecutableSchema({
query,
mutation,
authType,
reviewType,
entityType,
simpleEntityType,
userType,
Expand Down
12 changes: 12 additions & 0 deletions backend/typescript/graphql/resolvers/authResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import FirebaseRestClient from "../../utilities/firebaseRestClient";
import IUserService from "../../services/interfaces/userService";
import User from "../../models/user.model";
import { AuthDTO, RegisterUserDTO, Role } from "../../types";
import IReviewService from "../../services/interfaces/reviewService";
import ReviewService from "../../services/implementations/reviewService";

const userService: IUserService = new UserService();
const emailService: IEmailService = new EmailService(nodemailerConfig);
const authService: IAuthService = new AuthService(userService, emailService);
const reviewService: IReviewService = new ReviewService();

const cookieOptions: CookieOptions = {

Check warning on line 22 in backend/typescript/graphql/resolvers/authResolvers.ts

View workflow job for this annotation

GitHub Actions / run-lint

'cookieOptions' is assigned a value but never used
httpOnly: true,
Expand Down Expand Up @@ -51,6 +54,15 @@ const authResolvers = {
);
return isAuthorized;
},
isAuthorizedToReview: async (
_parent: undefined,
{
applicationId,
reviewerUserId,
}: { applicationId: number; reviewerUserId: string },
): Promise<boolean> => {
return reviewService.isAuthorizedToReview(applicationId, reviewerUserId);
},
},
Mutation: {
login: async (
Expand Down
39 changes: 39 additions & 0 deletions backend/typescript/graphql/resolvers/dashboardResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,45 @@ const dashboardResolvers = {
},
},
Mutation: {
createApplicationDashboard: async (
_parent: undefined,
{
reviewerEmail,
applicationId,
reviewerAuthId,
passionFSG,
teamPlayer,
desireToLearn,
skill,
skillCategory,
reviwerComments,
recommendedSecondChoice,
}: {
reviewerEmail: string;
applicationId: number;
reviewerAuthId: string;
passionFSG: number;
teamPlayer: number;
desireToLearn: number;
skill: number;
skillCategory: string;
reviwerComments: string;
recommendedSecondChoice: string;
},
): Promise<ApplicationDashboardDTO> => {
return dashboardService.createApplicationDashboard(
reviewerEmail,
applicationId,
reviewerAuthId,
passionFSG,
teamPlayer,
desireToLearn,
skill,
skillCategory,
reviwerComments,
recommendedSecondChoice,
);
},
changeRating: async (
_parent: undefined,
{
Expand Down
12 changes: 12 additions & 0 deletions backend/typescript/graphql/types/dashboardType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ const dashboardType = gql`
newSkillCategory: String!
newRecommendedSecondChoice: String
): ApplicationDashboardDTO!
createApplicationDashboard(
reviewerEmail: String!
applicationId: Int!
reviewerAuthId: String!
passionFSG: Int!
teamPlayer: Int!
desireToLearn: Int!
skill: Int!
skillCategory: String!
reviwerComments: String!
recommendedSecondChoice: String!
): ApplicationDashboardDTO!
}
`;

Expand Down
9 changes: 9 additions & 0 deletions backend/typescript/graphql/types/reviewType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { gql } from "apollo-server-express";

const reviewType = gql`
extend type Query {
isAuthorizedToReview(applicationId: Int!, reviewerUserId: String!): Boolean!
}
`;

export default reviewType;
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,20 @@ const SEEDED_DATA = [
last_name: "Doe",
email: "[email protected]",
auth_id: "bide",
id: 1,
role: "User",
},
{
first_name: "Jane",
last_name: "Doe",
email: "[email protected]",
auth_id: "none",
id: 2,
role: "Admin",
},
{
first_name: "UW",
last_name: "Blueprint",
email: "[email protected]",
auth_id: "1Z4wyuonu9MhAi4VoAEiTMVj1iT2",
id: 4,
role: "Admin",
},
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const userEmails = ["[email protected]", "[email protected]"];

const SEEDED_DATA = [
{
id: 1,
applicationId: 1,
reviewerId: 1,
reviewerEmail: userEmails[0],
Expand All @@ -21,7 +20,6 @@ const SEEDED_DATA = [
skillCategory: "junior",
},
{
id: 2,
applicationId: 1,
reviewerId: 2,
reviewerEmail: userEmails[1],
Expand All @@ -42,6 +40,7 @@ export const up: Migration = async ({ context: sequelize }) => {
allowNull: false,
primaryKey: true,
unique: true,
autoIncrement: true,
},
applicationId: {
type: DataType.INTEGER,
Expand Down
7 changes: 6 additions & 1 deletion backend/typescript/models/applicationDashboard.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ export default class ApplicationDashboardTable extends Model {
@Column({ type: DataType.STRING })
reviewerEmail!: string;

@Column({ type: DataType.INTEGER, primaryKey: true, unique: true })
@Column({
type: DataType.INTEGER,
primaryKey: true,
unique: true,
autoIncrement: true,
})
id!: number;

@Column({ type: DataType.INTEGER })
Expand Down
52 changes: 52 additions & 0 deletions backend/typescript/services/implementations/appDashboardService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,58 @@ class AppDashboardService implements IAppDashboardService {
};
}

async createApplicationDashboard(
reviewerEmail: string,
applicationId: number,
reviewerAuthId: string,
passionFSG: number,
teamPlayer: number,
desireToLearn: number,
skill: number,
skillCategory: string,
reviewerComments: string,
recommendedSecondChoice: string,
): Promise<ApplicationDashboardDTO> {
try {
const reviewerId = await userService.getUserIdByAuthId(reviewerAuthId);
await ApplicationDashboardTable.sync();
Logger.error(`the creation:`);
const dashboard = await ApplicationDashboardTable.create({
reviewerEmail,
applicationId,
reviewerId,
passionFSG,
teamPlayer,
desireToLearn,
skill,
skillCategory,
reviewerComments,
recommendedSecondChoice,
});
Logger.error(`the data: ${JSON.stringify(dashboard)}`);
return {
id: dashboard.id,
reviewerEmail: dashboard.reviewerEmail,
passionFSG: dashboard.passionFSG,
teamPlayer: dashboard.teamPlayer,
desireToLearn: dashboard.desireToLearn,
skill: dashboard.skill,
skillCategory: dashboard.skillCategory,
reviewerComments: dashboard.reviewerComments,
recommendedSecondChoice: dashboard.recommendedSecondChoice,
reviewerId: dashboard.reviewerId,
applicationId: dashboard.applicationId,
};
} catch (error: unknown) {
Logger.error(
`Failed to create application dashboard. Reason = ${getErrorMessage(
error,
)}`,
);
throw error;
}
}

async mutateSkillCategory(
id: number,
newValue: string,
Expand Down
33 changes: 33 additions & 0 deletions backend/typescript/services/implementations/reviewService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import User from "../../models/user.model";
import IReviewService from "../interfaces/reviewService";
import ApplicationDashboardTable from "../../models/applicationDashboard.model";

class ReviewService implements IReviewService {
/* eslint-disable class-methods-use-this */
async isAuthorizedToReview(
applicationId: number,
userId: string,
): Promise<boolean> {
const users: Array<User> | null = await User.findAll({
where: {
auth_id: userId,
},
});
if (users && users.length === 1) {
const user = users[0];
const application: ApplicationDashboardTable | null = await ApplicationDashboardTable.findOne(
{
where: {
reviewerId: user.id,
applicationId,
},
},
);
if (application) return true;
return false;
}
throw Error("Multiple or no user(s) found with same firebase userId");
}
}

export default ReviewService;
28 changes: 28 additions & 0 deletions backend/typescript/services/interfaces/appDashboardService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,34 @@ interface IAppDashboardService {
newValue: string,
): Promise<ApplicationDashboardDTO>;

/**
* Bulk updates applications in reviewer dashboard
* @Param reviewerEmail the email of the reviewer
* @param applicationId the id of the application (seperate from the postgres id field of the application)
* @param reviewerAuthId the Firebase auth id of the user (This is NOT the same as the postgress id field of the user)
* @param passionFSG passion for social good rating of applicatn
* @param teamPlayer teamwork rating of applicatn
* @param skill skill rating of applicatn
* @param skillCategory whether applicant is viewed as junior, intermediate, or senior
* @param reviewerComments comments of the application from reviewer
* @param recommendedSecondChoice an indication of whether 2nd choice is recommended
* @param reviewComplete whether the reviewer has finished the review
* @returns an array of the updated dashboard entry ids
* @throws Error if batch update failed
*/
createApplicationDashboard(
reviewerEmail: string,
applicationId: number,
reviewerAuthId: string,
passionFSG: number,
teamPlayer: number,
desireToLearn: number,
skill: number,
skillCategory: string,
reviewerComments: string,
recommendedSecondChoice: string,
): Promise<ApplicationDashboardDTO>;

/**
* Bulk updates applications in reviewer dashboard
* @param applicationData
Expand Down
12 changes: 12 additions & 0 deletions backend/typescript/services/interfaces/reviewService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
interface IReviewService {
/**
* Determine if the reviewerUserId has been assigned to the application with id applicationId
* with the specified email address
* @param applicationId the id of the application the reviewer is trying to review
* @param reviewerUserId the firebase user id of the revieweer
* @returns true if user is authorized to review the application and authorized, false otherwise
*/
isAuthorizedToReview(applicationId: number, userId: string): Promise<boolean>;
}

export default IReviewService;

0 comments on commit f39737d

Please sign in to comment.