@canopy-io/node 0.1.1 → 0.3.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/README.md +38 -1
- package/dist/index.cjs +190 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2738 -291
- package/dist/index.d.ts +2738 -291
- package/dist/index.js +189 -4
- package/dist/index.js.map +1 -1
- package/package.json +9 -4
package/dist/index.js
CHANGED
|
@@ -617,6 +617,162 @@ function withConcurrency(options = {}) {
|
|
|
617
617
|
return { headers: { "If-Match": options.ifMatch } };
|
|
618
618
|
}
|
|
619
619
|
|
|
620
|
+
// src/resources/organizations.ts
|
|
621
|
+
var Organizations = class {
|
|
622
|
+
constructor(client) {
|
|
623
|
+
this.client = client;
|
|
624
|
+
}
|
|
625
|
+
client;
|
|
626
|
+
list(query = {}) {
|
|
627
|
+
return paginate(
|
|
628
|
+
(params) => this.client.request("GET", "/api/v1/organizations", {
|
|
629
|
+
query: params
|
|
630
|
+
}),
|
|
631
|
+
{ ...query }
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
get(id) {
|
|
635
|
+
return this.client.request("GET", `/api/v1/organizations/${enc(id)}`);
|
|
636
|
+
}
|
|
637
|
+
create(input) {
|
|
638
|
+
return this.client.request("POST", "/api/v1/organizations", {
|
|
639
|
+
body: input
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Pass `ifMatch` with the organization's current `version` to make a
|
|
644
|
+
* read-modify-write safe — a concurrent edit answers 409 instead of being
|
|
645
|
+
* silently overwritten.
|
|
646
|
+
*/
|
|
647
|
+
update(id, input, options = {}) {
|
|
648
|
+
return this.client.request("PATCH", `/api/v1/organizations/${enc(id)}`, {
|
|
649
|
+
body: input,
|
|
650
|
+
...withConcurrency(options)
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Removes the organization with its memberships, pending invitations,
|
|
655
|
+
* policy, connection bindings, and the tree beneath it. Member identities
|
|
656
|
+
* survive.
|
|
657
|
+
*/
|
|
658
|
+
delete(id, options = {}) {
|
|
659
|
+
return this.client.request(
|
|
660
|
+
"DELETE",
|
|
661
|
+
`/api/v1/organizations/${enc(id)}`,
|
|
662
|
+
withConcurrency(options)
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
/** Empties the container: every organization goes, the step before switching it off. */
|
|
666
|
+
deleteAll() {
|
|
667
|
+
return this.client.request("DELETE", "/api/v1/organizations");
|
|
668
|
+
}
|
|
669
|
+
// ── Members: one role per member, held inside the organization only ──
|
|
670
|
+
listMembers(id, query = {}) {
|
|
671
|
+
return paginate(
|
|
672
|
+
(params) => this.client.request("GET", `/api/v1/organizations/${enc(id)}/members`, {
|
|
673
|
+
query: params
|
|
674
|
+
}),
|
|
675
|
+
{ ...query }
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
addMember(id, input) {
|
|
679
|
+
return this.client.request(
|
|
680
|
+
"POST",
|
|
681
|
+
`/api/v1/organizations/${enc(id)}/members`,
|
|
682
|
+
{ body: input }
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
changeMemberRole(id, identityId, input) {
|
|
686
|
+
return this.client.request(
|
|
687
|
+
"PATCH",
|
|
688
|
+
`/api/v1/organizations/${enc(id)}/members/${enc(identityId)}`,
|
|
689
|
+
{ body: input }
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
/** Revokes that organization's one role; the identity and its other memberships are untouched. */
|
|
693
|
+
removeMember(id, identityId) {
|
|
694
|
+
return this.client.request(
|
|
695
|
+
"DELETE",
|
|
696
|
+
`/api/v1/organizations/${enc(id)}/members/${enc(identityId)}`
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
// ── Invitations: pending membership, carrying the role the recipient will hold ──
|
|
700
|
+
listInvites(id, query = {}) {
|
|
701
|
+
return paginate(
|
|
702
|
+
(params) => this.client.request("GET", `/api/v1/organizations/${enc(id)}/invites`, {
|
|
703
|
+
query: params
|
|
704
|
+
}),
|
|
705
|
+
{ ...query }
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
createInvite(id, input) {
|
|
709
|
+
return this.client.request(
|
|
710
|
+
"POST",
|
|
711
|
+
`/api/v1/organizations/${enc(id)}/invites`,
|
|
712
|
+
{ body: input }
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
revokeInvite(id, inviteId) {
|
|
716
|
+
return this.client.request(
|
|
717
|
+
"DELETE",
|
|
718
|
+
`/api/v1/organizations/${enc(id)}/invites/${enc(inviteId)}`
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
// ── Policy: the organization's tightening of the Environment's sign-in rules ──
|
|
722
|
+
/**
|
|
723
|
+
* The organization's own values (null inherits), the Environment baseline
|
|
724
|
+
* they tighten from, and the effective policy its members sign in under.
|
|
725
|
+
*/
|
|
726
|
+
getPolicy(id) {
|
|
727
|
+
return this.client.request(
|
|
728
|
+
"GET",
|
|
729
|
+
`/api/v1/organizations/${enc(id)}/policy`
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Can only tighten the Environment: a value that would loosen it answers
|
|
734
|
+
* 400 `organization.policy_loosens`. Pass `ifMatch` with the policy's
|
|
735
|
+
* `version` (0 until the organization sets one) for a safe
|
|
736
|
+
* read-modify-write.
|
|
737
|
+
*/
|
|
738
|
+
updatePolicy(id, input, options = {}) {
|
|
739
|
+
return this.client.request(
|
|
740
|
+
"PATCH",
|
|
741
|
+
`/api/v1/organizations/${enc(id)}/policy`,
|
|
742
|
+
{ body: input, ...withConcurrency(options) }
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
// ── SSO: the organization's own identity provider ──
|
|
746
|
+
listSsoConnections(id) {
|
|
747
|
+
return this.client.request(
|
|
748
|
+
"GET",
|
|
749
|
+
`/api/v1/organizations/${enc(id)}/sso-connections`
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Sign-ins through the connection then land in this organization, joining
|
|
754
|
+
* as a member with `default_role_id`. The connection must already be bound
|
|
755
|
+
* to the organization's Environment, and a connection binds to one
|
|
756
|
+
* organization per Environment.
|
|
757
|
+
*/
|
|
758
|
+
bindSsoConnection(id, input) {
|
|
759
|
+
return this.client.request(
|
|
760
|
+
"POST",
|
|
761
|
+
`/api/v1/organizations/${enc(id)}/sso-connections`,
|
|
762
|
+
{ body: input }
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
unbindSsoConnection(id, connectionId) {
|
|
766
|
+
return this.client.request(
|
|
767
|
+
"DELETE",
|
|
768
|
+
`/api/v1/organizations/${enc(id)}/sso-connections/${enc(connectionId)}`
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
function enc(segment) {
|
|
773
|
+
return encodeURIComponent(segment);
|
|
774
|
+
}
|
|
775
|
+
|
|
620
776
|
// src/resources/permissions.ts
|
|
621
777
|
var Permissions = class {
|
|
622
778
|
constructor(client) {
|
|
@@ -778,12 +934,14 @@ var Canopy = class {
|
|
|
778
934
|
identities;
|
|
779
935
|
roles;
|
|
780
936
|
assignments;
|
|
937
|
+
organizations;
|
|
781
938
|
constructor(options) {
|
|
782
939
|
this.client = new CanopyClient(options);
|
|
783
940
|
this.permissions = new Permissions(this.client);
|
|
784
941
|
this.identities = new Identities(this.client);
|
|
785
942
|
this.roles = new Roles(this.client);
|
|
786
943
|
this.assignments = new Assignments(this.client);
|
|
944
|
+
this.organizations = new Organizations(this.client);
|
|
787
945
|
}
|
|
788
946
|
};
|
|
789
947
|
|
|
@@ -872,10 +1030,30 @@ var LocalAuthorizer = class {
|
|
|
872
1030
|
return { ...this.stats };
|
|
873
1031
|
}
|
|
874
1032
|
/**
|
|
875
|
-
* Drop
|
|
876
|
-
*
|
|
1033
|
+
* Drop what is held so the next evaluate refetches.
|
|
1034
|
+
*
|
|
1035
|
+
* With an `identityId`, only that identity's grants are dropped — the
|
|
1036
|
+
* cached hierarchy and every other identity's entries stay warm. This is
|
|
1037
|
+
* the shape an assignment webhook wants: the event names the identity
|
|
1038
|
+
* whose authority moved, and nothing else needs to pay a refetch for it.
|
|
1039
|
+
*
|
|
1040
|
+
* With no argument, everything goes: grants and the hierarchy tree. Not
|
|
1041
|
+
* needed in normal operation, where entries expire on their own; useful in
|
|
1042
|
+
* tests and after a change whose reach you cannot name (a role's
|
|
1043
|
+
* permissions edited, a node moved).
|
|
1044
|
+
*
|
|
1045
|
+
* Multi-instance honesty: an invalidation reaches THIS process only. A
|
|
1046
|
+
* webhook lands on one instance behind a load balancer; the others serve
|
|
1047
|
+
* their cached grants until their own TTL expires. Unless the app fans the
|
|
1048
|
+
* event out over its own pub/sub, the fleet-wide revocation guarantee is
|
|
1049
|
+
* the TTL, and webhook-driven invalidation is a latency optimization on
|
|
1050
|
+
* top of it — size the TTL to the revocation latency you can promise.
|
|
877
1051
|
*/
|
|
878
|
-
invalidate() {
|
|
1052
|
+
invalidate(identityId) {
|
|
1053
|
+
if (identityId !== void 0) {
|
|
1054
|
+
this.grants.delete(identityId);
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
879
1057
|
this.grants.clear();
|
|
880
1058
|
this.tree = void 0;
|
|
881
1059
|
}
|
|
@@ -988,6 +1166,13 @@ var DEFAULT_JWKS_MIN_REFETCH_INTERVAL_MS = 30 * 1e3;
|
|
|
988
1166
|
var DEFAULT_JWKS_TIMEOUT_MS = 5e3;
|
|
989
1167
|
var PRINCIPAL_TYPES = /* @__PURE__ */ new Set(["user", "identity", "api_key", "platform"]);
|
|
990
1168
|
var DEFAULT_CLOCK_TOLERANCE_SEC = 60;
|
|
1169
|
+
function orgContext(claims) {
|
|
1170
|
+
const { org_id, org_role } = claims;
|
|
1171
|
+
if (typeof org_id !== "string" || org_id === "" || typeof org_role !== "string" || org_role === "") {
|
|
1172
|
+
return null;
|
|
1173
|
+
}
|
|
1174
|
+
return { orgId: org_id, orgRole: org_role };
|
|
1175
|
+
}
|
|
991
1176
|
function decodeBase64Url(value) {
|
|
992
1177
|
const padded = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
993
1178
|
const binary = atob(padded.padEnd(Math.ceil(padded.length / 4) * 4, "="));
|
|
@@ -1298,6 +1483,6 @@ var TokenVerifier = class {
|
|
|
1298
1483
|
}
|
|
1299
1484
|
};
|
|
1300
1485
|
|
|
1301
|
-
export { Assignments, Canopy, CanopyAuthorizerError, CanopyClient, CanopyConnectionError, CanopyError, CanopyTokenError, Identities, LocalAuthorizer, Paginator, Permissions, Roles, TokenVerifier, isCanopyAuthorizerError, isCanopyConnectionError, isCanopyError, isCanopyTokenError, isCursorPagination, paginate, withConcurrency };
|
|
1486
|
+
export { Assignments, Canopy, CanopyAuthorizerError, CanopyClient, CanopyConnectionError, CanopyError, CanopyTokenError, Identities, LocalAuthorizer, Organizations, Paginator, Permissions, Roles, TokenVerifier, isCanopyAuthorizerError, isCanopyConnectionError, isCanopyError, isCanopyTokenError, isCursorPagination, orgContext, paginate, withConcurrency };
|
|
1302
1487
|
//# sourceMappingURL=index.js.map
|
|
1303
1488
|
//# sourceMappingURL=index.js.map
|