Skip to content

Commit

Permalink
fix(idp): user listing
Browse files Browse the repository at this point in the history
  • Loading branch information
bouassaba committed Dec 14, 2024
1 parent aa55a4c commit 94ecd73
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 60 deletions.
2 changes: 0 additions & 2 deletions idp/src/infra/error/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export type ErrorData = {
message: string
userMessage: string
moreInfo: string
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
error?: any
}

Expand All @@ -76,7 +75,6 @@ export type ErrorOptions = {
code: ErrorCode
message?: string
userMessage?: string
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
error?: any
}

Expand Down
49 changes: 36 additions & 13 deletions idp/src/infra/error/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,42 @@ export const password = z
export const picture = z
.string()
.optional()
.refine((value) => {
if (!value) {
return true
}
try {
return Buffer.from(value, 'base64').length <= 3000000
} catch {
return false
}
}, { message: 'Picture must be a valid Base64 string and <= 3MB' })
.refine(
(value) => {
if (!value) {
return true
}
try {
return Buffer.from(value, 'base64').length <= 3000000
} catch {
return false
}
},
{ message: 'Picture must be a valid Base64 string and <= 3MB' },
)

export const email = z
.string()
.email()
.trim()
.max(255)

export const fullName = z
.string()
.nonempty()
.trim()
.max(255)

export const email = z.string().email().trim().max(255)
export const token = z
.string()
.nonempty()

export const fullName = z.string().nonempty().trim().max(255)
export const page = z
.string()
.regex(/^\d+$/, 'Must be a numeric value')
.transform(Number)

export const token = z.string().nonempty()
export const size = z
.string()
.regex(/^\d+$/, 'Must be a numeric value')
.transform(Number)
1 change: 0 additions & 1 deletion idp/src/infra/mail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const transporter = nodemailer.createTransport({
export function sendTemplateMail(
template: string,
address: string,
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
variables: Record<string, any>,
) {
const params = yaml.load(
Expand Down
10 changes: 1 addition & 9 deletions idp/src/token/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
// the Business Source License, use of this software will be governed
// by the GNU Affero General Public License v3.0 only, included in the file
// AGPL-3.0-only in the root of this repository.
import { decode, sign } from 'hono/jwt'
import { sign } from 'hono/jwt'
import { getConfig } from '@/config/config.ts'
import {
newEmailNotConfirmedError,
newInvalidGrantType,
newInvalidUsernameOrPasswordError,
newMissingFormParamError,
newRefreshTokenExpiredError,
newUserIsNotAdminError,
newUserSuspendedError,
newUserTemporarilyLockedError,
} from '@/infra/error/creators.ts'
Expand Down Expand Up @@ -92,13 +91,6 @@ export async function exchange(options: TokenExchangeOptions): Promise<Token> {
}
}

export function checkAdmin(jwt: string) {
const { payload } = decode(jwt)
if (!payload.is_admin) {
throw newUserIsNotAdminError()
}
}

function validateParameters(options: TokenExchangeOptions) {
if (!options.grant_type) {
throw newMissingFormParamError('grant_type')
Expand Down
14 changes: 4 additions & 10 deletions idp/src/user/repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,26 +95,26 @@ class UserRepoImpl {
}

async list(page: number, size: number): Promise<User[]> {
const { rows } = await client.queryArray(
const { rows } = await client.queryObject(
`SELECT *
FROM "user"
ORDER BY create_time
OFFSET $1
LIMIT $2`,
[(page - 1) * size, size],
)
return this.mapList(rows)
return rows.map(this.mapRow)
}

async findMany(ids: string[]): Promise<User[]> {
const { rows } = await client.queryArray(
const { rows } = await client.queryObject(
`SELECT *
FROM "user"
WHERE id = ANY ($1)
ORDER BY create_time`,
[ids],
)
return this.mapList(rows)
return rows.map(this.mapRow)
}

async getCount(): Promise<number> {
Expand Down Expand Up @@ -255,7 +255,6 @@ class UserRepoImpl {
return result[0].count > 1
}

/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
private mapRow(row: any): User {
return {
id: row.id,
Expand All @@ -279,11 +278,6 @@ class UserRepoImpl {
updateTime: row.update_time,
}
}

/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
private mapList(list: any): User[] {
return list.map(this.mapRow)
}
}

const userRepo: UserRepoImpl = new UserRepoImpl()
Expand Down
28 changes: 17 additions & 11 deletions idp/src/user/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ import {
newInvalidJwtError,
newMissingQueryParamError,
newPictureNotFoundError,
newUserIsNotAdminError,
} from '@/infra/error/creators.ts'
import {
email,
fullName,
handleValidationError,
page,
password,
size,
token,
} from '@/infra/error/validation.ts'
import { checkAdmin } from '@/token/service.ts'
import {
deletePicture,
deleteUser,
Expand Down Expand Up @@ -194,17 +196,15 @@ router.get(
'query',
z.object({
query: z.string().optional(),
page: z.string().regex(/^\d+$/, 'Must be a numeric value.').transform(
Number,
),
size: z.string().regex(/^\d+$/, 'Must be a numeric value.').transform(
Number,
),
page,
size,
}),
handleValidationError,
),
async (c) => {
checkAdmin(c.req.header('Authorization')!)
if (!c.get('user').isAdmin) {
throw newUserIsNotAdminError()
}
const { query, size, page } = c.req.valid('query') as UserListOptions
return c.json(await list({ query, size, page }))
},
Expand All @@ -218,7 +218,9 @@ router.post(
handleValidationError,
),
async (c) => {
checkAdmin(c.req.header('Authorization')!)
if (!c.get('user').isAdmin) {
throw newUserIsNotAdminError()
}
const { id } = c.req.param()
const body = c.req.valid('json') as UserSuspendOptions
await suspendUser(id, body)
Expand All @@ -234,7 +236,9 @@ router.post(
handleValidationError,
),
async (c) => {
checkAdmin(c.req.header('Authorization')!)
if (!c.get('user').isAdmin) {
throw newUserIsNotAdminError()
}
const { id } = c.req.param()
const body = c.req.valid('json') as UserMakeAdminOptions
await makeAdminUser(id, body)
Expand All @@ -243,7 +247,9 @@ router.post(
)

router.get('/:id', async (c) => {
checkAdmin(c.req.header('Authorization')!)
if (!c.get('user').isAdmin) {
throw newUserIsNotAdminError()
}
const { id } = c.req.param()
return c.json(await getUserByAdmin(id))
})
Expand Down
22 changes: 8 additions & 14 deletions idp/src/user/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ export async function list({
size,
page,
}: UserListOptions): Promise<UserAdminList> {
if (query && query.length >= 3) {
const users = await meilisearch
if (query) {
const hits = await meilisearch
.index(USER_SEARCH_INDEX)
.search(query, { page: page, hitsPerPage: size })
.then((value) => {
Expand All @@ -161,24 +161,18 @@ export async function list({
totalElements: value.totalHits,
}
})
const users = await userRepo.findMany(hits.data.map((value) => value.id))
return {
data: (
await userRepo.findMany(
users.data.map((value) => {
return value.id
}),
)
).map((value) => adminMapEntity(value)),
totalElements: users.totalElements,
totalPages: Math.floor((users.totalElements + size - 1) / size),
data: users.map(adminMapEntity),
totalElements: hits.totalElements,
totalPages: Math.floor((hits.totalElements + size - 1) / size),
size: size,
page: page,
}
} else {
const users = await userRepo.list(page, size)
return {
data: (await userRepo.list(page, size)).map((value) =>
adminMapEntity(value)
),
data: users.map(adminMapEntity),
totalElements: await userRepo.getCount(),
totalPages: Math.floor(((await userRepo.getCount()) + size - 1) / size),
size: size,
Expand Down

0 comments on commit 94ecd73

Please sign in to comment.