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
3 changes: 3 additions & 0 deletions src/model/dto/register-user-dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export class RegisterUserDto extends BaseDto {
)
@Prop()
password!: string;
@IsOptional()
@Prop()
code!: string;

constructor(init?: Partial<RegisterUserDto>) {
super();
Expand Down
2 changes: 2 additions & 0 deletions src/model/dto/user-profile-dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export class UserProfile {
emailVerified!: boolean
username!: string
apiKey!: string;
instructions_url!: string | null | undefined;
token!: string;
constructor(init?: Partial<UserProfile>) {
Object.assign(this, init);
}
Expand Down
48 changes: 41 additions & 7 deletions src/service/user-management-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ProjectGroupRoleDto } from "../model/dto/project-group-role-dto";
import { environment } from "../environment/environment";
import { ResetCredentialsDto } from "../model/dto/reset-credentials-dto";
import projectgroupService from "./project-group-service";
import { ReferralCodeDto } from "../model/dto/referral-code-dto";


export class UserManagementService implements IUserManagement {
Expand Down Expand Up @@ -103,7 +104,20 @@ export class UserManagementService implements IUserManagement {
async registerUser(user: RegisterUserDto): Promise<UserProfile> {
let userProfile = new UserProfile();
try {
const result: Response = await fetch(environment.registerUserUrl as string, {
let referralCodeDetails: ReferralCodeDto | undefined = undefined;
//Check if referral code is valid
if (user.code && user.code.length > 0) {
let referralCodeQuery = format('SELECT * FROM promo_referrals WHERE UPPER(code) = %L AND is_active = true AND valid_from <= NOW() AND valid_to >= NOW() limit 1', user.code.toUpperCase());

const referralCodeResult = await dbClient.query(referralCodeQuery);
if (referralCodeResult.rows.length == 0) {
throw new HttpException(410, "Invalid/Expired referral code");
}
referralCodeDetails = ReferralCodeDto.from(referralCodeResult.rows[0]);
}


const result: Response = await fetch(environment.registerUserUrl, {
method: 'post',
body: JSON.stringify(user),
headers: { 'Content-Type': 'application/json' }
Expand All @@ -123,12 +137,32 @@ export class UserManagementService implements IUserManagement {
const data = await result.json();
userProfile = new UserProfile(data);

//Assign user with default role and permissions
let queryStr = format(`INSERT INTO user_roles (user_id, project_group_id, role_id)
SELECT %L, project_group_id, role_id
FROM roles, project_group
WHERE roles.name = %L AND project_group.name = %L`, userProfile.id, Role.TDEI_MEMBER, DEFAULT_PROJECT_GROUP);
await dbClient.query(queryStr);
//If referral code is valid, then assign the user to the project group associated with referral code with TDEI member role
//Else assign the user to default project group with TDEI member role
if (referralCodeDetails) {
const rolesDetails = await this.getRolesByNames([Role.TDEI_MEMBER]);
const role_id = rolesDetails.get(Role.TDEI_MEMBER);
let addRoleProjectQuery = format(`INSERT INTO user_roles (user_id, project_group_id, role_id) VALUES %L ON CONFLICT ON CONSTRAINT unq_user_role_project_group DO NOTHING`, [[userProfile.id, referralCodeDetails.project_group_id, role_id]]);
await dbClient.query(addRoleProjectQuery);

//Update the instructions url in the user profile if exists
userProfile.instructions_url = referralCodeDetails.instructions_url;
//Generate the auth token and assign refresh token to user profile
const loginDto = new LoginDto();
loginDto.username = user.email;
loginDto.password = user.password;
const authResponse = await this.login(loginDto);
userProfile.token = authResponse.refresh_token;

}
else {
//Assign user with default role and permissions
let queryStr = format(`INSERT INTO user_roles (user_id, project_group_id, role_id)
SELECT %L, project_group_id, role_id
FROM roles, project_group
WHERE roles.name = %L AND project_group.name = %L`, userProfile.id, Role.TDEI_MEMBER, DEFAULT_PROJECT_GROUP);
await dbClient.query(queryStr);
}

} catch (error: any) {
console.error(error);
Expand Down
71 changes: 71 additions & 0 deletions test/unit/user-management.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import { ForeignKeyException } from "../../src/exceptions/http/http-exceptions";
import { ResetCredentialsDto } from "../../src/model/dto/reset-credentials-dto";
import projectgroupService from "../../src/service/project-group-service";

beforeEach(() => {
jest.clearAllMocks();
fetchMock.resetMocks();
});

// group test using describe
describe("User Management Service Test", () => {

Expand Down Expand Up @@ -118,6 +123,53 @@ describe("User Management Service Test", () => {
expect(getDbSpy).toHaveBeenCalledTimes(1);
});

test("When requested with promo code, Expect to return user profile response on success with instruction url (optional) and token ", async () => {
//Arrange
let newuser = new RegisterUserDto({
firstName: "firstname",
lastName: "lastname",
email: "email",
phone: "phone",
password: "password",
code: "PROMO123"
});
fetchMock.mockResolvedValueOnce(Promise.resolve(<any>{
status: 200,
json: () => Promise.resolve(<UserProfile>{
firstName: "firstname",
lastName: "lastname",
email: "email",
phone: "phone",
id: "id",
username: "email",
emailVerified: true,
apiKey: "apiKey",
instructions_url: "http://example.com/instructions",
token: "token"
}),
}));
const getDbPromoSpy = jest
.spyOn(dbClient, "query")
.mockResolvedValueOnce(<QueryResult>{ rows: [{ code: 'PROMO123' }] });
const getDbRoleByNamesSpy = jest
.spyOn(dbClient, "query")
.mockResolvedValueOnce(<QueryResult>{ rows: [{ role_id: 'role_id_1', name: Role.TDEI_MEMBER }] });
const getDbSpy = jest
.spyOn(dbClient, "query")
.mockResolvedValueOnce(<QueryResult>{});
const getLoginSpy = jest
.spyOn(userManagementServiceInstance, "login")
.mockResolvedValueOnce(<any>{ refresh_token: "refresh_token", access_token: "access_token" });
//Act
let result = await userManagementServiceInstance.registerUser(newuser);
//Assert
// expect(result.apiKey).toBe("apiKey");
expect(getDbPromoSpy).toHaveBeenCalled();
expect(getDbSpy).toHaveBeenCalled();
expect(getLoginSpy).toHaveBeenCalled();
expect(getDbRoleByNamesSpy).toHaveBeenCalled();
});

test("When user already exists with same email, Expect to throw error", async () => {
//Arrange
let newuser = new RegisterUserDto({
Expand All @@ -136,6 +188,25 @@ describe("User Management Service Test", () => {
await expect(userManagementServiceInstance.registerUser(newuser)).rejects.toThrow(Error);
});

test("When promo code is invalid, Expect to throw error", async () => {
//Arrange
let newuser = new RegisterUserDto({
firstName: "firstname",
lastName: "lastname",
email: "email",
phone: "phone",
password: "password",
code: "INVALIDCODE"
});
fetchMock.mockResolvedValueOnce(Promise.resolve(<any>{
status: 410,
json: () => Promise.resolve("Invalid/Expired referral code"),
}));
//Act
//Assert
await expect(userManagementServiceInstance.registerUser(newuser)).rejects.toThrow(Error);
});

test("When error registering, Expect to throw error", async () => {
//Arrange
let newuser = new RegisterUserDto({
Expand Down
Loading