Skip to content

Commit 2acda30

Browse files
committed
Fixing all Unit Tests + adding back deleteUserByOtherUser functionality
1 parent 58178c8 commit 2acda30

File tree

6 files changed

+85
-33
lines changed

6 files changed

+85
-33
lines changed

src/api/controllers/UserController.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ export class UserController {
7373
async deleteUser(@CurrentUser() user: UserModel): Promise<UserModel> {
7474
return await this.userService.deleteUser(user);
7575
}
76-
77-
// @Delete('id/:id/')
78-
// async deleteUser(@Params() params: UuidParam, @CurrentUser() user: UserModel): Promise<GetUserResponse> {
79-
// return { user: await this.userService.deleteUser(user, params) };
80-
// }
76+
77+
@Delete('id/:id/')
78+
async deleteUserByOtherUser(@Params() params: FirebaseUidParam, @CurrentUser() user: UserModel): Promise<GetUserResponse> {
79+
return { user: await this.userService.deleteUserByOtherUser(user, params) };
80+
}
8181

8282
@Post('softDelete/id/:id/')
8383
async softDeleteUser(@Params() params: FirebaseUidParam): Promise<GetUserResponse> {

src/models/UserModel.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class UserModel {
2121
firebaseUid: string;
2222

2323
/** @deprecated This column will be removed after the AuthorizationRefactor migration */
24-
@Column()
24+
@Column({ nullable: true })
2525
id: string;
2626

2727
@Column({ unique: true })

src/services/UserService.ts

+12
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@ export class UserService {
173173
});
174174
}
175175

176+
public async deleteUserByOtherUser(user: UserModel, params: FirebaseUidParam): Promise<UserModel> {
177+
return this.transactions.readWrite(async (transactionalEntityManager) => {
178+
const userRepository = Repositories.user(transactionalEntityManager);
179+
const userToDelete = await userRepository.getUserById(params.id);
180+
if (!userToDelete) throw new NotFoundError('User not found!');
181+
if (user.firebaseUid !== userToDelete.firebaseUid && !user.admin) {
182+
throw new UnauthorizedError('User does not have permission to delete other users');
183+
}
184+
return userRepository.deleteUser(userToDelete);
185+
});
186+
}
187+
176188
public async softDeleteUser(params: FirebaseUidParam): Promise<UserModel> {
177189
return this.transactions.readWrite(async (transactionalEntityManager) => {
178190
const userRepository = Repositories.user(transactionalEntityManager);

src/tests/UserTest.test.ts

+55-27
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,21 @@ import { UuidParam } from '../api/validators/GenericRequests';
66
import { UserModel } from '../models/UserModel';
77
import { ControllerFactory } from './controllers';
88
import { DatabaseConnection, DataFactory, PostFactory, UserFactory } from './data';
9-
import e from 'express';
10-
import exp from 'constants';
9+
import { CreateUserRequest } from '../types';
10+
1111

1212
let uuidParam: UuidParam;
1313
let expectedUser: UserModel;
1414
let conn: Connection;
1515
let userController: UserController;
1616
let postController: PostController;
1717

18+
// Helper function to omit a property from an object. Used for testing without the deprecated id property in UserModel.
19+
function omit(obj: any, keyToOmit: string) {
20+
return Object.fromEntries(
21+
Object.entries(obj).filter(([key]) => key !== keyToOmit)
22+
);
23+
}
1824

1925
beforeAll(async () => {
2026
await DatabaseConnection.connect();
@@ -96,7 +102,8 @@ describe('user tests', () => {
96102
if (getUserResponse.user != undefined) {
97103
getUserResponse.user.stars = Number(getUserResponse.user.stars);
98104
}
99-
expect(getUserResponse.user).toEqual(expectedUser);
105+
106+
expect(omit(getUserResponse.user, 'id')).toEqual(omit(expectedUser, 'id'));
100107
});
101108

102109
test('get user by email', async () => {
@@ -110,7 +117,7 @@ describe('user tests', () => {
110117
if (getUserResponse.user != undefined) {
111118
getUserResponse.user.stars = Number(getUserResponse.user.stars);
112119
}
113-
expect(getUserResponse.user).toEqual(expectedUser);
120+
expect(omit(getUserResponse.user, 'id')).toEqual(omit(expectedUser, 'id'));
114121
});
115122

116123
test('get user by google id', async () => {
@@ -124,7 +131,7 @@ describe('user tests', () => {
124131
if (getUserResponse.user != undefined) {
125132
getUserResponse.user.stars = Number(getUserResponse.user.stars);
126133
}
127-
expect(getUserResponse.user).toEqual(expectedUser);
134+
expect(omit(getUserResponse.user, 'id')).toEqual(omit(expectedUser, 'id'));
128135
});
129136

130137
test('edit profile', async () => {
@@ -137,54 +144,75 @@ describe('user tests', () => {
137144
await userController.editProfile({
138145
photoUrlBase64: undefined,
139146
username: undefined,
140-
venmoHandle: '@Shungo-Najima1',
147+
venmoHandle: 'Shungo-Najima1',
141148
bio: 'Mateo Slay'
142149
}, user);
143150

144151
expectedUser.bio = "Mateo Slay";
145-
expectedUser.venmoHandle = "@Shungo-Najima1";
152+
expectedUser.venmoHandle = "Shungo-Najima1";
146153

147154
const getUserResponse = await userController.getUserByGoogleId('shungoGoogleID');
148155
if (getUserResponse.user != undefined) {
149156
getUserResponse.user.stars = Number(getUserResponse.user.stars);
150157
}
151-
expect(getUserResponse.user).toEqual(expectedUser);
158+
expect(omit(getUserResponse.user, 'id')).toEqual(omit(expectedUser, 'id'));
152159
});
153160

154161
test('set super admin status', async () => {
155-
const authController = ControllerFactory.auth(conn);
162+
// Create super admin user first
163+
const superAdmin = UserFactory.fake();
164+
superAdmin.email = '[email protected]';
165+
superAdmin.admin = true;
166+
167+
await new DataFactory()
168+
.createUsers(superAdmin)
169+
.write();
156170

157-
const createUserRequest = {
171+
const createUserRequest: CreateUserRequest = {
158172
username: "admin",
159173
netid: "adm999",
160174
givenName: "administrator",
161175
familyName: "Weiner",
162176
photoUrl: "https://melmagazine.com/wp-content/uploads/2021/01/66f-1.jpg",
163-
venmoHandle: "@admin-Weiner",
164-
177+
venmoHandle: "admin-Weiner",
178+
165179
googleId: "mateoGoogleId",
166180
bio: "Personally, I would not stand for this.",
181+
fcmToken: ""
167182
}
168183

169-
const createUserRequestResponse = await authController.createUser(createUserRequest);
184+
// Create a new regular user
185+
const newUser = await userController.createUser(superAdmin, createUserRequest);
186+
expect(newUser.admin).toEqual(false); // New users should not be admin by default
170187

171-
expect(createUserRequestResponse.user?.admin).toEqual(true);
188+
// Make the user an admin using setAdmin
189+
const setAdminResponse = await userController.setAdmin({
190+
email: createUserRequest.email,
191+
status: true
192+
}, superAdmin);
193+
expect(setAdminResponse.user?.admin).toBe(true);
172194
});
173195

174196
test('set admin status from super user', async () => {
175-
const admin = UserFactory.fakeTemplate();
176-
admin.email = '[email protected]';
177-
let user = UserFactory.fake();
197+
// Create super admin user first
198+
const superAdmin = UserFactory.fake();
199+
superAdmin.email = '[email protected]';
200+
superAdmin.admin = true;
201+
202+
// Create a regular user
203+
const regularUser = UserFactory.fake();
204+
regularUser.email = regularUser.netid + '@cornell.edu';
178205

179206
await new DataFactory()
180-
.createUsers(admin, user)
207+
.createUsers(superAdmin, regularUser)
181208
.write();
182209

183-
expectedUser.admin = true;
184-
185-
const getUserResponse = await userController.setAdmin({ email: user.email, status: true }, admin);
186-
187-
expect(getUserResponse.user?.admin).toBe(true);
210+
// Make the regular user an admin
211+
const setAdminResponse = await userController.setAdmin({
212+
email: regularUser.email,
213+
status: true
214+
}, superAdmin);
215+
expect(setAdminResponse.user?.admin).toBe(true);
188216
});
189217

190218
test('block users', async () => {
@@ -438,9 +466,9 @@ describe('user tests', () => {
438466
if (getUserResponse.user != undefined) {
439467
getUserResponse.user.stars = Number(getUserResponse.user.stars);
440468
}
441-
expect(getUserResponse.user).toEqual(expectedUser);
469+
expect(omit(getUserResponse.user, 'id')).toEqual(omit(expectedUser, 'id'));
442470

443-
const deleteUserResponse = await userController.deleteUser(uuidParam, user);
471+
const deleteUserResponse = await userController.deleteUserByOtherUser(uuidParam, user);
444472
if (deleteUserResponse.user != undefined) {
445473
deleteUserResponse.user.stars = Number(deleteUserResponse.user.stars);
446474
}
@@ -460,7 +488,7 @@ describe('user tests', () => {
460488
const preDeleteUserResponse = await userController.getUsers(admin);
461489
expect(preDeleteUserResponse.users).toHaveLength(2);
462490

463-
const deleteUserResponse = await userController.deleteUser(uuidParam, admin);
491+
const deleteUserResponse = await userController.deleteUserByOtherUser(uuidParam, admin);
464492
if (deleteUserResponse.user != undefined) {
465493
deleteUserResponse.user.stars = Number(deleteUserResponse.user.stars);
466494
}
@@ -476,7 +504,7 @@ describe('user tests', () => {
476504
.write();
477505

478506
try {
479-
await userController.deleteUser({firebaseUid: user2.firebaseUid}, user1);
507+
await userController.deleteUserByOtherUser({id: user2.firebaseUid}, user1);
480508
} catch (error) {
481509
expect(error.message).toBe('User does not have permission to delete other users');
482510
}

src/tests/data/DatabaseConnection.ts

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export class DatabaseConnection {
3333
'Feedback',
3434
'notifications', // Add notifications table before User since it has a fk to User
3535
'Post',
36+
'FCMToken',
3637
'Request',
3738
'UserReview',
3839
'User'

src/tests/data/UserFactory.ts

+11
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ export class UserFactory {
2929
fakeUser.username = 'snajima';
3030
fakeUser.netid = 'sn999';
3131
fakeUser.admin = false;
32+
fakeUser.stars = 0;
33+
fakeUser.numReviews = 0;
3234
fakeUser.photoUrl = 'https://media-exp1.licdn.com/dms/image/C5603AQGmvQtdub6nAQ/profile-displayphoto-shrink_400_400/0/1635358826496?e=1668643200&v=beta&t=ncqjrFUqgqipctcmaSwPzSPrkj0RIQHiCINup_55NNs';
3335
fakeUser.email = fakeUser.netid + '@cornell.edu';
3436
fakeUser.googleId = 'shungoGoogleID';
3537
fakeUser.venmoHandle = "@Shungo-Najima";
38+
fakeUser.bio = "";
3639
fakeUser.isActive = true;
3740

3841
return fakeUser;
@@ -48,15 +51,19 @@ export class UserFactory {
4851
*/
4952
const fakeUser = new UserModel();
5053
fakeUser.firebaseUid = 'c6f0a14a-48ae-4b1c-bd6f-5f3b7e8c2b99';
54+
fakeUser.id = fakeUser.firebaseUid; // Add deprecated id during refactor
5155
fakeUser.givenName = 'Tony';
5256
fakeUser.familyName = 'Matchev';
5357
fakeUser.username = 'tmatchev';
5458
fakeUser.netid = 'tkm21';
5559
fakeUser.admin = false;
60+
fakeUser.stars = 0;
61+
fakeUser.numReviews = 0;
5662
fakeUser.photoUrl = 'https://media-exp1.licdn.com/dms/image/C5603AQGmvQtdub6nAQ/profile-displayphoto-shrink_400_400/0/1635358826496?e=1668643200&v=beta&t=ncqjrFUqgqipctcmaSwPzSPrkj0RIQHiCINup_55NNs';
5763
fakeUser.email = fakeUser.netid + '@cornell.edu';
5864
fakeUser.googleId = 'tonyGoogleID';
5965
fakeUser.venmoHandle = "@Tony-Matchev";
66+
fakeUser.bio = "";
6067
fakeUser.isActive = true;
6168

6269
return fakeUser;
@@ -73,14 +80,18 @@ export class UserFactory {
7380

7481
const fakeUser = new UserModel();
7582
fakeUser.firebaseUid = faker.datatype.uuid();
83+
fakeUser.id = fakeUser.firebaseUid; // Add deprecated id during refactor
7684
fakeUser.givenName = firstName;
7785
fakeUser.familyName = lastName;
7886
fakeUser.username = faker.internet.userName(firstName, lastName);
7987
fakeUser.admin = false;
88+
fakeUser.stars = 0;
89+
fakeUser.numReviews = 0;
8090
fakeUser.netid = FactoryUtils.getRandomLetter() + FactoryUtils.getRandomLetter() + FactoryUtils.getRandomNumber(0, 9999);
8191
fakeUser.photoUrl = faker.internet.url();
8292
fakeUser.email = fakeUser.netid + '@cornell.edu';
8393
fakeUser.googleId = faker.datatype.uuid();
94+
fakeUser.bio = "";
8495
fakeUser.isActive = true;
8596

8697
return fakeUser;

0 commit comments

Comments
 (0)