@adatechnology/keycloak-admin 1.0.0-rc.2 → 1.0.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -35,6 +35,15 @@ const { id } = await keycloak.createUser({
35
35
  Operações de usuário: `createUser`, `findUserByEmail`, `listUsers`, `updateUser`, `setEnabled`,
36
36
  `updateAttributes`, `deleteUser`, `setPassword`, `setTemporaryPassword`.
37
37
 
38
+ Foto de perfil: `setProfilePicture({ userId, pictureUrl })`. O atributo é `picture`, o nome que o
39
+ OIDC reserva — com um mapeador no realm ele chega ao token, e a tela desenha o avatar sem uma
40
+ consulta por pessoa.
41
+
42
+ ⚠️ O Keycloak **não hospeda imagem**: o valor é uma URL e o arquivo é do produto. Base64 no atributo
43
+ cresce o token até ele parar de caber no cabeçalho, e o sintoma aparece longe — login que funciona
44
+ no navegador e falha no `curl`. A operação lê os atributos antes de gravar, porque o Admin API
45
+ substitui o conjunto: mandar só a foto apagaria `company_id` e o resto.
46
+
38
47
  Operações de grupo: `createGroup`, `updateGroup`, `deleteGroup`, `listGroups`, `addUserToGroup`,
39
48
  `removeUserFromGroup`. Só o **primeiro nível** — grupo aninhado muda o significado de "pertencer",
40
49
  porque quem está no filho herda o pai, e um produto que não modela hierarquia não deve criá-la por
package/dist/index.d.ts CHANGED
@@ -113,6 +113,20 @@ type SetEnabledParams = {
113
113
  readonly enabled: boolean;
114
114
  readonly userId: string;
115
115
  };
116
+ /**
117
+ * O atributo padrão da foto. `picture` é o nome que o OIDC já reserva para isso, e usá-lo é o que
118
+ * permite a foto chegar ao token por um mapeador do realm em vez de uma consulta extra por tela.
119
+ *
120
+ * ⚠️ O Keycloak **não hospeda imagem**: o valor é uma URL, e quem guarda o arquivo é o produto. Um
121
+ * atributo com base64 dentro cresce o token até ele parar de caber no cabeçalho, e aí o sintoma é
122
+ * login que funciona no navegador e falha no `curl`.
123
+ */
124
+ declare const PROFILE_PICTURE_ATTRIBUTE = "picture";
125
+ type SetProfilePictureParams = {
126
+ /** URL da imagem, ou `undefined` para tirar a foto sem mexer nos outros atributos. */
127
+ readonly pictureUrl: string | undefined;
128
+ readonly userId: string;
129
+ };
116
130
  type UpdateAttributesParams = {
117
131
  readonly attributes: KeycloakUserAttributes;
118
132
  readonly userId: string;
@@ -179,6 +193,7 @@ type KeycloakAdminClient = {
179
193
  findUserByEmail(params: FindUserByEmailParams): Promise<KeycloakUser | undefined>;
180
194
  listUsers(params?: ListUsersParams): Promise<ListUsersResult>;
181
195
  setEnabled(params: SetEnabledParams): Promise<void>;
196
+ setProfilePicture(params: SetProfilePictureParams): Promise<void>;
182
197
  setPassword(params: SetPasswordParams): Promise<void>;
183
198
  setTemporaryPassword(params: SetTemporaryPasswordParams): Promise<void>;
184
199
  updateAttributes(params: UpdateAttributesParams): Promise<void>;
@@ -203,4 +218,4 @@ declare function parseKeycloakAdminConfig(value: unknown): KeycloakAdminConfig;
203
218
 
204
219
  declare function createKeycloakAdminClient({ config: rawConfig, fetch: injectedFetch, now, }: CreateKeycloakAdminClientParams): KeycloakAdminClient;
205
220
 
206
- export { type CreateGroupParams, type CreateGroupResult, type CreateKeycloakAdminClientParams, type CreateUserParams, type CreateUserResult, type DeleteGroupParams, type DeleteUserParams, type FetchLike, type FindUserByEmailParams, type GroupMembershipParams, KEYCLOAK_ADMIN_ERROR_CODE, KEYCLOAK_ADMIN_TOKEN_RENEWAL_SKEW_MS, type KeycloakAdminClient, type KeycloakAdminConfig, type KeycloakAdminEndpoints, KeycloakAdminError, type KeycloakAdminErrorCode, type KeycloakAdminErrorContext, type KeycloakAdminErrorParams, type KeycloakGroup, type KeycloakPassword, type KeycloakUser, type KeycloakUserAttributes, type ListGroupsParams, type ListGroupsResult, type ListUsersParams, type ListUsersResult, type SerializedKeycloakAdminError, type SetEnabledParams, type SetPasswordParams, type SetTemporaryPasswordParams, type UpdateAttributesParams, type UpdateGroupParams, type UpdateUserParams, buildKeycloakAdminEndpoints, createKeycloakAdminClient, isKeycloakAdminError, keycloakAdminConfigSchema, parseKeycloakAdminConfig };
221
+ export { type CreateGroupParams, type CreateGroupResult, type CreateKeycloakAdminClientParams, type CreateUserParams, type CreateUserResult, type DeleteGroupParams, type DeleteUserParams, type FetchLike, type FindUserByEmailParams, type GroupMembershipParams, KEYCLOAK_ADMIN_ERROR_CODE, KEYCLOAK_ADMIN_TOKEN_RENEWAL_SKEW_MS, type KeycloakAdminClient, type KeycloakAdminConfig, type KeycloakAdminEndpoints, KeycloakAdminError, type KeycloakAdminErrorCode, type KeycloakAdminErrorContext, type KeycloakAdminErrorParams, type KeycloakGroup, type KeycloakPassword, type KeycloakUser, type KeycloakUserAttributes, type ListGroupsParams, type ListGroupsResult, type ListUsersParams, type ListUsersResult, PROFILE_PICTURE_ATTRIBUTE, type SerializedKeycloakAdminError, type SetEnabledParams, type SetPasswordParams, type SetProfilePictureParams, type SetTemporaryPasswordParams, type UpdateAttributesParams, type UpdateGroupParams, type UpdateUserParams, buildKeycloakAdminEndpoints, createKeycloakAdminClient, isKeycloakAdminError, keycloakAdminConfigSchema, parseKeycloakAdminConfig };
package/dist/index.js CHANGED
@@ -187,6 +187,9 @@ function createKeycloakTokenProvider({
187
187
  };
188
188
  }
189
189
 
190
+ // src/keycloak-admin.types.ts
191
+ var PROFILE_PICTURE_ATTRIBUTE = "picture";
192
+
190
193
  // src/keycloak-admin.client.ts
191
194
  var HTTP_CONFLICT = 409;
192
195
  var HTTP_NOT_FOUND = 404;
@@ -344,6 +347,26 @@ function createKeycloakAdminClient({
344
347
  const found = await response.json();
345
348
  return { hasMore: found.length > limit, users: found.slice(0, limit) };
346
349
  },
350
+ /**
351
+ * A foto é atributo, e o Admin API **substitui o conjunto** quando recebe `attributes`. Por isso
352
+ * esta operação lê o usuário antes: mandar só a foto apagaria `company_id`, `tax_id` e qualquer
353
+ * outro atributo do produto — e o sintoma seria login entrando sem empresa, longe daqui.
354
+ */
355
+ async setProfilePicture({ pictureUrl, userId }) {
356
+ const response = await adminRequest({ method: "GET", url: endpoints.user(userId) });
357
+ const current = await response.json();
358
+ const attributes = { ...current.attributes ?? {} };
359
+ if (pictureUrl === void 0 || pictureUrl === "") {
360
+ delete attributes[PROFILE_PICTURE_ATTRIBUTE];
361
+ } else {
362
+ attributes[PROFILE_PICTURE_ATTRIBUTE] = pictureUrl;
363
+ }
364
+ await adminRequest({
365
+ body: { attributes: normalizeAttributes(attributes) },
366
+ method: "PUT",
367
+ url: endpoints.user(userId)
368
+ });
369
+ },
347
370
  async setEnabled({ enabled, userId }) {
348
371
  await adminRequest({ body: { enabled }, method: "PUT", url: endpoints.user(userId) });
349
372
  },
@@ -367,6 +390,7 @@ export {
367
390
  KEYCLOAK_ADMIN_ERROR_CODE,
368
391
  KEYCLOAK_ADMIN_TOKEN_RENEWAL_SKEW_MS,
369
392
  KeycloakAdminError,
393
+ PROFILE_PICTURE_ATTRIBUTE,
370
394
  buildKeycloakAdminEndpoints,
371
395
  createKeycloakAdminClient,
372
396
  isKeycloakAdminError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adatechnology/keycloak-admin",
3
- "version": "1.0.0-rc.2",
3
+ "version": "1.0.0-rc.3",
4
4
  "description": "Agnostic Keycloak Admin API client authenticated as a service account (client_credentials)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",