@rixl/sdk 0.19.0 → 0.21.0
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/index.d.ts +99 -107
- package/dist/index.js +137 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3336,6 +3336,77 @@ const user = shared("user", () => {
|
|
|
3336
3336
|
return store;
|
|
3337
3337
|
});
|
|
3338
3338
|
|
|
3339
|
+
//#endregion
|
|
3340
|
+
//#region src/auth/permissions/matcher.ts
|
|
3341
|
+
/**
|
|
3342
|
+
* Permission strings follow a `service:resource:action` grammar, e.g.
|
|
3343
|
+
* `media:videos:read`. Only the trailing action segment carries the verb, so
|
|
3344
|
+
* matching splits on the *last* separator — a two- or four-segment grammar
|
|
3345
|
+
* still resolves correctly if the registry turns out to differ.
|
|
3346
|
+
*/
|
|
3347
|
+
const READ_VERBS = ["read"];
|
|
3348
|
+
const WRITE_VERBS = ["write"];
|
|
3349
|
+
/**
|
|
3350
|
+
* Verbs that satisfy a required verb on the same resource.
|
|
3351
|
+
*
|
|
3352
|
+
* The registry grants only `read` and `write`, and write implies read: being
|
|
3353
|
+
* able to change a video implies being able to see it. An unlisted verb is
|
|
3354
|
+
* satisfied only by an exact match, so a verb the registry adds later fails
|
|
3355
|
+
* closed until it is added here.
|
|
3356
|
+
*/
|
|
3357
|
+
const SUPERSETS = { read: ["write"] };
|
|
3358
|
+
/**
|
|
3359
|
+
* Whether the held permission set satisfies `required`.
|
|
3360
|
+
*
|
|
3361
|
+
* A permission with no verb separator is matched exactly — an unrecognized
|
|
3362
|
+
* shape must never widen access.
|
|
3363
|
+
*/
|
|
3364
|
+
const matches = (held, required) => {
|
|
3365
|
+
if (held.has(required)) return true;
|
|
3366
|
+
const separator = required.lastIndexOf(":");
|
|
3367
|
+
if (separator < 0) return false;
|
|
3368
|
+
const resource = required.slice(0, separator + 1);
|
|
3369
|
+
const verb = required.slice(separator + 1);
|
|
3370
|
+
return (SUPERSETS[verb] ?? []).some((superset) => held.has(resource + superset));
|
|
3371
|
+
};
|
|
3372
|
+
|
|
3373
|
+
//#endregion
|
|
3374
|
+
//#region src/auth/permissionStore.ts
|
|
3375
|
+
/**
|
|
3376
|
+
* The current identity's effective permissions in their active organization.
|
|
3377
|
+
*
|
|
3378
|
+
* Populated by `resolvePermissions`. Empty until then, so every check denies —
|
|
3379
|
+
* an unresolved set must never read as permissive.
|
|
3380
|
+
*
|
|
3381
|
+
* Resolution lives in `./permissions/resolve` rather than here: it needs
|
|
3382
|
+
* `getUserInfo`, whose module graph reaches back into `authStore`, and keeping
|
|
3383
|
+
* this module free of that import avoids an initialization cycle.
|
|
3384
|
+
*/
|
|
3385
|
+
const permissions = shared("permissions", () => atom(/* @__PURE__ */ new Set()));
|
|
3386
|
+
/**
|
|
3387
|
+
* Whether the set has been resolved at least once for the active organization.
|
|
3388
|
+
*
|
|
3389
|
+
* An empty set is ambiguous on its own: it means both "not loaded yet" and
|
|
3390
|
+
* "this user holds nothing". Hiding a control cannot tell them apart and should
|
|
3391
|
+
* not try — denying while unresolved is the safe default. A redirect must:
|
|
3392
|
+
* bouncing someone out of a page before their permissions arrive would lock
|
|
3393
|
+
* them out of the app.
|
|
3394
|
+
*/
|
|
3395
|
+
const permissionsResolved = shared("permissionsResolved", () => atom(false));
|
|
3396
|
+
/** Whether the held permissions satisfy `required`, honoring the verb hierarchy. */
|
|
3397
|
+
const hasPermission = (required) => matches(permissions.get(), required);
|
|
3398
|
+
/**
|
|
3399
|
+
* Empties the permission set and marks it unresolved.
|
|
3400
|
+
*
|
|
3401
|
+
* Called on sign-out so no grant outlives the session, and before an
|
|
3402
|
+
* organization switch so the previous organization's grants cannot be read as
|
|
3403
|
+
* the new one's while the fresh answer is in flight.
|
|
3404
|
+
*/
|
|
3405
|
+
const clearPermissions = () => {
|
|
3406
|
+
permissions.set(/* @__PURE__ */ new Set());
|
|
3407
|
+
permissionsResolved.set(false);
|
|
3408
|
+
};
|
|
3409
|
+
|
|
3339
3410
|
//#endregion
|
|
3340
3411
|
//#region src/auth/utils/jwt.ts
|
|
3341
3412
|
/**
|
|
@@ -3469,6 +3540,7 @@ const removeTokens = () => {
|
|
|
3469
3540
|
expireAt.set(0);
|
|
3470
3541
|
isLogged.set(false);
|
|
3471
3542
|
user.set(void 0);
|
|
3543
|
+
clearPermissions();
|
|
3472
3544
|
limitedAccessToken.set(null);
|
|
3473
3545
|
requiresAction.set(null);
|
|
3474
3546
|
authError.set(null);
|
|
@@ -4192,7 +4264,9 @@ const getUserInfo = async (userId) => {
|
|
|
4192
4264
|
image_url: data.image_url ?? "",
|
|
4193
4265
|
language_code: data.language_code ?? "",
|
|
4194
4266
|
country_code: data.country_code ?? "",
|
|
4195
|
-
active_org_id: data.active_org_id ?? ""
|
|
4267
|
+
active_org_id: data.active_org_id ?? "",
|
|
4268
|
+
policies: data.policies ?? [],
|
|
4269
|
+
permissions: data.permissions ?? []
|
|
4196
4270
|
};
|
|
4197
4271
|
}, { [HTTP_STATUS.UNAUTHORIZED]: () => /* @__PURE__ */ new Error("Token is missing or invalid; user is not authenticated.") });
|
|
4198
4272
|
};
|
|
@@ -4887,5 +4961,66 @@ const verifyPasskeyForLogin = async (session_id, credential) => {
|
|
|
4887
4961
|
};
|
|
4888
4962
|
|
|
4889
4963
|
//#endregion
|
|
4890
|
-
|
|
4964
|
+
//#region src/auth/permissions/resolve.ts
|
|
4965
|
+
/**
|
|
4966
|
+
* Incremented whenever the identity's scope changes — an organization switch,
|
|
4967
|
+
* a sign-out. A response that started before the change belongs to the previous
|
|
4968
|
+
* scope and must not be written into the store.
|
|
4969
|
+
*/
|
|
4970
|
+
let epoch = 0;
|
|
4971
|
+
/** An `ensurePermissions` call already in flight, so concurrent guards share one request. */
|
|
4972
|
+
let pending = null;
|
|
4973
|
+
/**
|
|
4974
|
+
* Invalidates any resolution already in flight.
|
|
4975
|
+
*
|
|
4976
|
+
* Call before switching the active organization: without it, a request issued
|
|
4977
|
+
* for the previous organization can land afterwards and repopulate the store
|
|
4978
|
+
* with permissions the user no longer holds.
|
|
4979
|
+
*/
|
|
4980
|
+
const invalidatePermissions = () => {
|
|
4981
|
+
epoch += 1;
|
|
4982
|
+
pending = null;
|
|
4983
|
+
};
|
|
4984
|
+
/**
|
|
4985
|
+
* Loads the effective permissions for the signed-in user.
|
|
4986
|
+
*
|
|
4987
|
+
* `GET /auth/v1/userinfo` is the authoritative source: it returns the
|
|
4988
|
+
* permissions and the policies granting them, scoped to the user's active
|
|
4989
|
+
* organization. Call this after sign-in and again whenever the active
|
|
4990
|
+
* organization changes, since the response is scoped to it.
|
|
4991
|
+
*
|
|
4992
|
+
* Always issues a fresh request — it is the caller's way of saying the answer
|
|
4993
|
+
* may have changed. On failure the error propagates and the held set is left
|
|
4994
|
+
* untouched, so a transient network error does not revoke the interface; a
|
|
4995
|
+
* caller changing scope should clear the set first so a failure denies rather
|
|
4996
|
+
* than keeps stale grants.
|
|
4997
|
+
*/
|
|
4998
|
+
const resolvePermissions = async () => {
|
|
4999
|
+
const started = epoch;
|
|
5000
|
+
const info = await getUserInfo();
|
|
5001
|
+
if (started !== epoch) return;
|
|
5002
|
+
permissions.set(new Set(info.permissions));
|
|
5003
|
+
permissionsResolved.set(true);
|
|
5004
|
+
};
|
|
5005
|
+
/**
|
|
5006
|
+
* Resolves permissions unless they already have been for the active
|
|
5007
|
+
* organization.
|
|
5008
|
+
*
|
|
5009
|
+
* Route guards need an answer before deciding whether to redirect, but must not
|
|
5010
|
+
* pay for a request on every navigation. Use `resolvePermissions` when the
|
|
5011
|
+
* answer must be refreshed — after an organization switch — and this when any
|
|
5012
|
+
* current answer will do.
|
|
5013
|
+
*/
|
|
5014
|
+
const ensurePermissions = async () => {
|
|
5015
|
+
if (permissionsResolved.get()) return;
|
|
5016
|
+
if (pending) return pending;
|
|
5017
|
+
const started = epoch;
|
|
5018
|
+
pending = resolvePermissions().finally(() => {
|
|
5019
|
+
if (started === epoch) pending = null;
|
|
5020
|
+
});
|
|
5021
|
+
return pending;
|
|
5022
|
+
};
|
|
5023
|
+
|
|
5024
|
+
//#endregion
|
|
5025
|
+
export { DomainStatus, MembershipRole, MembershipState, PasskeyUnavailableError, READ_VERBS, WRITE_VERBS, addEmail, analyticsV1DashboardServiceBatchQueryChart, analyticsV1DashboardServiceCreateDashboard, analyticsV1DashboardServiceCreateWidget, analyticsV1DashboardServiceDeleteDashboard, analyticsV1DashboardServiceDeleteWidget, analyticsV1DashboardServiceExportDashboard, analyticsV1DashboardServiceGetDashboard, analyticsV1DashboardServiceGetDashboardStats, analyticsV1DashboardServiceGetFilterOptions, analyticsV1DashboardServiceGetScopeTree, analyticsV1DashboardServiceListDashboards, analyticsV1DashboardServiceListDatasets, analyticsV1DashboardServiceQueryChart, analyticsV1DashboardServiceSetDefaultDashboard, analyticsV1DashboardServiceUpdateDashboard, analyticsV1DashboardServiceUpdateDashboardLayout, analyticsV1DashboardServiceUpdateWidget, analyticsV1EventsServiceTrackEvents, analyticsV1FeedsServiceGetFeedStats, analyticsV1FeedsServiceGetTopFeeds, analyticsV1FunnelsServiceGetFunnelAnalytics, analyticsV1FunnelsServiceGetRetentionAnalytics, analyticsV1HeatmapServiceGetHotSegments, analyticsV1HeatmapServiceGetVideoHeatmap, analyticsV1ImagesServiceGetImageStats, analyticsV1ImagesServiceGetTopImages, analyticsV1PostsServiceGetPostStats, analyticsV1PostsServiceGetTopPosts, analyticsV1RealtimeServiceGetRealtimeStats, analyticsV1VideosServiceGetTopVideos, analyticsV1VideosServiceGetVideoStats, apikeysV1ApiKeyServiceCreateApiKey, apikeysV1ApiKeyServiceDeleteApiKey, apikeysV1ApiKeyServiceListApiKeys, apikeysV1ApiKeyServiceRotateApiKey, apikeysV1ApiKeyServiceUpdateApiKey, authError, authV1BlogServiceGetBlogSubscription, authV1BlogServiceSendBlogBroadcast, authV1BlogServiceSubscribeBlog, authV1BlogServiceUnsubscribeBlog, authV1BlogServiceUnsubscribeBlogByEmail, authV1DomainServiceCheckDomainVerification, authV1DomainServiceCreateDomainVerification, authV1DomainServiceGetDomainAutoJoin, authV1DomainServiceGetDomainStatus, authV1DomainServiceRemoveDomain, authV1DomainServiceSetDomainAutoJoin, authV1EmailServiceAddEmail, authV1EmailServiceGetUserEmailStatus, authV1EmailServiceInitiateEmailChange, authV1EmailServiceLogin, authV1EmailServiceRegister, authV1EmailServiceResendVerification, authV1EmailServiceResetPassword, authV1EmailServiceSendPasswordReset, authV1EmailServiceVerifyEmail, authV1MembershipServiceAcceptInvitation, authV1MembershipServiceCancelInvitation, authV1MembershipServiceCheckMembership, authV1MembershipServiceDeclineInvitation, authV1MembershipServiceGetInternalMembershipInfo, authV1MembershipServiceInviteMember, authV1MembershipServiceLeaveOrganization, authV1MembershipServiceListMembershipApplications, authV1MembershipServiceListMemberships, authV1MembershipServiceListOrganizationMembers, authV1MembershipServiceReactivateMember, authV1MembershipServiceRemoveMember, authV1MembershipServiceResendInvitation, authV1MembershipServiceSuspendMember, authV1MembershipServiceUpdateActiveMembership, authV1MembershipServiceUpdateMemberRole, authV1MembershipServiceUpdateMembershipState, authV1MembershipServiceUpdateOrgName, authV1MembershipServiceUpdateOrgUsername, authV1OtpServiceDeleteOtp, authV1OtpServiceGetOtpStatus, authV1OtpServiceRegenerateBackupCodes, authV1OtpServiceSetupOtp, authV1OtpServiceVerifyOtp, authV1OtpServiceVerifyTotpForLogin, authV1PasskeyServiceDeletePasskey, authV1PasskeyServiceListPasskeys, authV1PasskeyServicePasskeyLoginBegin, authV1PasskeyServicePasskeyLoginFinish, authV1PasskeyServicePasskeyRegisterBegin, authV1PasskeyServicePasskeyRegisterFinish, authV1PasskeyServiceRenamePasskey, authV1PasskeyServiceVerifyPasskeyForLogin, authV1PolicyServiceAttachPolicy, authV1PolicyServiceCreatePolicy, authV1PolicyServiceDeletePolicy, authV1PolicyServiceDetachPolicy, authV1PolicyServiceGetPolicy, authV1PolicyServiceListPermissionRegistry, authV1PolicyServiceListPolicies, authV1PolicyServiceListPolicyAttachments, authV1PolicyServiceListUserPolicies, authV1PolicyServiceUpdatePolicy, authV1ProvidersServiceConnectProvider, authV1ProvidersServiceDisconnectProvider, authV1ProvidersServiceListProviders, authV1TokenServiceLogout, authV1TokenServiceRefreshToken, authV1UserServiceCreateAvatarUpload, authV1UserServiceGetUser, authV1UserServiceGetUserInfo, authV1UserServiceUpdateName, authV1UserServiceUpdateUserAvatar, authV1UserServiceUpdateUsername, beginPasskeyLogin, beginPasskeyRegistration, billingV1InvoiceServiceListInvoices, billingV1InvoiceServiceUpdateInvoiceStatus, billingV1PaymentServiceCalculateGenericTax, billingV1PaymentServiceCalculateTax, billingV1PaymentServiceCreateCheckoutSession, billingV1PaymentServiceCreateSetupIntent, billingV1PaymentServiceDeletePaymentMethod, billingV1PaymentServiceGetBillingAddress, billingV1PaymentServiceGetPaymentMethodFromPaymentIntent, billingV1PaymentServiceGetPaymentMethodFromSetupIntent, billingV1PaymentServiceListPaymentMethods, billingV1PaymentServiceUpgradeSubscription, billingV1PaymentServiceUpsertBillingAddress, billingV1PaymentServiceUpsertPaymentMethod, billingV1PlanServiceGetPlan, billingV1PlanServiceListPlans, billingV1SalesServiceContactSales, billingV1SubscriptionServiceCancelSubscription, billingV1SubscriptionServiceCreateSubscription, billingV1SubscriptionServiceGetSubscription, billingV1SubscriptionServiceGetSubscriptionHistory, billingV1SubscriptionServiceReactivateSubscription, billingV1UsageServiceGetBandwidthUsage, billingV1UsageServiceGetBandwidthUsageHistory, billingV1UsageServiceGetStorageUsage, billingV1UsageServiceGetStorageUsageHistory, billingV1UsageServiceRefreshBandwidthUsage, billingV1UsageServiceRefreshStorageUsage, checkDomainVerification, clearAuthError, clearLimitedAccessState, clearPermissions, client, clientauthV1ClientCredentialServiceCreateClientCredential, clientauthV1ClientCredentialServiceListClientCredentials, clientauthV1ClientCredentialServiceMintClientToken, clientauthV1ClientCredentialServiceRevokeClientCredential, confirmPasswordReset, connect, connectSocial, createClient, decodeRequestOptions, deleteMember, deletePasskey, deleteUserOTP, disconnectSocial, ensurePermissions, feedsV1FeedServiceCreateFeed, feedsV1FeedServiceDeleteFeed, feedsV1FeedServiceGetFeed, feedsV1FeedServiceListFeeds, feedsV1FeedServiceUpdateFeed, finishPasskeyLogin, finishPasskeyRegistration, getBlogSubscriptionStatus, getDomainStatus, getEmailVerificationStatus, getOTPStatus, getToken, getUserInfo, hasPermission, imagesV1ImageConversionServiceMarkImageFailed, imagesV1ImageConversionServiceMarkImageProcessed, imagesV1ImageConversionServiceTakeUnprocessedImage, imagesV1ImageServiceCreateImageUpload, imagesV1ImageServiceDeleteImage, imagesV1ImageServiceGetImage, imagesV1ImageServiceListImages, imagesV1ImageServiceUpdateImageVisibility, initClient, initiateDomainVerification, initiateEmailChange, invalidatePermissions, inviteMember, isLogged, leaveOrganization, limitedAccessToken, listActiveMemberships, listOrganizationMembers, listPasskeys, listPendingMemberships, listSocials, login, loginWithEmail, logout, matches as matchesPermission, permissions, permissionsResolved, platformauthV1PlatformAuthServiceExchangeApiKey, platformauthV1PlatformAuthServiceRefreshPlatformToken, postsV1PostServiceCreatePost, postsV1PostServiceCreatePostUpload, postsV1PostServiceDeletePost, postsV1PostServiceDeletePost2, postsV1PostServiceGetPost, postsV1PostServiceGetPost2, postsV1PostServiceGetPost3, postsV1PostServiceListPosts, postsV1PostServiceListPosts2, postsV1PostServiceListPosts3, postsV1PostServiceListPosts4, projectV1ProjectServiceCreateProject, projectV1ProjectServiceDeleteProject, projectV1ProjectServiceGetProject, projectV1ProjectServiceListProjects, projectV1ProjectServiceMoveProject, projectV1ProjectServiceRemoveCustomDomain, projectV1ProjectServiceSetCustomDomain, projectV1ProjectServiceUpdateProjectName, projectV1ProjectServiceUpdateVideoQuality, publicRespondToInvitation, regenerateBackupCodes, registerWithEmail, removeDomain, renamePasskey, requiresAction, resendEmailVerificationCode, resendMemberInvite, resolvePermissions, respondToInvitation, sendPasswordResetEmail, setLimitedAccessState, setupUserOTP, subscribeToBlog, supportV1SupportChatServiceListChatMessages, supportV1SupportChatServiceSendChatMessage, supportV1SupportTicketServiceAddTicketMessage, supportV1SupportTicketServiceCloseTicket, supportV1SupportTicketServiceCreateTicket, supportV1SupportTicketServiceGetTicket, supportV1SupportTicketServiceListCategories, supportV1SupportTicketServiceListTickets, supportV1SupportTicketServiceListTopics, supportV1SupportTicketServiceListTopics2, unsubscribeFromBlog, updateActiveMembership, updateAutoJoin, updateFullName, updateMemberRole, updateOrgName, updateOrgUsername, updateUsername, user, verifyEmailWithCode, verifyPasskeyForLogin, verifyTOTPForLogin, verifyUserOTP, videosV1AudioTrackServiceCreateAudioTrackUpload, videosV1AudioTrackServiceDeleteAllAudioTracks, videosV1AudioTrackServiceDeleteAudioTrack, videosV1AudioTrackServiceDeleteAudioTracksByLanguage, videosV1AudioTrackServiceListAudioTracks, videosV1ChapterServiceDeleteVideoChapter, videosV1ChapterServiceGetVideoChapters, videosV1ChapterServiceUpdateVideoChapters, videosV1LanguageServiceListLanguages, videosV1SubtitleServiceCreateSubtitleUpload, videosV1SubtitleServiceDeleteAllSubtitles, videosV1SubtitleServiceDeleteSubtitle, videosV1SubtitleServiceDeleteSubtitlesByLanguage, videosV1SubtitleServiceListSubtitles, videosV1VideoConversionServiceMarkVideoFailed, videosV1VideoConversionServiceMarkVideoProcessed, videosV1VideoServiceCreateVideoUpload, videosV1VideoServiceDeleteVideo, videosV1VideoServiceGetVideo, videosV1VideoServiceListVideos, videosV1VideoServiceUpdateVideoVisibility };
|
|
4891
5026
|
//# sourceMappingURL=index.js.map
|