@finueva/auth 0.8.1 → 0.10.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 +90 -4
- package/dist/device.d.ts +15 -2
- package/dist/device.js +509 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +447 -28
- package/dist/server.d.ts +15 -3
- package/dist/server.js +445 -24
- package/dist/types-Byw9JQwL.d.ts +235 -0
- package/package.json +1 -1
- package/dist/types-DDopQNZR.d.ts +0 -123
package/dist/server.js
CHANGED
|
@@ -181,6 +181,7 @@ const messages = {
|
|
|
181
181
|
password_reset_invalid: "The password reset request is invalid.",
|
|
182
182
|
authentication_required: "Authentication is required.",
|
|
183
183
|
request_origin_denied: "The request origin is not allowed.",
|
|
184
|
+
invalid_request: "The request is invalid.",
|
|
184
185
|
invalid_invitation: "The invitation is invalid.",
|
|
185
186
|
invitation_unavailable: "The invitation is not available.",
|
|
186
187
|
invitation_recipient_mismatch: "The invitation cannot be accepted by this account.",
|
|
@@ -474,6 +475,12 @@ const DRIVE_CREDENTIAL_LIFETIME_SECONDS = 840;
|
|
|
474
475
|
const id = /^[A-Za-z0-9_-]{1,128}$/;
|
|
475
476
|
const email = /^[^\s@]+@[^\s@]+$/;
|
|
476
477
|
const MAX_SOCIAL_ID_TOKEN_BYTES = 16 * 1024;
|
|
478
|
+
function normalizeEmail(value) {
|
|
479
|
+
if (typeof value !== "string") throw new TypeError("email is invalid");
|
|
480
|
+
const normalized = value.trim().toLowerCase();
|
|
481
|
+
if (normalized.length === 0 || normalized.length > 320 || !email.test(normalized)) throw new TypeError("email is invalid");
|
|
482
|
+
return normalized;
|
|
483
|
+
}
|
|
477
484
|
function normalizeSocialIdTokenInput(value) {
|
|
478
485
|
if (!isObject(value)) throw new TypeError("social ID token input is invalid");
|
|
479
486
|
const keys = Object.keys(value);
|
|
@@ -538,18 +545,283 @@ function normalizeDriveCredential(value, now) {
|
|
|
538
545
|
expiresAt: new Date(now + value.expiresIn * 1e3)
|
|
539
546
|
};
|
|
540
547
|
}
|
|
548
|
+
function normalizeOrganizationPageInput(value) {
|
|
549
|
+
if (value === void 0) return new URLSearchParams();
|
|
550
|
+
if (!isObject(value) || Object.keys(value).some((key) => key !== "limit" && key !== "cursor")) throw new AuthError("invalid_request", 400);
|
|
551
|
+
const input = value;
|
|
552
|
+
const query = new URLSearchParams();
|
|
553
|
+
if (input.limit !== void 0) {
|
|
554
|
+
if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 100) throw new AuthError("invalid_request", 400);
|
|
555
|
+
query.set("limit", String(input.limit));
|
|
556
|
+
}
|
|
557
|
+
if (input.cursor !== void 0) {
|
|
558
|
+
if (typeof input.cursor !== "string" || input.cursor.length < 1 || input.cursor.length > 820 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(input.cursor)) throw new AuthError("invalid_request", 400);
|
|
559
|
+
query.set("cursor", input.cursor);
|
|
560
|
+
}
|
|
561
|
+
return query;
|
|
562
|
+
}
|
|
563
|
+
function normalizeIdInput(value) {
|
|
564
|
+
if (!isId(value)) throw new AuthError("invalid_request", 400);
|
|
565
|
+
return value;
|
|
566
|
+
}
|
|
567
|
+
function normalizeOrganization(value) {
|
|
568
|
+
exact(value, [
|
|
569
|
+
"capabilities",
|
|
570
|
+
"id",
|
|
571
|
+
"lifecycle",
|
|
572
|
+
"logo",
|
|
573
|
+
"name",
|
|
574
|
+
"role",
|
|
575
|
+
"slug"
|
|
576
|
+
]);
|
|
577
|
+
if (!isId(value.id) || !boundedString(value.name, 255) || !boundedString(value.slug, 255) || value.lifecycle !== "ordinary" && value.lifecycle !== "managed" || !role(value.role) || !isObject(value.capabilities)) throw authorityUnavailable();
|
|
578
|
+
exact(value.capabilities, [
|
|
579
|
+
"readInvitations",
|
|
580
|
+
"readMembers",
|
|
581
|
+
"readTeams"
|
|
582
|
+
]);
|
|
583
|
+
if (value.capabilities.readMembers !== true || value.capabilities.readTeams !== true || typeof value.capabilities.readInvitations !== "boolean") throw authorityUnavailable();
|
|
584
|
+
return {
|
|
585
|
+
id: value.id,
|
|
586
|
+
name: value.name,
|
|
587
|
+
slug: value.slug,
|
|
588
|
+
logo: nullableHttpsUrl(value.logo),
|
|
589
|
+
lifecycle: value.lifecycle,
|
|
590
|
+
role: value.role,
|
|
591
|
+
capabilities: {
|
|
592
|
+
readMembers: true,
|
|
593
|
+
readTeams: true,
|
|
594
|
+
readInvitations: value.capabilities.readInvitations
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function normalizeOrganizationDisplayInput(value) {
|
|
599
|
+
if (!isObject(value) || Object.keys(value).sort().join(",") !== "logo,name,slug") throw new AuthError("invalid_request", 400);
|
|
600
|
+
if (!boundedString(value.name, 255) || !boundedString(value.slug, 255)) throw new AuthError("invalid_request", 400);
|
|
601
|
+
let logo;
|
|
602
|
+
try {
|
|
603
|
+
logo = nullableHttpsUrl(value.logo);
|
|
604
|
+
} catch {
|
|
605
|
+
throw new AuthError("invalid_request", 400);
|
|
606
|
+
}
|
|
607
|
+
return {
|
|
608
|
+
name: value.name,
|
|
609
|
+
slug: value.slug,
|
|
610
|
+
logo
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
function normalizeOrganizationDisplay(value) {
|
|
614
|
+
try {
|
|
615
|
+
return normalizeOrganizationDisplayInput(value);
|
|
616
|
+
} catch {
|
|
617
|
+
throw authorityUnavailable();
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
function normalizeOrganizationTeamDisplayInput(value) {
|
|
621
|
+
if (!isObject(value) || Object.keys(value).join(",") !== "name" || !boundedString(value.name, 255)) throw new AuthError("invalid_request", 400);
|
|
622
|
+
return { name: value.name };
|
|
623
|
+
}
|
|
624
|
+
function normalizeOrganizationTeamDisplay(value) {
|
|
625
|
+
try {
|
|
626
|
+
return normalizeOrganizationTeamDisplayInput(value);
|
|
627
|
+
} catch {
|
|
628
|
+
throw authorityUnavailable();
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function normalizeOrganizationTeamCreationInput(name, idempotencyKey) {
|
|
632
|
+
if (!boundedString(name, 255) || !boundedString(idempotencyKey, 255)) throw new AuthError("invalid_request", 400);
|
|
633
|
+
return {
|
|
634
|
+
name,
|
|
635
|
+
idempotencyKey
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function normalizeCreatedOrganizationTeam(value) {
|
|
639
|
+
exact(value, ["id", "name"]);
|
|
640
|
+
if (!isId(value.id) || !boundedString(value.name, 255)) throw authorityUnavailable();
|
|
641
|
+
return {
|
|
642
|
+
id: value.id,
|
|
643
|
+
name: value.name
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
function normalizeOrganizationMemberInvitationCreationInput(value) {
|
|
647
|
+
if (!isObject(value)) throw new AuthError("invalid_request", 400);
|
|
648
|
+
const keys = Object.keys(value).sort().join(",");
|
|
649
|
+
if (keys !== "email,idempotencyKey" && keys !== "email,idempotencyKey,teamIds") throw new AuthError("invalid_request", 400);
|
|
650
|
+
let normalizedEmail;
|
|
651
|
+
try {
|
|
652
|
+
normalizedEmail = normalizeEmail(value.email);
|
|
653
|
+
} catch {
|
|
654
|
+
throw new AuthError("invalid_request", 400);
|
|
655
|
+
}
|
|
656
|
+
if (new TextEncoder().encode(normalizedEmail).byteLength > 320 || !boundedString(value.idempotencyKey, 255) || value.teamIds !== void 0 && (!Array.isArray(value.teamIds) || value.teamIds.length > 100)) throw new AuthError("invalid_request", 400);
|
|
657
|
+
const teamIds = value.teamIds?.map((teamId) => normalizeIdInput(teamId));
|
|
658
|
+
if (teamIds && new Set(teamIds).size !== teamIds.length) throw new AuthError("invalid_request", 400);
|
|
659
|
+
return {
|
|
660
|
+
email: normalizedEmail,
|
|
661
|
+
...teamIds === void 0 ? {} : { teamIds },
|
|
662
|
+
idempotencyKey: value.idempotencyKey
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function normalizeCreatedOrganizationMemberInvitation(value) {
|
|
666
|
+
exact(value, ["expiresAt", "id"]);
|
|
667
|
+
if (!isId(value.id)) throw authorityUnavailable();
|
|
668
|
+
return {
|
|
669
|
+
id: value.id,
|
|
670
|
+
expiresAt: responseDate(value.expiresAt)
|
|
671
|
+
};
|
|
672
|
+
}
|
|
541
673
|
function normalizeOrganizations(value) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
return
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
674
|
+
exact(value, ["nextCursor", "organizations"]);
|
|
675
|
+
if (!Array.isArray(value.organizations) || value.organizations.length > 100) throw authorityUnavailable();
|
|
676
|
+
return {
|
|
677
|
+
organizations: unique(value.organizations.map(normalizeOrganization), (item) => item.id),
|
|
678
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
function normalizeOrganizationMembers(value) {
|
|
682
|
+
exact(value, ["members", "nextCursor"]);
|
|
683
|
+
if (!Array.isArray(value.members) || value.members.length > 100) throw authorityUnavailable();
|
|
684
|
+
return {
|
|
685
|
+
members: unique(value.members.map((member) => {
|
|
686
|
+
exact(member, [
|
|
687
|
+
"email",
|
|
688
|
+
"id",
|
|
689
|
+
"image",
|
|
690
|
+
"joinedAt",
|
|
691
|
+
"name",
|
|
692
|
+
"owner",
|
|
693
|
+
"role",
|
|
694
|
+
"teamIds",
|
|
695
|
+
"userId"
|
|
696
|
+
]);
|
|
697
|
+
if (!isId(member.id) || !isId(member.userId) || !boundedString(member.name, 255) || typeof member.email !== "string" || member.email.length > 320 || !email.test(member.email) || !role(member.role) || typeof member.owner !== "boolean" || !Array.isArray(member.teamIds) || member.teamIds.length > 100) throw authorityUnavailable();
|
|
698
|
+
const teamIds = unique(member.teamIds.map((teamId) => normalizeResponseId(teamId)), (item) => item);
|
|
699
|
+
return {
|
|
700
|
+
id: member.id,
|
|
701
|
+
userId: member.userId,
|
|
702
|
+
name: member.name,
|
|
703
|
+
email: member.email,
|
|
704
|
+
image: nullableHttpsUrl(member.image),
|
|
705
|
+
role: member.role,
|
|
706
|
+
owner: member.owner,
|
|
707
|
+
joinedAt: responseDate(member.joinedAt),
|
|
708
|
+
teamIds
|
|
709
|
+
};
|
|
710
|
+
}), (item) => item.id),
|
|
711
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function normalizeOrganizationTeams(value) {
|
|
715
|
+
exact(value, ["nextCursor", "teams"]);
|
|
716
|
+
if (!Array.isArray(value.teams) || value.teams.length > 100) throw authorityUnavailable();
|
|
717
|
+
return {
|
|
718
|
+
teams: unique(value.teams.map((team) => {
|
|
719
|
+
exact(team, [
|
|
720
|
+
"category",
|
|
721
|
+
"createdAt",
|
|
722
|
+
"id",
|
|
723
|
+
"name"
|
|
724
|
+
]);
|
|
725
|
+
if (!isId(team.id) || !boundedString(team.name, 255) || team.category !== "manual" && team.category !== "managed") throw authorityUnavailable();
|
|
726
|
+
return {
|
|
727
|
+
id: team.id,
|
|
728
|
+
name: team.name,
|
|
729
|
+
category: team.category,
|
|
730
|
+
createdAt: responseDate(team.createdAt)
|
|
731
|
+
};
|
|
732
|
+
}), (item) => item.id),
|
|
733
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
function normalizeOrganizationTeamMembers(value) {
|
|
737
|
+
exact(value, ["memberIds", "nextCursor"]);
|
|
738
|
+
if (!Array.isArray(value.memberIds) || value.memberIds.length > 100) throw authorityUnavailable();
|
|
739
|
+
return {
|
|
740
|
+
memberIds: unique(value.memberIds.map((item) => normalizeResponseId(item)), (item) => item),
|
|
741
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
function normalizeOrganizationInvitation(value) {
|
|
745
|
+
exact(value, [
|
|
746
|
+
"createdAt",
|
|
747
|
+
"email",
|
|
748
|
+
"expiresAt",
|
|
749
|
+
"id",
|
|
750
|
+
"inviter",
|
|
751
|
+
"role",
|
|
752
|
+
"status",
|
|
753
|
+
"teamIds"
|
|
754
|
+
]);
|
|
755
|
+
if (!isId(value.id) || typeof value.email !== "string" || value.email.length > 320 || !email.test(value.email) || !role(value.role) || value.status !== "pending" || !Array.isArray(value.teamIds) || value.teamIds.length > 100 || !isObject(value.inviter)) throw authorityUnavailable();
|
|
756
|
+
exact(value.inviter, ["membershipId", "name"]);
|
|
757
|
+
if (!isId(value.inviter.membershipId) || !boundedString(value.inviter.name, 255)) throw authorityUnavailable();
|
|
758
|
+
return {
|
|
759
|
+
id: value.id,
|
|
760
|
+
email: value.email,
|
|
761
|
+
role: value.role,
|
|
762
|
+
teamIds: unique(value.teamIds.map(normalizeResponseId), (item) => item),
|
|
763
|
+
inviter: {
|
|
764
|
+
membershipId: value.inviter.membershipId,
|
|
765
|
+
name: value.inviter.name
|
|
766
|
+
},
|
|
767
|
+
createdAt: responseDate(value.createdAt),
|
|
768
|
+
expiresAt: responseDate(value.expiresAt),
|
|
769
|
+
status: "pending"
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
function normalizeOrganizationInvitations(value) {
|
|
773
|
+
exact(value, ["invitations", "nextCursor"]);
|
|
774
|
+
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
775
|
+
return {
|
|
776
|
+
invitations: unique(value.invitations.map(normalizeOrganizationInvitation), (item) => item.id),
|
|
777
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
function normalizeReceivedInvitation(value) {
|
|
781
|
+
exact(value, [
|
|
782
|
+
"expiresAt",
|
|
783
|
+
"id",
|
|
784
|
+
"inviterName",
|
|
785
|
+
"organization",
|
|
786
|
+
"role",
|
|
787
|
+
"teams"
|
|
788
|
+
]);
|
|
789
|
+
if (!isId(value.id) || !boundedString(value.inviterName, 255) || !role(value.role) || !Array.isArray(value.teams) || value.teams.length > 100 || !isObject(value.organization)) throw authorityUnavailable();
|
|
790
|
+
exact(value.organization, [
|
|
791
|
+
"id",
|
|
792
|
+
"logo",
|
|
793
|
+
"name",
|
|
794
|
+
"slug"
|
|
795
|
+
]);
|
|
796
|
+
if (!isId(value.organization.id) || !boundedString(value.organization.name, 255) || !boundedString(value.organization.slug, 255)) throw authorityUnavailable();
|
|
797
|
+
return {
|
|
798
|
+
id: value.id,
|
|
799
|
+
organization: {
|
|
800
|
+
id: value.organization.id,
|
|
801
|
+
name: value.organization.name,
|
|
802
|
+
slug: value.organization.slug,
|
|
803
|
+
logo: nullableHttpsUrl(value.organization.logo)
|
|
804
|
+
},
|
|
805
|
+
role: value.role,
|
|
806
|
+
teams: unique(value.teams.map((team) => {
|
|
807
|
+
exact(team, ["id", "name"]);
|
|
808
|
+
if (!isId(team.id) || !boundedString(team.name, 255)) throw authorityUnavailable();
|
|
809
|
+
return {
|
|
810
|
+
id: team.id,
|
|
811
|
+
name: team.name
|
|
812
|
+
};
|
|
813
|
+
}), (item) => item.id),
|
|
814
|
+
inviterName: value.inviterName,
|
|
815
|
+
expiresAt: responseDate(value.expiresAt)
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
function normalizeReceivedInvitations(value) {
|
|
819
|
+
exact(value, ["invitations", "nextCursor"]);
|
|
820
|
+
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
821
|
+
return {
|
|
822
|
+
invitations: unique(value.invitations.map(normalizeReceivedInvitation), (item) => item.id),
|
|
823
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
824
|
+
};
|
|
553
825
|
}
|
|
554
826
|
function normalizeInvitationInput(value) {
|
|
555
827
|
if (!isObject(value) || Object.keys(value).length !== 1 || !isId(value.invitationId)) throw new AuthError("invalid_invitation", 422);
|
|
@@ -601,6 +873,20 @@ function fromOrganizationListError(error) {
|
|
|
601
873
|
if (error instanceof AuthError) return error;
|
|
602
874
|
return authorityUnavailable();
|
|
603
875
|
}
|
|
876
|
+
function fromOrganizationReadAuthorityError(value, status) {
|
|
877
|
+
if (status === 400) return new AuthError("invalid_request", 400);
|
|
878
|
+
if (status === 401) return new AuthError("authentication_required", 401);
|
|
879
|
+
if (status === 403) return new AuthError("access_denied", 403);
|
|
880
|
+
return authorityUnavailable();
|
|
881
|
+
}
|
|
882
|
+
function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
|
|
883
|
+
if (status === 400 || status === 413 || status === 415) return new AuthError("invalid_request", 400);
|
|
884
|
+
if (status === 409) return new AuthError("state_conflict", 409);
|
|
885
|
+
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
886
|
+
const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
|
|
887
|
+
if (status === 403 && code === "REQUEST_ORIGIN_DENIED") return new AuthError("request_origin_denied", 403);
|
|
888
|
+
return fromOrganizationReadAuthorityError(value, status);
|
|
889
|
+
}
|
|
604
890
|
function fromInvitationAuthorityError(value, status) {
|
|
605
891
|
const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
|
|
606
892
|
if (status === 401 && code === "UNAUTHORIZED") return new AuthError("authentication_required", 401);
|
|
@@ -675,6 +961,46 @@ function toDate(value) {
|
|
|
675
961
|
function isId(value) {
|
|
676
962
|
return typeof value === "string" && id.test(value);
|
|
677
963
|
}
|
|
964
|
+
function exact(value, keys) {
|
|
965
|
+
if (!isObject(value) || Object.keys(value).sort().join(",") !== [...keys].sort().join(",")) throw authorityUnavailable();
|
|
966
|
+
}
|
|
967
|
+
function boundedString(value, maximum) {
|
|
968
|
+
return typeof value === "string" && value.length > 0 && new TextEncoder().encode(value).byteLength <= maximum;
|
|
969
|
+
}
|
|
970
|
+
function role(value) {
|
|
971
|
+
return value === "owner" || value === "admin" || value === "member";
|
|
972
|
+
}
|
|
973
|
+
function nullableHttpsUrl(value) {
|
|
974
|
+
if (value === null) return null;
|
|
975
|
+
if (typeof value !== "string" || value.length > 2048) throw authorityUnavailable();
|
|
976
|
+
let url;
|
|
977
|
+
try {
|
|
978
|
+
url = new URL(value);
|
|
979
|
+
} catch {
|
|
980
|
+
throw authorityUnavailable();
|
|
981
|
+
}
|
|
982
|
+
if (url.protocol !== "https:" || url.username || url.password || url.toString() !== value) throw authorityUnavailable();
|
|
983
|
+
return value;
|
|
984
|
+
}
|
|
985
|
+
function responseDate(value) {
|
|
986
|
+
if (typeof value !== "string") throw authorityUnavailable();
|
|
987
|
+
const date = new Date(value);
|
|
988
|
+
if (!Number.isFinite(date.getTime()) || date.toISOString() !== value) throw authorityUnavailable();
|
|
989
|
+
return date;
|
|
990
|
+
}
|
|
991
|
+
function nullableCursor(value) {
|
|
992
|
+
if (value === null) return null;
|
|
993
|
+
if (typeof value !== "string" || value.length < 1 || value.length > 820 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value)) throw authorityUnavailable();
|
|
994
|
+
return value;
|
|
995
|
+
}
|
|
996
|
+
function normalizeResponseId(value) {
|
|
997
|
+
if (!isId(value)) throw authorityUnavailable();
|
|
998
|
+
return value;
|
|
999
|
+
}
|
|
1000
|
+
function unique(items, key) {
|
|
1001
|
+
if (new Set(items.map(key)).size !== items.length) throw authorityUnavailable();
|
|
1002
|
+
return items;
|
|
1003
|
+
}
|
|
678
1004
|
function isObject(value) {
|
|
679
1005
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
680
1006
|
}
|
|
@@ -704,18 +1030,18 @@ async function requestJsonResponse(url, options) {
|
|
|
704
1030
|
}
|
|
705
1031
|
const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
706
1032
|
if (response.status >= 300 || response.status < 200 || contentType !== "application/json") {
|
|
707
|
-
const body = contentType === "application/json" ? await readJson(response) : void 0;
|
|
1033
|
+
const body = contentType === "application/json" ? await readJson(response, options.maxResponseBytes) : void 0;
|
|
708
1034
|
await response.body?.cancel();
|
|
709
1035
|
throw (options.mapError ?? fromAuthorityError)(body, response.status, response.headers.get("retry-after"));
|
|
710
1036
|
}
|
|
711
1037
|
return {
|
|
712
|
-
value: await readJson(response),
|
|
1038
|
+
value: await readJson(response, options.maxResponseBytes),
|
|
713
1039
|
headers: response.headers
|
|
714
1040
|
};
|
|
715
1041
|
}
|
|
716
|
-
async function readJson(response) {
|
|
1042
|
+
async function readJson(response, maximum = MAX_RESPONSE_BYTES) {
|
|
717
1043
|
const length = response.headers.get("content-length");
|
|
718
|
-
if (length && (!/^\d+$/.test(length) || Number(length) >
|
|
1044
|
+
if (length && (!/^\d+$/.test(length) || Number(length) > maximum)) {
|
|
719
1045
|
await response.body?.cancel();
|
|
720
1046
|
throw authorityUnavailable();
|
|
721
1047
|
}
|
|
@@ -728,7 +1054,7 @@ async function readJson(response) {
|
|
|
728
1054
|
const { done, value } = await reader.read();
|
|
729
1055
|
if (done) break;
|
|
730
1056
|
size += value.byteLength;
|
|
731
|
-
if (size >
|
|
1057
|
+
if (size > maximum) throw authorityUnavailable();
|
|
732
1058
|
chunks.push(value);
|
|
733
1059
|
}
|
|
734
1060
|
} catch (error) {
|
|
@@ -766,6 +1092,18 @@ function createServerAuth(options) {
|
|
|
766
1092
|
...authorization ? { authorization } : { cookie },
|
|
767
1093
|
...includeOrigin ? { origin: appOrigin } : {}
|
|
768
1094
|
});
|
|
1095
|
+
async function organizationRead(path, input, normalize) {
|
|
1096
|
+
const query = normalizeOrganizationPageInput(input);
|
|
1097
|
+
return normalize(await requestJson(`${joinURL(authOrigin, "api/v1/auth/organizations", path)}${query.size ? `?${query}` : ""}`, {
|
|
1098
|
+
fetch: fetchImpl,
|
|
1099
|
+
timeoutMs,
|
|
1100
|
+
method: "GET",
|
|
1101
|
+
credentials,
|
|
1102
|
+
headers: authHeaders(false),
|
|
1103
|
+
mapError: fromOrganizationReadAuthorityError,
|
|
1104
|
+
maxResponseBytes: 256 * 1024
|
|
1105
|
+
}));
|
|
1106
|
+
}
|
|
769
1107
|
return {
|
|
770
1108
|
async acceptInvitation(input) {
|
|
771
1109
|
const invitation = normalizeInvitationInput(input);
|
|
@@ -803,19 +1141,102 @@ function createServerAuth(options) {
|
|
|
803
1141
|
headers: authHeaders(false)
|
|
804
1142
|
}));
|
|
805
1143
|
},
|
|
806
|
-
async listOrganizations() {
|
|
1144
|
+
async listOrganizations(input) {
|
|
807
1145
|
try {
|
|
808
|
-
return
|
|
809
|
-
fetch: fetchImpl,
|
|
810
|
-
timeoutMs,
|
|
811
|
-
method: "GET",
|
|
812
|
-
credentials,
|
|
813
|
-
headers: authHeaders()
|
|
814
|
-
}));
|
|
1146
|
+
return await organizationRead("", input, normalizeOrganizations);
|
|
815
1147
|
} catch (error) {
|
|
816
1148
|
throw fromOrganizationListError(error);
|
|
817
1149
|
}
|
|
818
1150
|
},
|
|
1151
|
+
getOrganization(organizationId) {
|
|
1152
|
+
return organizationRead(normalizeIdInput(organizationId), void 0, normalizeOrganization);
|
|
1153
|
+
},
|
|
1154
|
+
async createOrganizationTeam(organizationId, name, idempotencyKey) {
|
|
1155
|
+
const id = normalizeIdInput(organizationId);
|
|
1156
|
+
const body = normalizeOrganizationTeamCreationInput(name, idempotencyKey);
|
|
1157
|
+
return normalizeCreatedOrganizationTeam(await requestJson(joinURL(authOrigin, "api/v1/auth/organizations", id, "teams"), {
|
|
1158
|
+
fetch: fetchImpl,
|
|
1159
|
+
timeoutMs,
|
|
1160
|
+
method: "POST",
|
|
1161
|
+
credentials,
|
|
1162
|
+
headers: {
|
|
1163
|
+
...authHeaders(!authorization),
|
|
1164
|
+
"content-type": "application/json"
|
|
1165
|
+
},
|
|
1166
|
+
body,
|
|
1167
|
+
mapError: fromOrganizationMutationAuthorityError
|
|
1168
|
+
}));
|
|
1169
|
+
},
|
|
1170
|
+
async createOrganizationMemberInvitation(organizationId, input) {
|
|
1171
|
+
const id = normalizeIdInput(organizationId);
|
|
1172
|
+
const body = normalizeOrganizationMemberInvitationCreationInput(input);
|
|
1173
|
+
return normalizeCreatedOrganizationMemberInvitation(await requestJson(joinURL(authOrigin, "api/v1/auth/organizations", id, "invitations"), {
|
|
1174
|
+
fetch: fetchImpl,
|
|
1175
|
+
timeoutMs,
|
|
1176
|
+
method: "POST",
|
|
1177
|
+
credentials,
|
|
1178
|
+
headers: {
|
|
1179
|
+
...authHeaders(!authorization),
|
|
1180
|
+
"content-type": "application/json"
|
|
1181
|
+
},
|
|
1182
|
+
body,
|
|
1183
|
+
mapError: fromOrganizationMutationAuthorityError
|
|
1184
|
+
}));
|
|
1185
|
+
},
|
|
1186
|
+
async updateOrganizationDisplay(organizationId, input) {
|
|
1187
|
+
const id = normalizeIdInput(organizationId);
|
|
1188
|
+
const desired = normalizeOrganizationDisplayInput(input);
|
|
1189
|
+
return normalizeOrganizationDisplay(await requestJson(joinURL(authOrigin, "api/v1/auth/organizations", id, "display"), {
|
|
1190
|
+
fetch: fetchImpl,
|
|
1191
|
+
timeoutMs,
|
|
1192
|
+
method: "POST",
|
|
1193
|
+
credentials,
|
|
1194
|
+
headers: {
|
|
1195
|
+
...authHeaders(!authorization),
|
|
1196
|
+
"content-type": "application/json"
|
|
1197
|
+
},
|
|
1198
|
+
body: desired,
|
|
1199
|
+
mapError: fromOrganizationMutationAuthorityError
|
|
1200
|
+
}));
|
|
1201
|
+
},
|
|
1202
|
+
async updateOrganizationTeamDisplay(organizationId, teamId, input) {
|
|
1203
|
+
const organization = normalizeIdInput(organizationId);
|
|
1204
|
+
const team = normalizeIdInput(teamId);
|
|
1205
|
+
const desired = normalizeOrganizationTeamDisplayInput(input);
|
|
1206
|
+
return normalizeOrganizationTeamDisplay(await requestJson(joinURL(authOrigin, "api/v1/auth/organizations", organization, "teams", team, "display"), {
|
|
1207
|
+
fetch: fetchImpl,
|
|
1208
|
+
timeoutMs,
|
|
1209
|
+
method: "POST",
|
|
1210
|
+
credentials,
|
|
1211
|
+
headers: {
|
|
1212
|
+
...authHeaders(!authorization),
|
|
1213
|
+
"content-type": "application/json"
|
|
1214
|
+
},
|
|
1215
|
+
body: desired,
|
|
1216
|
+
mapError: fromOrganizationMutationAuthorityError
|
|
1217
|
+
}));
|
|
1218
|
+
},
|
|
1219
|
+
listOrganizationMembers(organizationId, input) {
|
|
1220
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/members`, input, normalizeOrganizationMembers);
|
|
1221
|
+
},
|
|
1222
|
+
listOrganizationTeams(organizationId, input) {
|
|
1223
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/teams`, input, normalizeOrganizationTeams);
|
|
1224
|
+
},
|
|
1225
|
+
listOrganizationTeamMembers(organizationId, teamId, input) {
|
|
1226
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/teams/${normalizeIdInput(teamId)}/members`, input, normalizeOrganizationTeamMembers);
|
|
1227
|
+
},
|
|
1228
|
+
listOrganizationInvitations(organizationId, input) {
|
|
1229
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/invitations`, input, normalizeOrganizationInvitations);
|
|
1230
|
+
},
|
|
1231
|
+
getOrganizationInvitation(organizationId, invitationId) {
|
|
1232
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/invitations/${normalizeIdInput(invitationId)}`, void 0, normalizeOrganizationInvitation);
|
|
1233
|
+
},
|
|
1234
|
+
listReceivedInvitations(input) {
|
|
1235
|
+
return organizationRead("received-invitations", input, normalizeReceivedInvitations);
|
|
1236
|
+
},
|
|
1237
|
+
getReceivedInvitation(invitationId) {
|
|
1238
|
+
return organizationRead(`received-invitations/${normalizeIdInput(invitationId)}`, void 0, normalizeReceivedInvitation);
|
|
1239
|
+
},
|
|
819
1240
|
async signInWithSocialIdToken(input) {
|
|
820
1241
|
if (authorization) throw new AuthError("state_conflict", 409);
|
|
821
1242
|
const body = socialIdTokenRequest(normalizeSocialIdTokenInput(input));
|