From addd4caa63a04739ac2cedcbc2e19ce8422a9dca Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:24:24 +0700 Subject: [PATCH] feat: add update user data endpoint --- src/controllers/keycloak-controller.ts | 20 ++++++++++++--- src/services/keycloak.ts | 34 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/controllers/keycloak-controller.ts b/src/controllers/keycloak-controller.ts index 209b943..f2aa82d 100644 --- a/src/controllers/keycloak-controller.ts +++ b/src/controllers/keycloak-controller.ts @@ -1,8 +1,14 @@ -import { Body, Controller, Delete, Get, Path, Post, Route, Security, Tags } from "tsoa"; -import { addUserRoles, createUser, getRoles, removeUserRoles } from "../services/keycloak"; +import { Body, Controller, Delete, Get, Path, Post, Put, Route, Security, Tags } from "tsoa"; +import { + addUserRoles, + createUser, + editUser, + getRoles, + removeUserRoles, +} from "../services/keycloak"; @Route("api/keycloak") -@Tags("Keycloak") +@Tags("Single-Sign On") @Security("keycloak") export class KeycloakController extends Controller { @Post("user") @@ -15,6 +21,14 @@ export class KeycloakController extends Controller { }); } + @Put("user/{userId}") + async editUser( + @Path() userId: string, + @Body() body: { username?: string; password?: string; firstName?: string; lastName?: string }, + ) { + return await editUser(userId, body); + } + @Get("role") async getRole() { const role = await getRoles(); diff --git a/src/services/keycloak.ts b/src/services/keycloak.ts index c12a3b4..15089e1 100644 --- a/src/services/keycloak.ts +++ b/src/services/keycloak.ts @@ -91,6 +91,40 @@ export async function createUser(username: string, password: string, opts?: Reco return id || true; } +/** + * Update keycloak user by given username and password with roles + * + * Client must have permission to manage realm's user + * + * @returns user uuid or true if success, false otherwise. + */ +export async function editUser(userId: string, opts: Record) { + const { password, ...rest } = opts; + + const res = await fetch(`${KC_URL}/admin/realms/${KC_REALM}/users/${userId}`, { + // prettier-ignore + headers: { + "authorization": `Bearer ${await getToken()}`, + "content-type": `application/json`, + }, + method: "PUT", + body: JSON.stringify({ + enabled: true, + credentials: (password && [{ type: "password", value: opts?.password }]) || undefined, + ...rest, + }), + }).catch((e) => console.log("Keycloak Error: ", e)); + + if (!res) return false; + if (!res.ok) { + return Boolean(console.error("Keycloak Error Response: ", await res.json())); + } + + const path = res.headers.get("Location"); + const id = path?.split("/").at(-1); + return id || true; +} + /** * Get roles list or specific role data *