mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-24 01:18:01 +02:00
feat: sync fields when logging in via SSO (#916)
This commit is contained in:
parent
4f31df4061
commit
8cbf378286
@ -23,6 +23,7 @@ import Controller from './routes/controller';
|
|||||||
import { IAuthRequest } from './routes/unleash-types';
|
import { IAuthRequest } from './routes/unleash-types';
|
||||||
import * as permissions from './types/permissions';
|
import * as permissions from './types/permissions';
|
||||||
import * as eventType from './types/events';
|
import * as eventType from './types/events';
|
||||||
|
import { RoleName } from './types/model';
|
||||||
|
|
||||||
async function createApp(
|
async function createApp(
|
||||||
config: IUnleashConfig,
|
config: IUnleashConfig,
|
||||||
@ -155,6 +156,7 @@ export {
|
|||||||
AuthenticationRequired,
|
AuthenticationRequired,
|
||||||
User,
|
User,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
|
RoleName,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -286,7 +286,7 @@ export class AccessService {
|
|||||||
return this.store.getRootRoles();
|
return this.store.getRootRoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async resolveRootRole(rootRole: number | RoleName): Promise<IRole> {
|
public async resolveRootRole(rootRole: number | RoleName): Promise<IRole> {
|
||||||
const rootRoles = await this.getRootRoles();
|
const rootRoles = await this.getRootRoles();
|
||||||
let role: IRole;
|
let role: IRole;
|
||||||
if (typeof rootRole === 'number') {
|
if (typeof rootRole === 'number') {
|
||||||
|
@ -39,6 +39,13 @@ export interface IUpdateUser {
|
|||||||
rootRole?: number | RoleName;
|
rootRole?: number | RoleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ILoginUserRequest {
|
||||||
|
email: string;
|
||||||
|
name?: string;
|
||||||
|
rootRole?: number | RoleName;
|
||||||
|
autoCreate?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface IUserWithRole extends IUser {
|
interface IUserWithRole extends IUser {
|
||||||
rootRole: number;
|
rootRole: number;
|
||||||
}
|
}
|
||||||
@ -260,18 +267,30 @@ class UserService {
|
|||||||
email: string,
|
email: string,
|
||||||
autoCreateUser: boolean = false,
|
autoCreateUser: boolean = false,
|
||||||
): Promise<IUser> {
|
): Promise<IUser> {
|
||||||
|
return this.loginUserSSO({ email, autoCreate: autoCreateUser });
|
||||||
|
}
|
||||||
|
|
||||||
|
async loginUserSSO({
|
||||||
|
email,
|
||||||
|
name,
|
||||||
|
rootRole,
|
||||||
|
autoCreate = false,
|
||||||
|
}: ILoginUserRequest): Promise<IUser> {
|
||||||
let user: IUser;
|
let user: IUser;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
user = await this.store.getByQuery({ email });
|
user = await this.store.getByQuery({ email });
|
||||||
|
// Update user if autCreate is enabled.
|
||||||
|
if (user.name !== name) {
|
||||||
|
user = await this.store.update(user.id, { name, email });
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (autoCreateUser) {
|
// User does not exists. Create if "autoCreate" is enabled
|
||||||
const defaultRole = await this.accessService.getRootRole(
|
if (autoCreate) {
|
||||||
RoleName.EDITOR,
|
|
||||||
);
|
|
||||||
user = await this.createUser({
|
user = await this.createUser({
|
||||||
email,
|
email,
|
||||||
rootRole: defaultRole.id,
|
name,
|
||||||
|
rootRole: rootRole || RoleName.EDITOR,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -16,6 +16,7 @@ let stores;
|
|||||||
let userService: UserService;
|
let userService: UserService;
|
||||||
let userStore: UserStore;
|
let userStore: UserStore;
|
||||||
let adminRole: IRole;
|
let adminRole: IRole;
|
||||||
|
let viewerRole: IRole;
|
||||||
let sessionService: SessionService;
|
let sessionService: SessionService;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
@ -36,6 +37,7 @@ beforeAll(async () => {
|
|||||||
userStore = stores.userStore;
|
userStore = stores.userStore;
|
||||||
const rootRoles = await accessService.getRootRoles();
|
const rootRoles = await accessService.getRootRoles();
|
||||||
adminRole = rootRoles.find((r) => r.name === RoleName.ADMIN);
|
adminRole = rootRoles.find((r) => r.name === RoleName.ADMIN);
|
||||||
|
viewerRole = rootRoles.find((r) => r.name === RoleName.VIEWER);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@ -141,3 +143,93 @@ test("deleting a user should delete the user's sessions", async () => {
|
|||||||
sessionService.getSessionsForUser(user.id),
|
sessionService.getSessionsForUser(user.id),
|
||||||
).rejects.toThrow(NotFoundError);
|
).rejects.toThrow(NotFoundError);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should login and create user via SSO', async () => {
|
||||||
|
const email = 'some@test.com';
|
||||||
|
const user = await userService.loginUserSSO({
|
||||||
|
email,
|
||||||
|
rootRole: RoleName.VIEWER,
|
||||||
|
name: 'some',
|
||||||
|
autoCreate: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const userWithRole = await userService.getUser(user.id);
|
||||||
|
expect(user.email).toBe(email);
|
||||||
|
expect(user.name).toBe('some');
|
||||||
|
expect(userWithRole.name).toBe('some');
|
||||||
|
expect(userWithRole.rootRole).toBe(viewerRole.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should throw if rootRole is wrong via SSO', async () => {
|
||||||
|
expect.assertions(1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await userService.loginUserSSO({
|
||||||
|
email: 'some@test.com',
|
||||||
|
rootRole: RoleName.MEMBER,
|
||||||
|
name: 'some',
|
||||||
|
autoCreate: true,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toBe('Could not find rootRole=Member');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should update user name when signing in via SSO', async () => {
|
||||||
|
const email = 'some@test.com';
|
||||||
|
const originalUser = await userService.createUser({
|
||||||
|
email,
|
||||||
|
rootRole: RoleName.VIEWER,
|
||||||
|
name: 'some',
|
||||||
|
});
|
||||||
|
|
||||||
|
await userService.loginUserSSO({
|
||||||
|
email,
|
||||||
|
rootRole: RoleName.ADMIN,
|
||||||
|
name: 'New name!',
|
||||||
|
autoCreate: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const actualUser = await userService.getUser(originalUser.id);
|
||||||
|
|
||||||
|
expect(actualUser.email).toBe(email);
|
||||||
|
expect(actualUser.name).toBe('New name!');
|
||||||
|
expect(actualUser.rootRole).toBe(viewerRole.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should update name if it is different via SSO', async () => {
|
||||||
|
const email = 'some@test.com';
|
||||||
|
const originalUser = await userService.createUser({
|
||||||
|
email,
|
||||||
|
rootRole: RoleName.VIEWER,
|
||||||
|
name: 'some',
|
||||||
|
});
|
||||||
|
|
||||||
|
await userService.loginUserSSO({
|
||||||
|
email,
|
||||||
|
rootRole: RoleName.ADMIN,
|
||||||
|
name: 'New name!',
|
||||||
|
autoCreate: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const actualUser = await userService.getUser(originalUser.id);
|
||||||
|
|
||||||
|
expect(actualUser.email).toBe(email);
|
||||||
|
expect(actualUser.name).toBe('New name!');
|
||||||
|
expect(actualUser.rootRole).toBe(viewerRole.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should throw if autoCreate is false via SSO', async () => {
|
||||||
|
expect.assertions(1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await userService.loginUserSSO({
|
||||||
|
email: 'some@test.com',
|
||||||
|
rootRole: RoleName.MEMBER,
|
||||||
|
name: 'some',
|
||||||
|
autoCreate: false,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toBe('No user found');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user