@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/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", "saml", "email"];
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
- emailVerified: !!userData.confirmed_at,
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
- metadata: userMeta,
658
- appMetadata: appMeta,
659
- rawGoTrueData: { ...safeUserData }
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
- metadata: userMeta,
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
- if (!isBrowser()) {
920
- const params = new URLSearchParams();
921
- if (options?.page != null) params.set("page", String(options.page));
922
- if (options?.perPage != null) params.set("per_page", String(options.perPage));
923
- const query = params.toString();
924
- const path = `/admin/users${query ? `?${query}` : ""}`;
925
- const res = await adminFetch(path);
926
- const body = await res.json();
927
- return body.users.map(toUser);
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
- if (!isBrowser()) {
940
- const res = await adminFetch(`/admin/users/${userId}`);
941
- const userData = await res.json();
942
- return toUser(userData);
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
- if (!isBrowser()) {
955
- const res = await adminFetch("/admin/users", {
956
- method: "POST",
957
- body: JSON.stringify({
958
- email: params.email,
959
- password: params.password,
960
- ...params.data,
961
- confirm: true
962
- })
963
- });
964
- const userData = await res.json();
965
- return toUser(userData);
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
- if (!isBrowser()) {
981
- const res = await adminFetch(`/admin/users/${userId}`, {
982
- method: "PUT",
983
- body: JSON.stringify(attributes)
984
- });
985
- const userData = await res.json();
986
- return toUser(userData);
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
- if (!isBrowser()) {
999
- await adminFetch(`/admin/users/${userId}`, { method: "DELETE" });
1000
- return;
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 {