@netlify/identity 0.4.1 → 1.0.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 +50 -30
- package/dist/index.cjs +77 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -68
- package/dist/index.d.ts +73 -68
- package/dist/index.js +77 -97
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
// src/types.ts
|
|
9
|
-
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "
|
|
9
|
+
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "email"];
|
|
10
10
|
|
|
11
11
|
// src/environment.ts
|
|
12
12
|
import GoTrue from "gotrue-js";
|
|
@@ -631,6 +631,7 @@ var hydrateSession = async () => {
|
|
|
631
631
|
|
|
632
632
|
// src/user.ts
|
|
633
633
|
var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
|
|
634
|
+
var toOptionalString = (value) => typeof value === "string" && value !== "" ? value : void 0;
|
|
634
635
|
var toRoles = (appMeta) => {
|
|
635
636
|
const roles = appMeta.roles;
|
|
636
637
|
if (Array.isArray(roles) && roles.every((r) => typeof r === "string")) {
|
|
@@ -643,20 +644,25 @@ var toUser = (userData) => {
|
|
|
643
644
|
const appMeta = userData.app_metadata ?? {};
|
|
644
645
|
const name = userMeta.full_name || userMeta.name;
|
|
645
646
|
const pictureUrl = userMeta.avatar_url;
|
|
646
|
-
const { token: _token, ...safeUserData } = userData;
|
|
647
647
|
return {
|
|
648
648
|
id: userData.id,
|
|
649
649
|
email: userData.email,
|
|
650
|
-
|
|
650
|
+
confirmedAt: toOptionalString(userData.confirmed_at),
|
|
651
651
|
createdAt: userData.created_at,
|
|
652
652
|
updatedAt: userData.updated_at,
|
|
653
|
+
role: toOptionalString(userData.role),
|
|
653
654
|
provider: toAuthProvider(appMeta.provider),
|
|
654
655
|
name: typeof name === "string" ? name : void 0,
|
|
655
656
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
656
657
|
roles: toRoles(appMeta),
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
658
|
+
invitedAt: toOptionalString(userData.invited_at),
|
|
659
|
+
confirmationSentAt: toOptionalString(userData.confirmation_sent_at),
|
|
660
|
+
recoverySentAt: toOptionalString(userData.recovery_sent_at),
|
|
661
|
+
pendingEmail: toOptionalString(userData.new_email),
|
|
662
|
+
emailChangeSentAt: toOptionalString(userData.email_change_sent_at),
|
|
663
|
+
lastSignInAt: toOptionalString(userData.last_sign_in_at),
|
|
664
|
+
userMetadata: userMeta,
|
|
665
|
+
appMetadata: appMeta
|
|
660
666
|
};
|
|
661
667
|
};
|
|
662
668
|
var claimsToUser = (claims) => {
|
|
@@ -671,7 +677,7 @@ var claimsToUser = (claims) => {
|
|
|
671
677
|
name: typeof name === "string" ? name : void 0,
|
|
672
678
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
673
679
|
roles: toRoles(appMeta),
|
|
674
|
-
|
|
680
|
+
userMetadata: userMeta,
|
|
675
681
|
appMetadata: appMeta
|
|
676
682
|
};
|
|
677
683
|
};
|
|
@@ -768,8 +774,7 @@ var getSettings = async () => {
|
|
|
768
774
|
gitlab: external.gitlab ?? false,
|
|
769
775
|
bitbucket: external.bitbucket ?? false,
|
|
770
776
|
facebook: external.facebook ?? false,
|
|
771
|
-
email: external.email ?? false
|
|
772
|
-
saml: external.saml ?? false
|
|
777
|
+
email: external.email ?? false
|
|
773
778
|
}
|
|
774
779
|
};
|
|
775
780
|
} catch (err) {
|
|
@@ -876,6 +881,19 @@ var updateUser = async (updates) => {
|
|
|
876
881
|
};
|
|
877
882
|
|
|
878
883
|
// src/admin.ts
|
|
884
|
+
var SERVER_ONLY_MESSAGE = "Admin operations are server-only. Call admin methods from a Netlify Function or Edge Function, not from browser code.";
|
|
885
|
+
var sanitizeUserId = (userId) => {
|
|
886
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
887
|
+
if (!uuidRegex.test(userId)) {
|
|
888
|
+
throw new AuthError("User ID is not a valid UUID");
|
|
889
|
+
}
|
|
890
|
+
return encodeURIComponent(userId);
|
|
891
|
+
};
|
|
892
|
+
var assertServer = () => {
|
|
893
|
+
if (isBrowser()) {
|
|
894
|
+
throw new AuthError(SERVER_ONLY_MESSAGE);
|
|
895
|
+
}
|
|
896
|
+
};
|
|
879
897
|
var getAdminAuth = () => {
|
|
880
898
|
const ctx = getIdentityContext();
|
|
881
899
|
if (!ctx?.url) {
|
|
@@ -907,105 +925,67 @@ var adminFetch = async (path, options = {}) => {
|
|
|
907
925
|
}
|
|
908
926
|
return res;
|
|
909
927
|
};
|
|
910
|
-
var getAdminUser = () => {
|
|
911
|
-
const client = getClient();
|
|
912
|
-
const user = client.currentUser();
|
|
913
|
-
if (!user) {
|
|
914
|
-
throw new AuthError("Admin operations require a logged-in user with admin role");
|
|
915
|
-
}
|
|
916
|
-
return user;
|
|
917
|
-
};
|
|
918
928
|
var listUsers = async (options) => {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
try {
|
|
930
|
-
const user = getAdminUser();
|
|
931
|
-
const users = await user.admin.listUsers("");
|
|
932
|
-
return users.map(toUser);
|
|
933
|
-
} catch (error) {
|
|
934
|
-
if (error instanceof AuthError) throw error;
|
|
935
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
936
|
-
}
|
|
929
|
+
assertServer();
|
|
930
|
+
const params = new URLSearchParams();
|
|
931
|
+
if (options?.page != null) params.set("page", String(options.page));
|
|
932
|
+
if (options?.perPage != null) params.set("per_page", String(options.perPage));
|
|
933
|
+
const query = params.toString();
|
|
934
|
+
const path = `/admin/users${query ? `?${query}` : ""}`;
|
|
935
|
+
const res = await adminFetch(path);
|
|
936
|
+
const body = await res.json();
|
|
937
|
+
return body.users.map(toUser);
|
|
937
938
|
};
|
|
938
939
|
var getUser2 = async (userId) => {
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
try {
|
|
945
|
-
const user = getAdminUser();
|
|
946
|
-
const userData = await user.admin.getUser({ id: userId });
|
|
947
|
-
return toUser(userData);
|
|
948
|
-
} catch (error) {
|
|
949
|
-
if (error instanceof AuthError) throw error;
|
|
950
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
951
|
-
}
|
|
940
|
+
assertServer();
|
|
941
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
942
|
+
const res = await adminFetch(`/admin/users/${sanitizedUserId}`);
|
|
943
|
+
const userData = await res.json();
|
|
944
|
+
return toUser(userData);
|
|
952
945
|
};
|
|
953
946
|
var createUser = async (params) => {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
try {
|
|
968
|
-
const user = getAdminUser();
|
|
969
|
-
const userData = await user.admin.createUser(params.email, params.password, {
|
|
970
|
-
...params.data,
|
|
971
|
-
confirm: true
|
|
972
|
-
});
|
|
973
|
-
return toUser(userData);
|
|
974
|
-
} catch (error) {
|
|
975
|
-
if (error instanceof AuthError) throw error;
|
|
976
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
947
|
+
assertServer();
|
|
948
|
+
const body = {
|
|
949
|
+
email: params.email,
|
|
950
|
+
password: params.password,
|
|
951
|
+
confirm: true
|
|
952
|
+
};
|
|
953
|
+
if (params.data) {
|
|
954
|
+
const allowedKeys = ["role", "app_metadata", "user_metadata"];
|
|
955
|
+
for (const key of allowedKeys) {
|
|
956
|
+
if (key in params.data) {
|
|
957
|
+
body[key] = params.data[key];
|
|
958
|
+
}
|
|
959
|
+
}
|
|
977
960
|
}
|
|
961
|
+
const res = await adminFetch("/admin/users", {
|
|
962
|
+
method: "POST",
|
|
963
|
+
body: JSON.stringify(body)
|
|
964
|
+
});
|
|
965
|
+
const userData = await res.json();
|
|
966
|
+
return toUser(userData);
|
|
978
967
|
};
|
|
979
968
|
var updateUser2 = async (userId, attributes) => {
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
try {
|
|
989
|
-
const user = getAdminUser();
|
|
990
|
-
const userData = await user.admin.updateUser({ id: userId }, attributes);
|
|
991
|
-
return toUser(userData);
|
|
992
|
-
} catch (error) {
|
|
993
|
-
if (error instanceof AuthError) throw error;
|
|
994
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
969
|
+
assertServer();
|
|
970
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
971
|
+
const body = {};
|
|
972
|
+
const allowedKeys = ["email", "password", "role", "confirm", "app_metadata", "user_metadata"];
|
|
973
|
+
for (const key of allowedKeys) {
|
|
974
|
+
if (key in attributes) {
|
|
975
|
+
body[key] = attributes[key];
|
|
976
|
+
}
|
|
995
977
|
}
|
|
978
|
+
const res = await adminFetch(`/admin/users/${sanitizedUserId}`, {
|
|
979
|
+
method: "PUT",
|
|
980
|
+
body: JSON.stringify(body)
|
|
981
|
+
});
|
|
982
|
+
const userData = await res.json();
|
|
983
|
+
return toUser(userData);
|
|
996
984
|
};
|
|
997
985
|
var deleteUser = async (userId) => {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
}
|
|
1002
|
-
try {
|
|
1003
|
-
const user = getAdminUser();
|
|
1004
|
-
await user.admin.deleteUser({ id: userId });
|
|
1005
|
-
} catch (error) {
|
|
1006
|
-
if (error instanceof AuthError) throw error;
|
|
1007
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
1008
|
-
}
|
|
986
|
+
assertServer();
|
|
987
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
988
|
+
await adminFetch(`/admin/users/${sanitizedUserId}`, { method: "DELETE" });
|
|
1009
989
|
};
|
|
1010
990
|
var admin = { listUsers, getUser: getUser2, createUser, updateUser: updateUser2, deleteUser };
|
|
1011
991
|
export {
|