refactor(server): auth dto (#5593)
* refactor: AuthUserDto => AuthDto * refactor: reorganize auth-dto * refactor: AuthUser() => Auth()
This commit is contained in:
@@ -31,7 +31,7 @@ import {
|
||||
IUserTokenRepository,
|
||||
} from '../repositories';
|
||||
import { AuthType } from './auth.constant';
|
||||
import { AuthUserDto, SignUpDto } from './auth.dto';
|
||||
import { AuthDto, SignUpDto } from './auth.dto';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
// const token = Buffer.from('my-api-key', 'utf8').toString('base64');
|
||||
@@ -145,7 +145,7 @@ describe('AuthService', () => {
|
||||
|
||||
describe('changePassword', () => {
|
||||
it('should change the password', async () => {
|
||||
const authUser = { email: 'test@imimch.com' } as UserEntity;
|
||||
const auth = { user: { email: 'test@imimch.com' } } as AuthDto;
|
||||
const dto = { password: 'old-password', newPassword: 'new-password' };
|
||||
|
||||
userMock.getByEmail.mockResolvedValue({
|
||||
@@ -153,23 +153,23 @@ describe('AuthService', () => {
|
||||
password: 'hash-password',
|
||||
} as UserEntity);
|
||||
|
||||
await sut.changePassword(authUser, dto);
|
||||
await sut.changePassword(auth, dto);
|
||||
|
||||
expect(userMock.getByEmail).toHaveBeenCalledWith(authUser.email, true);
|
||||
expect(userMock.getByEmail).toHaveBeenCalledWith(auth.user.email, true);
|
||||
expect(cryptoMock.compareBcrypt).toHaveBeenCalledWith('old-password', 'hash-password');
|
||||
});
|
||||
|
||||
it('should throw when auth user email is not found', async () => {
|
||||
const authUser = { email: 'test@imimch.com' } as UserEntity;
|
||||
const auth = { user: { email: 'test@imimch.com' } } as AuthDto;
|
||||
const dto = { password: 'old-password', newPassword: 'new-password' };
|
||||
|
||||
userMock.getByEmail.mockResolvedValue(null);
|
||||
|
||||
await expect(sut.changePassword(authUser, dto)).rejects.toBeInstanceOf(UnauthorizedException);
|
||||
await expect(sut.changePassword(auth, dto)).rejects.toBeInstanceOf(UnauthorizedException);
|
||||
});
|
||||
|
||||
it('should throw when password does not match existing password', async () => {
|
||||
const authUser = { email: 'test@imimch.com' } as UserEntity;
|
||||
const auth = { user: { email: 'test@imimch.com' } as UserEntity };
|
||||
const dto = { password: 'old-password', newPassword: 'new-password' };
|
||||
|
||||
cryptoMock.compareBcrypt.mockReturnValue(false);
|
||||
@@ -179,11 +179,11 @@ describe('AuthService', () => {
|
||||
password: 'hash-password',
|
||||
} as UserEntity);
|
||||
|
||||
await expect(sut.changePassword(authUser, dto)).rejects.toBeInstanceOf(BadRequestException);
|
||||
await expect(sut.changePassword(auth, dto)).rejects.toBeInstanceOf(BadRequestException);
|
||||
});
|
||||
|
||||
it('should throw when user does not have a password', async () => {
|
||||
const authUser = { email: 'test@imimch.com' } as UserEntity;
|
||||
const auth = { user: { email: 'test@imimch.com' } } as AuthDto;
|
||||
const dto = { password: 'old-password', newPassword: 'new-password' };
|
||||
|
||||
userMock.getByEmail.mockResolvedValue({
|
||||
@@ -191,33 +191,33 @@ describe('AuthService', () => {
|
||||
password: '',
|
||||
} as UserEntity);
|
||||
|
||||
await expect(sut.changePassword(authUser, dto)).rejects.toBeInstanceOf(BadRequestException);
|
||||
await expect(sut.changePassword(auth, dto)).rejects.toBeInstanceOf(BadRequestException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('logout', () => {
|
||||
it('should return the end session endpoint', async () => {
|
||||
configMock.load.mockResolvedValue(systemConfigStub.enabled);
|
||||
const authUser = { id: '123' } as AuthUserDto;
|
||||
await expect(sut.logout(authUser, AuthType.OAUTH)).resolves.toEqual({
|
||||
const auth = { user: { id: '123' } } as AuthDto;
|
||||
await expect(sut.logout(auth, AuthType.OAUTH)).resolves.toEqual({
|
||||
successful: true,
|
||||
redirectUri: 'http://end-session-endpoint',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the default redirect', async () => {
|
||||
const authUser = { id: '123' } as AuthUserDto;
|
||||
const auth = { user: { id: '123' } } as AuthDto;
|
||||
|
||||
await expect(sut.logout(authUser, AuthType.PASSWORD)).resolves.toEqual({
|
||||
await expect(sut.logout(auth, AuthType.PASSWORD)).resolves.toEqual({
|
||||
successful: true,
|
||||
redirectUri: '/auth/login?autoLaunch=0',
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete the access token', async () => {
|
||||
const authUser = { id: '123', accessTokenId: 'token123' } as AuthUserDto;
|
||||
const auth = { user: { id: '123' }, userToken: { id: 'token123' } } as AuthDto;
|
||||
|
||||
await expect(sut.logout(authUser, AuthType.PASSWORD)).resolves.toEqual({
|
||||
await expect(sut.logout(auth, AuthType.PASSWORD)).resolves.toEqual({
|
||||
successful: true,
|
||||
redirectUri: '/auth/login?autoLaunch=0',
|
||||
});
|
||||
@@ -226,9 +226,9 @@ describe('AuthService', () => {
|
||||
});
|
||||
|
||||
it('should return the default redirect if auth type is OAUTH but oauth is not enabled', async () => {
|
||||
const authUser = { id: '123' } as AuthUserDto;
|
||||
const auth = { user: { id: '123' } } as AuthDto;
|
||||
|
||||
await expect(sut.logout(authUser, AuthType.OAUTH)).resolves.toEqual({
|
||||
await expect(sut.logout(auth, AuthType.OAUTH)).resolves.toEqual({
|
||||
successful: true,
|
||||
redirectUri: '/auth/login?autoLaunch=0',
|
||||
});
|
||||
@@ -268,7 +268,10 @@ describe('AuthService', () => {
|
||||
userMock.get.mockResolvedValue(userStub.user1);
|
||||
userTokenMock.getByToken.mockResolvedValue(userTokenStub.userToken);
|
||||
const client = { request: { headers: { authorization: 'Bearer auth_token' } } };
|
||||
await expect(sut.validate((client as Socket).request.headers, {})).resolves.toEqual(userStub.user1);
|
||||
await expect(sut.validate((client as Socket).request.headers, {})).resolves.toEqual({
|
||||
user: userStub.user1,
|
||||
userToken: userTokenStub.userToken,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -296,7 +299,10 @@ describe('AuthService', () => {
|
||||
shareMock.getByKey.mockResolvedValue(sharedLinkStub.valid);
|
||||
userMock.get.mockResolvedValue(userStub.admin);
|
||||
const headers: IncomingHttpHeaders = { 'x-immich-share-key': sharedLinkStub.valid.key.toString('base64url') };
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual(authStub.adminSharedLink);
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual({
|
||||
user: userStub.admin,
|
||||
sharedLink: sharedLinkStub.valid,
|
||||
});
|
||||
expect(shareMock.getByKey).toHaveBeenCalledWith(sharedLinkStub.valid.key);
|
||||
});
|
||||
|
||||
@@ -304,7 +310,10 @@ describe('AuthService', () => {
|
||||
shareMock.getByKey.mockResolvedValue(sharedLinkStub.valid);
|
||||
userMock.get.mockResolvedValue(userStub.admin);
|
||||
const headers: IncomingHttpHeaders = { 'x-immich-share-key': sharedLinkStub.valid.key.toString('hex') };
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual(authStub.adminSharedLink);
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual({
|
||||
user: userStub.admin,
|
||||
sharedLink: sharedLinkStub.valid,
|
||||
});
|
||||
expect(shareMock.getByKey).toHaveBeenCalledWith(sharedLinkStub.valid.key);
|
||||
});
|
||||
});
|
||||
@@ -319,14 +328,20 @@ describe('AuthService', () => {
|
||||
it('should return an auth dto', async () => {
|
||||
userTokenMock.getByToken.mockResolvedValue(userTokenStub.userToken);
|
||||
const headers: IncomingHttpHeaders = { cookie: 'immich_access_token=auth_token' };
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual(userStub.user1);
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual({
|
||||
user: userStub.user1,
|
||||
userToken: userTokenStub.userToken,
|
||||
});
|
||||
});
|
||||
|
||||
it('should update when access time exceeds an hour', async () => {
|
||||
userTokenMock.getByToken.mockResolvedValue(userTokenStub.inactiveToken);
|
||||
userTokenMock.save.mockResolvedValue(userTokenStub.userToken);
|
||||
const headers: IncomingHttpHeaders = { cookie: 'immich_access_token=auth_token' };
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual(userStub.user1);
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual({
|
||||
user: userStub.user1,
|
||||
userToken: userTokenStub.userToken,
|
||||
});
|
||||
expect(userTokenMock.save.mock.calls[0][0]).toMatchObject({
|
||||
id: 'not_active',
|
||||
token: 'auth_token',
|
||||
@@ -350,7 +365,7 @@ describe('AuthService', () => {
|
||||
it('should return an auth dto', async () => {
|
||||
keyMock.getKey.mockResolvedValue(keyStub.admin);
|
||||
const headers: IncomingHttpHeaders = { 'x-api-key': 'auth_token' };
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual(authStub.admin);
|
||||
await expect(sut.validate(headers, {})).resolves.toEqual({ user: userStub.admin, apiKey: keyStub.admin });
|
||||
expect(keyMock.getKey).toHaveBeenCalledWith('auth_token (hashed)');
|
||||
});
|
||||
});
|
||||
@@ -377,7 +392,7 @@ describe('AuthService', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
expect(userTokenMock.getAll).toHaveBeenCalledWith(authStub.user1.id);
|
||||
expect(userTokenMock.getAll).toHaveBeenCalledWith(authStub.user1.user.id);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -387,7 +402,7 @@ describe('AuthService', () => {
|
||||
|
||||
await sut.logoutDevices(authStub.user1);
|
||||
|
||||
expect(userTokenMock.getAll).toHaveBeenCalledWith(authStub.user1.id);
|
||||
expect(userTokenMock.getAll).toHaveBeenCalledWith(authStub.user1.user.id);
|
||||
expect(userTokenMock.delete).toHaveBeenCalledWith('not_active');
|
||||
expect(userTokenMock.delete).not.toHaveBeenCalledWith('token-id');
|
||||
});
|
||||
@@ -399,7 +414,7 @@ describe('AuthService', () => {
|
||||
|
||||
await sut.logoutDevice(authStub.user1, 'token-1');
|
||||
|
||||
expect(accessMock.authDevice.checkOwnerAccess).toHaveBeenCalledWith(authStub.user1.id, new Set(['token-1']));
|
||||
expect(accessMock.authDevice.checkOwnerAccess).toHaveBeenCalledWith(authStub.user1.user.id, new Set(['token-1']));
|
||||
expect(userTokenMock.delete).toHaveBeenCalledWith('token-1');
|
||||
});
|
||||
});
|
||||
@@ -506,7 +521,7 @@ describe('AuthService', () => {
|
||||
|
||||
await sut.link(authStub.user1, { url: 'http://immich/user-settings?code=abc123' });
|
||||
|
||||
expect(userMock.update).toHaveBeenCalledWith(authStub.user1.id, { oauthId: sub });
|
||||
expect(userMock.update).toHaveBeenCalledWith(authStub.user1.user.id, { oauthId: sub });
|
||||
});
|
||||
|
||||
it('should not link an already linked oauth.sub', async () => {
|
||||
@@ -528,7 +543,7 @@ describe('AuthService', () => {
|
||||
|
||||
await sut.unlink(authStub.user1);
|
||||
|
||||
expect(userMock.update).toHaveBeenCalledWith(authStub.user1.id, { oauthId: '' });
|
||||
expect(userMock.update).toHaveBeenCalledWith(authStub.user1.user.id, { oauthId: '' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user