Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions backend/typescript/graphql/resolvers/authResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ const authResolvers = {
);
return isAuthorized;
},
isAuthorizedReviewer: async (
_parent: undefined,
{
accessToken,
applicantRecordId,
}: { accessToken: string; applicantRecordId: string },
): Promise<boolean> => {
const isAuthorized = await authService.isAuthorizedReviewer(
accessToken,
applicantRecordId,
);
return isAuthorized;
},
},
Mutation: {
login: async (
Expand Down
4 changes: 4 additions & 0 deletions backend/typescript/graphql/types/authType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const authType = gql`
extend type Query {
login(email: String!, password: String!): loginOK!
isAuthorizedByRole(accessToken: String!, roles: [Role!]!): Boolean!
isAuthorizedReviewer(
accessToken: String!
applicantRecordId: String!
): Boolean!
}

extend type Mutation {
Expand Down
36 changes: 36 additions & 0 deletions backend/typescript/services/implementations/authService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AuthDTO, Role, Token } from "../../types";
import { getErrorMessage } from "../../utilities/errorUtils";
import FirebaseRestClient from "../../utilities/firebaseRestClient";
import logger from "../../utilities/logger";
import ReviewedApplicantRecord from "../../models/reviewedApplicantRecord.model";

const Logger = logger(__filename);

Expand Down Expand Up @@ -272,6 +273,41 @@ class AuthService implements IAuthService {
throw error;
}
}

async isAuthorizedReviewer(
accessToken: string,
applicantRecordId: string,
): Promise<boolean> {
try {
const decodedIdToken: firebaseAdmin.auth.DecodedIdToken =
await firebaseAdmin.auth().verifyIdToken(accessToken, true);
const userId = await this.userService.getUserIdByAuthId(
decodedIdToken.uid,
);

const firebaseUser = await firebaseAdmin
.auth()
.getUser(decodedIdToken.uid);

if (!firebaseUser.emailVerified) {
return false;
}

const reviewedApplicantRecord = await ReviewedApplicantRecord.findOne({
where: {
applicantRecordId,
reviewerId: Number(userId),
},
});

return reviewedApplicantRecord !== null;
} catch (error) {
Logger.error(
`Failed to verify if user is authorized reviewer for applicant record ${applicantRecordId}`,
);
throw error;
}
}
}

export default AuthService;
11 changes: 11 additions & 0 deletions backend/typescript/services/interfaces/authService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ interface IAuthService {
* @returns true if email sent successfully
*/
sendSignInLink(email: string): Promise<boolean>;

/**
* Checks whether a user is an authorized reviewer for a specific applicant record
* @param accessToken user's access token
* @param applicantRecordId ID of the applicant record
* @returns true if user is authorized as a reviewer, false otherwise
*/
isAuthorizedReviewer(
accessToken: string,
applicantRecordId: string,
): Promise<boolean>;
}

export default IAuthService;
Loading