Skip to content

Commit

Permalink
fix(nodejs): no credential information is returned
Browse files Browse the repository at this point in the history
  • Loading branch information
takoring committed Feb 10, 2025
1 parent ceebb3f commit aa6d077
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 40 deletions.
2 changes: 1 addition & 1 deletion example/nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"dependencies": {
"@aws-sdk/client-s3": "^3.451.0",
"@types/sanitize-html": "^2.13.0",
"@viron/lib": "2.4.0-alpha.7",
"@viron/lib": "2.4.0-alpha.8",
"accepts": "^1.3.7",
"compression": "^1.7.4",
"cookie-parser": "^1.4.5",
Expand Down
19 changes: 11 additions & 8 deletions example/nodejs/src/security_handlers/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const authFailure = (err: VironError): AuthenticationFailure => {
};

const authSuccess = (
user: domainsAdminUser.AdminUserView
user: domainsAdminUser.AdminUserWithCredential
): AuthenticationSuccess => {
return { type: AUTHENTICATION_RESULT_TYPE.SUCCESS, user };
};
Expand Down Expand Up @@ -73,19 +73,22 @@ export const jwt = async (
return authFailure(forbidden());
}

const user = await domainsAdminUser.findOneById(userId);
// credentialsありでユーザー情報取得
const user = await domainsAdminUser.findOneById(userId, true);
if (user) {
switch (user.authType) {
const adminUserWithCredential =
user as domainsAdminUser.AdminUserWithCredential;
switch (adminUserWithCredential.authType) {
case AUTH_TYPE.GOOGLE: {
// Google認証の場合はアクセストークンの検証
if (
await domainsAuth.verifyGoogleOAuth2AccessToken(
userId,
user,
adminUserWithCredential,
ctx.config.auth.googleOAuth2
)
) {
return authSuccess(user);
return authSuccess(adminUserWithCredential);
}
break;
}
Expand All @@ -97,15 +100,15 @@ export const jwt = async (
client,
ctx.config.auth.oidc,
userId,
user
adminUserWithCredential
)
) {
return authSuccess(user);
return authSuccess(adminUserWithCredential);
}
break;
}
default:
return authSuccess(user);
return authSuccess(adminUserWithCredential);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/nodejs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@viron/lib",
"version": "2.4.0-alpha.7",
"version": "2.4.0-alpha.8",
"scripts": {
"build": "npm run clean && tsc --project tsconfig.json && cp -fr src/openapi dist/",
"clean": "rm -rf dist && rm -f tsconfig.tsbuildinfo",
Expand Down
11 changes: 8 additions & 3 deletions packages/nodejs/src/domains/adminaccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { ListWithPager, genPasswordHash } from '../helpers';
import { repositoryContainer } from '../repositories';
import { adminUserNotFound, forbidden } from '../errors';
import { listRoles } from './adminrole';
import { AdminUserView, findOneById, formatAdminUser } from './adminuser';
import {
AdminUserWithCredential,
AdminUserView,
findOneById,
formatAdminUser,
} from './adminuser';

export interface AdminAccountUpdatePayload {
password: string;
Expand All @@ -12,7 +17,7 @@ export interface AdminAccountUpdatePayload {
// 一覧取得(idを指定するので結果は必ず1件)
export const listById = async (
id: string
): Promise<ListWithPager<AdminUserView>> => {
): Promise<ListWithPager<AdminUserWithCredential | AdminUserView>> => {
const repository = repositoryContainer.getAdminUserRepository();
const result = await repository.findWithPager({ id });
const adminRoles = await Promise.all(
Expand All @@ -21,7 +26,7 @@ export const listById = async (
return {
...result,
list: result.list.map((adminUser) =>
formatAdminUser(adminUser, adminRoles.shift())
formatAdminUser(false, adminUser, adminRoles.shift())
),
};
};
Expand Down
103 changes: 84 additions & 19 deletions packages/nodejs/src/domains/adminuser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ export type AdminUserUpdateAttributes =
| AdminUserGoogleUpdateAttributes
| AdminUserOidcUpdateAttributes;

export interface AdminUserView extends AdminUser {
export interface AdminUserWithCredential extends AdminUser {
roleIds: string[];
}
export interface AdminUserView extends AdminUserBase {
roleIds: string[];
}

Expand Down Expand Up @@ -171,8 +174,22 @@ export type AdminUserUpdatePayload =
| AdminUserGoogleUpdatePayload
| AdminUserOidcUpdatePayload;

const format = (adminUser: AdminUser, roleIds?: string[]): AdminUserView => {
return Object.assign({}, adminUser, { roleIds: roleIds ?? [] });
const format = (
withCredential: boolean,
adminUser: AdminUser,
roleIds?: string[]
): AdminUserWithCredential | AdminUserView => {
if (withCredential === true) {
return Object.assign({}, adminUser, { roleIds: roleIds ?? [] });
}
return {
id: adminUser.id,
email: adminUser.email,
authType: adminUser.authType,
roleIds: roleIds ?? [],
createdAt: adminUser.createdAt,
updatedAt: adminUser.updatedAt,
};
};
export const formatAdminUser = format;

Expand All @@ -181,8 +198,9 @@ export const list = async (
conditions: FindConditions<AdminUser> & { roleId?: string } = {},
size?: number,
page?: number,
sort = [`createdAt${TABLE_SORT_DELIMITER}${TABLE_SORT_ORDER.DESC}`]
): Promise<ListWithPager<AdminUserView>> => {
sort = [`createdAt${TABLE_SORT_DELIMITER}${TABLE_SORT_ORDER.DESC}`],
withCredential = false
): Promise<ListWithPager<AdminUserWithCredential | AdminUserView>> => {
const repository = repositoryContainer.getAdminUserRepository();
if (conditions.roleId) {
const userIds = await listUsers(conditions.roleId);
Expand All @@ -195,15 +213,43 @@ export const list = async (
);
return {
...result,
list: result.list.map((adminUser) => format(adminUser, adminRoles.shift())),
list: result.list.map((adminUser) =>
format(withCredential, adminUser, adminRoles.shift())
),
};
};

// オーバーロード
export async function createOne(
payload: AdminUserCreatePayload,
authType: AuthType,
withCredential: true
): Promise<AdminUserWithCredential>;

// オーバーロード
export async function createOne(
payload: AdminUserCreatePayload,
authType: AuthType,
withCredential: false
): Promise<AdminUserView>;

// オーバーロード
export async function createOne(
payload: AdminUserCreatePayload,
authType: AuthType
): Promise<AdminUserView>;

// オーバーロード
export async function createOne(
payload: AdminUserCreatePayload
): Promise<AdminUserView>;

// 1件作成
export const createOne = async (
export async function createOne(
payload: AdminUserCreatePayload,
authType: AuthType = AUTH_TYPE.EMAIL
): Promise<AdminUserView> => {
authType: AuthType = AUTH_TYPE.EMAIL,
withCredential = false
): Promise<AdminUserWithCredential | AdminUserView> {
const repository = repositoryContainer.getAdminUserRepository();
const { roleIds, ...adminUser } = payload;

Expand Down Expand Up @@ -242,8 +288,8 @@ export const createOne = async (
if (roleIds?.length) {
await updateRolesForUser(user.id, roleIds);
}
return format(user, roleIds);
};
return format(withCredential, user, roleIds);
}

// IDで1件更新
export const updateOneById = async (
Expand Down Expand Up @@ -319,29 +365,48 @@ export const removeOneById = async (id: string): Promise<void> => {

// IDで1件取得
export const findOneById = async (
id: string
): Promise<AdminUserView | null> => {
id: string,
withCredencial = false
): Promise<AdminUserWithCredential | AdminUserView | null> => {
const repository = repositoryContainer.getAdminUserRepository();
const user = await repository.findOneById(id);
if (!user) {
return null;
}
const roleIds = await listRoles(user.id);
return format(user, roleIds);
return format(withCredencial, user, roleIds);
};

// emailで1件取得
export const findOneByEmail = async (
// オーバーロード
export async function findOneByEmail(
email: string,
withCredential: true
): Promise<AdminUserWithCredential | null>;

// オーバーロード
export async function findOneByEmail(
email: string,
withCredential: false
): Promise<AdminUserView | null>;

// オーバーロード
export async function findOneByEmail(
email: string
): Promise<AdminUserView | null> => {
): Promise<AdminUserView | null>;

// emailで1件取得
export async function findOneByEmail(
email: string,
withCredential = false
): Promise<AdminUserWithCredential | AdminUserView | null> {
const repository = repositoryContainer.getAdminUserRepository();
const user = await repository.findOne({ email });
if (!user) {
return null;
}
const roleIds = await listRoles(user.id);
return format(user, roleIds);
};
return format(withCredential, user, roleIds);
}

// 件数取得
export const count = async (): Promise<number> => {
Expand Down
15 changes: 8 additions & 7 deletions packages/nodejs/src/domains/auth/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { addRoleForUser } from '../adminrole';
import {
createOne,
count,
AdminUserView,
AdminUserWithCredential,
AdminUserCreatePayload,
} from '../adminuser';

Expand All @@ -14,20 +14,21 @@ const debug = getDebug('domains:auth:common');
export const createFirstAdminUser = async (
obj: AdminUserCreatePayload,
authType: AuthType
): Promise<AdminUserView | null> => {
): Promise<AdminUserWithCredential | null> => {
const adminUserNum = await count();
if (adminUserNum) {
// すでに管理ユーザーがいる場合は作成しない
debug('Skip create first admin user.');
return null;
}
const user = await createOne(obj, authType);
await addRoleForUser(user.id, ADMIN_ROLE.SUPER);
// 作成後にcredentialsありで返却
const userWithCredential = await createOne(obj, authType, true);
await addRoleForUser(userWithCredential.id, ADMIN_ROLE.SUPER);
debug(
'Created first admin user. id: %s, email: %s, roleId: %s',
user.id,
user.email,
userWithCredential.id,
userWithCredential.email,
ADMIN_ROLE.SUPER
);
return user;
return userWithCredential;
};
3 changes: 2 additions & 1 deletion packages/nodejs/src/domains/auth/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export const signinEmail = async (
email: string,
password: string
): Promise<string> => {
let adminUser = await findOneByEmail(email);
// credentialありで取得
let adminUser = await findOneByEmail(email, true);
if (!adminUser) {
const firstAdminUser = await createFirstAdminUser(
{ email, password },
Expand Down

0 comments on commit aa6d077

Please sign in to comment.