Skip to content

Commit 6efa0b2

Browse files
authored
Merge pull request #139 from TaskarCenterAtUW/feature-2389
2389 changes
2 parents 22dc1ba + 89430de commit 6efa0b2

File tree

4 files changed

+117
-7
lines changed

4 files changed

+117
-7
lines changed

src/model/dto/register-user-dto.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export class RegisterUserDto extends BaseDto {
2929
)
3030
@Prop()
3131
password!: string;
32+
@IsOptional()
33+
@Prop()
34+
code!: string;
3235

3336
constructor(init?: Partial<RegisterUserDto>) {
3437
super();

src/model/dto/user-profile-dto.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export class UserProfile {
77
emailVerified!: boolean
88
username!: string
99
apiKey!: string;
10+
instructions_url!: string | null | undefined;
11+
token!: string;
1012
constructor(init?: Partial<UserProfile>) {
1113
Object.assign(this, init);
1214
}

src/service/user-management-service.ts

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { ProjectGroupRoleDto } from "../model/dto/project-group-role-dto";
1616
import { environment } from "../environment/environment";
1717
import { ResetCredentialsDto } from "../model/dto/reset-credentials-dto";
1818
import projectgroupService from "./project-group-service";
19+
import { ReferralCodeDto } from "../model/dto/referral-code-dto";
1920

2021

2122
export class UserManagementService implements IUserManagement {
@@ -103,7 +104,20 @@ export class UserManagementService implements IUserManagement {
103104
async registerUser(user: RegisterUserDto): Promise<UserProfile> {
104105
let userProfile = new UserProfile();
105106
try {
106-
const result: Response = await fetch(environment.registerUserUrl as string, {
107+
let referralCodeDetails: ReferralCodeDto | undefined = undefined;
108+
//Check if referral code is valid
109+
if (user.code && user.code.length > 0) {
110+
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());
111+
112+
const referralCodeResult = await dbClient.query(referralCodeQuery);
113+
if (referralCodeResult.rows.length == 0) {
114+
throw new HttpException(410, "Invalid/Expired referral code");
115+
}
116+
referralCodeDetails = ReferralCodeDto.from(referralCodeResult.rows[0]);
117+
}
118+
119+
120+
const result: Response = await fetch(environment.registerUserUrl, {
107121
method: 'post',
108122
body: JSON.stringify(user),
109123
headers: { 'Content-Type': 'application/json' }
@@ -123,12 +137,32 @@ export class UserManagementService implements IUserManagement {
123137
const data = await result.json();
124138
userProfile = new UserProfile(data);
125139

126-
//Assign user with default role and permissions
127-
let queryStr = format(`INSERT INTO user_roles (user_id, project_group_id, role_id)
128-
SELECT %L, project_group_id, role_id
129-
FROM roles, project_group
130-
WHERE roles.name = %L AND project_group.name = %L`, userProfile.id, Role.TDEI_MEMBER, DEFAULT_PROJECT_GROUP);
131-
await dbClient.query(queryStr);
140+
//If referral code is valid, then assign the user to the project group associated with referral code with TDEI member role
141+
//Else assign the user to default project group with TDEI member role
142+
if (referralCodeDetails) {
143+
const rolesDetails = await this.getRolesByNames([Role.TDEI_MEMBER]);
144+
const role_id = rolesDetails.get(Role.TDEI_MEMBER);
145+
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]]);
146+
await dbClient.query(addRoleProjectQuery);
147+
148+
//Update the instructions url in the user profile if exists
149+
userProfile.instructions_url = referralCodeDetails.instructions_url;
150+
//Generate the auth token and assign refresh token to user profile
151+
const loginDto = new LoginDto();
152+
loginDto.username = user.email;
153+
loginDto.password = user.password;
154+
const authResponse = await this.login(loginDto);
155+
userProfile.token = authResponse.refresh_token;
156+
157+
}
158+
else {
159+
//Assign user with default role and permissions
160+
let queryStr = format(`INSERT INTO user_roles (user_id, project_group_id, role_id)
161+
SELECT %L, project_group_id, role_id
162+
FROM roles, project_group
163+
WHERE roles.name = %L AND project_group.name = %L`, userProfile.id, Role.TDEI_MEMBER, DEFAULT_PROJECT_GROUP);
164+
await dbClient.query(queryStr);
165+
}
132166

133167
} catch (error: any) {
134168
console.error(error);

test/unit/user-management.service.test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import { ForeignKeyException } from "../../src/exceptions/http/http-exceptions";
1313
import { ResetCredentialsDto } from "../../src/model/dto/reset-credentials-dto";
1414
import projectgroupService from "../../src/service/project-group-service";
1515

16+
beforeEach(() => {
17+
jest.clearAllMocks();
18+
fetchMock.resetMocks();
19+
});
20+
1621
// group test using describe
1722
describe("User Management Service Test", () => {
1823

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

126+
test("When requested with promo code, Expect to return user profile response on success with instruction url (optional) and token ", async () => {
127+
//Arrange
128+
let newuser = new RegisterUserDto({
129+
firstName: "firstname",
130+
lastName: "lastname",
131+
email: "email",
132+
phone: "phone",
133+
password: "password",
134+
code: "PROMO123"
135+
});
136+
fetchMock.mockResolvedValueOnce(Promise.resolve(<any>{
137+
status: 200,
138+
json: () => Promise.resolve(<UserProfile>{
139+
firstName: "firstname",
140+
lastName: "lastname",
141+
email: "email",
142+
phone: "phone",
143+
id: "id",
144+
username: "email",
145+
emailVerified: true,
146+
apiKey: "apiKey",
147+
instructions_url: "http://example.com/instructions",
148+
token: "token"
149+
}),
150+
}));
151+
const getDbPromoSpy = jest
152+
.spyOn(dbClient, "query")
153+
.mockResolvedValueOnce(<QueryResult>{ rows: [{ code: 'PROMO123' }] });
154+
const getDbRoleByNamesSpy = jest
155+
.spyOn(dbClient, "query")
156+
.mockResolvedValueOnce(<QueryResult>{ rows: [{ role_id: 'role_id_1', name: Role.TDEI_MEMBER }] });
157+
const getDbSpy = jest
158+
.spyOn(dbClient, "query")
159+
.mockResolvedValueOnce(<QueryResult>{});
160+
const getLoginSpy = jest
161+
.spyOn(userManagementServiceInstance, "login")
162+
.mockResolvedValueOnce(<any>{ refresh_token: "refresh_token", access_token: "access_token" });
163+
//Act
164+
let result = await userManagementServiceInstance.registerUser(newuser);
165+
//Assert
166+
// expect(result.apiKey).toBe("apiKey");
167+
expect(getDbPromoSpy).toHaveBeenCalled();
168+
expect(getDbSpy).toHaveBeenCalled();
169+
expect(getLoginSpy).toHaveBeenCalled();
170+
expect(getDbRoleByNamesSpy).toHaveBeenCalled();
171+
});
172+
121173
test("When user already exists with same email, Expect to throw error", async () => {
122174
//Arrange
123175
let newuser = new RegisterUserDto({
@@ -136,6 +188,25 @@ describe("User Management Service Test", () => {
136188
await expect(userManagementServiceInstance.registerUser(newuser)).rejects.toThrow(Error);
137189
});
138190

191+
test("When promo code is invalid, Expect to throw error", async () => {
192+
//Arrange
193+
let newuser = new RegisterUserDto({
194+
firstName: "firstname",
195+
lastName: "lastname",
196+
email: "email",
197+
phone: "phone",
198+
password: "password",
199+
code: "INVALIDCODE"
200+
});
201+
fetchMock.mockResolvedValueOnce(Promise.resolve(<any>{
202+
status: 410,
203+
json: () => Promise.resolve("Invalid/Expired referral code"),
204+
}));
205+
//Act
206+
//Assert
207+
await expect(userManagementServiceInstance.registerUser(newuser)).rejects.toThrow(Error);
208+
});
209+
139210
test("When error registering, Expect to throw error", async () => {
140211
//Arrange
141212
let newuser = new RegisterUserDto({

0 commit comments

Comments
 (0)