|
@@ -12,6 +12,38 @@ import { IUserRepository } from '../user/user-repository';
|
|
|
const email = 'user@immich.com';
|
|
|
const sub = 'my-auth-user-sub';
|
|
|
|
|
|
+const config = {
|
|
|
+ disabled: {
|
|
|
+ oauth: {
|
|
|
+ enabled: false,
|
|
|
+ buttonText: 'OAuth',
|
|
|
+ issuerUrl: 'http://issuer,',
|
|
|
+ },
|
|
|
+ } as SystemConfig,
|
|
|
+ enabled: {
|
|
|
+ oauth: {
|
|
|
+ enabled: true,
|
|
|
+ autoRegister: true,
|
|
|
+ buttonText: 'OAuth',
|
|
|
+ },
|
|
|
+ } as SystemConfig,
|
|
|
+ noAutoRegister: {
|
|
|
+ oauth: {
|
|
|
+ enabled: true,
|
|
|
+ autoRegister: false,
|
|
|
+ },
|
|
|
+ } as SystemConfig,
|
|
|
+ override: {
|
|
|
+ oauth: {
|
|
|
+ enabled: true,
|
|
|
+ autoRegister: true,
|
|
|
+ buttonText: 'OAuth',
|
|
|
+ mobileOverrideEnabled: true,
|
|
|
+ mobileRedirectUri: 'http://mobile-redirect',
|
|
|
+ },
|
|
|
+ } as SystemConfig,
|
|
|
+};
|
|
|
+
|
|
|
const user = {
|
|
|
id: 'user_id',
|
|
|
email,
|
|
@@ -49,8 +81,11 @@ describe('OAuthService', () => {
|
|
|
let userRepositoryMock: jest.Mocked<IUserRepository>;
|
|
|
let immichConfigServiceMock: jest.Mocked<ImmichConfigService>;
|
|
|
let immichJwtServiceMock: jest.Mocked<ImmichJwtService>;
|
|
|
+ let callbackMock: jest.Mock;
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
+ callbackMock = jest.fn().mockReturnValue({ access_token: 'access-token' });
|
|
|
+
|
|
|
jest.spyOn(generators, 'state').mockReturnValue('state');
|
|
|
jest.spyOn(Issuer, 'discover').mockResolvedValue({
|
|
|
id_token_signing_alg_values_supported: ['HS256'],
|
|
@@ -62,7 +97,7 @@ describe('OAuthService', () => {
|
|
|
},
|
|
|
authorizationUrl: jest.fn().mockReturnValue('http://authorization-url'),
|
|
|
callbackParams: jest.fn().mockReturnValue({ state: 'state' }),
|
|
|
- callback: jest.fn().mockReturnValue({ access_token: 'access-token' }),
|
|
|
+ callback: callbackMock,
|
|
|
userinfo: jest.fn().mockResolvedValue({ sub, email }),
|
|
|
}),
|
|
|
} as any);
|
|
@@ -89,10 +124,11 @@ describe('OAuthService', () => {
|
|
|
} as unknown as jest.Mocked<ImmichJwtService>;
|
|
|
|
|
|
immichConfigServiceMock = {
|
|
|
+ config$: { subscribe: jest.fn() },
|
|
|
getConfig: jest.fn().mockResolvedValue({ oauth: { enabled: false } }),
|
|
|
} as unknown as jest.Mocked<ImmichConfigService>;
|
|
|
|
|
|
- sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.disabled);
|
|
|
});
|
|
|
|
|
|
it('should be defined', () => {
|
|
@@ -102,17 +138,10 @@ describe('OAuthService', () => {
|
|
|
describe('generateConfig', () => {
|
|
|
it('should work when oauth is not configured', async () => {
|
|
|
await expect(sut.generateConfig({ redirectUri: 'http://callback' })).resolves.toEqual({ enabled: false });
|
|
|
- expect(immichConfigServiceMock.getConfig).toHaveBeenCalled();
|
|
|
});
|
|
|
|
|
|
it('should generate the config', async () => {
|
|
|
- immichConfigServiceMock.getConfig.mockResolvedValue({
|
|
|
- oauth: {
|
|
|
- enabled: true,
|
|
|
- buttonText: 'OAuth',
|
|
|
- },
|
|
|
- } as SystemConfig);
|
|
|
- sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.enabled);
|
|
|
await expect(sut.generateConfig({ redirectUri: 'http://redirect' })).resolves.toEqual({
|
|
|
enabled: true,
|
|
|
buttonText: 'OAuth',
|
|
@@ -127,13 +156,7 @@ describe('OAuthService', () => {
|
|
|
});
|
|
|
|
|
|
it('should not allow auto registering', async () => {
|
|
|
- immichConfigServiceMock.getConfig.mockResolvedValue({
|
|
|
- oauth: {
|
|
|
- enabled: true,
|
|
|
- autoRegister: false,
|
|
|
- },
|
|
|
- } as SystemConfig);
|
|
|
- sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.noAutoRegister);
|
|
|
userRepositoryMock.getByEmail.mockResolvedValue(null);
|
|
|
await expect(sut.login({ url: 'http://immich/auth/login?code=abc123' })).rejects.toBeInstanceOf(
|
|
|
BadRequestException,
|
|
@@ -142,13 +165,7 @@ describe('OAuthService', () => {
|
|
|
});
|
|
|
|
|
|
it('should link an existing user', async () => {
|
|
|
- immichConfigServiceMock.getConfig.mockResolvedValue({
|
|
|
- oauth: {
|
|
|
- enabled: true,
|
|
|
- autoRegister: false,
|
|
|
- },
|
|
|
- } as SystemConfig);
|
|
|
- sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.noAutoRegister);
|
|
|
userRepositoryMock.getByEmail.mockResolvedValue(user);
|
|
|
userRepositoryMock.update.mockResolvedValue(user);
|
|
|
immichJwtServiceMock.createLoginResponse.mockResolvedValue(loginResponse);
|
|
@@ -160,13 +177,8 @@ describe('OAuthService', () => {
|
|
|
});
|
|
|
|
|
|
it('should allow auto registering by default', async () => {
|
|
|
- immichConfigServiceMock.getConfig.mockResolvedValue({
|
|
|
- oauth: {
|
|
|
- enabled: true,
|
|
|
- autoRegister: true,
|
|
|
- },
|
|
|
- } as SystemConfig);
|
|
|
- sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.enabled);
|
|
|
+
|
|
|
userRepositoryMock.getByEmail.mockResolvedValue(null);
|
|
|
userRepositoryMock.getAdmin.mockResolvedValue(user);
|
|
|
userRepositoryMock.create.mockResolvedValue(user);
|
|
@@ -178,16 +190,21 @@ describe('OAuthService', () => {
|
|
|
expect(userRepositoryMock.create).toHaveBeenCalledTimes(1);
|
|
|
expect(immichJwtServiceMock.createLoginResponse).toHaveBeenCalledTimes(1);
|
|
|
});
|
|
|
+
|
|
|
+ it('should use the mobile redirect override', async () => {
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.override);
|
|
|
+
|
|
|
+ userRepositoryMock.getByOAuthId.mockResolvedValue(user);
|
|
|
+
|
|
|
+ await sut.login({ url: `app.immich:/?code=abc123` });
|
|
|
+
|
|
|
+ expect(callbackMock).toHaveBeenCalledWith('http://mobile-redirect', { state: 'state' }, { state: 'state' });
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
describe('link', () => {
|
|
|
it('should link an account', async () => {
|
|
|
- immichConfigServiceMock.getConfig.mockResolvedValue({
|
|
|
- oauth: {
|
|
|
- enabled: true,
|
|
|
- autoRegister: true,
|
|
|
- },
|
|
|
- } as SystemConfig);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.enabled);
|
|
|
|
|
|
userRepositoryMock.update.mockResolvedValue(user);
|
|
|
|
|
@@ -197,12 +214,7 @@ describe('OAuthService', () => {
|
|
|
});
|
|
|
|
|
|
it('should not link an already linked oauth.sub', async () => {
|
|
|
- immichConfigServiceMock.getConfig.mockResolvedValue({
|
|
|
- oauth: {
|
|
|
- enabled: true,
|
|
|
- autoRegister: true,
|
|
|
- },
|
|
|
- } as SystemConfig);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.enabled);
|
|
|
|
|
|
userRepositoryMock.getByOAuthId.mockResolvedValue({ id: 'other-user' } as UserEntity);
|
|
|
|
|
@@ -216,12 +228,7 @@ describe('OAuthService', () => {
|
|
|
|
|
|
describe('unlink', () => {
|
|
|
it('should unlink an account', async () => {
|
|
|
- immichConfigServiceMock.getConfig.mockResolvedValue({
|
|
|
- oauth: {
|
|
|
- enabled: true,
|
|
|
- autoRegister: true,
|
|
|
- },
|
|
|
- } as SystemConfig);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.enabled);
|
|
|
|
|
|
userRepositoryMock.update.mockResolvedValue(user);
|
|
|
|
|
@@ -237,13 +244,7 @@ describe('OAuthService', () => {
|
|
|
});
|
|
|
|
|
|
it('should get the session endpoint from the discovery document', async () => {
|
|
|
- immichConfigServiceMock.getConfig.mockResolvedValue({
|
|
|
- oauth: {
|
|
|
- enabled: true,
|
|
|
- issuerUrl: 'http://issuer,',
|
|
|
- },
|
|
|
- } as SystemConfig);
|
|
|
- sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock);
|
|
|
+ sut = new OAuthService(immichJwtServiceMock, immichConfigServiceMock, userRepositoryMock, config.enabled);
|
|
|
|
|
|
await expect(sut.getLogoutEndpoint()).resolves.toBe('http://end-session-endpoint');
|
|
|
});
|