@finueva/auth 0.8.0 → 0.9.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 +408 -90
- package/dist/device.d.ts +11 -2
- package/dist/device.js +320 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +299 -28
- package/dist/server.d.ts +11 -3
- package/dist/server.js +291 -24
- package/dist/types-B67VIvTQ.d.ts +208 -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.",
|
|
@@ -538,18 +539,208 @@ function normalizeDriveCredential(value, now) {
|
|
|
538
539
|
expiresAt: new Date(now + value.expiresIn * 1e3)
|
|
539
540
|
};
|
|
540
541
|
}
|
|
542
|
+
function normalizeOrganizationPageInput(value) {
|
|
543
|
+
if (value === void 0) return new URLSearchParams();
|
|
544
|
+
if (!isObject(value) || Object.keys(value).some((key) => key !== "limit" && key !== "cursor")) throw new AuthError("invalid_request", 400);
|
|
545
|
+
const input = value;
|
|
546
|
+
const query = new URLSearchParams();
|
|
547
|
+
if (input.limit !== void 0) {
|
|
548
|
+
if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 100) throw new AuthError("invalid_request", 400);
|
|
549
|
+
query.set("limit", String(input.limit));
|
|
550
|
+
}
|
|
551
|
+
if (input.cursor !== void 0) {
|
|
552
|
+
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);
|
|
553
|
+
query.set("cursor", input.cursor);
|
|
554
|
+
}
|
|
555
|
+
return query;
|
|
556
|
+
}
|
|
557
|
+
function normalizeIdInput(value) {
|
|
558
|
+
if (!isId(value)) throw new AuthError("invalid_request", 400);
|
|
559
|
+
return value;
|
|
560
|
+
}
|
|
561
|
+
function normalizeOrganization(value) {
|
|
562
|
+
exact(value, [
|
|
563
|
+
"capabilities",
|
|
564
|
+
"id",
|
|
565
|
+
"lifecycle",
|
|
566
|
+
"logo",
|
|
567
|
+
"name",
|
|
568
|
+
"role",
|
|
569
|
+
"slug"
|
|
570
|
+
]);
|
|
571
|
+
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();
|
|
572
|
+
exact(value.capabilities, [
|
|
573
|
+
"readInvitations",
|
|
574
|
+
"readMembers",
|
|
575
|
+
"readTeams"
|
|
576
|
+
]);
|
|
577
|
+
if (value.capabilities.readMembers !== true || value.capabilities.readTeams !== true || typeof value.capabilities.readInvitations !== "boolean") throw authorityUnavailable();
|
|
578
|
+
return {
|
|
579
|
+
id: value.id,
|
|
580
|
+
name: value.name,
|
|
581
|
+
slug: value.slug,
|
|
582
|
+
logo: nullableHttpsUrl(value.logo),
|
|
583
|
+
lifecycle: value.lifecycle,
|
|
584
|
+
role: value.role,
|
|
585
|
+
capabilities: {
|
|
586
|
+
readMembers: true,
|
|
587
|
+
readTeams: true,
|
|
588
|
+
readInvitations: value.capabilities.readInvitations
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
}
|
|
541
592
|
function normalizeOrganizations(value) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
return
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
593
|
+
exact(value, ["nextCursor", "organizations"]);
|
|
594
|
+
if (!Array.isArray(value.organizations) || value.organizations.length > 100) throw authorityUnavailable();
|
|
595
|
+
return {
|
|
596
|
+
organizations: unique(value.organizations.map(normalizeOrganization), (item) => item.id),
|
|
597
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
function normalizeOrganizationMembers(value) {
|
|
601
|
+
exact(value, ["members", "nextCursor"]);
|
|
602
|
+
if (!Array.isArray(value.members) || value.members.length > 100) throw authorityUnavailable();
|
|
603
|
+
return {
|
|
604
|
+
members: unique(value.members.map((member) => {
|
|
605
|
+
exact(member, [
|
|
606
|
+
"email",
|
|
607
|
+
"id",
|
|
608
|
+
"image",
|
|
609
|
+
"joinedAt",
|
|
610
|
+
"name",
|
|
611
|
+
"owner",
|
|
612
|
+
"role",
|
|
613
|
+
"teamIds",
|
|
614
|
+
"userId"
|
|
615
|
+
]);
|
|
616
|
+
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();
|
|
617
|
+
const teamIds = unique(member.teamIds.map((teamId) => normalizeResponseId(teamId)), (item) => item);
|
|
618
|
+
return {
|
|
619
|
+
id: member.id,
|
|
620
|
+
userId: member.userId,
|
|
621
|
+
name: member.name,
|
|
622
|
+
email: member.email,
|
|
623
|
+
image: nullableHttpsUrl(member.image),
|
|
624
|
+
role: member.role,
|
|
625
|
+
owner: member.owner,
|
|
626
|
+
joinedAt: responseDate(member.joinedAt),
|
|
627
|
+
teamIds
|
|
628
|
+
};
|
|
629
|
+
}), (item) => item.id),
|
|
630
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
function normalizeOrganizationTeams(value) {
|
|
634
|
+
exact(value, ["nextCursor", "teams"]);
|
|
635
|
+
if (!Array.isArray(value.teams) || value.teams.length > 100) throw authorityUnavailable();
|
|
636
|
+
return {
|
|
637
|
+
teams: unique(value.teams.map((team) => {
|
|
638
|
+
exact(team, [
|
|
639
|
+
"category",
|
|
640
|
+
"createdAt",
|
|
641
|
+
"id",
|
|
642
|
+
"name"
|
|
643
|
+
]);
|
|
644
|
+
if (!isId(team.id) || !boundedString(team.name, 255) || team.category !== "manual" && team.category !== "managed") throw authorityUnavailable();
|
|
645
|
+
return {
|
|
646
|
+
id: team.id,
|
|
647
|
+
name: team.name,
|
|
648
|
+
category: team.category,
|
|
649
|
+
createdAt: responseDate(team.createdAt)
|
|
650
|
+
};
|
|
651
|
+
}), (item) => item.id),
|
|
652
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
function normalizeOrganizationTeamMembers(value) {
|
|
656
|
+
exact(value, ["memberIds", "nextCursor"]);
|
|
657
|
+
if (!Array.isArray(value.memberIds) || value.memberIds.length > 100) throw authorityUnavailable();
|
|
658
|
+
return {
|
|
659
|
+
memberIds: unique(value.memberIds.map((item) => normalizeResponseId(item)), (item) => item),
|
|
660
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
function normalizeOrganizationInvitation(value) {
|
|
664
|
+
exact(value, [
|
|
665
|
+
"createdAt",
|
|
666
|
+
"email",
|
|
667
|
+
"expiresAt",
|
|
668
|
+
"id",
|
|
669
|
+
"inviter",
|
|
670
|
+
"role",
|
|
671
|
+
"status",
|
|
672
|
+
"teamIds"
|
|
673
|
+
]);
|
|
674
|
+
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();
|
|
675
|
+
exact(value.inviter, ["membershipId", "name"]);
|
|
676
|
+
if (!isId(value.inviter.membershipId) || !boundedString(value.inviter.name, 255)) throw authorityUnavailable();
|
|
677
|
+
return {
|
|
678
|
+
id: value.id,
|
|
679
|
+
email: value.email,
|
|
680
|
+
role: value.role,
|
|
681
|
+
teamIds: unique(value.teamIds.map(normalizeResponseId), (item) => item),
|
|
682
|
+
inviter: {
|
|
683
|
+
membershipId: value.inviter.membershipId,
|
|
684
|
+
name: value.inviter.name
|
|
685
|
+
},
|
|
686
|
+
createdAt: responseDate(value.createdAt),
|
|
687
|
+
expiresAt: responseDate(value.expiresAt),
|
|
688
|
+
status: "pending"
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function normalizeOrganizationInvitations(value) {
|
|
692
|
+
exact(value, ["invitations", "nextCursor"]);
|
|
693
|
+
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
694
|
+
return {
|
|
695
|
+
invitations: unique(value.invitations.map(normalizeOrganizationInvitation), (item) => item.id),
|
|
696
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
function normalizeReceivedInvitation(value) {
|
|
700
|
+
exact(value, [
|
|
701
|
+
"expiresAt",
|
|
702
|
+
"id",
|
|
703
|
+
"inviterName",
|
|
704
|
+
"organization",
|
|
705
|
+
"role",
|
|
706
|
+
"teams"
|
|
707
|
+
]);
|
|
708
|
+
if (!isId(value.id) || !boundedString(value.inviterName, 255) || !role(value.role) || !Array.isArray(value.teams) || value.teams.length > 100 || !isObject(value.organization)) throw authorityUnavailable();
|
|
709
|
+
exact(value.organization, [
|
|
710
|
+
"id",
|
|
711
|
+
"logo",
|
|
712
|
+
"name",
|
|
713
|
+
"slug"
|
|
714
|
+
]);
|
|
715
|
+
if (!isId(value.organization.id) || !boundedString(value.organization.name, 255) || !boundedString(value.organization.slug, 255)) throw authorityUnavailable();
|
|
716
|
+
return {
|
|
717
|
+
id: value.id,
|
|
718
|
+
organization: {
|
|
719
|
+
id: value.organization.id,
|
|
720
|
+
name: value.organization.name,
|
|
721
|
+
slug: value.organization.slug,
|
|
722
|
+
logo: nullableHttpsUrl(value.organization.logo)
|
|
723
|
+
},
|
|
724
|
+
role: value.role,
|
|
725
|
+
teams: unique(value.teams.map((team) => {
|
|
726
|
+
exact(team, ["id", "name"]);
|
|
727
|
+
if (!isId(team.id) || !boundedString(team.name, 255)) throw authorityUnavailable();
|
|
728
|
+
return {
|
|
729
|
+
id: team.id,
|
|
730
|
+
name: team.name
|
|
731
|
+
};
|
|
732
|
+
}), (item) => item.id),
|
|
733
|
+
inviterName: value.inviterName,
|
|
734
|
+
expiresAt: responseDate(value.expiresAt)
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
function normalizeReceivedInvitations(value) {
|
|
738
|
+
exact(value, ["invitations", "nextCursor"]);
|
|
739
|
+
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
740
|
+
return {
|
|
741
|
+
invitations: unique(value.invitations.map(normalizeReceivedInvitation), (item) => item.id),
|
|
742
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
743
|
+
};
|
|
553
744
|
}
|
|
554
745
|
function normalizeInvitationInput(value) {
|
|
555
746
|
if (!isObject(value) || Object.keys(value).length !== 1 || !isId(value.invitationId)) throw new AuthError("invalid_invitation", 422);
|
|
@@ -601,6 +792,12 @@ function fromOrganizationListError(error) {
|
|
|
601
792
|
if (error instanceof AuthError) return error;
|
|
602
793
|
return authorityUnavailable();
|
|
603
794
|
}
|
|
795
|
+
function fromOrganizationReadAuthorityError(value, status) {
|
|
796
|
+
if (status === 400) return new AuthError("invalid_request", 400);
|
|
797
|
+
if (status === 401) return new AuthError("authentication_required", 401);
|
|
798
|
+
if (status === 403) return new AuthError("access_denied", 403);
|
|
799
|
+
return authorityUnavailable();
|
|
800
|
+
}
|
|
604
801
|
function fromInvitationAuthorityError(value, status) {
|
|
605
802
|
const code = isObject(value) && typeof value.code === "string" ? value.code : void 0;
|
|
606
803
|
if (status === 401 && code === "UNAUTHORIZED") return new AuthError("authentication_required", 401);
|
|
@@ -675,6 +872,46 @@ function toDate(value) {
|
|
|
675
872
|
function isId(value) {
|
|
676
873
|
return typeof value === "string" && id.test(value);
|
|
677
874
|
}
|
|
875
|
+
function exact(value, keys) {
|
|
876
|
+
if (!isObject(value) || Object.keys(value).sort().join(",") !== [...keys].sort().join(",")) throw authorityUnavailable();
|
|
877
|
+
}
|
|
878
|
+
function boundedString(value, maximum) {
|
|
879
|
+
return typeof value === "string" && value.length > 0 && new TextEncoder().encode(value).byteLength <= maximum;
|
|
880
|
+
}
|
|
881
|
+
function role(value) {
|
|
882
|
+
return value === "owner" || value === "admin" || value === "member";
|
|
883
|
+
}
|
|
884
|
+
function nullableHttpsUrl(value) {
|
|
885
|
+
if (value === null) return null;
|
|
886
|
+
if (typeof value !== "string" || value.length > 2048) throw authorityUnavailable();
|
|
887
|
+
let url;
|
|
888
|
+
try {
|
|
889
|
+
url = new URL(value);
|
|
890
|
+
} catch {
|
|
891
|
+
throw authorityUnavailable();
|
|
892
|
+
}
|
|
893
|
+
if (url.protocol !== "https:" || url.username || url.password || url.toString() !== value) throw authorityUnavailable();
|
|
894
|
+
return value;
|
|
895
|
+
}
|
|
896
|
+
function responseDate(value) {
|
|
897
|
+
if (typeof value !== "string") throw authorityUnavailable();
|
|
898
|
+
const date = new Date(value);
|
|
899
|
+
if (!Number.isFinite(date.getTime()) || date.toISOString() !== value) throw authorityUnavailable();
|
|
900
|
+
return date;
|
|
901
|
+
}
|
|
902
|
+
function nullableCursor(value) {
|
|
903
|
+
if (value === null) return null;
|
|
904
|
+
if (typeof value !== "string" || value.length < 1 || value.length > 820 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value)) throw authorityUnavailable();
|
|
905
|
+
return value;
|
|
906
|
+
}
|
|
907
|
+
function normalizeResponseId(value) {
|
|
908
|
+
if (!isId(value)) throw authorityUnavailable();
|
|
909
|
+
return value;
|
|
910
|
+
}
|
|
911
|
+
function unique(items, key) {
|
|
912
|
+
if (new Set(items.map(key)).size !== items.length) throw authorityUnavailable();
|
|
913
|
+
return items;
|
|
914
|
+
}
|
|
678
915
|
function isObject(value) {
|
|
679
916
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
680
917
|
}
|
|
@@ -704,18 +941,18 @@ async function requestJsonResponse(url, options) {
|
|
|
704
941
|
}
|
|
705
942
|
const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
706
943
|
if (response.status >= 300 || response.status < 200 || contentType !== "application/json") {
|
|
707
|
-
const body = contentType === "application/json" ? await readJson(response) : void 0;
|
|
944
|
+
const body = contentType === "application/json" ? await readJson(response, options.maxResponseBytes) : void 0;
|
|
708
945
|
await response.body?.cancel();
|
|
709
946
|
throw (options.mapError ?? fromAuthorityError)(body, response.status, response.headers.get("retry-after"));
|
|
710
947
|
}
|
|
711
948
|
return {
|
|
712
|
-
value: await readJson(response),
|
|
949
|
+
value: await readJson(response, options.maxResponseBytes),
|
|
713
950
|
headers: response.headers
|
|
714
951
|
};
|
|
715
952
|
}
|
|
716
|
-
async function readJson(response) {
|
|
953
|
+
async function readJson(response, maximum = MAX_RESPONSE_BYTES) {
|
|
717
954
|
const length = response.headers.get("content-length");
|
|
718
|
-
if (length && (!/^\d+$/.test(length) || Number(length) >
|
|
955
|
+
if (length && (!/^\d+$/.test(length) || Number(length) > maximum)) {
|
|
719
956
|
await response.body?.cancel();
|
|
720
957
|
throw authorityUnavailable();
|
|
721
958
|
}
|
|
@@ -728,7 +965,7 @@ async function readJson(response) {
|
|
|
728
965
|
const { done, value } = await reader.read();
|
|
729
966
|
if (done) break;
|
|
730
967
|
size += value.byteLength;
|
|
731
|
-
if (size >
|
|
968
|
+
if (size > maximum) throw authorityUnavailable();
|
|
732
969
|
chunks.push(value);
|
|
733
970
|
}
|
|
734
971
|
} catch (error) {
|
|
@@ -766,6 +1003,18 @@ function createServerAuth(options) {
|
|
|
766
1003
|
...authorization ? { authorization } : { cookie },
|
|
767
1004
|
...includeOrigin ? { origin: appOrigin } : {}
|
|
768
1005
|
});
|
|
1006
|
+
async function organizationRead(path, input, normalize) {
|
|
1007
|
+
const query = normalizeOrganizationPageInput(input);
|
|
1008
|
+
return normalize(await requestJson(`${joinURL(authOrigin, "api/v1/auth/organizations", path)}${query.size ? `?${query}` : ""}`, {
|
|
1009
|
+
fetch: fetchImpl,
|
|
1010
|
+
timeoutMs,
|
|
1011
|
+
method: "GET",
|
|
1012
|
+
credentials,
|
|
1013
|
+
headers: authHeaders(false),
|
|
1014
|
+
mapError: fromOrganizationReadAuthorityError,
|
|
1015
|
+
maxResponseBytes: 256 * 1024
|
|
1016
|
+
}));
|
|
1017
|
+
}
|
|
769
1018
|
return {
|
|
770
1019
|
async acceptInvitation(input) {
|
|
771
1020
|
const invitation = normalizeInvitationInput(input);
|
|
@@ -803,19 +1052,37 @@ function createServerAuth(options) {
|
|
|
803
1052
|
headers: authHeaders(false)
|
|
804
1053
|
}));
|
|
805
1054
|
},
|
|
806
|
-
async listOrganizations() {
|
|
1055
|
+
async listOrganizations(input) {
|
|
807
1056
|
try {
|
|
808
|
-
return
|
|
809
|
-
fetch: fetchImpl,
|
|
810
|
-
timeoutMs,
|
|
811
|
-
method: "GET",
|
|
812
|
-
credentials,
|
|
813
|
-
headers: authHeaders()
|
|
814
|
-
}));
|
|
1057
|
+
return await organizationRead("", input, normalizeOrganizations);
|
|
815
1058
|
} catch (error) {
|
|
816
1059
|
throw fromOrganizationListError(error);
|
|
817
1060
|
}
|
|
818
1061
|
},
|
|
1062
|
+
getOrganization(organizationId) {
|
|
1063
|
+
return organizationRead(normalizeIdInput(organizationId), void 0, normalizeOrganization);
|
|
1064
|
+
},
|
|
1065
|
+
listOrganizationMembers(organizationId, input) {
|
|
1066
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/members`, input, normalizeOrganizationMembers);
|
|
1067
|
+
},
|
|
1068
|
+
listOrganizationTeams(organizationId, input) {
|
|
1069
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/teams`, input, normalizeOrganizationTeams);
|
|
1070
|
+
},
|
|
1071
|
+
listOrganizationTeamMembers(organizationId, teamId, input) {
|
|
1072
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/teams/${normalizeIdInput(teamId)}/members`, input, normalizeOrganizationTeamMembers);
|
|
1073
|
+
},
|
|
1074
|
+
listOrganizationInvitations(organizationId, input) {
|
|
1075
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/invitations`, input, normalizeOrganizationInvitations);
|
|
1076
|
+
},
|
|
1077
|
+
getOrganizationInvitation(organizationId, invitationId) {
|
|
1078
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/invitations/${normalizeIdInput(invitationId)}`, void 0, normalizeOrganizationInvitation);
|
|
1079
|
+
},
|
|
1080
|
+
listReceivedInvitations(input) {
|
|
1081
|
+
return organizationRead("received-invitations", input, normalizeReceivedInvitations);
|
|
1082
|
+
},
|
|
1083
|
+
getReceivedInvitation(invitationId) {
|
|
1084
|
+
return organizationRead(`received-invitations/${normalizeIdInput(invitationId)}`, void 0, normalizeReceivedInvitation);
|
|
1085
|
+
},
|
|
819
1086
|
async signInWithSocialIdToken(input) {
|
|
820
1087
|
if (authorization) throw new AuthError("state_conflict", 409);
|
|
821
1088
|
const body = socialIdTokenRequest(normalizeSocialIdTokenInput(input));
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
//#region src/errors.d.ts
|
|
2
|
+
type AuthErrorCode = "invalid_credentials" | "invalid_auth_input" | "account_conflict" | "password_reset_invalid" | "authentication_required" | "request_origin_denied" | "invalid_request" | "invalid_invitation" | "invitation_unavailable" | "invitation_recipient_mismatch" | "email_verification_required" | "invalid_workspace_selection" | "organization_context_too_large" | "credential_rate_limited" | "auth_request_rate_limited" | "state_conflict" | "access_denied" | "identity_authority_unavailable";
|
|
3
|
+
type AuthErrorStatus = 400 | 401 | 403 | 409 | 422 | 429 | 503;
|
|
4
|
+
declare class AuthError extends Error {
|
|
5
|
+
readonly code: AuthErrorCode;
|
|
6
|
+
readonly status: AuthErrorStatus;
|
|
7
|
+
readonly retryAfterSeconds?: number;
|
|
8
|
+
constructor(code: AuthErrorCode, status: AuthErrorStatus, retryAfterSeconds?: number);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/types.d.ts
|
|
12
|
+
interface AuthUser {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
email: string;
|
|
16
|
+
emailVerified: boolean;
|
|
17
|
+
image: string | null;
|
|
18
|
+
}
|
|
19
|
+
interface AuthSession {
|
|
20
|
+
id: string;
|
|
21
|
+
expiresAt: Date;
|
|
22
|
+
user: AuthUser;
|
|
23
|
+
}
|
|
24
|
+
interface AuthOrganization {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
slug: string;
|
|
28
|
+
logo: string | null;
|
|
29
|
+
lifecycle: "ordinary" | "managed";
|
|
30
|
+
role: "owner" | "admin" | "member";
|
|
31
|
+
capabilities: {
|
|
32
|
+
readMembers: true;
|
|
33
|
+
readTeams: true;
|
|
34
|
+
readInvitations: boolean;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
interface OrganizationPageInput {
|
|
38
|
+
limit?: number;
|
|
39
|
+
cursor?: string;
|
|
40
|
+
}
|
|
41
|
+
interface OrganizationPage {
|
|
42
|
+
organizations: AuthOrganization[];
|
|
43
|
+
nextCursor: string | null;
|
|
44
|
+
}
|
|
45
|
+
interface OrganizationMember {
|
|
46
|
+
id: string;
|
|
47
|
+
userId: string;
|
|
48
|
+
name: string;
|
|
49
|
+
email: string;
|
|
50
|
+
image: string | null;
|
|
51
|
+
role: "owner" | "admin" | "member";
|
|
52
|
+
owner: boolean;
|
|
53
|
+
joinedAt: Date;
|
|
54
|
+
teamIds: string[];
|
|
55
|
+
}
|
|
56
|
+
interface OrganizationMemberPage {
|
|
57
|
+
members: OrganizationMember[];
|
|
58
|
+
nextCursor: string | null;
|
|
59
|
+
}
|
|
60
|
+
interface OrganizationTeam {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
category: "manual" | "managed";
|
|
64
|
+
createdAt: Date;
|
|
65
|
+
}
|
|
66
|
+
interface OrganizationTeamPage {
|
|
67
|
+
teams: OrganizationTeam[];
|
|
68
|
+
nextCursor: string | null;
|
|
69
|
+
}
|
|
70
|
+
interface OrganizationTeamMemberPage {
|
|
71
|
+
memberIds: string[];
|
|
72
|
+
nextCursor: string | null;
|
|
73
|
+
}
|
|
74
|
+
interface OrganizationInvitation {
|
|
75
|
+
id: string;
|
|
76
|
+
email: string;
|
|
77
|
+
role: "owner" | "admin" | "member";
|
|
78
|
+
teamIds: string[];
|
|
79
|
+
inviter: {
|
|
80
|
+
membershipId: string;
|
|
81
|
+
name: string;
|
|
82
|
+
};
|
|
83
|
+
createdAt: Date;
|
|
84
|
+
expiresAt: Date;
|
|
85
|
+
status: "pending";
|
|
86
|
+
}
|
|
87
|
+
interface OrganizationInvitationPage {
|
|
88
|
+
invitations: OrganizationInvitation[];
|
|
89
|
+
nextCursor: string | null;
|
|
90
|
+
}
|
|
91
|
+
interface ReceivedOrganizationInvitation {
|
|
92
|
+
id: string;
|
|
93
|
+
organization: Pick<AuthOrganization, "id" | "name" | "slug" | "logo">;
|
|
94
|
+
role: "owner" | "admin" | "member";
|
|
95
|
+
teams: Array<{
|
|
96
|
+
id: string;
|
|
97
|
+
name: string;
|
|
98
|
+
}>;
|
|
99
|
+
inviterName: string;
|
|
100
|
+
expiresAt: Date;
|
|
101
|
+
}
|
|
102
|
+
interface ReceivedOrganizationInvitationPage {
|
|
103
|
+
invitations: ReceivedOrganizationInvitation[];
|
|
104
|
+
nextCursor: string | null;
|
|
105
|
+
}
|
|
106
|
+
interface AcceptInvitationInput {
|
|
107
|
+
invitationId: string;
|
|
108
|
+
}
|
|
109
|
+
interface InvitationAcceptance {
|
|
110
|
+
organizationId: string;
|
|
111
|
+
}
|
|
112
|
+
type AuthState = {
|
|
113
|
+
status: "loading";
|
|
114
|
+
} | {
|
|
115
|
+
status: "cached";
|
|
116
|
+
session: AuthSession;
|
|
117
|
+
authoritative: false;
|
|
118
|
+
} | {
|
|
119
|
+
status: "authenticated";
|
|
120
|
+
session: AuthSession;
|
|
121
|
+
authoritative: true;
|
|
122
|
+
} | {
|
|
123
|
+
status: "unauthenticated";
|
|
124
|
+
session: null;
|
|
125
|
+
authoritative: true;
|
|
126
|
+
} | {
|
|
127
|
+
status: "unavailable";
|
|
128
|
+
session: AuthSession | null;
|
|
129
|
+
authoritative: false;
|
|
130
|
+
};
|
|
131
|
+
interface AuthPersistenceDriver {
|
|
132
|
+
getItem(key: string): string | null | Promise<string | null>;
|
|
133
|
+
setItem(key: string, value: string): void | Promise<void>;
|
|
134
|
+
removeItem(key: string): void | Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
type AuthPersistence = "local" | "session" | "memory" | AuthPersistenceDriver;
|
|
137
|
+
interface PersonalWorkspaceSelection {
|
|
138
|
+
type: "personal";
|
|
139
|
+
}
|
|
140
|
+
interface OrganizationWorkspaceSelection {
|
|
141
|
+
type: "organization";
|
|
142
|
+
organizationId: string;
|
|
143
|
+
}
|
|
144
|
+
type WorkspaceSelection = PersonalWorkspaceSelection | OrganizationWorkspaceSelection;
|
|
145
|
+
interface DriveCredential {
|
|
146
|
+
tokenType: "Bearer";
|
|
147
|
+
token: string;
|
|
148
|
+
expiresAt: Date;
|
|
149
|
+
}
|
|
150
|
+
interface SignInInput {
|
|
151
|
+
email: string;
|
|
152
|
+
password: string;
|
|
153
|
+
}
|
|
154
|
+
type SocialIdTokenProvider = "google" | "apple";
|
|
155
|
+
interface SocialIdTokenInput {
|
|
156
|
+
provider: SocialIdTokenProvider;
|
|
157
|
+
idToken: string;
|
|
158
|
+
nonce?: string;
|
|
159
|
+
signUp: boolean;
|
|
160
|
+
}
|
|
161
|
+
interface UpdateProfileInput {
|
|
162
|
+
name?: string;
|
|
163
|
+
image?: string | null;
|
|
164
|
+
}
|
|
165
|
+
interface SendVerificationEmailInput {
|
|
166
|
+
email: string;
|
|
167
|
+
callbackURL?: string;
|
|
168
|
+
}
|
|
169
|
+
interface DriveCredentialInput {
|
|
170
|
+
workspace: WorkspaceSelection;
|
|
171
|
+
forceRefresh?: boolean;
|
|
172
|
+
}
|
|
173
|
+
interface AuthClientOptions {
|
|
174
|
+
authOrigin: string;
|
|
175
|
+
appOrigin: string;
|
|
176
|
+
fetch?: typeof globalThis.fetch;
|
|
177
|
+
now?: () => number;
|
|
178
|
+
persistence?: AuthPersistence;
|
|
179
|
+
timeoutMs?: number;
|
|
180
|
+
}
|
|
181
|
+
interface FinuevaAuthClient {
|
|
182
|
+
readonly _type: "browser";
|
|
183
|
+
acceptInvitation(input: AcceptInvitationInput): Promise<InvitationAcceptance>;
|
|
184
|
+
getSession(): Promise<AuthSession | null>;
|
|
185
|
+
listOrganizations(input?: OrganizationPageInput): Promise<OrganizationPage>;
|
|
186
|
+
getOrganization(organizationId: string): Promise<AuthOrganization>;
|
|
187
|
+
listOrganizationMembers(organizationId: string, input?: OrganizationPageInput): Promise<OrganizationMemberPage>;
|
|
188
|
+
listOrganizationTeams(organizationId: string, input?: OrganizationPageInput): Promise<OrganizationTeamPage>;
|
|
189
|
+
listOrganizationTeamMembers(organizationId: string, teamId: string, input?: OrganizationPageInput): Promise<OrganizationTeamMemberPage>;
|
|
190
|
+
listOrganizationInvitations(organizationId: string, input?: OrganizationPageInput): Promise<OrganizationInvitationPage>;
|
|
191
|
+
getOrganizationInvitation(organizationId: string, invitationId: string): Promise<OrganizationInvitation>;
|
|
192
|
+
listReceivedInvitations(input?: OrganizationPageInput): Promise<ReceivedOrganizationInvitationPage>;
|
|
193
|
+
getReceivedInvitation(invitationId: string): Promise<ReceivedOrganizationInvitation>;
|
|
194
|
+
sendVerificationEmail(input: SendVerificationEmailInput): Promise<void>;
|
|
195
|
+
signUp(email: string, password: string, name: string): Promise<AuthSession>;
|
|
196
|
+
signIn(input: SignInInput): Promise<AuthSession>;
|
|
197
|
+
signInWithSocialIdToken(input: SocialIdTokenInput): Promise<AuthSession>;
|
|
198
|
+
updateProfile(input: UpdateProfileInput): Promise<AuthSession>;
|
|
199
|
+
changePassword(currentPassword: string, newPassword: string, revokeOtherSessions?: boolean): Promise<AuthSession>;
|
|
200
|
+
requestPasswordReset(email: string, redirectTo: string): Promise<void>;
|
|
201
|
+
resetPassword(token: string, newPassword: string): Promise<void>;
|
|
202
|
+
signOut(): Promise<void>;
|
|
203
|
+
getDriveCredential(input: DriveCredentialInput): Promise<DriveCredential>;
|
|
204
|
+
onAuthStateChange(listener: (state: AuthState) => void): () => void;
|
|
205
|
+
onSessionChange(listener: (session: AuthSession | null) => void): () => void;
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
export { UpdateProfileInput as A, PersonalWorkspaceSelection as C, SignInInput as D, SendVerificationEmailInput as E, AuthError as M, AuthErrorCode as N, SocialIdTokenInput as O, AuthErrorStatus as P, OrganizationWorkspaceSelection as S, ReceivedOrganizationInvitationPage as T, OrganizationPage as _, AuthPersistenceDriver as a, OrganizationTeamMemberPage as b, AuthUser as c, FinuevaAuthClient as d, InvitationAcceptance as f, OrganizationMemberPage as g, OrganizationMember as h, AuthPersistence as i, WorkspaceSelection as j, SocialIdTokenProvider as k, DriveCredential as l, OrganizationInvitationPage as m, AuthClientOptions as n, AuthSession as o, OrganizationInvitation as p, AuthOrganization as r, AuthState as s, AcceptInvitationInput as t, DriveCredentialInput as u, OrganizationPageInput as v, ReceivedOrganizationInvitation as w, OrganizationTeamPage as x, OrganizationTeam as y };
|