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
44 changes: 39 additions & 5 deletions backend/src/auth/__test__/auth.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ const mockInitiateAuth = vi.fn().mockReturnThis();
const mockGetUser = vi.fn().mockReturnThis();
const mockRespondToAuthChallenge = vi.fn().mockReturnThis();
const mockCognitoPromise = vi.fn();
// adminAddUserToGroup is called without .promise() in the service; return a resolved promise so `await` works
const mockAdminAddUserToGroup = vi.fn().mockResolvedValue({});


// Create mock functions for DynamoDB operations
const mockDynamoGet = vi.fn().mockReturnThis();
const mockDynamoPut = vi.fn().mockReturnThis();
const mockDynamoUpdate = vi.fn().mockReturnThis();
const mockDynamoScan = vi.fn().mockReturnThis();
const mockDynamoPromise = vi.fn();

// Mock AWS SDK
Expand All @@ -26,6 +30,7 @@ vi.mock('aws-sdk', () => ({
initiateAuth: mockInitiateAuth,
getUser: mockGetUser,
respondToAuthChallenge: mockRespondToAuthChallenge,
adminAddUserToGroup: mockAdminAddUserToGroup,
promise: mockCognitoPromise,
})),
DynamoDB: {
Expand All @@ -34,6 +39,7 @@ vi.mock('aws-sdk', () => ({
put: mockDynamoPut,
update: mockDynamoUpdate,
promise: mockDynamoPromise,
scan: mockDynamoScan
}))
}
}
Expand Down Expand Up @@ -73,8 +79,11 @@ describe('AuthService', () => {
// 4. Assert that Cognito methods were called with correct parameters
// 5. Assert that DynamoDB put was called with correct user data
it('should successfully register a user', async () => {
// Ensure scan returns no items (email not in use)
mockDynamoPromise.mockResolvedValueOnce({ Items: [] });

// Cognito promise chain (adminCreateUser().promise(), adminSetUserPassword().promise())
mockCognitoPromise
.mockResolvedValueOnce({})
.mockResolvedValueOnce({})
.mockResolvedValueOnce({});

Expand All @@ -89,9 +98,33 @@ describe('AuthService', () => {
],
MessageAction: 'SUPPRESS',
});
expect(mockAdminSetUserPassword).toHaveBeenCalled();
expect(mockDynamoPut).toHaveBeenCalled();

expect(mockAdminSetUserPassword).toHaveBeenCalledWith({
UserPoolId: 'test-user-pool-id',
Username: 'c4c',
Password: 'Pass123!',
Permanent: true,
});

// adminAddUserToGroup is called without .promise() so verify invocation
expect(mockAdminAddUserToGroup).toHaveBeenCalledWith({
GroupName: 'Inactive',
UserPoolId: 'test-user-pool-id',
Username: 'c4c',
});

expect(mockDynamoPut).toHaveBeenCalledWith(
expect.objectContaining({
TableName: 'test-users-table',
Item: expect.objectContaining({ userId: 'c4c', email: 'c4c@example.com' }),
}),
);
});


it("should deny someone from making an email when it is already in use", async () => {

})
});

describe('login', () => {
Expand Down Expand Up @@ -168,7 +201,7 @@ describe('AuthService', () => {
expect(result.requiredAttributes).toEqual(['email']);
expect(result.username).toBe('c4c');
expect(result.access_token).toBeUndefined();
expect(result.user).toBeUndefined();
expect(result.user).toEqual({});
});

it('should create new DynamoDB user if not exists', async () => {
Expand Down Expand Up @@ -211,7 +244,8 @@ describe('AuthService', () => {
expect(result.user).toEqual({
userId: 'c4c',
email: 'c4c@gmail.com',
biography: '',
name: "",
position: "Inactive"
});
expect(result.message).toBe('Login Successful!');

Expand Down
29 changes: 27 additions & 2 deletions backend/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
import { User } from '../types/User';

@Controller('auth')
export class AuthController {
Expand All @@ -15,17 +16,29 @@ export class AuthController {
return { message: 'User registered successfully' };
}

// Make sure to put a guard on this route
@Post('change-role')
async addToGroup(
@Body('username') username: string,
@Body('groupName') groupName: string,
@Body('requestedBy') requestedBy: string,
): Promise<{ message: string }> {
await this.authService.addUserToGroup(username, groupName,requestedBy);
return { message: `User changed to ${groupName} successfully` };
}

@Post('login')
async login(
@Body('username') username: string,
@Body('password') password: string,
): Promise<{
access_token?: string;
user?: any;
user: User;
session?: string;
challenge?: string;
requiredAttributes?: string[];
username?: string;
position?: string;
}> {
return await this.authService.login(username, password);
}
Expand All @@ -48,5 +61,17 @@ export class AuthController {
): Promise<{ message: string }> {
await this.authService.updateProfile(username, email, position_or_role);
return { message: 'Profile has been updated' };
}
}

@Post('delete-user')
async deleteUser(
@Body('username') username: string,
): Promise<{ message: string }> {
await this.authService.deleteUser(username);
return { message: `${username} has been deleted` };
}




}
Loading