diff --git a/src/controllers/keycloak/user-controller.ts b/src/controllers/keycloak/user-controller.ts new file mode 100644 index 0000000..086efe6 --- /dev/null +++ b/src/controllers/keycloak/user-controller.ts @@ -0,0 +1,51 @@ +import { Body, Controller, Delete, Get, Path, Post, Route, Security, Tags } from "tsoa"; +import { addUserRoles, createUser, getRoles, removeUserRoles } from "../../services/keycloak"; + +@Route("api/keycloak") +@Tags("Keycloak") +@Security("keycloak") +export class KeycloakController extends Controller { + @Post("user") + async createUser( + @Body() body: { username: string; password: string; firstName?: string; lastName?: string }, + ) { + return await createUser(body.username, body.password, { + firstName: body.firstName, + lastName: body.lastName, + }); + } + + @Get("role") + async getRole() { + const role = await getRoles(); + if (Array.isArray(role)) return role; + throw new Error("Failed. Cannot get role."); + } + + @Post("{userId}/role") + async addRole(@Path() userId: string, @Body() body: { role: string[] }) { + const list = await getRoles(); + + if (!Array.isArray(list)) throw new Error("Failed. Cannot get role(s) data from the server."); + + const result = await addUserRoles( + userId, + list.filter((v) => body.role.includes(v.id)), + ); + + if (!result) throw new Error("Failed. Cannot set user's role."); + } + + @Delete("{userId}/role/{roleId}") + async deleteRole(@Path() userId: string, @Path() roleId: string) { + const list = await getRoles(); + + if (!Array.isArray(list)) throw new Error("Failed. Cannot get role(s) data from the server."); + + const result = await removeUserRoles( + userId, + list.filter((v) => roleId === v.id), + ); + if (!result) throw new Error("Failed. Cannot remove user's role."); + } +} diff --git a/src/services/keycloak.ts b/src/services/keycloak.ts index 7a5ce4a..c12a3b4 100644 --- a/src/services/keycloak.ts +++ b/src/services/keycloak.ts @@ -121,7 +121,7 @@ export async function getRoles(name?: string) { const data = await res.json(); if (Array.isArray(data)) { - return data.map((v: Record) => ({ id: v.id, name: v.name })); + return data.map((v: Record) => ({ id: v.id, name: v.name })); } return { @@ -137,7 +137,7 @@ export async function getRoles(name?: string) { * * @returns true if success, false otherwise. */ -export async function addUserRoles(userId: string, roleId: string[]) { +export async function addUserRoles(userId: string, roles: { id: string; name: string }[]) { const res = await fetch( `${KC_URL}/admin/realms/${KC_REALM}/users/${userId}/role-mappings/realm`, { @@ -147,7 +147,7 @@ export async function addUserRoles(userId: string, roleId: string[]) { "content-type": `application/json`, }, method: "POST", - body: JSON.stringify(roleId.map((v) => ({ id: v }))), + body: JSON.stringify(roles), }, ).catch((e) => console.log(e)); @@ -165,7 +165,7 @@ export async function addUserRoles(userId: string, roleId: string[]) { * * @returns true if success, false otherwise. */ -export async function removeUserRoles(userId: string, roleId: string[]) { +export async function removeUserRoles(userId: string, roles: { id: string; name: string }[]) { const res = await fetch( `${KC_URL}/admin/realms/${KC_REALM}/users/${userId}/role-mappings/realm`, { @@ -175,7 +175,7 @@ export async function removeUserRoles(userId: string, roleId: string[]) { "content-type": `application/json`, }, method: "DELETE", - body: JSON.stringify(roleId.map((v) => ({ id: v }))), + body: JSON.stringify(roles), }, ).catch((e) => console.log(e));