0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-31 22:51:25 -05:00

feat(core): register with admin role (#1140)

* feat(core): register with admin role

register user with admin role

* fix(core): cr fix

cr fix
This commit is contained in:
simeng-li 2022-06-20 11:32:50 +08:00 committed by GitHub
parent ac99c26181
commit 4f32ad3a51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 2 deletions

View file

@ -1,4 +1,5 @@
import { User } from '@logto/schemas';
import { adminConsoleApplicationId } from '@logto/schemas/lib/seeds';
import { Provider } from 'oidc-provider';
import { mockUser } from '@/__mocks__';
@ -29,6 +30,8 @@ jest.mock('@/lib/user', () => ({
const insertUser = jest.fn(async (..._args: unknown[]) => ({ id: 'id' }));
const findUserById = jest.fn(async (): Promise<User> => mockUser);
const updateUserById = jest.fn(async (..._args: unknown[]) => ({ id: 'id' }));
const hasActiveUsers = jest.fn(async () => true);
jest.mock('@/queries/user', () => ({
findUserById: async () => findUserById(),
findUserByIdentity: async () => ({ id: 'id', identities: {} }),
@ -41,6 +44,7 @@ jest.mock('@/queries/user', () => ({
connectorId === 'connectorId' && userId === 'id',
hasUserWithPhone: async (phone: string) => phone === '13000000000',
hasUserWithEmail: async (email: string) => email === 'a@a.com',
hasActiveUsers: async () => hasActiveUsers(),
}));
const grantSave = jest.fn(async () => 'finalGrantId');
@ -149,6 +153,8 @@ describe('sessionRoutes', () => {
describe('POST /session/register/username-password', () => {
it('assign result and redirect', async () => {
interactionDetails.mockResolvedValueOnce({ params: {} });
const response = await sessionRequest
.post('/session/register/username-password')
.send({ username: 'username', password: 'password' });
@ -158,6 +164,7 @@ describe('sessionRoutes', () => {
username: 'username',
passwordEncrypted: 'password_user1',
passwordEncryptionMethod: 'Argon2i',
roleNames: [],
})
);
expect(response.body).toHaveProperty('redirectTo');
@ -169,6 +176,40 @@ describe('sessionRoutes', () => {
);
});
it('register user with admin role for admin console if no active user found', async () => {
interactionDetails.mockResolvedValueOnce({
params: { client_id: adminConsoleApplicationId },
});
hasActiveUsers.mockResolvedValueOnce(false);
await sessionRequest
.post('/session/register/username-password')
.send({ username: 'username', password: 'password' });
expect(insertUser).toHaveBeenCalledWith(
expect.objectContaining({
roleNames: ['admin'],
})
);
});
it('should not register user with admin role for admin console if any active user found', async () => {
interactionDetails.mockResolvedValueOnce({
params: { client_id: adminConsoleApplicationId },
});
await sessionRequest
.post('/session/register/username-password')
.send({ username: 'username', password: 'password' });
expect(insertUser).toHaveBeenCalledWith(
expect.objectContaining({
roleNames: [],
})
);
});
it('throw error if username not valid', async () => {
const usernameStartedWithNumber = '1username';
const response = await sessionRequest

View file

@ -1,6 +1,8 @@
import path from 'path';
import { LogtoErrorCode } from '@logto/phrases';
import { UserRole } from '@logto/schemas';
import { adminConsoleApplicationId } from '@logto/schemas/lib/seeds';
import { passwordRegEx, usernameRegEx } from '@logto/shared';
import { conditional } from '@silverhand/essentials';
import { Provider } from 'oidc-provider';
@ -15,7 +17,7 @@ import {
updateLastSignInAt,
} from '@/lib/user';
import koaGuard from '@/middleware/koa-guard';
import { hasUser, insertUser } from '@/queries/user';
import { hasUser, insertUser, hasActiveUsers } from '@/queries/user';
import assertThat from '@/utils/assert-that';
import { AnonymousRouter } from '../types';
@ -120,8 +122,17 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
})
);
const {
params: { client_id },
} = await provider.interactionDetails(ctx.req, ctx.res);
const createAdminUser =
String(client_id) === adminConsoleApplicationId && !(await hasActiveUsers());
const roleNames = createAdminUser ? [UserRole.Admin] : [];
const id = await generateUserId();
ctx.log(type, { userId: id });
ctx.log(type, { userId: id, roleNames });
const { passwordEncrypted, passwordEncryptionMethod } = await encryptUserPassword(password);
@ -130,6 +141,7 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
username,
passwordEncrypted,
passwordEncryptionMethod,
roleNames,
});
await updateLastSignInAt(id);
await assignInteractionResults(ctx, provider, { login: { accountId: id } });