@xcitedbs/client 0.3.7 → 0.3.8
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/dist/client.d.ts +44 -2
- package/dist/client.js +86 -6
- package/dist/index.d.ts +1 -1
- package/dist/types.d.ts +84 -3
- package/dist/user-isolation.test.js +151 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AccessCheckResult, AppAuthConfig, AppEmailConfig, AppEmailTemplates, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, BranchInfo, BookmarkRecord, CheckpointRecord, CommitRecord, CompareRef, CompareResult, DatabaseContext, DiffRef, DiffResult, SmartDiffRef, SmartDiffResult, DocumentBatchResponse, DocumentExportFormat, ExportDocumentResult, Flags, JsonDocumentBatchItem, ImportDocumentOptions, ImportDocumentResult, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, AcquireLockOptions, LogEntry, MergeResult, PublishResult, RebaseUserWorkspaceResult, WorkspaceInfo, MetaValue, PlatformRegisterResult, PolicySubjectInput, UnqueryResult, UnqueryTemplate, PolicyUpdateResponse, RealtimeEvent, SecurityConfig, SecurityPolicy, StoredTriggerResponse, TriggerDefinition, TriggerEventsResponse, StoredPolicyResponse, TxnRequest, TxnResponse, VerifyAppUserTokenOptions, SubscriptionOptions, TagRecord, TextSearchQuery, TextSearchResult, ProjectSearchSettings, ProjectSearchSettingsUpdate, ProjectDocConfResponse, AssetGcDryRunResult, AssetHeadResult, AssetListResponse, AssetMagicLinkListResponse, AssetMagicLinkResult, AssetShareListResponse, AssetShareRequest, AssetUnshareRequest, AssetUploadResult, CreateAssetMagicLinkRequest, ListAssetsOptions, ProjectAssetStorageConfig, UploadAssetOptions, PlatformDefaultDocConfResponse, VectorIndexEstimate, RagQueryOptions, RagQueryResult, RagStreamEvent, OAuthProvidersResponse, ProjectInfo, PlatformRegistrationConfig, PlatformWorkspacesResponse, TokenPair, UserInfo, ApiKeyInfo, WriteDocumentOptions, XmlDocumentBatchItem, CreateTestSessionOptions, XCiteDBClientOptions, XCiteDBJwtClaims, TestSessionBootstrapSummary, TestSessionInfo, XCiteQuery, UserIsolationConfig, UserIsolationCreateShareParams, UserIsolationShareResult } from './types';
|
|
1
|
+
import { AccessCheckResult, AppAuthConfig, AppEmailConfig, AppEmailTemplates, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, BranchInfo, BookmarkRecord, CheckpointRecord, CommitRecord, CompareRef, CompareResult, DatabaseContext, DiffRef, DiffResult, SmartDiffRef, SmartDiffResult, DocumentBatchResponse, DocumentExportFormat, ExportDocumentResult, Flags, JsonDocumentBatchItem, ImportDocumentOptions, ImportDocumentResult, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, AcquireLockOptions, LogEntry, MergeResult, PublishResult, RebaseUserWorkspaceResult, WorkspaceInfo, MetaValue, PlatformRegisterResult, PolicySubjectInput, UnqueryResult, UnqueryTemplate, PolicyUpdateResponse, RealtimeEvent, SecurityConfig, SecurityPolicy, StoredTriggerResponse, TriggerDefinition, TriggerEventsResponse, StoredPolicyResponse, TxnRequest, TxnResponse, VerifyAppUserTokenOptions, SubscriptionOptions, TagRecord, TextSearchQuery, TextSearchResult, ProjectSearchSettings, ProjectSearchSettingsUpdate, ProjectDocConfResponse, AssetGcDryRunResult, AssetHeadResult, AssetListResponse, AssetMagicLinkListResponse, AssetMagicLinkResult, AssetShareListResponse, AssetShareRequest, AssetUnshareRequest, AssetUploadResult, CreateAssetMagicLinkRequest, ListAssetsOptions, ProjectAssetStorageConfig, UploadAssetOptions, PlatformDefaultDocConfResponse, VectorIndexEstimate, RagQueryOptions, RagQueryResult, RagStreamEvent, OAuthProvidersResponse, ProjectInfo, PlatformRegistrationConfig, PlatformWorkspacesResponse, TokenPair, UserInfo, ApiKeyInfo, WriteDocumentOptions, XmlDocumentBatchItem, CreateTestSessionOptions, XCiteDBClientOptions, XCiteDBJwtClaims, TestSessionBootstrapSummary, TestSessionInfo, XCiteQuery, UserIsolationConfig, UserIsolationCreateShareParams, UserIsolationShareResult, UserIsolationShareListResponse, UserIsolationUnshareParams, ShareDirection, AppUserGroup, CreateGroupParams, ListGroupsResponse } from './types';
|
|
2
2
|
import { WebSocketSubscription } from './websocket';
|
|
3
3
|
export declare class XCiteDBClient {
|
|
4
4
|
private baseUrl;
|
|
@@ -500,15 +500,57 @@ export declare class XCiteDBClient {
|
|
|
500
500
|
* When {@link XCiteDBClient.enableUserIsolation} / `userIsolation` is active, `identifier` is prefixed like other document APIs.
|
|
501
501
|
*/
|
|
502
502
|
createUserIsolationShare(params: UserIsolationCreateShareParams): Promise<UserIsolationShareResult>;
|
|
503
|
+
/**
|
|
504
|
+
* Revoke a document share previously created with {@link XCiteDBClient.createUserIsolationShare}
|
|
505
|
+
* (`DELETE /api/v1/security/user-isolation/shares`). Requires an **app user** session.
|
|
506
|
+
*/
|
|
507
|
+
removeUserIsolationShare(params: UserIsolationUnshareParams): Promise<void>;
|
|
508
|
+
/**
|
|
509
|
+
* List document share aliases visible to the caller (`GET /api/v1/security/user-isolation/shares`).
|
|
510
|
+
* `direction: "outgoing"` is not enumerated server-side — the server returns a `note` and an empty
|
|
511
|
+
* list; track outgoing shares in the app if needed.
|
|
512
|
+
*/
|
|
513
|
+
listUserIsolationShares(opts: {
|
|
514
|
+
direction: ShareDirection;
|
|
515
|
+
scope?: string;
|
|
516
|
+
}): Promise<UserIsolationShareListResponse>;
|
|
503
517
|
/** Share an asset path via prefix alias (`POST /api/v1/security/user-isolation/asset-shares`). */
|
|
504
518
|
createAssetShare(params: AssetShareRequest): Promise<UserIsolationShareResult>;
|
|
505
519
|
/** Remove an asset share (`DELETE /api/v1/security/user-isolation/asset-shares`). */
|
|
506
520
|
deleteAssetShare(params: AssetUnshareRequest): Promise<void>;
|
|
507
521
|
/** List incoming/public asset share aliases (`GET /api/v1/security/user-isolation/asset-shares`). */
|
|
508
522
|
listAssetShares(opts?: {
|
|
509
|
-
direction?:
|
|
523
|
+
direction?: ShareDirection;
|
|
510
524
|
scope?: string;
|
|
511
525
|
}): Promise<AssetShareListResponse>;
|
|
526
|
+
/**
|
|
527
|
+
* Create an app-user group (`POST /api/v1/security/user-isolation/groups`). Requires an **app user**
|
|
528
|
+
* session for `kind: "team"` (caller becomes the owner) or a tenant admin for `kind: "admin"`. Use
|
|
529
|
+
* group ids as `ShareTarget` values to share documents/assets with all current and future members.
|
|
530
|
+
*
|
|
531
|
+
* Note: do **not** confuse with {@link XCiteDBClient.updateAppUserGroups}, which is a developer/admin
|
|
532
|
+
* endpoint that overwrites a user's group list — this endpoint creates the group itself.
|
|
533
|
+
*/
|
|
534
|
+
createGroup(params: CreateGroupParams): Promise<AppUserGroup>;
|
|
535
|
+
/**
|
|
536
|
+
* List groups visible to the caller (`GET /api/v1/security/user-isolation/groups`). For app users,
|
|
537
|
+
* returns admin groups, groups they own, and groups they belong to.
|
|
538
|
+
*/
|
|
539
|
+
listGroups(): Promise<ListGroupsResponse>;
|
|
540
|
+
/** Fetch a single group (`GET /api/v1/security/user-isolation/groups/{id}`). 404 if not visible. */
|
|
541
|
+
getGroup(id: string): Promise<AppUserGroup>;
|
|
542
|
+
/** Delete a group (`DELETE /api/v1/security/user-isolation/groups/{id}`). Owner or admin only. */
|
|
543
|
+
deleteGroup(id: string): Promise<void>;
|
|
544
|
+
/**
|
|
545
|
+
* Add an app user to a group (`POST /api/v1/security/user-isolation/groups/{id}/members`).
|
|
546
|
+
* Owner or admin only. Returns the updated group record.
|
|
547
|
+
*/
|
|
548
|
+
addGroupMember(id: string, userId: string): Promise<AppUserGroup>;
|
|
549
|
+
/**
|
|
550
|
+
* Remove an app user from a group
|
|
551
|
+
* (`DELETE /api/v1/security/user-isolation/groups/{id}/members/{user_id}`). Owner or admin only.
|
|
552
|
+
*/
|
|
553
|
+
removeGroupMember(id: string, userId: string): Promise<void>;
|
|
512
554
|
/** Issue a time-limited magic link for one asset identifier (`POST /api/v1/security/asset-magic-links`). */
|
|
513
555
|
createAssetMagicLink(body: CreateAssetMagicLinkRequest): Promise<AssetMagicLinkResult>;
|
|
514
556
|
/** List issued magic links (no secrets) (`GET /api/v1/security/asset-magic-links`). */
|
package/dist/client.js
CHANGED
|
@@ -71,6 +71,18 @@ function buildQuery(params) {
|
|
|
71
71
|
const s = sp.toString();
|
|
72
72
|
return s ? `?${s}` : '';
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Forward share-target fields (legacy `target_user_id`/`target_group_id` and the preferred `target`
|
|
76
|
+
* object) into a request body. Server `parseShareTarget` accepts either shape.
|
|
77
|
+
*/
|
|
78
|
+
function applyShareTargetToBody(body, src) {
|
|
79
|
+
if (src.target_user_id !== undefined)
|
|
80
|
+
body.target_user_id = src.target_user_id;
|
|
81
|
+
if (src.target_group_id !== undefined)
|
|
82
|
+
body.target_group_id = src.target_group_id;
|
|
83
|
+
if (src.target !== undefined)
|
|
84
|
+
body.target = src.target;
|
|
85
|
+
}
|
|
74
86
|
/** Best-effort filename from `Content-Disposition` (attachment; filename="…"). */
|
|
75
87
|
function parseContentDispositionFilename(cd) {
|
|
76
88
|
if (!cd)
|
|
@@ -1656,18 +1668,45 @@ class XCiteDBClient {
|
|
|
1656
1668
|
* When {@link XCiteDBClient.enableUserIsolation} / `userIsolation` is active, `identifier` is prefixed like other document APIs.
|
|
1657
1669
|
*/
|
|
1658
1670
|
async createUserIsolationShare(params) {
|
|
1659
|
-
|
|
1671
|
+
const body = {
|
|
1660
1672
|
identifier: this.isoPrefixId(params.identifier),
|
|
1661
|
-
target_user_id: params.target_user_id,
|
|
1662
1673
|
mode: params.mode,
|
|
1674
|
+
};
|
|
1675
|
+
applyShareTargetToBody(body, params);
|
|
1676
|
+
return this.request('POST', '/api/v1/security/user-isolation/shares', body);
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Revoke a document share previously created with {@link XCiteDBClient.createUserIsolationShare}
|
|
1680
|
+
* (`DELETE /api/v1/security/user-isolation/shares`). Requires an **app user** session.
|
|
1681
|
+
*/
|
|
1682
|
+
async removeUserIsolationShare(params) {
|
|
1683
|
+
const body = {
|
|
1684
|
+
identifier: this.isoPrefixId(params.identifier),
|
|
1685
|
+
};
|
|
1686
|
+
applyShareTargetToBody(body, params);
|
|
1687
|
+
if (params.sharer_user_id !== undefined) {
|
|
1688
|
+
body.sharer_user_id = params.sharer_user_id;
|
|
1689
|
+
}
|
|
1690
|
+
await this.request('DELETE', '/api/v1/security/user-isolation/shares', body);
|
|
1691
|
+
}
|
|
1692
|
+
/**
|
|
1693
|
+
* List document share aliases visible to the caller (`GET /api/v1/security/user-isolation/shares`).
|
|
1694
|
+
* `direction: "outgoing"` is not enumerated server-side — the server returns a `note` and an empty
|
|
1695
|
+
* list; track outgoing shares in the app if needed.
|
|
1696
|
+
*/
|
|
1697
|
+
async listUserIsolationShares(opts) {
|
|
1698
|
+
const q = buildQuery({
|
|
1699
|
+
direction: opts.direction,
|
|
1700
|
+
...(opts.scope ? { scope: opts.scope } : {}),
|
|
1663
1701
|
});
|
|
1702
|
+
return this.request('GET', `/api/v1/security/user-isolation/shares${q}`);
|
|
1664
1703
|
}
|
|
1665
1704
|
/** Share an asset path via prefix alias (`POST /api/v1/security/user-isolation/asset-shares`). */
|
|
1666
1705
|
async createAssetShare(params) {
|
|
1667
1706
|
const body = {
|
|
1668
|
-
target_user_id: params.target_user_id,
|
|
1669
1707
|
mode: params.mode,
|
|
1670
1708
|
};
|
|
1709
|
+
applyShareTargetToBody(body, params);
|
|
1671
1710
|
if (params.source_uri !== undefined && params.source_uri !== '') {
|
|
1672
1711
|
body.source_uri = params.source_uri;
|
|
1673
1712
|
}
|
|
@@ -1691,9 +1730,7 @@ class XCiteDBClient {
|
|
|
1691
1730
|
else {
|
|
1692
1731
|
throw new types_1.XCiteDBError('deleteAssetShare requires identifier or source_uri', 400, null);
|
|
1693
1732
|
}
|
|
1694
|
-
|
|
1695
|
-
body.target_user_id = params.target_user_id;
|
|
1696
|
-
}
|
|
1733
|
+
applyShareTargetToBody(body, params);
|
|
1697
1734
|
if (params.sharer_user_id !== undefined) {
|
|
1698
1735
|
body.sharer_user_id = params.sharer_user_id;
|
|
1699
1736
|
}
|
|
@@ -1707,6 +1744,49 @@ class XCiteDBClient {
|
|
|
1707
1744
|
});
|
|
1708
1745
|
return this.request('GET', `/api/v1/security/user-isolation/asset-shares${q}`);
|
|
1709
1746
|
}
|
|
1747
|
+
/**
|
|
1748
|
+
* Create an app-user group (`POST /api/v1/security/user-isolation/groups`). Requires an **app user**
|
|
1749
|
+
* session for `kind: "team"` (caller becomes the owner) or a tenant admin for `kind: "admin"`. Use
|
|
1750
|
+
* group ids as `ShareTarget` values to share documents/assets with all current and future members.
|
|
1751
|
+
*
|
|
1752
|
+
* Note: do **not** confuse with {@link XCiteDBClient.updateAppUserGroups}, which is a developer/admin
|
|
1753
|
+
* endpoint that overwrites a user's group list — this endpoint creates the group itself.
|
|
1754
|
+
*/
|
|
1755
|
+
async createGroup(params) {
|
|
1756
|
+
const body = { name: params.name };
|
|
1757
|
+
if (params.kind !== undefined)
|
|
1758
|
+
body.kind = params.kind;
|
|
1759
|
+
return this.request('POST', '/api/v1/security/user-isolation/groups', body);
|
|
1760
|
+
}
|
|
1761
|
+
/**
|
|
1762
|
+
* List groups visible to the caller (`GET /api/v1/security/user-isolation/groups`). For app users,
|
|
1763
|
+
* returns admin groups, groups they own, and groups they belong to.
|
|
1764
|
+
*/
|
|
1765
|
+
async listGroups() {
|
|
1766
|
+
return this.request('GET', '/api/v1/security/user-isolation/groups');
|
|
1767
|
+
}
|
|
1768
|
+
/** Fetch a single group (`GET /api/v1/security/user-isolation/groups/{id}`). 404 if not visible. */
|
|
1769
|
+
async getGroup(id) {
|
|
1770
|
+
return this.request('GET', `/api/v1/security/user-isolation/groups/${encodeURIComponent(id)}`);
|
|
1771
|
+
}
|
|
1772
|
+
/** Delete a group (`DELETE /api/v1/security/user-isolation/groups/{id}`). Owner or admin only. */
|
|
1773
|
+
async deleteGroup(id) {
|
|
1774
|
+
await this.request('DELETE', `/api/v1/security/user-isolation/groups/${encodeURIComponent(id)}`);
|
|
1775
|
+
}
|
|
1776
|
+
/**
|
|
1777
|
+
* Add an app user to a group (`POST /api/v1/security/user-isolation/groups/{id}/members`).
|
|
1778
|
+
* Owner or admin only. Returns the updated group record.
|
|
1779
|
+
*/
|
|
1780
|
+
async addGroupMember(id, userId) {
|
|
1781
|
+
return this.request('POST', `/api/v1/security/user-isolation/groups/${encodeURIComponent(id)}/members`, { user_id: userId });
|
|
1782
|
+
}
|
|
1783
|
+
/**
|
|
1784
|
+
* Remove an app user from a group
|
|
1785
|
+
* (`DELETE /api/v1/security/user-isolation/groups/{id}/members/{user_id}`). Owner or admin only.
|
|
1786
|
+
*/
|
|
1787
|
+
async removeGroupMember(id, userId) {
|
|
1788
|
+
await this.request('DELETE', `/api/v1/security/user-isolation/groups/${encodeURIComponent(id)}/members/${encodeURIComponent(userId)}`);
|
|
1789
|
+
}
|
|
1710
1790
|
/** Issue a time-limited magic link for one asset identifier (`POST /api/v1/security/asset-magic-links`). */
|
|
1711
1791
|
async createAssetMagicLink(body) {
|
|
1712
1792
|
return this.request('POST', '/api/v1/security/asset-magic-links', body);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { XCiteDBClient } from './client';
|
|
2
2
|
export { parseAssetUri, formatAssetUri, collectIdentifiersFromText, ASSET_URI_PREFIX } from './assetUri';
|
|
3
3
|
export { WebSocketSubscription } from './websocket';
|
|
4
|
-
export type { AccessCheckResult, ApiKeyInfo, AppAuthConfig, AppEmailConfig, AppEmailSmtpConfig, AppEmailTemplateEntry, AppEmailTemplates, AppEmailWebhookConfig, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, BookmarkRecord, BranchInfo, BranchListItem, CheckpointRecord, CommitRecord, CompareEntry, CompareRef, CompareResult, DatabaseContext, DiffEntry, DiffRef, DiffResult, SmartDiffRef, SmartDiffResult, SmartDiffStats, DocumentBatchResponse, DocumentBatchResultRow, DocumentExportFormat, DocumentImportFormat, ExportDocumentResult, Flags, ImportDocumentOptions, ImportDocumentResult, JsonDocumentData, JsonDocumentBatchItem, IdentifierChildNode, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, AcquireLockOptions, LockConflictBody, LockExpiredBody, LockUnknownBody, MergeConflict, MergeResult, OAuthProviderInfo, OAuthProvidersResponse, OwnedTenantInfo, ProjectInfo, PlatformRegistrationConfig, PlatformWorkspaceOrg, PlatformWorkspacesResponse, ProjectSearchSettings, ProjectSearchSettingsUpdate, ProjectDocConfResponse, AssetGcDryRunResult, AssetHeadResult, AssetListItem, AssetListResponse, AssetMagicLinkListResponse, AssetMagicLinkRecord, AssetMagicLinkResult, AssetShareListEntry, AssetShareListResponse, AssetShareRequest, AssetStorageImport, AssetStorageMount, AssetStorageTarget, AssetStorageTargetType, AssetUnshareRequest, AssetUploadResult, CreateAssetMagicLinkRequest, ListAssetsOptions, ProjectAssetStorageConfig, UploadAssetOptions, PlatformDefaultDocConfResponse, LogEntry, MetaValue, PlatformRegisterResult, PolicyUpdateResponse, PublishConflict, PublishResult, RebaseUserWorkspaceResult, PolicyConditions, PolicyIdentifierPattern, PolicyResources, PolicySubjectInput, PolicySubjects, RagQueryOptions, RagQueryResult, RagStreamEvent, RealtimeEvent, SandboxApiKeyMintResult, SandboxInfo, SandboxMember, SearchIndexingProgress, SecurityConfig, SecurityPolicy, StoredPolicyResponse, StoredTriggerResponse, SubscriptionOptions, TagRecord, TextSearchHit, TextSearchQuery, TextSearchResult, TriggerDefinition, TriggerEvent, TriggerEventsResponse, TxnOperation, TxnOperationResult, TxnPrecondition, TxnPreconditionResult, TxnRequest, TxnResponse, JwksKey, JwksResponse, VerifyAppUserTokenOptions, TokenPair, UserInfo, UserIsolationConfig, UserIsolationCreateShareParams, UserIsolationOptions, UserIsolationShareMode, UserIsolationShareResult, WorkspaceInfo, WriteDocumentOptions, XmlDocumentBatchItem, CreateSandboxOptions, CreateTestSessionOptions, TestSessionBootstrap, TestSessionBootstrapSummary, TestSessionInfo, XCiteDBClientOptions, XCiteDBErrorExtras, XCiteDBJwtClaims, UnqueryResult, UnqueryTemplate, XCiteQuery, } from './types';
|
|
4
|
+
export type { AccessCheckResult, ApiKeyInfo, AppAuthConfig, AppEmailConfig, AppEmailSmtpConfig, AppEmailTemplateEntry, AppEmailTemplates, AppEmailWebhookConfig, AppUser, AppUserTokenPair, EmailTestResponse, ForgotPasswordResponse, SendVerificationResponse, BookmarkRecord, BranchInfo, BranchListItem, CheckpointRecord, CommitRecord, CompareEntry, CompareRef, CompareResult, DatabaseContext, DiffEntry, DiffRef, DiffResult, SmartDiffRef, SmartDiffResult, SmartDiffStats, DocumentBatchResponse, DocumentBatchResultRow, DocumentExportFormat, DocumentImportFormat, ExportDocumentResult, Flags, ImportDocumentOptions, ImportDocumentResult, JsonDocumentData, JsonDocumentBatchItem, IdentifierChildNode, ListIdentifierChildrenResult, ListIdentifiersResult, LockInfo, AcquireLockOptions, LockConflictBody, LockExpiredBody, LockUnknownBody, MergeConflict, MergeResult, OAuthProviderInfo, OAuthProvidersResponse, OwnedTenantInfo, ProjectInfo, PlatformRegistrationConfig, PlatformWorkspaceOrg, PlatformWorkspacesResponse, ProjectSearchSettings, ProjectSearchSettingsUpdate, ProjectDocConfResponse, AssetGcDryRunResult, AssetHeadResult, AssetListItem, AssetListResponse, AssetMagicLinkListResponse, AssetMagicLinkRecord, AssetMagicLinkResult, AssetShareListEntry, AssetShareListResponse, AssetShareRequest, AssetStorageImport, AssetStorageMount, AssetStorageTarget, AssetStorageTargetType, AssetUnshareRequest, AssetUploadResult, CreateAssetMagicLinkRequest, ListAssetsOptions, ProjectAssetStorageConfig, UploadAssetOptions, PlatformDefaultDocConfResponse, LogEntry, MetaValue, PlatformRegisterResult, PolicyUpdateResponse, PublishConflict, PublishResult, RebaseUserWorkspaceResult, PolicyConditions, PolicyIdentifierPattern, PolicyResources, PolicySubjectInput, PolicySubjects, RagQueryOptions, RagQueryResult, RagStreamEvent, RealtimeEvent, SandboxApiKeyMintResult, SandboxInfo, SandboxMember, SearchIndexingProgress, SecurityConfig, SecurityPolicy, StoredPolicyResponse, StoredTriggerResponse, SubscriptionOptions, TagRecord, TextSearchHit, TextSearchQuery, TextSearchResult, TriggerDefinition, TriggerEvent, TriggerEventsResponse, TxnOperation, TxnOperationResult, TxnPrecondition, TxnPreconditionResult, TxnRequest, TxnResponse, JwksKey, JwksResponse, VerifyAppUserTokenOptions, TokenPair, UserInfo, UserIsolationConfig, UserIsolationCreateShareParams, UserIsolationOptions, UserIsolationShareMode, UserIsolationShareResult, UserIsolationShareListEntry, UserIsolationShareListResponse, UserIsolationUnshareParams, ShareTarget, ShareDirection, AppUserGroup, AppUserGroupKind, CreateGroupParams, ListGroupsResponse, WorkspaceInfo, WriteDocumentOptions, XmlDocumentBatchItem, CreateSandboxOptions, CreateTestSessionOptions, TestSessionBootstrap, TestSessionBootstrapSummary, TestSessionInfo, XCiteDBClientOptions, XCiteDBErrorExtras, XCiteDBJwtClaims, UnqueryResult, UnqueryTemplate, XCiteQuery, } from './types';
|
|
5
5
|
export { XCiteDBError, XCiteDBForbiddenError, XCiteDBNotFoundError, XCiteDBAuthError, XCiteDBLockConflictError, } from './types';
|
package/dist/types.d.ts
CHANGED
|
@@ -278,14 +278,24 @@ export interface AssetShareRequest {
|
|
|
278
278
|
identifier?: string;
|
|
279
279
|
/** `xcitedb:asset:/…` or raw `/…` path; not prefixed by the client. */
|
|
280
280
|
source_uri?: string;
|
|
281
|
-
|
|
281
|
+
/** Legacy: prefer `target`. App user id, `"*"` (public), or `"#anonymous"`. */
|
|
282
|
+
target_user_id?: string;
|
|
283
|
+
/** Legacy: prefer `target`. */
|
|
284
|
+
target_group_id?: string;
|
|
285
|
+
/** Preferred share-target shape. */
|
|
286
|
+
target?: ShareTarget;
|
|
282
287
|
mode: UserIsolationShareMode;
|
|
283
288
|
}
|
|
284
289
|
/** Body for `DELETE /api/v1/security/user-isolation/asset-shares`. */
|
|
285
290
|
export interface AssetUnshareRequest {
|
|
286
291
|
identifier?: string;
|
|
287
292
|
source_uri?: string;
|
|
293
|
+
/** Legacy: prefer `target`. */
|
|
288
294
|
target_user_id?: string;
|
|
295
|
+
/** Legacy: prefer `target`. */
|
|
296
|
+
target_group_id?: string;
|
|
297
|
+
/** Preferred share-target shape. */
|
|
298
|
+
target?: ShareTarget;
|
|
289
299
|
sharer_user_id?: string;
|
|
290
300
|
}
|
|
291
301
|
export interface AssetShareListEntry {
|
|
@@ -652,11 +662,32 @@ export interface UserIsolationConfig {
|
|
|
652
662
|
}
|
|
653
663
|
/** `read` or `readwrite` for {@link XCiteDBClient.createUserIsolationShare}. */
|
|
654
664
|
export type UserIsolationShareMode = 'read' | 'readwrite';
|
|
665
|
+
/**
|
|
666
|
+
* Share target for {@link XCiteDBClient.createUserIsolationShare}, {@link XCiteDBClient.createAssetShare},
|
|
667
|
+
* and the corresponding revoke methods. Server reference: `parseShareTarget` in `SecurityController.cpp`.
|
|
668
|
+
*/
|
|
669
|
+
export type ShareTarget = {
|
|
670
|
+
type: 'user';
|
|
671
|
+
id: string;
|
|
672
|
+
} | {
|
|
673
|
+
type: 'group';
|
|
674
|
+
id: string;
|
|
675
|
+
} | {
|
|
676
|
+
type: 'public';
|
|
677
|
+
} | {
|
|
678
|
+
type: 'anonymous';
|
|
679
|
+
};
|
|
680
|
+
/** Direction filter for {@link XCiteDBClient.listUserIsolationShares} and {@link XCiteDBClient.listAssetShares}. */
|
|
681
|
+
export type ShareDirection = 'incoming' | 'outgoing' | 'public';
|
|
655
682
|
/** Body for `POST /api/v1/security/user-isolation/shares` (app user). */
|
|
656
683
|
export interface UserIsolationCreateShareParams {
|
|
657
684
|
identifier: string;
|
|
658
|
-
/**
|
|
659
|
-
target_user_id
|
|
685
|
+
/** Legacy: prefer `target`. App user id, `"*"` (public), or `"#anonymous"`. */
|
|
686
|
+
target_user_id?: string;
|
|
687
|
+
/** Legacy: prefer `target`. App user group id. */
|
|
688
|
+
target_group_id?: string;
|
|
689
|
+
/** Preferred share-target shape; supersedes the legacy fields. */
|
|
690
|
+
target?: ShareTarget;
|
|
660
691
|
mode: UserIsolationShareMode;
|
|
661
692
|
}
|
|
662
693
|
/** JSON body returned with HTTP 201 from create share. */
|
|
@@ -664,6 +695,56 @@ export interface UserIsolationShareResult {
|
|
|
664
695
|
alias: string;
|
|
665
696
|
mode: string;
|
|
666
697
|
}
|
|
698
|
+
/** Single entry in {@link UserIsolationShareListResponse.identifiers}. */
|
|
699
|
+
export interface UserIsolationShareListEntry {
|
|
700
|
+
identifier: string;
|
|
701
|
+
mode: UserIsolationShareMode;
|
|
702
|
+
}
|
|
703
|
+
/** Response from `GET /api/v1/security/user-isolation/shares?direction=…`. */
|
|
704
|
+
export interface UserIsolationShareListResponse {
|
|
705
|
+
direction: ShareDirection;
|
|
706
|
+
identifiers: UserIsolationShareListEntry[];
|
|
707
|
+
scope?: string;
|
|
708
|
+
/** Set for `direction: "outgoing"` — server does not enumerate outgoing shares. */
|
|
709
|
+
note?: string;
|
|
710
|
+
}
|
|
711
|
+
/** Body for `DELETE /api/v1/security/user-isolation/shares` (app user). */
|
|
712
|
+
export interface UserIsolationUnshareParams {
|
|
713
|
+
identifier: string;
|
|
714
|
+
/** Legacy: prefer `target`. */
|
|
715
|
+
target_user_id?: string;
|
|
716
|
+
/** Legacy: prefer `target`. */
|
|
717
|
+
target_group_id?: string;
|
|
718
|
+
/** Preferred share-target shape. */
|
|
719
|
+
target?: ShareTarget;
|
|
720
|
+
/** When the caller is the share recipient revoking incoming access; otherwise omit. */
|
|
721
|
+
sharer_user_id?: string;
|
|
722
|
+
}
|
|
723
|
+
/** App-user group kind. `team` is owned by the creating app user; `admin` is tenant-wide. */
|
|
724
|
+
export type AppUserGroupKind = 'team' | 'admin';
|
|
725
|
+
/** App-user group record returned by group endpoints (`AppUserGroupService::recordToPublicJson`). */
|
|
726
|
+
export interface AppUserGroup {
|
|
727
|
+
group_id: string;
|
|
728
|
+
name: string;
|
|
729
|
+
kind: AppUserGroupKind;
|
|
730
|
+
/** App user id of the owner. Empty for `kind: "admin"`. */
|
|
731
|
+
owner_id: string;
|
|
732
|
+
member_ids: string[];
|
|
733
|
+
/** Epoch seconds. */
|
|
734
|
+
created_at: number;
|
|
735
|
+
/** Epoch seconds. */
|
|
736
|
+
updated_at: number;
|
|
737
|
+
}
|
|
738
|
+
/** Body for `POST /api/v1/security/user-isolation/groups`. */
|
|
739
|
+
export interface CreateGroupParams {
|
|
740
|
+
name: string;
|
|
741
|
+
/** Defaults to `"team"`. `"admin"` requires a tenant-admin caller. */
|
|
742
|
+
kind?: AppUserGroupKind;
|
|
743
|
+
}
|
|
744
|
+
/** Response from `GET /api/v1/security/user-isolation/groups`. */
|
|
745
|
+
export interface ListGroupsResponse {
|
|
746
|
+
groups: AppUserGroup[];
|
|
747
|
+
}
|
|
667
748
|
export interface XCiteDBClientOptions {
|
|
668
749
|
baseUrl: string;
|
|
669
750
|
apiKey?: string;
|
|
@@ -261,3 +261,154 @@ function slugifyForAssert(name) {
|
|
|
261
261
|
.replace(/^-+|-+$/g, '')
|
|
262
262
|
.slice(0, 64);
|
|
263
263
|
}
|
|
264
|
+
wd('app-user groups + group-aware shares (wet)', () => {
|
|
265
|
+
(0, node_test_1.it)('groups lifecycle: owner creates, adds member, non-owner mutation rejected, owner deletes', async () => {
|
|
266
|
+
const e = wetEnv();
|
|
267
|
+
if (!e)
|
|
268
|
+
throw new Error('missing env');
|
|
269
|
+
const admin = adminClient(e);
|
|
270
|
+
const suffix = (0, node_crypto_1.randomUUID)().slice(0, 8);
|
|
271
|
+
const ownerEmail = `js_grp_o_${suffix}@apitest.invalid`;
|
|
272
|
+
const memberEmail = `js_grp_m_${suffix}@apitest.invalid`;
|
|
273
|
+
const password = `Js_${suffix}!aA1`;
|
|
274
|
+
let owner;
|
|
275
|
+
let member;
|
|
276
|
+
let groupId;
|
|
277
|
+
try {
|
|
278
|
+
await admin.setUserIsolationConfig({ enabled: true, namespace_pattern: '/users/${user.id}' });
|
|
279
|
+
owner = await admin.createAppUser(ownerEmail, password, undefined, [
|
|
280
|
+
client_js_1.XCiteDBClient.buildProjectGroup(e.tenantId, 'editor'),
|
|
281
|
+
]);
|
|
282
|
+
member = await admin.createAppUser(memberEmail, password, undefined, [
|
|
283
|
+
client_js_1.XCiteDBClient.buildProjectGroup(e.tenantId, 'editor'),
|
|
284
|
+
]);
|
|
285
|
+
const ownerClient = new client_js_1.XCiteDBClient({
|
|
286
|
+
baseUrl: e.baseUrl,
|
|
287
|
+
context: { branch: 'main', project_id: e.tenantId },
|
|
288
|
+
userIsolation: { enabled: true },
|
|
289
|
+
});
|
|
290
|
+
await ownerClient.loginAppUser(ownerEmail, password);
|
|
291
|
+
const created = await ownerClient.createGroup({ name: `g-${suffix}`, kind: 'team' });
|
|
292
|
+
groupId = created.group_id;
|
|
293
|
+
strict_1.default.equal(created.kind, 'team');
|
|
294
|
+
strict_1.default.equal(created.owner_id, owner.user_id);
|
|
295
|
+
const afterAdd = await ownerClient.addGroupMember(groupId, member.user_id);
|
|
296
|
+
strict_1.default.ok(afterAdd.member_ids.includes(member.user_id), `member_ids should include ${member.user_id}, got ${JSON.stringify(afterAdd.member_ids)}`);
|
|
297
|
+
const fetched = await ownerClient.getGroup(groupId);
|
|
298
|
+
strict_1.default.equal(fetched.name, `g-${suffix}`);
|
|
299
|
+
strict_1.default.deepEqual(fetched.member_ids.sort(), afterAdd.member_ids.sort());
|
|
300
|
+
const list = await ownerClient.listGroups();
|
|
301
|
+
strict_1.default.ok(list.groups.some((g) => g.group_id === groupId), 'listGroups missing created group');
|
|
302
|
+
// Non-owner cannot mutate.
|
|
303
|
+
const memberClient = new client_js_1.XCiteDBClient({
|
|
304
|
+
baseUrl: e.baseUrl,
|
|
305
|
+
context: { branch: 'main', project_id: e.tenantId },
|
|
306
|
+
userIsolation: { enabled: true },
|
|
307
|
+
});
|
|
308
|
+
await memberClient.loginAppUser(memberEmail, password);
|
|
309
|
+
await strict_1.default.rejects(() => memberClient.deleteGroup(groupId), (err) => {
|
|
310
|
+
const status = err.status;
|
|
311
|
+
return status === 403;
|
|
312
|
+
}, 'non-owner deleteGroup must be rejected with 403');
|
|
313
|
+
await ownerClient.removeGroupMember(groupId, member.user_id);
|
|
314
|
+
const afterRemove = await ownerClient.getGroup(groupId);
|
|
315
|
+
strict_1.default.ok(!afterRemove.member_ids.includes(member.user_id), 'member_ids should not include removed user');
|
|
316
|
+
await ownerClient.deleteGroup(groupId);
|
|
317
|
+
groupId = undefined;
|
|
318
|
+
await strict_1.default.rejects(() => ownerClient.getGroup(created.group_id), (err) => err.status === 404);
|
|
319
|
+
}
|
|
320
|
+
finally {
|
|
321
|
+
if (groupId && owner) {
|
|
322
|
+
const cleanupClient = new client_js_1.XCiteDBClient({
|
|
323
|
+
baseUrl: e.baseUrl,
|
|
324
|
+
context: { branch: 'main', project_id: e.tenantId },
|
|
325
|
+
userIsolation: { enabled: true },
|
|
326
|
+
});
|
|
327
|
+
await cleanupClient.loginAppUser(ownerEmail, password).catch(() => { });
|
|
328
|
+
await cleanupClient.deleteGroup(groupId).catch(() => { });
|
|
329
|
+
}
|
|
330
|
+
if (member)
|
|
331
|
+
await admin.deleteAppUser(member.user_id).catch(() => { });
|
|
332
|
+
if (owner)
|
|
333
|
+
await admin.deleteAppUser(owner.user_id).catch(() => { });
|
|
334
|
+
await admin.disableUserIsolation().catch(() => { });
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
(0, node_test_1.it)('group-aware share: owner shares to group, member reads via alias, revoke removes access', async () => {
|
|
338
|
+
const e = wetEnv();
|
|
339
|
+
if (!e)
|
|
340
|
+
throw new Error('missing env');
|
|
341
|
+
const admin = adminClient(e);
|
|
342
|
+
const suffix = (0, node_crypto_1.randomUUID)().slice(0, 8);
|
|
343
|
+
const ownerEmail = `js_gs_o_${suffix}@apitest.invalid`;
|
|
344
|
+
const memberEmail = `js_gs_m_${suffix}@apitest.invalid`;
|
|
345
|
+
const password = `Js_${suffix}!aA1`;
|
|
346
|
+
const slug = `js-gs-doc-${suffix}`;
|
|
347
|
+
let owner;
|
|
348
|
+
let member;
|
|
349
|
+
let groupId;
|
|
350
|
+
try {
|
|
351
|
+
await admin.setUserIsolationConfig({ enabled: true, namespace_pattern: '/users/${user.id}' });
|
|
352
|
+
owner = await admin.createAppUser(ownerEmail, password, undefined, [
|
|
353
|
+
client_js_1.XCiteDBClient.buildProjectGroup(e.tenantId, 'editor'),
|
|
354
|
+
]);
|
|
355
|
+
member = await admin.createAppUser(memberEmail, password, undefined, [
|
|
356
|
+
client_js_1.XCiteDBClient.buildProjectGroup(e.tenantId, 'editor'),
|
|
357
|
+
]);
|
|
358
|
+
const ownerClient = new client_js_1.XCiteDBClient({
|
|
359
|
+
baseUrl: e.baseUrl,
|
|
360
|
+
context: { branch: 'main', project_id: e.tenantId },
|
|
361
|
+
userIsolation: { enabled: true },
|
|
362
|
+
});
|
|
363
|
+
await ownerClient.loginAppUser(ownerEmail, password);
|
|
364
|
+
const grp = await ownerClient.createGroup({ name: `gs-${suffix}`, kind: 'team' });
|
|
365
|
+
groupId = grp.group_id;
|
|
366
|
+
await ownerClient.addGroupMember(groupId, member.user_id);
|
|
367
|
+
await ownerClient.writeJsonDocument(`/${slug}`, { _xcite_json_doc: true, who: 'owner', v: 1 });
|
|
368
|
+
const share = await ownerClient.createUserIsolationShare({
|
|
369
|
+
identifier: `/${slug}`,
|
|
370
|
+
target: { type: 'group', id: groupId },
|
|
371
|
+
mode: 'read',
|
|
372
|
+
});
|
|
373
|
+
strict_1.default.ok(share.alias && typeof share.alias === 'string', 'share.alias missing');
|
|
374
|
+
const memberClient = new client_js_1.XCiteDBClient({
|
|
375
|
+
baseUrl: e.baseUrl,
|
|
376
|
+
context: { branch: 'main', project_id: e.tenantId },
|
|
377
|
+
userIsolation: { enabled: true },
|
|
378
|
+
});
|
|
379
|
+
await memberClient.loginAppUser(memberEmail, password);
|
|
380
|
+
const incoming = await memberClient.listUserIsolationShares({ direction: 'incoming' });
|
|
381
|
+
strict_1.default.ok(incoming.identifiers.some((row) => row.identifier === share.alias), `incoming list should include alias ${share.alias}; got ${JSON.stringify(incoming.identifiers)}`);
|
|
382
|
+
const doc = await memberClient.readJsonDocument(share.alias);
|
|
383
|
+
strict_1.default.equal(doc.who, 'owner');
|
|
384
|
+
strict_1.default.equal(doc.v, 1);
|
|
385
|
+
await ownerClient.removeUserIsolationShare({
|
|
386
|
+
identifier: `/${slug}`,
|
|
387
|
+
target: { type: 'group', id: groupId },
|
|
388
|
+
});
|
|
389
|
+
await strict_1.default.rejects(() => memberClient.readJsonDocument(share.alias), (err) => {
|
|
390
|
+
const status = err.status;
|
|
391
|
+
return status === 403 || status === 404;
|
|
392
|
+
}, 'after revoke, member read should be 403/404');
|
|
393
|
+
}
|
|
394
|
+
finally {
|
|
395
|
+
if (owner) {
|
|
396
|
+
await admin.deleteJsonDocument(`/users/${owner.user_id}/${slug}`).catch(() => { });
|
|
397
|
+
}
|
|
398
|
+
if (groupId && owner) {
|
|
399
|
+
const cleanupClient = new client_js_1.XCiteDBClient({
|
|
400
|
+
baseUrl: e.baseUrl,
|
|
401
|
+
context: { branch: 'main', project_id: e.tenantId },
|
|
402
|
+
userIsolation: { enabled: true },
|
|
403
|
+
});
|
|
404
|
+
await cleanupClient.loginAppUser(ownerEmail, password).catch(() => { });
|
|
405
|
+
await cleanupClient.deleteGroup(groupId).catch(() => { });
|
|
406
|
+
}
|
|
407
|
+
if (member)
|
|
408
|
+
await admin.deleteAppUser(member.user_id).catch(() => { });
|
|
409
|
+
if (owner)
|
|
410
|
+
await admin.deleteAppUser(owner.user_id).catch(() => { });
|
|
411
|
+
await admin.disableUserIsolation().catch(() => { });
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
});
|