Skip to content

Commit 0e6cf02

Browse files
Sarath1018claude
andcommitted
feat(identity): onboard Users service with getById
First slice of the Identity user management onboarding: introduces the modular Users service (@uipath/uipath-typescript/users) with - getById(userId) GET /api/User/{userId} Identity routes at the organization level, so endpoints use a `../identity_` base (IDENTITY_ORG_BASE) to collapse the tenant segment ApiClient inserts — same pattern as the notification service. Live-API findings encoded (Swagger spec is wrong on these): `type`/`category` come back as numeric codes, not string enums — mapped to UserType/UserCategory via value maps; internal `legacyId` is dropped. Follow-up PRs add updateById/deleteById/create (with bound entity methods) and invite. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent e4a5eca commit 0e6cf02

23 files changed

Lines changed: 561 additions & 12 deletions

File tree

docs/oauth-scopes.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ The `ConversationalAgents` scope is required for real-time WebSocket sessions (`
145145
|--------|-------------|
146146
| `getAll()` | `OR.Execution` or `OR.Execution.Read` |
147147
| `getById()` | `OR.Execution` or `OR.Execution.Read` |
148-
| `downloadCitationSource()` | NA |
149148

150149
### Conversations
151150

@@ -272,3 +271,9 @@ The `ConversationalAgents` scope is required for real-time WebSocket sessions (`
272271
| `getSpansByReference()` | `Insights.RealTimeData Insights OR.Folders.Read` |
273272
| `getGovernanceDecisions()` | `Insights.RealTimeData Insights OR.Folders.Read` |
274273
| `getGovernanceSummary()` | `Insights.RealTimeData Insights OR.Folders.Read` |
274+
275+
## Users
276+
277+
| Method | OAuth Scope |
278+
|--------|-------------|
279+
| `getById()` | `PM.Users` or `PM.Users.Read` |

mkdocs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ nav:
208208
- Processes: api/interfaces/ProcessServiceModel.md
209209
- Queues: api/interfaces/QueueServiceModel.md
210210
- Tasks: api/interfaces/TaskServiceModel.md
211+
- Users: api/interfaces/UserServiceModel.md
211212
- Traces:
212213
- api/interfaces/traces/index.md
213214
- Agent: api/interfaces/AgentTracesServiceModel.md
@@ -224,7 +225,7 @@ nav:
224225
- SDK Reference: coded-action-app-sdk/interfaces/CodedActionAppServiceModel.md
225226
- Plugins:
226227
- Codex: plugins/codex.md
227-
- Sample Apps Gallery: samples/index.md
228+
- Sample Application: https://github.com/UiPath/uipath-typescript/tree/main/samples
228229
- FAQ: FAQ.md
229230
- How To Contribute: CONTRIBUTING.md
230231
- Integration Testing: integration-testing.md

package.json

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@uipath/uipath-typescript",
3-
"version": "1.5.5",
3+
"version": "1.5.4",
44
"description": "UiPath TypeScript SDK",
55
"license": "MIT",
66
"keywords": [
@@ -225,12 +225,21 @@
225225
"types": "./dist/notifications/index.d.ts",
226226
"default": "./dist/notifications/index.cjs"
227227
}
228+
},
229+
"./users": {
230+
"import": {
231+
"types": "./dist/users/index.d.ts",
232+
"default": "./dist/users/index.mjs"
233+
},
234+
"require": {
235+
"types": "./dist/users/index.d.ts",
236+
"default": "./dist/users/index.cjs"
237+
}
228238
}
229239
},
230240
"files": [
231241
"dist",
232-
"README.md",
233-
"docs/oauth-scopes.md"
242+
"README.md"
234243
],
235244
"scripts": {
236245
"prepack": "rimraf *.tgz",
@@ -242,7 +251,6 @@
242251
"docs:coded-action-app": "npm run docs --prefix packages/coded-action-app",
243252
"docs:post-process": "node scripts/docs-post-process.mjs",
244253
"lint": "oxlint",
245-
"check:samples": "node scripts/check-samples.mjs",
246254
"typecheck": "tsc --noEmit",
247255
"test": "vitest",
248256
"test:unit": "vitest run",
@@ -276,7 +284,6 @@
276284
"@vitest/ui": "^4.1.9",
277285
"builtin-modules": "^3.3.0",
278286
"dotenv": "^17.2.0",
279-
"node-html-parser": "^9.0.0",
280287
"oxlint": "^1.43.0",
281288
"rimraf": "^6.0.1",
282289
"rollup": "^4.60.4",

rollup.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ const serviceEntries = [
233233
name: 'notifications',
234234
input: 'src/services/notification/index.ts',
235235
output: 'notifications/index'
236+
},
237+
{
238+
name: 'users',
239+
input: 'src/services/identity/index.ts',
240+
output: 'users/index'
236241
}
237242
];
238243

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export * from './models/conversational-agent';
1919
export * from './models/agents';
2020
export * as DuFramework from './models/document-understanding/framework';
2121
export * from './models/governance';
22+
export * from './models/identity';
2223
export * from './models/observability';
2324

2425
// Export error handling functionality (public API only)

src/models/identity/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* Identity models barrel export.
3+
*/
4+
5+
export * from './users.types';
6+
export * from './users.models';
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { UserType, UserCategory } from './users.types';
2+
3+
/**
4+
* User field mappings (API field name → SDK field name).
5+
*
6+
* Semantic renames only — the API already returns camelCase, so no case
7+
* conversion is involved.
8+
*/
9+
export const UserMap: { [key: string]: string } = {
10+
creationTime: 'createdTime',
11+
lastModificationTime: 'lastModifiedTime',
12+
groupIDs: 'groupIds',
13+
};
14+
15+
/**
16+
* Maps numeric user type codes (from API) to {@link UserType} enum values.
17+
*/
18+
export const UserTypeMap: { [key: number]: UserType } = {
19+
0: UserType.User,
20+
1: UserType.Robot,
21+
2: UserType.DirectoryUser,
22+
3: UserType.DirectoryGroup,
23+
4: UserType.RobotAccount,
24+
5: UserType.Application,
25+
};
26+
27+
/**
28+
* Maps numeric user category codes (from API) to {@link UserCategory} enum values.
29+
*/
30+
export const UserCategoryMap: { [key: number]: UserCategory } = {
31+
0: UserCategory.Local,
32+
1: UserCategory.LinkedLocal,
33+
2: UserCategory.Directory,
34+
};
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Internal-only types for the Identity Users service.
3+
*
4+
* NOT exported from the public barrel (`src/models/identity/index.ts`).
5+
*/
6+
7+
/**
8+
* Raw user shape as returned by the Identity user management API.
9+
*
10+
* Mirrors the API contract exactly: it uses the API's field names
11+
* (`creationTime`, `groupIDs`, …) and numeric `type`/`category` codes — the
12+
* Swagger spec declares string enums for these, but the live API returns
13+
* numbers. The SDK renames/maps them before returning to consumers.
14+
*/
15+
export interface RawUserEntry {
16+
id: string;
17+
userName: string;
18+
email: string;
19+
emailConfirmed: boolean;
20+
name: string | null;
21+
surname: string | null;
22+
displayName: string | null;
23+
/** Renamed to `createdTime` in the SDK response. */
24+
creationTime: string;
25+
/** Renamed to `lastModifiedTime` in the SDK response. */
26+
lastModificationTime: string | null;
27+
lastLoginTime: string | null;
28+
/** Renamed to `groupIds` in the SDK response. */
29+
groupIDs: string[];
30+
isActive: boolean;
31+
bypassBasicAuthRestriction: boolean;
32+
/** Numeric code mapped to the {@link UserType} enum in the SDK response. */
33+
type: number;
34+
/** Numeric code mapped to the {@link UserCategory} enum in the SDK response. */
35+
category: number;
36+
invitationAccepted: boolean;
37+
// Internal field the SDK strips before returning to consumers:
38+
/** Internal platform synchronization id — dropped from the SDK response. */
39+
legacyId?: number;
40+
}
41+
42+
/**
43+
* Fields stripped from each {@link RawUserEntry} before it is returned to the
44+
* SDK consumer.
45+
*/
46+
export const INTERNAL_USER_FIELDS = [
47+
'legacyId',
48+
] as const satisfies ReadonlyArray<keyof RawUserEntry>;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Identity Users service model — public response shapes and the ServiceModel
3+
* interface that drives generated API documentation.
4+
*/
5+
6+
import type { RawUserGetResponse } from './users.types';
7+
8+
/**
9+
* User returned by the Users service.
10+
*/
11+
export interface UserGetResponse extends RawUserGetResponse {}
12+
13+
/**
14+
* Service model for managing users in a UiPath organization.
15+
*
16+
* Provides organization-level user administration.
17+
*
18+
* ### Usage
19+
*
20+
* Prerequisites: Initialize the SDK first - see [Getting Started](/uipath-typescript/getting-started/#import-initialize)
21+
*
22+
* ```typescript
23+
* import { Users } from '@uipath/uipath-typescript/users';
24+
*
25+
* const users = new Users(sdk);
26+
* const user = await users.getById('<userId>');
27+
* ```
28+
*/
29+
export interface UserServiceModel {
30+
/**
31+
* Gets a user by ID.
32+
*
33+
* Returns the full user details including profile fields, group membership,
34+
* activity flags and invitation state.
35+
*
36+
* @param userId - User GUID
37+
* @returns Promise resolving to the user
38+
* {@link UserGetResponse}
39+
*
40+
* @example
41+
* ```typescript
42+
* const user = await users.getById('<userId>');
43+
* console.log(`${user.displayName} (${user.email}) — active: ${user.isActive}`);
44+
* ```
45+
*/
46+
getById(userId: string): Promise<UserGetResponse>;
47+
}

src/models/identity/users.types.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Identity user management types — response shapes and enums.
3+
*/
4+
5+
/**
6+
* Defines how a user was created and how it is supposed to be used.
7+
*/
8+
export enum UserType {
9+
/** Standard interactive user. */
10+
User = 'user',
11+
/** Robot user driving unattended automation. */
12+
Robot = 'robot',
13+
/** User provisioned from an external directory (e.g. Azure AD). */
14+
DirectoryUser = 'directoryUser',
15+
/** Group provisioned from an external directory. */
16+
DirectoryGroup = 'directoryGroup',
17+
/** Robot account (non-interactive machine identity). */
18+
RobotAccount = 'robotAccount',
19+
/** External application identity. */
20+
Application = 'application',
21+
}
22+
23+
/**
24+
* Discriminates a user by how they relate to directory provisioning.
25+
*/
26+
export enum UserCategory {
27+
/** Local account managed in UiPath. */
28+
Local = 'local',
29+
/** Local account linked to a directory identity. */
30+
LinkedLocal = 'linkedLocal',
31+
/** Account provisioned from an external directory. */
32+
Directory = 'directory',
33+
}
34+
35+
/**
36+
* User as returned by the Identity user management API.
37+
*
38+
* Field selection: `legacyId` (an internal platform synchronization field) is returned
39+
* by the API but dropped from the SDK because it has no use for an application developer.
40+
*/
41+
export interface RawUserGetResponse {
42+
/** User GUID. */
43+
id: string;
44+
/** The username. */
45+
userName: string;
46+
/** Email address. Empty string when the user has no email. */
47+
email: string;
48+
/** Whether the email address has been confirmed. */
49+
emailConfirmed: boolean;
50+
/** First name. */
51+
name: string | null;
52+
/** Last name. */
53+
surname: string | null;
54+
/** Display name. */
55+
displayName: string | null;
56+
/** When the user was created. */
57+
createdTime: string;
58+
/** When the user was last modified. */
59+
lastModifiedTime: string | null;
60+
/** When the user last logged in. `null` if the user has never logged in. */
61+
lastLoginTime: string | null;
62+
/** GUIDs of the groups the user is a member of. */
63+
groupIds: string[];
64+
/** Whether the user is active. */
65+
isActive: boolean;
66+
/** Whether this user bypasses the basic authentication restriction. */
67+
bypassBasicAuthRestriction: boolean;
68+
/** How the user was created and is supposed to be used. */
69+
type: UserType;
70+
/** How the user relates to directory provisioning. */
71+
category: UserCategory;
72+
/** Whether the user has accepted their invitation. */
73+
invitationAccepted: boolean;
74+
}

0 commit comments

Comments
 (0)