chore: added teacher comments to all service methods
This commit is contained in:
@@ -6,10 +6,10 @@ WORKDIR /usr/src/app
|
|||||||
RUN npm i -g pnpm
|
RUN npm i -g pnpm
|
||||||
|
|
||||||
# Prisma bits
|
# Prisma bits
|
||||||
COPY prisma ./
|
COPY prisma ./prisma/
|
||||||
RUN pnpx prisma generate
|
RUN pnpx prisma generate
|
||||||
|
|
||||||
# # NPM package install
|
# # PNPM package install
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN pnpm i
|
RUN pnpm i
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,13 @@ export class AuthService {
|
|||||||
private readonly mailerService: MailerService,
|
private readonly mailerService: MailerService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
// generate Id and token for email magiclink
|
//
|
||||||
|
/**
|
||||||
|
* Generate Id and token for email Magic-Link auth
|
||||||
|
*
|
||||||
|
* @param {AuthUser} user User Object
|
||||||
|
* @returns {Promise<PasswordlessVerification>} Created PasswordlessVerification token
|
||||||
|
*/
|
||||||
private async generatePasswordlessTokens(user: AuthUser) {
|
private async generatePasswordlessTokens(user: AuthUser) {
|
||||||
const salt = await bcrypt.genSalt(10);
|
const salt = await bcrypt.genSalt(10);
|
||||||
const expiresOn = DateTime.now().plus({ hours: 3 }).toISO().toString();
|
const expiresOn = DateTime.now().plus({ hours: 3 }).toISO().toString();
|
||||||
@@ -56,6 +62,12 @@ export class AuthService {
|
|||||||
return idToken;
|
return idToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and check passwordlessVerification exists or not
|
||||||
|
*
|
||||||
|
* @param {verifyMagicDto} data Object containing deviceIdentifier and token
|
||||||
|
* @returns {Promise<O.None | O.Some<PasswordlessVerification>>} Option of PasswordlessVerification token
|
||||||
|
*/
|
||||||
private async validatePasswordlessTokens(data: verifyMagicDto) {
|
private async validatePasswordlessTokens(data: verifyMagicDto) {
|
||||||
try {
|
try {
|
||||||
const tokens =
|
const tokens =
|
||||||
@@ -73,6 +85,13 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update User with new generated hashed refresh token
|
||||||
|
*
|
||||||
|
* @param {string} tokenHash Hash of newly generated refresh token
|
||||||
|
* @param {string} userUid User uid
|
||||||
|
* @returns {Promise<E.Right<User> | E.Left<"user/not_found">>} Either of User with updated refreshToken
|
||||||
|
*/
|
||||||
private async UpdateUserRefreshToken(tokenHash: string, userUid: string) {
|
private async UpdateUserRefreshToken(tokenHash: string, userUid: string) {
|
||||||
try {
|
try {
|
||||||
const user = await this.prismaService.user.update({
|
const user = await this.prismaService.user.update({
|
||||||
@@ -90,6 +109,12 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate new refresh token for user
|
||||||
|
*
|
||||||
|
* @param {string} userUid User Id
|
||||||
|
* @returns {Promise<E.Left<AuthErrorHandler> | E.Right<string>>} Generated refreshToken
|
||||||
|
*/
|
||||||
private async generateRefreshToken(userUid: string) {
|
private async generateRefreshToken(userUid: string) {
|
||||||
const refreshTokenPayload: RefreshTokenPayload = {
|
const refreshTokenPayload: RefreshTokenPayload = {
|
||||||
iss: process.env.APP_DOMAIN,
|
iss: process.env.APP_DOMAIN,
|
||||||
@@ -116,6 +141,12 @@ export class AuthService {
|
|||||||
return E.right(refreshToken);
|
return E.right(refreshToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate access and refresh token pair
|
||||||
|
*
|
||||||
|
* @param {string} userUid User ID
|
||||||
|
* @returns {Promise<E.Left<AuthErrorHandler> | E.Right<AuthTokens>>} Either of generated AuthTokens
|
||||||
|
*/
|
||||||
async generateAuthTokens(userUid: string) {
|
async generateAuthTokens(userUid: string) {
|
||||||
const accessTokenPayload: AccessTokenPayload = {
|
const accessTokenPayload: AccessTokenPayload = {
|
||||||
iss: process.env.APP_DOMAIN,
|
iss: process.env.APP_DOMAIN,
|
||||||
@@ -138,6 +169,12 @@ export class AuthService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deleted used PasswordlessVerification tokens
|
||||||
|
*
|
||||||
|
* @param {PasswordlessVerification} passwordlessTokens
|
||||||
|
* @returns {Promise<E.Right<PasswordlessVerification> | E.Left<"auth/passwordless_token_data_not_found">>} Either of deleted PasswordlessVerification token
|
||||||
|
*/
|
||||||
private async deletePasswordlessVerificationToken(
|
private async deletePasswordlessVerificationToken(
|
||||||
passwordlessTokens: PasswordlessVerification,
|
passwordlessTokens: PasswordlessVerification,
|
||||||
) {
|
) {
|
||||||
@@ -157,6 +194,13 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if Provider account exists for User
|
||||||
|
*
|
||||||
|
* @param {User} user User Object
|
||||||
|
* @param profile Provider Account type (Magic,Google,Github,Microsoft)
|
||||||
|
* @returns {Promise<O.None | O.Some<Account>>} Either of existing user provider Account
|
||||||
|
*/
|
||||||
async checkIfProviderAccountExists(user: User, profile) {
|
async checkIfProviderAccountExists(user: User, profile) {
|
||||||
const provider = await this.prismaService.account.findUnique({
|
const provider = await this.prismaService.account.findUnique({
|
||||||
where: {
|
where: {
|
||||||
@@ -172,9 +216,13 @@ export class AuthService {
|
|||||||
return O.some(provider);
|
return O.some(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
async signIn(
|
/**
|
||||||
email: string,
|
* Send Magic-Link to provider User email
|
||||||
): Promise<E.Left<AuthErrorHandler> | E.Right<DeviceIdentifierToken>> {
|
*
|
||||||
|
* @param {string} email User's email
|
||||||
|
* @returns {Promise<E.Left<AuthErrorHandler> | E.Right<DeviceIdentifierToken>>} Either containing DeviceIdentifierToken
|
||||||
|
*/
|
||||||
|
async signIn(email: string) {
|
||||||
if (!validateEmail(email))
|
if (!validateEmail(email))
|
||||||
return E.left({
|
return E.left({
|
||||||
message: INVALID_EMAIL,
|
message: INVALID_EMAIL,
|
||||||
@@ -205,6 +253,12 @@ export class AuthService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify and authenticate user from received data for Magic-Link
|
||||||
|
*
|
||||||
|
* @param {verifyMagicDto} data
|
||||||
|
* @returns {Promise<E.Right<AuthTokens> | E.Left<AuthErrorHandler>>} Either of generated AuthTokens
|
||||||
|
*/
|
||||||
async verifyPasswordlessTokens(
|
async verifyPasswordlessTokens(
|
||||||
data: verifyMagicDto,
|
data: verifyMagicDto,
|
||||||
): Promise<E.Right<AuthTokens> | E.Left<AuthErrorHandler>> {
|
): Promise<E.Right<AuthTokens> | E.Left<AuthErrorHandler>> {
|
||||||
@@ -273,10 +327,14 @@ export class AuthService {
|
|||||||
return E.right(tokens.right);
|
return E.right(tokens.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshAuthTokens(
|
/**
|
||||||
refresh_token: string,
|
* Refresh refresh and auth tokens
|
||||||
user: AuthUser,
|
*
|
||||||
): Promise<E.Left<AuthErrorHandler> | E.Right<AuthTokens>> {
|
* @param {string} refresh_token Hashed refresh token received from client
|
||||||
|
* @param {AuthUser} user User Object
|
||||||
|
* @returns {Promise<E.Left<AuthErrorHandler> | E.Right<AuthTokens>>} Either of generated AuthTokens
|
||||||
|
*/
|
||||||
|
async refreshAuthTokens(refresh_token: string, user: AuthUser) {
|
||||||
if (!user)
|
if (!user)
|
||||||
return E.left({
|
return E.left({
|
||||||
message: USER_NOT_FOUND,
|
message: USER_NOT_FOUND,
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ export class GithubStrategy extends PassportStrategy(Strategy) {
|
|||||||
return createdUser;
|
return createdUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * displayName and photoURL maybe null if user logged-in via magic-link before SSO
|
||||||
|
*/
|
||||||
if (!user.value.displayName || !user.value.photoURL) {
|
if (!user.value.displayName || !user.value.photoURL) {
|
||||||
const updatedUser = await this.usersService.updateUserDetails(
|
const updatedUser = await this.usersService.updateUserDetails(
|
||||||
user.value,
|
user.value,
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ export class GoogleStrategy extends PassportStrategy(Strategy) {
|
|||||||
return createdUser;
|
return createdUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * displayName and photoURL maybe null if user logged-in via magic-link before SSO
|
||||||
|
*/
|
||||||
if (!user.value.displayName || !user.value.photoURL) {
|
if (!user.value.displayName || !user.value.photoURL) {
|
||||||
const updatedUser = await this.usersService.updateUserDetails(
|
const updatedUser = await this.usersService.updateUserDetails(
|
||||||
user.value,
|
user.value,
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy) {
|
|||||||
return createdUser;
|
return createdUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * displayName and photoURL maybe null if user logged-in via magic-link before SSO
|
||||||
|
*/
|
||||||
if (!user.value.displayName || !user.value.photoURL) {
|
if (!user.value.displayName || !user.value.photoURL) {
|
||||||
const updatedUser = await this.usersService.updateUserDetails(
|
const updatedUser = await this.usersService.updateUserDetails(
|
||||||
user.value,
|
user.value,
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ export class MailerService implements OnModuleInit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} to Receiver's email id
|
||||||
|
* @param {UserMagicLinkMailDescription} mailDesc Details of email to be sent for Magic-Link auth
|
||||||
|
* @returns {Promise<postmark.Models.MessageSendingResponse>} Response if email was send successfully or not
|
||||||
|
*/
|
||||||
async sendAuthEmail(to: string, mailDesc: UserMagicLinkMailDescription) {
|
async sendAuthEmail(to: string, mailDesc: UserMagicLinkMailDescription) {
|
||||||
try {
|
try {
|
||||||
const res = await this.client.sendEmailWithTemplate({
|
const res = await this.client.sendEmailWithTemplate({
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ import { USER_NOT_FOUND } from 'src/errors';
|
|||||||
export class UserService {
|
export class UserService {
|
||||||
constructor(private prisma: PrismaService) {}
|
constructor(private prisma: PrismaService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find User with given email id
|
||||||
|
*
|
||||||
|
* @param {string} email User's email
|
||||||
|
* @returns {Promise<O.None | O.Some<User>>} Option of found User
|
||||||
|
*/
|
||||||
async findUserByEmail(email: string) {
|
async findUserByEmail(email: string) {
|
||||||
try {
|
try {
|
||||||
const user = await this.prisma.user.findUniqueOrThrow({
|
const user = await this.prisma.user.findUniqueOrThrow({
|
||||||
@@ -22,6 +28,12 @@ export class UserService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find User with given ID
|
||||||
|
*
|
||||||
|
* @param {string} userUid User ID
|
||||||
|
* @returns {Promise<O.None | O.Some<User>>} Option of found User
|
||||||
|
*/
|
||||||
async findUserById(userUid: string) {
|
async findUserById(userUid: string) {
|
||||||
try {
|
try {
|
||||||
const user = await this.prisma.user.findUniqueOrThrow({
|
const user = await this.prisma.user.findUniqueOrThrow({
|
||||||
@@ -35,6 +47,12 @@ export class UserService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new User when logged in via a Magic Link
|
||||||
|
*
|
||||||
|
* @param {string} email User's Email
|
||||||
|
* @returns {Promise<User>} Created User
|
||||||
|
*/
|
||||||
async createUserMagic(email: string) {
|
async createUserMagic(email: string) {
|
||||||
const createdUser = await this.prisma.user.create({
|
const createdUser = await this.prisma.user.create({
|
||||||
data: {
|
data: {
|
||||||
@@ -51,6 +69,14 @@ export class UserService {
|
|||||||
return createdUser;
|
return createdUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new User when logged in via a SSO provider
|
||||||
|
*
|
||||||
|
* @param {string} accessToken User's access token generated by providers
|
||||||
|
* @param {string} refreshToken User's refresh token generated by providers
|
||||||
|
* @param {any} profile Data received from SSO provider on the users account
|
||||||
|
* @returns {Promise<User>} Created User
|
||||||
|
*/
|
||||||
async createUserSSO(accessToken: string, refreshToken: string, profile) {
|
async createUserSSO(accessToken: string, refreshToken: string, profile) {
|
||||||
const createdUser = await this.prisma.user.create({
|
const createdUser = await this.prisma.user.create({
|
||||||
data: {
|
data: {
|
||||||
@@ -71,6 +97,15 @@ export class UserService {
|
|||||||
return createdUser;
|
return createdUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Account for a given User
|
||||||
|
*
|
||||||
|
* @param {AuthUser} user User object
|
||||||
|
* @param {string} accessToken User's access token generated by providers
|
||||||
|
* @param {string} refreshToken User's refresh token generated by providers
|
||||||
|
* @param {any} profile Data received from SSO provider on the users account
|
||||||
|
* @returns {Promise<Account>} Created Account
|
||||||
|
*/
|
||||||
async createProviderAccount(
|
async createProviderAccount(
|
||||||
user: AuthUser,
|
user: AuthUser,
|
||||||
accessToken: string,
|
accessToken: string,
|
||||||
@@ -94,6 +129,13 @@ export class UserService {
|
|||||||
return createdProvider;
|
return createdProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update User displayName and photoURL
|
||||||
|
*
|
||||||
|
* @param {AuthUser} user User object
|
||||||
|
* @param {any} profile Data received from SSO provider on the users account
|
||||||
|
* @returns {Promise<E.Right<User> | E.Left<"user/not_found">>} Updated user object
|
||||||
|
*/
|
||||||
async updateUserDetails(user: AuthUser, profile) {
|
async updateUserDetails(user: AuthUser, profile) {
|
||||||
try {
|
try {
|
||||||
const updatedUser = await this.prisma.user.update({
|
const updatedUser = await this.prisma.user.update({
|
||||||
|
|||||||
Reference in New Issue
Block a user