@stackframe/stack 2.5.32 → 2.5.35
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/CHANGELOG.md +30 -0
- package/dist/components/credential-sign-in.js +14 -12
- package/dist/components/credential-sign-in.js.map +1 -1
- package/dist/components/credential-sign-up.js +17 -15
- package/dist/components/credential-sign-up.js.map +1 -1
- package/dist/components/elements/maybe-full-page.d.mts +2 -2
- package/dist/components/elements/maybe-full-page.d.ts +2 -2
- package/dist/components/elements/sidebar-layout.d.mts +5 -5
- package/dist/components/elements/sidebar-layout.d.ts +5 -5
- package/dist/components/magic-link-sign-in.js +11 -9
- package/dist/components/magic-link-sign-in.js.map +1 -1
- package/dist/components/message-cards/message-card.d.mts +2 -2
- package/dist/components/message-cards/message-card.d.ts +2 -2
- package/dist/components/oauth-button-group.js.map +1 -1
- package/dist/components/oauth-button.js +48 -2
- package/dist/components/oauth-button.js.map +1 -1
- package/dist/components/profile-image-editor.js +5 -3
- package/dist/components/profile-image-editor.js.map +1 -1
- package/dist/components/selected-team-switcher.js +8 -5
- package/dist/components/selected-team-switcher.js.map +1 -1
- package/dist/components/team-icon.js.map +1 -1
- package/dist/components/user-button.d.mts +2 -2
- package/dist/components/user-button.d.ts +2 -2
- package/dist/components/user-button.js +11 -11
- package/dist/components/user-button.js.map +1 -1
- package/dist/components-page/account-settings.js +79 -66
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/auth-page.js +11 -7
- package/dist/components-page/auth-page.js.map +1 -1
- package/dist/components-page/email-verification.js +4 -2
- package/dist/components-page/email-verification.js.map +1 -1
- package/dist/components-page/error-page.js +6 -4
- package/dist/components-page/error-page.js.map +1 -1
- package/dist/components-page/forgot-password.js +12 -8
- package/dist/components-page/forgot-password.js.map +1 -1
- package/dist/components-page/magic-link-callback.js +5 -3
- package/dist/components-page/magic-link-callback.js.map +1 -1
- package/dist/components-page/oauth-callback.js +6 -5
- package/dist/components-page/oauth-callback.js.map +1 -1
- package/dist/components-page/password-reset.js +25 -22
- package/dist/components-page/password-reset.js.map +1 -1
- package/dist/components-page/team-creation.js +9 -7
- package/dist/components-page/team-creation.js.map +1 -1
- package/dist/components-page/team-invitation.js +14 -11
- package/dist/components-page/team-invitation.js.map +1 -1
- package/dist/esm/components/credential-sign-in.js +14 -12
- package/dist/esm/components/credential-sign-in.js.map +1 -1
- package/dist/esm/components/credential-sign-up.js +17 -15
- package/dist/esm/components/credential-sign-up.js.map +1 -1
- package/dist/esm/components/magic-link-sign-in.js +11 -9
- package/dist/esm/components/magic-link-sign-in.js.map +1 -1
- package/dist/esm/components/oauth-button-group.js.map +1 -1
- package/dist/esm/components/oauth-button.js +48 -2
- package/dist/esm/components/oauth-button.js.map +1 -1
- package/dist/esm/components/profile-image-editor.js +5 -3
- package/dist/esm/components/profile-image-editor.js.map +1 -1
- package/dist/esm/components/selected-team-switcher.js +8 -5
- package/dist/esm/components/selected-team-switcher.js.map +1 -1
- package/dist/esm/components/team-icon.js.map +1 -1
- package/dist/esm/components/user-button.js +12 -15
- package/dist/esm/components/user-button.js.map +1 -1
- package/dist/esm/components-page/account-settings.js +79 -66
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/auth-page.js +11 -7
- package/dist/esm/components-page/auth-page.js.map +1 -1
- package/dist/esm/components-page/email-verification.js +4 -2
- package/dist/esm/components-page/email-verification.js.map +1 -1
- package/dist/esm/components-page/error-page.js +6 -4
- package/dist/esm/components-page/error-page.js.map +1 -1
- package/dist/esm/components-page/forgot-password.js +12 -8
- package/dist/esm/components-page/forgot-password.js.map +1 -1
- package/dist/esm/components-page/magic-link-callback.js +5 -3
- package/dist/esm/components-page/magic-link-callback.js.map +1 -1
- package/dist/esm/components-page/oauth-callback.js +6 -5
- package/dist/esm/components-page/oauth-callback.js.map +1 -1
- package/dist/esm/components-page/password-reset.js +25 -22
- package/dist/esm/components-page/password-reset.js.map +1 -1
- package/dist/esm/components-page/team-creation.js +9 -7
- package/dist/esm/components-page/team-creation.js.map +1 -1
- package/dist/esm/components-page/team-invitation.js +14 -11
- package/dist/esm/components-page/team-invitation.js.map +1 -1
- package/dist/esm/generated/quetzal-translations.js +1425 -0
- package/dist/esm/generated/quetzal-translations.js.map +1 -0
- package/dist/esm/lib/stack-app.js +1 -1
- package/dist/esm/lib/translations.js +20 -0
- package/dist/esm/lib/translations.js.map +1 -0
- package/dist/esm/providers/stack-provider.js +4 -2
- package/dist/esm/providers/stack-provider.js.map +1 -1
- package/dist/esm/providers/theme-provider.js.map +1 -1
- package/dist/esm/providers/translation-provider-client.js +18 -0
- package/dist/esm/providers/translation-provider-client.js.map +1 -0
- package/dist/esm/providers/translation-provider.js +12 -0
- package/dist/esm/providers/translation-provider.js.map +1 -0
- package/dist/esm/utils/browser-script.js +38 -6
- package/dist/esm/utils/browser-script.js.map +1 -1
- package/dist/generated/quetzal-translations.d.mts +4 -0
- package/dist/generated/quetzal-translations.d.ts +4 -0
- package/dist/generated/quetzal-translations.js +1451 -0
- package/dist/generated/quetzal-translations.js.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/lib/stack-app.js +1 -1
- package/dist/lib/translations.d.mts +5 -0
- package/dist/lib/translations.d.ts +5 -0
- package/dist/lib/translations.js +55 -0
- package/dist/lib/translations.js.map +1 -0
- package/dist/providers/stack-provider-client.d.mts +3 -3
- package/dist/providers/stack-provider-client.d.ts +3 -3
- package/dist/providers/stack-provider.d.mts +6 -3
- package/dist/providers/stack-provider.d.ts +6 -3
- package/dist/providers/stack-provider.js +4 -2
- package/dist/providers/stack-provider.js.map +1 -1
- package/dist/providers/theme-provider.d.mts +2 -2
- package/dist/providers/theme-provider.d.ts +2 -2
- package/dist/providers/theme-provider.js.map +1 -1
- package/dist/providers/translation-provider-client.d.mts +14 -0
- package/dist/providers/translation-provider-client.d.ts +14 -0
- package/dist/providers/translation-provider-client.js +43 -0
- package/dist/providers/translation-provider-client.js.map +1 -0
- package/dist/providers/translation-provider.d.mts +9 -0
- package/dist/providers/translation-provider.d.ts +9 -0
- package/dist/providers/translation-provider.js +37 -0
- package/dist/providers/translation-provider.js.map +1 -0
- package/dist/utils/browser-script.js +38 -6
- package/dist/utils/browser-script.js.map +1 -1
- package/package.json +20 -12
|
@@ -57,8 +57,10 @@ var import_user_avatar = require("../components/elements/user-avatar");
|
|
|
57
57
|
var import_profile_image_editor = require("../components/profile-image-editor");
|
|
58
58
|
var import_team_icon = require("../components/team-icon");
|
|
59
59
|
var import_maybe_full_page = require("../components/elements/maybe-full-page");
|
|
60
|
+
var import_translations = require("../lib/translations");
|
|
60
61
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
61
62
|
function AccountSettings(props) {
|
|
63
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
62
64
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
63
65
|
const teams = user.useTeams();
|
|
64
66
|
const stackApp = (0, import__.useStackApp)();
|
|
@@ -68,14 +70,14 @@ function AccountSettings(props) {
|
|
|
68
70
|
{
|
|
69
71
|
items: [
|
|
70
72
|
{
|
|
71
|
-
title: "My Profile",
|
|
73
|
+
title: t("My Profile"),
|
|
72
74
|
type: "item",
|
|
73
75
|
subpath: "/profile",
|
|
74
76
|
icon: import_lucide_react.Contact,
|
|
75
77
|
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfileSection, {})
|
|
76
78
|
},
|
|
77
79
|
{
|
|
78
|
-
title: "Security",
|
|
80
|
+
title: t("Security"),
|
|
79
81
|
type: "item",
|
|
80
82
|
icon: import_lucide_react.ShieldCheck,
|
|
81
83
|
subpath: "/security",
|
|
@@ -86,7 +88,7 @@ function AccountSettings(props) {
|
|
|
86
88
|
] })
|
|
87
89
|
},
|
|
88
90
|
{
|
|
89
|
-
title: "Sign Out",
|
|
91
|
+
title: t("Sign Out"),
|
|
90
92
|
subpath: "/sign-out",
|
|
91
93
|
type: "item",
|
|
92
94
|
icon: import_lucide_react.LogOut,
|
|
@@ -100,7 +102,7 @@ function AccountSettings(props) {
|
|
|
100
102
|
content: item.content
|
|
101
103
|
})) || [],
|
|
102
104
|
...teams.length > 0 || project.config.clientTeamCreationEnabled ? [{
|
|
103
|
-
title: "Teams",
|
|
105
|
+
title: t("Teams"),
|
|
104
106
|
type: "divider"
|
|
105
107
|
}] : [],
|
|
106
108
|
...teams.map((team) => ({
|
|
@@ -119,23 +121,24 @@ function AccountSettings(props) {
|
|
|
119
121
|
] })
|
|
120
122
|
})),
|
|
121
123
|
...project.config.clientTeamCreationEnabled ? [{
|
|
122
|
-
title: "Create a team",
|
|
124
|
+
title: t("Create a team"),
|
|
123
125
|
icon: import_lucide_react.CirclePlus,
|
|
124
126
|
type: "item",
|
|
125
127
|
subpath: "/team-creation",
|
|
126
128
|
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TeamCreation, {})
|
|
127
129
|
}] : []
|
|
128
130
|
].filter((p) => p.type === "divider" || p.content),
|
|
129
|
-
title: "Account Settings",
|
|
131
|
+
title: t("Account Settings"),
|
|
130
132
|
basePath: stackApp.urls.accountSettings
|
|
131
133
|
}
|
|
132
134
|
) }) });
|
|
133
135
|
}
|
|
134
136
|
function ProfileSection() {
|
|
137
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
135
138
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
136
139
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-8", children: [
|
|
137
140
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-start", children: [
|
|
138
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { className: "mb-2", children: "Profile image" }),
|
|
141
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { className: "mb-2", children: t("Profile image") }),
|
|
139
142
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
140
143
|
import_profile_image_editor.ProfileImageEditor,
|
|
141
144
|
{
|
|
@@ -147,7 +150,7 @@ function ProfileSection() {
|
|
|
147
150
|
)
|
|
148
151
|
] }),
|
|
149
152
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col", children: [
|
|
150
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Display name" }),
|
|
153
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Display name") }),
|
|
151
154
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.EditableText, { value: user.displayName || "", onSave: async (newDisplayName) => {
|
|
152
155
|
await user.update({ displayName: newDisplayName });
|
|
153
156
|
} })
|
|
@@ -155,15 +158,16 @@ function ProfileSection() {
|
|
|
155
158
|
] });
|
|
156
159
|
}
|
|
157
160
|
function EmailVerificationSection() {
|
|
161
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
158
162
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
159
163
|
const [emailSent, setEmailSent] = (0, import_react.useState)(false);
|
|
160
164
|
if (!user.primaryEmail) {
|
|
161
165
|
return null;
|
|
162
166
|
}
|
|
163
167
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
164
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Email Verification" }),
|
|
165
|
-
user.primaryEmailVerified ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: "Your email has been verified." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
166
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: "Your email has not been verified." }),
|
|
168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Email Verification") }),
|
|
169
|
+
user.primaryEmailVerified ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: t("Your email has been verified.") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
170
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Your email has not been verified.") }),
|
|
167
171
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
168
172
|
import_stack_ui.Button,
|
|
169
173
|
{
|
|
@@ -172,28 +176,29 @@ function EmailVerificationSection() {
|
|
|
172
176
|
await user.sendVerificationEmail();
|
|
173
177
|
setEmailSent(true);
|
|
174
178
|
},
|
|
175
|
-
children: emailSent ? "Email sent!" : "Send Verification Email"
|
|
179
|
+
children: emailSent ? t("Email sent!") : t("Send Verification Email")
|
|
176
180
|
}
|
|
177
181
|
) })
|
|
178
182
|
] })
|
|
179
183
|
] }) });
|
|
180
184
|
}
|
|
181
|
-
var passwordSchema = (0, import_schema_fields.yupObject)({
|
|
182
|
-
oldPassword: (0, import_schema_fields.yupString)().required("Please enter your old password"),
|
|
183
|
-
newPassword: (0, import_schema_fields.yupString)().required("Please enter your password").test({
|
|
184
|
-
name: "is-valid-password",
|
|
185
|
-
test: (value, ctx) => {
|
|
186
|
-
const error = (0, import_password.getPasswordError)(value);
|
|
187
|
-
if (error) {
|
|
188
|
-
return ctx.createError({ message: error.message });
|
|
189
|
-
} else {
|
|
190
|
-
return true;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}),
|
|
194
|
-
newPasswordRepeat: (0, import_schema_fields.yupString)().nullable().oneOf([yup.ref("newPassword"), "", null], "Passwords do not match").required("Please repeat your password")
|
|
195
|
-
});
|
|
196
185
|
function PasswordSection() {
|
|
186
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
187
|
+
const passwordSchema = (0, import_schema_fields.yupObject)({
|
|
188
|
+
oldPassword: (0, import_schema_fields.yupString)().required(t("Please enter your old password")),
|
|
189
|
+
newPassword: (0, import_schema_fields.yupString)().required(t("Please enter your password")).test({
|
|
190
|
+
name: "is-valid-password",
|
|
191
|
+
test: (value, ctx) => {
|
|
192
|
+
const error = (0, import_password.getPasswordError)(value);
|
|
193
|
+
if (error) {
|
|
194
|
+
return ctx.createError({ message: error.message });
|
|
195
|
+
} else {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}),
|
|
200
|
+
newPasswordRepeat: (0, import_schema_fields.yupString)().nullable().oneOf([yup.ref("newPassword"), "", null], t("Passwords do not match")).required(t("Please repeat your password"))
|
|
201
|
+
});
|
|
197
202
|
const user = (0, import__.useUser)({ or: "throw" });
|
|
198
203
|
const [changingPassword, setChangingPassword] = (0, import_react.useState)(false);
|
|
199
204
|
const { register, handleSubmit, setError, formState: { errors }, clearErrors, reset } = (0, import_react_hook_form.useForm)({
|
|
@@ -207,7 +212,7 @@ function PasswordSection() {
|
|
|
207
212
|
const { oldPassword, newPassword } = data;
|
|
208
213
|
const error = await user.updatePassword({ oldPassword, newPassword });
|
|
209
214
|
if (error) {
|
|
210
|
-
setError("oldPassword", { type: "manual", message: "Incorrect password" });
|
|
215
|
+
setError("oldPassword", { type: "manual", message: t("Incorrect password") });
|
|
211
216
|
} else {
|
|
212
217
|
reset();
|
|
213
218
|
setAlreadyReset(true);
|
|
@@ -222,15 +227,15 @@ function PasswordSection() {
|
|
|
222
227
|
return null;
|
|
223
228
|
}
|
|
224
229
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
225
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Change password" }),
|
|
226
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: alreadyReset ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: "Password changed successfully!" }) : !changingPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
230
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Change password") }),
|
|
231
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: alreadyReset ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: t("Password changed successfully!") }) : !changingPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
227
232
|
import_stack_ui.Button,
|
|
228
233
|
{
|
|
229
234
|
variant: "secondary",
|
|
230
235
|
onClick: async () => {
|
|
231
236
|
setChangingPassword(true);
|
|
232
237
|
},
|
|
233
|
-
children: "Change Password"
|
|
238
|
+
children: t("Change Password")
|
|
234
239
|
}
|
|
235
240
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
236
241
|
"form",
|
|
@@ -238,7 +243,7 @@ function PasswordSection() {
|
|
|
238
243
|
onSubmit: (e) => (0, import_promises.runAsynchronouslyWithAlert)(handleSubmit(onSubmit)(e)),
|
|
239
244
|
noValidate: true,
|
|
240
245
|
children: [
|
|
241
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "old-password", className: "mb-1", children: "Old password" }),
|
|
246
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "old-password", className: "mb-1", children: t("Old password") }),
|
|
242
247
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
243
248
|
import_stack_ui.Input,
|
|
244
249
|
{
|
|
@@ -248,7 +253,7 @@ function PasswordSection() {
|
|
|
248
253
|
}
|
|
249
254
|
),
|
|
250
255
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.oldPassword?.message?.toString() }),
|
|
251
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "new-password", className: "mt-4 mb-1", children: "Password" }),
|
|
256
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "new-password", className: "mt-4 mb-1", children: t("Password") }),
|
|
252
257
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
253
258
|
import_stack_ui.PasswordInput,
|
|
254
259
|
{
|
|
@@ -262,7 +267,7 @@ function PasswordSection() {
|
|
|
262
267
|
}
|
|
263
268
|
),
|
|
264
269
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.newPassword?.message?.toString() }),
|
|
265
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "repeat-password", className: "mt-4 mb-1", children: "Repeat password" }),
|
|
270
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "repeat-password", className: "mt-4 mb-1", children: t("Repeat password") }),
|
|
266
271
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
267
272
|
import_stack_ui.PasswordInput,
|
|
268
273
|
{
|
|
@@ -276,13 +281,14 @@ function PasswordSection() {
|
|
|
276
281
|
}
|
|
277
282
|
),
|
|
278
283
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.newPasswordRepeat?.message?.toString() }),
|
|
279
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", className: "mt-6", loading, children: "Change Password" })
|
|
284
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", className: "mt-6", loading, children: t("Change Password") })
|
|
280
285
|
]
|
|
281
286
|
}
|
|
282
287
|
) })
|
|
283
288
|
] });
|
|
284
289
|
}
|
|
285
290
|
function MfaSection() {
|
|
291
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
286
292
|
const project = (0, import__.useStackApp)().useProject();
|
|
287
293
|
const user = (0, import__.useUser)({ or: "throw" });
|
|
288
294
|
const [generatedSecret, setGeneratedSecret] = (0, import_react.useState)(null);
|
|
@@ -308,12 +314,12 @@ function MfaSection() {
|
|
|
308
314
|
});
|
|
309
315
|
}, [mfaCode, generatedSecret, handleSubmit]);
|
|
310
316
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
311
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Multi-factor Authentication" }),
|
|
317
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Multi-factor Authentication") }),
|
|
312
318
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
313
|
-
isEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: "Multi-factor authentication is currently enabled." }) : generatedSecret ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-4 items-center", children: [
|
|
314
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: "Scan this QR code with your authenticator app:" }),
|
|
315
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { width: 200, height: 200, src: qrCodeUrl ?? (0, import_errors.throwErr)("TOTP QR code failed to generate"), alt: "TOTP multi-factor authentication QR code" }),
|
|
316
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: "Then, enter your six-digit MFA code:" }),
|
|
319
|
+
isEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: t("Multi-factor authentication is currently enabled.") }) : generatedSecret ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-4 items-center", children: [
|
|
320
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: t("Scan this QR code with your authenticator app:") }),
|
|
321
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { width: 200, height: 200, src: qrCodeUrl ?? (0, import_errors.throwErr)("TOTP QR code failed to generate"), alt: t("TOTP multi-factor authentication QR code") }),
|
|
322
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: t("Then, enter your six-digit MFA code:") }),
|
|
317
323
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
318
324
|
import_stack_ui.Input,
|
|
319
325
|
{
|
|
@@ -327,8 +333,8 @@ function MfaSection() {
|
|
|
327
333
|
disabled: isLoading
|
|
328
334
|
}
|
|
329
335
|
),
|
|
330
|
-
isMaybeWrong && mfaCode.length === 6 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: "Incorrect code. Please try again." })
|
|
331
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: "Multi-factor authentication is currently disabled." }),
|
|
336
|
+
isMaybeWrong && mfaCode.length === 6 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Incorrect code. Please try again.") })
|
|
337
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Multi-factor authentication is currently disabled.") }),
|
|
332
338
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
333
339
|
import_stack_ui.Button,
|
|
334
340
|
{
|
|
@@ -349,7 +355,7 @@ function MfaSection() {
|
|
|
349
355
|
setMfaCode("");
|
|
350
356
|
}
|
|
351
357
|
},
|
|
352
|
-
children: isEnabled ? "Disable" : generatedSecret ? "Cancel" : "Enable"
|
|
358
|
+
children: isEnabled ? t("Disable") : generatedSecret ? t("Cancel") : t("Enable")
|
|
353
359
|
}
|
|
354
360
|
)
|
|
355
361
|
] })
|
|
@@ -360,17 +366,19 @@ async function generateTotpQrCode(project, user, secret) {
|
|
|
360
366
|
return await QRCode.toDataURL(uri);
|
|
361
367
|
}
|
|
362
368
|
function SignOutSection() {
|
|
369
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
363
370
|
const user = (0, import__.useUser)({ or: "throw" });
|
|
364
371
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
365
372
|
import_stack_ui.Button,
|
|
366
373
|
{
|
|
367
374
|
variant: "secondary",
|
|
368
375
|
onClick: () => user.signOut(),
|
|
369
|
-
children: "Sign Out"
|
|
376
|
+
children: t("Sign Out")
|
|
370
377
|
}
|
|
371
378
|
) }) });
|
|
372
379
|
}
|
|
373
380
|
function UserSettings(props) {
|
|
381
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
374
382
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
375
383
|
const [leaving, setLeaving] = (0, import_react.useState)(false);
|
|
376
384
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: !leaving ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -378,20 +386,21 @@ function UserSettings(props) {
|
|
|
378
386
|
{
|
|
379
387
|
variant: "secondary",
|
|
380
388
|
onClick: async () => setLeaving(true),
|
|
381
|
-
children: "Leave team"
|
|
389
|
+
children: t("Leave team")
|
|
382
390
|
}
|
|
383
391
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "", children: [
|
|
384
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: "Are you sure you want to leave the team?" }),
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Are you sure you want to leave the team?") }),
|
|
385
393
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-2", children: [
|
|
386
394
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { variant: "destructive", onClick: async () => {
|
|
387
395
|
await user.leaveTeam(props.team);
|
|
388
396
|
window.location.reload();
|
|
389
|
-
}, children: "Leave" }),
|
|
390
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { variant: "secondary", onClick: () => setLeaving(false), children: "Cancel" })
|
|
397
|
+
}, children: t("Leave") }),
|
|
398
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { variant: "secondary", onClick: () => setLeaving(false), children: t("Cancel") })
|
|
391
399
|
] })
|
|
392
400
|
] }) }) });
|
|
393
401
|
}
|
|
394
402
|
function ManagementSettings(props) {
|
|
403
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
395
404
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
396
405
|
const updateTeamPermission = user.usePermission(props.team, "$update_team");
|
|
397
406
|
if (!updateTeamPermission) {
|
|
@@ -399,7 +408,7 @@ function ManagementSettings(props) {
|
|
|
399
408
|
}
|
|
400
409
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
401
410
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col", children: [
|
|
402
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Team display name" }),
|
|
411
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Team display name") }),
|
|
403
412
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
404
413
|
import_profile_image_editor.ProfileImageEditor,
|
|
405
414
|
{
|
|
@@ -411,7 +420,7 @@ function ManagementSettings(props) {
|
|
|
411
420
|
)
|
|
412
421
|
] }),
|
|
413
422
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col", children: [
|
|
414
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Team display name" }),
|
|
423
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Team display name") }),
|
|
415
424
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
416
425
|
import_stack_ui.EditableText,
|
|
417
426
|
{
|
|
@@ -423,11 +432,12 @@ function ManagementSettings(props) {
|
|
|
423
432
|
] });
|
|
424
433
|
}
|
|
425
434
|
function ProfileSettings(props) {
|
|
435
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
426
436
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
427
437
|
const profile = user.useTeamProfile(props.team);
|
|
428
438
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col", children: [
|
|
429
439
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Label, { className: "flex gap-2", children: [
|
|
430
|
-
"User display name
|
|
440
|
+
t("User display name"),
|
|
431
441
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.SimpleTooltip, { tooltip: "This overwrites your user display name in the account setting", type: "info" })
|
|
432
442
|
] }),
|
|
433
443
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -441,10 +451,11 @@ function ProfileSettings(props) {
|
|
|
441
451
|
)
|
|
442
452
|
] }) });
|
|
443
453
|
}
|
|
444
|
-
var invitationSchema = (0, import_schema_fields.yupObject)({
|
|
445
|
-
email: (0, import_schema_fields.yupString)().email().required("Please enter an email address")
|
|
446
|
-
});
|
|
447
454
|
function MemberInvitation(props) {
|
|
455
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
456
|
+
const invitationSchema = (0, import_schema_fields.yupObject)({
|
|
457
|
+
email: (0, import_schema_fields.yupString)().email().required(t("Please enter an email address"))
|
|
458
|
+
});
|
|
448
459
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
449
460
|
const inviteMemberPermission = user.usePermission(props.team, "$invite_members");
|
|
450
461
|
if (!inviteMemberPermission) {
|
|
@@ -468,7 +479,7 @@ function MemberInvitation(props) {
|
|
|
468
479
|
setInvitedEmail(null);
|
|
469
480
|
}, [watch("email")]);
|
|
470
481
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
471
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Invite a user to team" }),
|
|
482
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Invite a user to team") }),
|
|
472
483
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
473
484
|
"form",
|
|
474
485
|
{
|
|
@@ -479,11 +490,11 @@ function MemberInvitation(props) {
|
|
|
479
490
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
480
491
|
import_stack_ui.Input,
|
|
481
492
|
{
|
|
482
|
-
placeholder: "Email",
|
|
493
|
+
placeholder: t("Email"),
|
|
483
494
|
...register("email")
|
|
484
495
|
}
|
|
485
496
|
) }),
|
|
486
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", loading, children: "Invite User" })
|
|
497
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", loading, children: t("Invite User") })
|
|
487
498
|
] }),
|
|
488
499
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.email?.message?.toString() }),
|
|
489
500
|
invitedEmail && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Typography, { type: "label", variant: "secondary", children: [
|
|
@@ -496,6 +507,7 @@ function MemberInvitation(props) {
|
|
|
496
507
|
] });
|
|
497
508
|
}
|
|
498
509
|
function MembersSettings(props) {
|
|
510
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
499
511
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
500
512
|
const readMemberPermission = user.usePermission(props.team, "$read_members");
|
|
501
513
|
const inviteMemberPermission = user.usePermission(props.team, "$invite_members");
|
|
@@ -507,11 +519,11 @@ function MembersSettings(props) {
|
|
|
507
519
|
return null;
|
|
508
520
|
}
|
|
509
521
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
510
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Members" }),
|
|
522
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Members") }),
|
|
511
523
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Table, { children: [
|
|
512
524
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.TableRow, { children: [
|
|
513
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[100px]", children: "User" }),
|
|
514
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[200px]", children: "Name" })
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[100px]", children: t("User") }),
|
|
526
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[200px]", children: t("Name") })
|
|
515
527
|
] }) }),
|
|
516
528
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableBody, { children: users.map(({ id, teamProfile }, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.TableRow, { children: [
|
|
517
529
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_user_avatar.UserAvatar, { user: teamProfile }) }),
|
|
@@ -520,10 +532,11 @@ function MembersSettings(props) {
|
|
|
520
532
|
] })
|
|
521
533
|
] });
|
|
522
534
|
}
|
|
523
|
-
var teamCreationSchema = (0, import_schema_fields.yupObject)({
|
|
524
|
-
displayName: (0, import_schema_fields.yupString)().required("Please enter a team name")
|
|
525
|
-
});
|
|
526
535
|
function TeamCreation() {
|
|
536
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
537
|
+
const teamCreationSchema = (0, import_schema_fields.yupObject)({
|
|
538
|
+
displayName: (0, import_schema_fields.yupString)().required(t("Please enter a team name"))
|
|
539
|
+
});
|
|
527
540
|
const { register, handleSubmit, formState: { errors } } = (0, import_react_hook_form.useForm)({
|
|
528
541
|
resolver: (0, import_yup.yupResolver)(teamCreationSchema)
|
|
529
542
|
});
|
|
@@ -532,7 +545,7 @@ function TeamCreation() {
|
|
|
532
545
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
533
546
|
const [loading, setLoading] = (0, import_react.useState)(false);
|
|
534
547
|
if (!project.config.clientTeamCreationEnabled) {
|
|
535
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.MessageCard, { title: "Team creation is not enabled" });
|
|
548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.MessageCard, { title: t("Team creation is not enabled") });
|
|
536
549
|
}
|
|
537
550
|
const onSubmit = async (data) => {
|
|
538
551
|
setLoading(true);
|
|
@@ -550,7 +563,7 @@ function TeamCreation() {
|
|
|
550
563
|
noValidate: true,
|
|
551
564
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-end gap-4", children: [
|
|
552
565
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
553
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "email", className: "mb-1", children: "Display name" }),
|
|
566
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "email", className: "mb-1", children: t("Display name") }),
|
|
554
567
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
555
568
|
import_stack_ui.Input,
|
|
556
569
|
{
|
|
@@ -561,7 +574,7 @@ function TeamCreation() {
|
|
|
561
574
|
)
|
|
562
575
|
] }),
|
|
563
576
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.displayName?.message?.toString() }),
|
|
564
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", className: "mt-6", loading, children: "Create" })
|
|
577
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", className: "mt-6", loading, children: t("Create") })
|
|
565
578
|
] })
|
|
566
579
|
}
|
|
567
580
|
) }) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components-page/account-settings.tsx"],"sourcesContent":["'use client';\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { getPasswordError } from '@stackframe/stack-shared/dist/helpers/password';\nimport { useAsyncCallback } from '@stackframe/stack-shared/dist/hooks/use-async-callback';\nimport { yupObject, yupString } from '@stackframe/stack-shared/dist/schema-fields';\nimport { generateRandomValues } from '@stackframe/stack-shared/dist/utils/crypto';\nimport { throwErr } from '@stackframe/stack-shared/dist/utils/errors';\nimport { runAsynchronously, runAsynchronouslyWithAlert } from '@stackframe/stack-shared/dist/utils/promises';\nimport { Button, EditableText, Input, Label, PasswordInput, SimpleTooltip, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from '@stackframe/stack-ui';\nimport { CirclePlus, Contact, LogOut, ShieldCheck, LucideIcon } from 'lucide-react';\nimport { TOTPController, createTOTPKeyURI } from \"oslo/otp\";\nimport * as QRCode from 'qrcode';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport * as yup from \"yup\";\nimport { CurrentUser, MessageCard, Project, Team, useStackApp, useUser } from '..';\nimport { FormWarningText } from '../components/elements/form-warning';\nimport { SidebarLayout } from '../components/elements/sidebar-layout';\nimport { UserAvatar } from '../components/elements/user-avatar';\nimport { ProfileImageEditor } from \"../components/profile-image-editor\";\nimport { TeamIcon } from '../components/team-icon';\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\n\n\nexport function AccountSettings(props: {\n fullPage?: boolean,\n extraItems?: {\n title: string,\n icon: LucideIcon,\n content: React.ReactNode,\n subpath: string,\n }[],\n}) {\n const user = useUser({ or: 'redirect' });\n const teams = user.useTeams();\n const stackApp = useStackApp();\n const project = stackApp.useProject();\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div style={{ alignSelf: 'stretch', flexGrow: 1 }}>\n <SidebarLayout\n items={([\n {\n title: 'My Profile',\n type: 'item',\n subpath: '/profile',\n icon: Contact,\n content: <ProfileSection/>,\n },\n {\n title: 'Security',\n type: 'item',\n icon: ShieldCheck,\n subpath: '/security',\n content: (\n <div className='flex flex-col gap-8'>\n <EmailVerificationSection />\n <PasswordSection />\n <MfaSection />\n </div>\n ),\n },\n {\n title: 'Sign Out',\n subpath: '/sign-out',\n type: 'item',\n icon: LogOut,\n content: <SignOutSection />,\n },\n ...(props.extraItems?.map(item => ({\n title: item.title,\n type: 'item',\n subpath: item.subpath,\n icon: item.icon,\n content: item.content,\n } as const)) || []),\n ...(teams.length > 0 || project.config.clientTeamCreationEnabled) ? [{\n title: 'Teams',\n type: 'divider',\n }] as const : [],\n ...teams.map(team => ({\n title: <div className='flex gap-2 items-center'>\n <TeamIcon team={team}/>\n {team.displayName}\n </div>,\n type: 'item',\n subpath: `/teams/${team.id}`,\n content: (\n <div className=\"flex flex-col gap-8\">\n <ProfileSettings team={team}/>\n <ManagementSettings team={team}/>\n <MemberInvitation team={team}/>\n <MembersSettings team={team}/>\n <UserSettings team={team}/>\n </div>\n ),\n } as const)),\n ...project.config.clientTeamCreationEnabled ? [{\n title: 'Create a team',\n icon: CirclePlus,\n type: 'item',\n subpath: '/team-creation',\n content: <TeamCreation />,\n }] as const : [],\n ] as const).filter((p) => p.type === 'divider' || (p as any).content )}\n title='Account Settings'\n basePath={stackApp.urls.accountSettings}\n />\n </div>\n </MaybeFullPage>\n );\n}\n\nfunction ProfileSection() {\n const user = useUser({ or: 'redirect' });\n\n return (\n <div className='flex flex-col gap-8'>\n <div className='flex flex-col items-start'>\n <Label className=\"mb-2\">Profile image</Label>\n <ProfileImageEditor\n user={user}\n onProfileImageUrlChange={async (profileImageUrl) => {\n await user.update({ profileImageUrl });\n }}\n />\n </div>\n <div className='flex flex-col'>\n <Label>Display name</Label>\n <EditableText value={user.displayName || ''} onSave={async (newDisplayName) => {\n await user.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nfunction EmailVerificationSection() {\n const user = useUser({ or: 'redirect' });\n const [emailSent, setEmailSent] = useState(false);\n\n if (!user.primaryEmail) {\n return null;\n }\n\n return (\n <>\n <div>\n <Label>Email Verification</Label>\n {user.primaryEmailVerified ? (\n <Typography variant='success'>Your email has been verified.</Typography>\n ) : (\n <>\n <Typography variant='destructive'>Your email has not been verified.</Typography>\n <div className='flex mt-4'>\n <Button\n disabled={emailSent}\n onClick={async () => {\n await user.sendVerificationEmail();\n setEmailSent(true);\n }}\n >\n {emailSent ? 'Email sent!' : 'Send Verification Email'}\n </Button>\n </div>\n </>\n )}\n\n </div>\n </>\n );\n}\n\nconst passwordSchema = yupObject({\n oldPassword: yupString().required('Please enter your old password'),\n newPassword: yupString().required('Please enter your password').test({\n name: 'is-valid-password',\n test: (value, ctx) => {\n const error = getPasswordError(value);\n if (error) {\n return ctx.createError({ message: error.message });\n } else {\n return true;\n }\n }\n }),\n newPasswordRepeat: yupString().nullable().oneOf([yup.ref('newPassword'), \"\", null], 'Passwords do not match').required('Please repeat your password')\n});\n\nfunction PasswordSection() {\n const user = useUser({ or: \"throw\" });\n const [changingPassword, setChangingPassword] = useState(false);\n const { register, handleSubmit, setError, formState: { errors }, clearErrors, reset } = useForm({\n resolver: yupResolver(passwordSchema)\n });\n const [alreadyReset, setAlreadyReset] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof passwordSchema>) => {\n setLoading(true);\n try {\n const { oldPassword, newPassword } = data;\n const error = await user.updatePassword({ oldPassword, newPassword });\n if (error) {\n setError('oldPassword', { type: 'manual', message: 'Incorrect password' });\n } else {\n reset();\n setAlreadyReset(true);\n }\n } finally {\n setLoading(false);\n }\n };\n\n const registerPassword = register('newPassword');\n const registerPasswordRepeat = register('newPasswordRepeat');\n\n if (!user.hasPassword) {\n return null;\n }\n\n return (\n <div>\n <Label>Change password</Label>\n <div>\n {\n alreadyReset ?\n <Typography variant='success'>Password changed successfully!</Typography> :\n !changingPassword ?\n <Button\n variant='secondary'\n onClick={async () => {\n setChangingPassword(true);\n }}\n >\n Change Password\n </Button> :\n <form\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"old-password\" className=\"mb-1\">Old password</Label>\n <Input\n id=\"old-password\"\n type=\"password\"\n {...register('oldPassword')}\n />\n <FormWarningText text={errors.oldPassword?.message?.toString()} />\n\n <Label htmlFor=\"new-password\" className=\"mt-4 mb-1\">Password</Label>\n <PasswordInput\n id=\"new-password\"\n {...registerPassword}\n onChange={(e) => {\n clearErrors('newPassword');\n clearErrors('newPasswordRepeat');\n runAsynchronously(registerPassword.onChange(e));\n }}\n />\n <FormWarningText text={errors.newPassword?.message?.toString()} />\n\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">Repeat password</Label>\n <PasswordInput\n id=\"repeat-password\"\n {...registerPasswordRepeat}\n onChange={(e) => {\n clearErrors('newPassword');\n clearErrors('newPasswordRepeat');\n runAsynchronously(registerPasswordRepeat.onChange(e));\n }}\n />\n <FormWarningText text={errors.newPasswordRepeat?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Change Password\n </Button>\n </form>\n }\n </div>\n </div>\n );\n}\n\nfunction MfaSection() {\n const project = useStackApp().useProject();\n const user = useUser({ or: \"throw\" });\n const [generatedSecret, setGeneratedSecret] = useState<Uint8Array | null>(null);\n const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);\n const [mfaCode, setMfaCode] = useState<string>(\"\");\n const [isMaybeWrong, setIsMaybeWrong] = useState(false);\n const isEnabled = user.isMultiFactorRequired;\n\n const [handleSubmit, isLoading] = useAsyncCallback(async () => {\n await user.update({\n totpMultiFactorSecret: generatedSecret,\n });\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }, [generatedSecret, user]);\n\n useEffect(() => {\n setIsMaybeWrong(false);\n runAsynchronouslyWithAlert(async () => {\n if (generatedSecret && await new TOTPController().verify(mfaCode, generatedSecret)) {\n await handleSubmit();\n }\n setIsMaybeWrong(true);\n });\n }, [mfaCode, generatedSecret, handleSubmit]);\n\n return (\n <div>\n <div>\n <Label>Multi-factor Authentication</Label>\n\n <div>\n {isEnabled ? (\n <Typography variant=\"success\">Multi-factor authentication is currently enabled.</Typography>\n ) : (\n generatedSecret ? (\n <div className='flex flex-col gap-4 items-center'>\n <Typography>Scan this QR code with your authenticator app:</Typography>\n <img width={200} height={200} src={qrCodeUrl ?? throwErr(\"TOTP QR code failed to generate\")} alt=\"TOTP multi-factor authentication QR code\" />\n <Typography>Then, enter your six-digit MFA code:</Typography>\n <Input\n value={mfaCode}\n onChange={(e) => {\n setIsMaybeWrong(false);\n setMfaCode(e.target.value);\n }}\n placeholder=\"123456\"\n maxLength={6}\n disabled={isLoading}\n />\n {isMaybeWrong && mfaCode.length === 6 && (\n <Typography variant=\"destructive\">Incorrect code. Please try again.</Typography>\n )}\n </div>\n ) : (\n <Typography variant=\"destructive\">Multi-factor authentication is currently disabled.</Typography>\n )\n )}\n\n <Button\n className=\"mt-4\"\n variant={isEnabled ? 'secondary' : 'default'}\n onClick={async () => {\n if (isEnabled) {\n await user.update({\n totpMultiFactorSecret: null,\n });\n } else if (!generatedSecret) {\n const secret = generateRandomValues(new Uint8Array(20));\n setQrCodeUrl(await generateTotpQrCode(project, user, secret));\n setGeneratedSecret(secret);\n } else {\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }\n }}\n >\n {isEnabled ? 'Disable' : (generatedSecret ? 'Cancel' : 'Enable')}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\nasync function generateTotpQrCode(project: Project, user: CurrentUser, secret: Uint8Array) {\n const uri = createTOTPKeyURI(project.displayName, user.primaryEmail ?? user.id, secret);\n return await QRCode.toDataURL(uri) as any;\n}\n\nfunction SignOutSection() {\n const user = useUser({ or: \"throw\" });\n return (\n <div className='flex flex-col gap-2'>\n <div>\n <Button\n variant='secondary'\n onClick={() => user.signOut()}\n >\n Sign Out\n </Button>\n </div>\n </div>\n );\n}\n\nfunction UserSettings(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const [leaving, setLeaving] = useState(false);\n\n return (\n <div className='flex flex-col gap-2'>\n <div>\n { !leaving ?\n <Button\n variant='secondary'\n onClick={async () => setLeaving(true)}\n >\n Leave team\n </Button> :\n <div className=''>\n <Typography variant='destructive'>Are you sure you want to leave the team?</Typography>\n <div className='flex gap-2'>\n <Button variant='destructive' onClick={async () => {\n await user.leaveTeam(props.team);\n window.location.reload();\n }}>\n Leave\n </Button>\n <Button variant='secondary' onClick={() => setLeaving(false)}>\n Cancel\n </Button>\n </div>\n </div>}\n </div>\n </div>\n );\n}\n\nfunction ManagementSettings(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const updateTeamPermission = user.usePermission(props.team, '$update_team');\n\n if (!updateTeamPermission) {\n return null;\n }\n\n return (\n <>\n <div className='flex flex-col'>\n <Label>Team display name</Label>\n <ProfileImageEditor\n user={props.team}\n onProfileImageUrlChange={async (profileImageUrl) => {\n await props.team.update({ profileImageUrl });\n }}\n />\n </div>\n\n <div className='flex flex-col'>\n <Label>Team display name</Label>\n <EditableText\n value={props.team.displayName}\n onSave={async (newDisplayName) => await props.team.update({ displayName: newDisplayName })}\n />\n </div>\n </>\n );\n}\n\nfunction ProfileSettings(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const profile = user.useTeamProfile(props.team);\n\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex flex-col\">\n <Label className=\"flex gap-2\">User display name <SimpleTooltip tooltip=\"This overwrites your user display name in the account setting\" type='info'/></Label>\n <EditableText\n value={profile.displayName || ''}\n onSave={async (newDisplayName) => {\n await profile.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nconst invitationSchema = yupObject({\n email: yupString().email().required('Please enter an email address'),\n});\n\nfunction MemberInvitation(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n\n if (!inviteMemberPermission) {\n return null;\n }\n\n const { register, handleSubmit, formState: { errors }, watch } = useForm({\n resolver: yupResolver(invitationSchema)\n });\n const [loading, setLoading] = useState(false);\n const [invitedEmail, setInvitedEmail] = useState<string | null>(null);\n\n const onSubmit = async (data: yup.InferType<typeof invitationSchema>) => {\n setLoading(true);\n\n try {\n await props.team.inviteUser({ email: data.email });\n setInvitedEmail(data.email);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n setInvitedEmail(null);\n }, [watch('email')]);\n\n return (\n <div>\n <Label>Invite a user to team</Label>\n <form\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <div className=\"flex flex-col gap-4 md:flex-row\">\n <div>\n <Input\n placeholder=\"Email\"\n {...register('email')}\n />\n </div>\n <Button type=\"submit\" loading={loading}>\n Invite User\n </Button>\n </div>\n <FormWarningText text={errors.email?.message?.toString()} />\n {invitedEmail && <Typography type='label' variant='secondary'>Invited {invitedEmail}</Typography>}\n </form>\n </div>\n );\n}\n\n\nfunction MembersSettings(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const readMemberPermission = user.usePermission(props.team, '$read_members');\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n\n if (!readMemberPermission && !inviteMemberPermission) {\n return null;\n }\n\n const users = props.team.useUsers();\n\n if (!readMemberPermission) {\n return null;\n }\n\n return (\n <div>\n <Label>Members</Label>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[100px]\">User</TableHead>\n <TableHead className=\"w-[200px]\">Name</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {users.map(({ id, teamProfile }, i) => (\n <TableRow key={id}>\n <TableCell>\n <UserAvatar user={teamProfile}/>\n </TableCell>\n <TableCell>\n <Typography>{teamProfile.displayName}</Typography>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n );\n}\n\nconst teamCreationSchema = yupObject({\n displayName: yupString().required('Please enter a team name'),\n});\n\nexport function TeamCreation() {\n const { register, handleSubmit, formState: { errors } } = useForm({\n resolver: yupResolver(teamCreationSchema)\n });\n const app = useStackApp();\n const project = app.useProject();\n const user = useUser({ or: 'redirect' });\n const [loading, setLoading] = useState(false);\n\n if (!project.config.clientTeamCreationEnabled) {\n return <MessageCard title='Team creation is not enabled' />;\n }\n\n const onSubmit = async (data: yup.InferType<typeof teamCreationSchema>) => {\n setLoading(true);\n\n try {\n const team = await user.createTeam({ displayName: data.displayName });\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className='stack-scope flex flex-col items-stretch'>\n <div className=\"mb-6\">\n <form\n className=\"flex flex-col items-stretch stack-scope\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <div className=\"flex items-end gap-4\">\n <div>\n <Label htmlFor=\"email\" className=\"mb-1\">Display name</Label>\n <Input\n id=\"email\"\n type=\"email\"\n {...register('displayName')}\n />\n </div>\n <FormWarningText text={errors.displayName?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Create\n </Button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components-page/account-settings.tsx"],"sourcesContent":["'use client';\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { getPasswordError } from '@stackframe/stack-shared/dist/helpers/password';\nimport { useAsyncCallback } from '@stackframe/stack-shared/dist/hooks/use-async-callback';\nimport { yupObject, yupString } from '@stackframe/stack-shared/dist/schema-fields';\nimport { generateRandomValues } from '@stackframe/stack-shared/dist/utils/crypto';\nimport { throwErr } from '@stackframe/stack-shared/dist/utils/errors';\nimport { runAsynchronously, runAsynchronouslyWithAlert } from '@stackframe/stack-shared/dist/utils/promises';\nimport { Button, EditableText, Input, Label, PasswordInput, SimpleTooltip, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from '@stackframe/stack-ui';\nimport { CirclePlus, Contact, LogOut, ShieldCheck, LucideIcon } from 'lucide-react';\nimport { TOTPController, createTOTPKeyURI } from \"oslo/otp\";\nimport * as QRCode from 'qrcode';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport * as yup from \"yup\";\nimport { CurrentUser, MessageCard, Project, Team, useStackApp, useUser } from '..';\nimport { FormWarningText } from '../components/elements/form-warning';\nimport { SidebarLayout } from '../components/elements/sidebar-layout';\nimport { UserAvatar } from '../components/elements/user-avatar';\nimport { ProfileImageEditor } from \"../components/profile-image-editor\";\nimport { TeamIcon } from '../components/team-icon';\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { useTranslation } from \"../lib/translations\";\n\n\nexport function AccountSettings(props: {\n fullPage?: boolean,\n extraItems?: {\n title: string,\n icon: LucideIcon,\n content: React.ReactNode,\n subpath: string,\n }[],\n}) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const teams = user.useTeams();\n const stackApp = useStackApp();\n const project = stackApp.useProject();\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div style={{ alignSelf: 'stretch', flexGrow: 1 }}>\n <SidebarLayout\n items={([\n {\n title: t('My Profile'),\n type: 'item',\n subpath: '/profile',\n icon: Contact,\n content: <ProfileSection/>,\n },\n {\n title: t('Security'),\n type: 'item',\n icon: ShieldCheck,\n subpath: '/security',\n content: (\n <div className='flex flex-col gap-8'>\n <EmailVerificationSection />\n <PasswordSection />\n <MfaSection />\n </div>\n ),\n },\n {\n title: t('Sign Out'),\n subpath: '/sign-out',\n type: 'item',\n icon: LogOut,\n content: <SignOutSection />,\n },\n ...(props.extraItems?.map(item => ({\n title: item.title,\n type: 'item',\n subpath: item.subpath,\n icon: item.icon,\n content: item.content,\n } as const)) || []),\n ...(teams.length > 0 || project.config.clientTeamCreationEnabled) ? [{\n title: t('Teams'),\n type: 'divider',\n }] as const : [],\n ...teams.map(team => ({\n title: <div className='flex gap-2 items-center'>\n <TeamIcon team={team}/>\n {team.displayName}\n </div>,\n type: 'item',\n subpath: `/teams/${team.id}`,\n content: (\n <div className=\"flex flex-col gap-8\">\n <ProfileSettings team={team}/>\n <ManagementSettings team={team}/>\n <MemberInvitation team={team}/>\n <MembersSettings team={team}/>\n <UserSettings team={team}/>\n </div>\n ),\n } as const)),\n ...project.config.clientTeamCreationEnabled ? [{\n title: t('Create a team'),\n icon: CirclePlus,\n type: 'item',\n subpath: '/team-creation',\n content: <TeamCreation />,\n }] as const : [],\n ] as const).filter((p) => p.type === 'divider' || (p as any).content )}\n title={t(\"Account Settings\")}\n basePath={stackApp.urls.accountSettings}\n />\n </div>\n </MaybeFullPage>\n );\n}\n\nfunction ProfileSection() {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n\n return (\n <div className='flex flex-col gap-8'>\n <div className='flex flex-col items-start'>\n <Label className=\"mb-2\">{t(\"Profile image\")}</Label>\n <ProfileImageEditor\n user={user}\n onProfileImageUrlChange={async (profileImageUrl) => {\n await user.update({ profileImageUrl });\n }}\n />\n </div>\n <div className='flex flex-col'>\n <Label>{t(\"Display name\")}</Label>\n <EditableText value={user.displayName || ''} onSave={async (newDisplayName) => {\n await user.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nfunction EmailVerificationSection() {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const [emailSent, setEmailSent] = useState(false);\n\n if (!user.primaryEmail) {\n return null;\n }\n\n return (\n <>\n <div>\n <Label>{t(\"Email Verification\")}</Label>\n {user.primaryEmailVerified ? (\n <Typography variant='success'>{t(\"Your email has been verified.\")}</Typography>\n ) : (\n <>\n <Typography variant='destructive'>{t(\"Your email has not been verified.\")}</Typography>\n <div className='flex mt-4'>\n <Button\n disabled={emailSent}\n onClick={async () => {\n await user.sendVerificationEmail();\n setEmailSent(true);\n }}\n >\n {emailSent ? t(\"Email sent!\") : t(\"Send Verification Email\")}\n </Button>\n </div>\n </>\n )}\n\n </div>\n </>\n );\n}\n\nfunction PasswordSection() {\n const { t } = useTranslation();\n\n const passwordSchema = yupObject({\n oldPassword: yupString().required(t('Please enter your old password')),\n newPassword: yupString().required(t('Please enter your password')).test({\n name: 'is-valid-password',\n test: (value, ctx) => {\n const error = getPasswordError(value);\n if (error) {\n return ctx.createError({ message: error.message });\n } else {\n return true;\n }\n }\n }),\n newPasswordRepeat: yupString().nullable().oneOf([yup.ref('newPassword'), \"\", null], t('Passwords do not match')).required(t('Please repeat your password'))\n });\n\n const user = useUser({ or: \"throw\" });\n const [changingPassword, setChangingPassword] = useState(false);\n const { register, handleSubmit, setError, formState: { errors }, clearErrors, reset } = useForm({\n resolver: yupResolver(passwordSchema)\n });\n const [alreadyReset, setAlreadyReset] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof passwordSchema>) => {\n setLoading(true);\n try {\n const { oldPassword, newPassword } = data;\n const error = await user.updatePassword({ oldPassword, newPassword });\n if (error) {\n setError('oldPassword', { type: 'manual', message: t('Incorrect password') });\n } else {\n reset();\n setAlreadyReset(true);\n }\n } finally {\n setLoading(false);\n }\n };\n\n const registerPassword = register('newPassword');\n const registerPasswordRepeat = register('newPasswordRepeat');\n\n if (!user.hasPassword) {\n return null;\n }\n\n return (\n <div>\n <Label>{t(\"Change password\")}</Label>\n <div>\n {\n alreadyReset ?\n <Typography variant='success'>{t(\"Password changed successfully!\")}</Typography> :\n !changingPassword ?\n <Button\n variant='secondary'\n onClick={async () => {\n setChangingPassword(true);\n }}\n >{t(\"Change Password\")}</Button> :\n <form\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"old-password\" className=\"mb-1\">{t(\"Old password\")}</Label>\n <Input\n id=\"old-password\"\n type=\"password\"\n {...register(\"oldPassword\")}\n />\n <FormWarningText text={errors.oldPassword?.message?.toString()} />\n\n <Label htmlFor=\"new-password\" className=\"mt-4 mb-1\">{t(\"Password\")}</Label>\n <PasswordInput\n id=\"new-password\"\n {...registerPassword}\n onChange={(e) => {\n clearErrors('newPassword');\n clearErrors('newPasswordRepeat');\n runAsynchronously(registerPassword.onChange(e));\n }}\n />\n <FormWarningText text={errors.newPassword?.message?.toString()} />\n\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">{t(\"Repeat password\")}</Label>\n <PasswordInput\n id=\"repeat-password\"\n {...registerPasswordRepeat}\n onChange={(e) => {\n clearErrors('newPassword');\n clearErrors('newPasswordRepeat');\n runAsynchronously(registerPasswordRepeat.onChange(e));\n }}\n />\n <FormWarningText text={errors.newPasswordRepeat?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>{t(\"Change Password\")}</Button>\n </form>\n }\n </div>\n </div>\n );\n}\n\nfunction MfaSection() {\n const { t } = useTranslation();\n const project = useStackApp().useProject();\n const user = useUser({ or: \"throw\" });\n const [generatedSecret, setGeneratedSecret] = useState<Uint8Array | null>(null);\n const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);\n const [mfaCode, setMfaCode] = useState<string>(\"\");\n const [isMaybeWrong, setIsMaybeWrong] = useState(false);\n const isEnabled = user.isMultiFactorRequired;\n\n const [handleSubmit, isLoading] = useAsyncCallback(async () => {\n await user.update({\n totpMultiFactorSecret: generatedSecret,\n });\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }, [generatedSecret, user]);\n\n useEffect(() => {\n setIsMaybeWrong(false);\n runAsynchronouslyWithAlert(async () => {\n if (generatedSecret && await new TOTPController().verify(mfaCode, generatedSecret)) {\n await handleSubmit();\n }\n setIsMaybeWrong(true);\n });\n }, [mfaCode, generatedSecret, handleSubmit]);\n\n return (\n <div>\n <div>\n <Label>{t(\"Multi-factor Authentication\")}</Label>\n\n <div>\n {isEnabled ? (\n <Typography variant=\"success\">{t(\"Multi-factor authentication is currently enabled.\")}</Typography>\n ) : (\n generatedSecret ? (\n <div className='flex flex-col gap-4 items-center'>\n <Typography>{t(\"Scan this QR code with your authenticator app:\")}</Typography>\n <img width={200} height={200} src={qrCodeUrl ?? throwErr(\"TOTP QR code failed to generate\")} alt={t(\"TOTP multi-factor authentication QR code\")} />\n <Typography>{t(\"Then, enter your six-digit MFA code:\")}</Typography>\n <Input\n value={mfaCode}\n onChange={(e) => {\n setIsMaybeWrong(false);\n setMfaCode(e.target.value);\n }}\n placeholder=\"123456\"\n maxLength={6}\n disabled={isLoading}\n />\n {isMaybeWrong && mfaCode.length === 6 && (\n <Typography variant=\"destructive\">{t(\"Incorrect code. Please try again.\")}</Typography>\n )}\n </div>\n ) : (\n <Typography variant=\"destructive\">{t(\"Multi-factor authentication is currently disabled.\")}</Typography>\n )\n )}\n\n <Button\n className=\"mt-4\"\n variant={isEnabled ? 'secondary' : 'default'}\n onClick={async () => {\n if (isEnabled) {\n await user.update({\n totpMultiFactorSecret: null,\n });\n } else if (!generatedSecret) {\n const secret = generateRandomValues(new Uint8Array(20));\n setQrCodeUrl(await generateTotpQrCode(project, user, secret));\n setGeneratedSecret(secret);\n } else {\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }\n }}\n >\n {isEnabled ? t(\"Disable\") : (generatedSecret ? t(\"Cancel\") : t(\"Enable\"))}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\nasync function generateTotpQrCode(project: Project, user: CurrentUser, secret: Uint8Array) {\n const uri = createTOTPKeyURI(project.displayName, user.primaryEmail ?? user.id, secret);\n return await QRCode.toDataURL(uri) as any;\n}\n\nfunction SignOutSection() {\n const { t } = useTranslation();\n const user = useUser({ or: \"throw\" });\n return (\n <div className='flex flex-col gap-2'>\n <div>\n <Button\n variant='secondary'\n onClick={() => user.signOut()}\n >{t(\"Sign Out\")}</Button>\n </div>\n </div>\n );\n}\n\nfunction UserSettings(props: { team: Team }) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const [leaving, setLeaving] = useState(false);\n\n return (\n <div className='flex flex-col gap-2'>\n <div>\n { !leaving ?\n <Button\n variant='secondary'\n onClick={async () => setLeaving(true)}\n >{t(\"Leave team\")}</Button> :\n <div className=''>\n <Typography variant='destructive'>{t(\"Are you sure you want to leave the team?\")}</Typography>\n <div className='flex gap-2'>\n <Button variant='destructive' onClick={async () => {\n await user.leaveTeam(props.team);\n window.location.reload();\n }}>{t(\"Leave\")}</Button>\n <Button variant='secondary' onClick={() => setLeaving(false)}>{t(\"Cancel\")}</Button>\n </div>\n </div>}\n </div>\n </div>\n );\n}\n\nfunction ManagementSettings(props: { team: Team }) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const updateTeamPermission = user.usePermission(props.team, '$update_team');\n\n if (!updateTeamPermission) {\n return null;\n }\n\n return (\n <>\n <div className='flex flex-col'>\n <Label>{t(\"Team display name\")}</Label>\n <ProfileImageEditor\n user={props.team}\n onProfileImageUrlChange={async (profileImageUrl) => {\n await props.team.update({ profileImageUrl });\n }}\n />\n </div>\n\n <div className='flex flex-col'>\n <Label>{t(\"Team display name\")}</Label>\n <EditableText\n value={props.team.displayName}\n onSave={async (newDisplayName) => await props.team.update({ displayName: newDisplayName })}\n />\n </div>\n </>\n );\n}\n\nfunction ProfileSettings(props: { team: Team }) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const profile = user.useTeamProfile(props.team);\n\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex flex-col\">\n <Label className=\"flex gap-2\">{t(\"User display name\")}<SimpleTooltip tooltip=\"This overwrites your user display name in the account setting\" type='info'/></Label>\n <EditableText\n value={profile.displayName || ''}\n onSave={async (newDisplayName) => {\n await profile.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nfunction MemberInvitation(props: { team: Team }) {\n const { t } = useTranslation();\n\n const invitationSchema = yupObject({\n email: yupString().email().required(t('Please enter an email address')),\n });\n\n const user = useUser({ or: 'redirect' });\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n\n if (!inviteMemberPermission) {\n return null;\n }\n\n const { register, handleSubmit, formState: { errors }, watch } = useForm({\n resolver: yupResolver(invitationSchema)\n });\n const [loading, setLoading] = useState(false);\n const [invitedEmail, setInvitedEmail] = useState<string | null>(null);\n\n const onSubmit = async (data: yup.InferType<typeof invitationSchema>) => {\n setLoading(true);\n\n try {\n await props.team.inviteUser({ email: data.email });\n setInvitedEmail(data.email);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n setInvitedEmail(null);\n }, [watch('email')]);\n\n return (\n <div>\n <Label>{t(\"Invite a user to team\")}</Label>\n <form\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <div className=\"flex flex-col gap-4 md:flex-row\">\n <div>\n <Input\n placeholder={t(\"Email\")}\n {...register(\"email\")}\n />\n </div>\n <Button type=\"submit\" loading={loading}>{t(\"Invite User\")}</Button>\n </div>\n <FormWarningText text={errors.email?.message?.toString()} />\n {invitedEmail && <Typography type='label' variant='secondary'>Invited {invitedEmail}</Typography>}\n </form>\n </div>\n );\n}\n\n\nfunction MembersSettings(props: { team: Team }) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const readMemberPermission = user.usePermission(props.team, '$read_members');\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n\n if (!readMemberPermission && !inviteMemberPermission) {\n return null;\n }\n\n const users = props.team.useUsers();\n\n if (!readMemberPermission) {\n return null;\n }\n\n return (\n <div>\n <Label>{t(\"Members\")}</Label>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[100px]\">{t(\"User\")}</TableHead>\n <TableHead className=\"w-[200px]\">{t(\"Name\")}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {users.map(({ id, teamProfile }, i) => (\n <TableRow key={id}>\n <TableCell>\n <UserAvatar user={teamProfile}/>\n </TableCell>\n <TableCell>\n <Typography>{teamProfile.displayName}</Typography>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n );\n}\n\nexport function TeamCreation() {\n const { t } = useTranslation();\n\n const teamCreationSchema = yupObject({\n displayName: yupString().required(t(\"Please enter a team name\")),\n });\n\n const { register, handleSubmit, formState: { errors } } = useForm({\n resolver: yupResolver(teamCreationSchema)\n });\n const app = useStackApp();\n const project = app.useProject();\n const user = useUser({ or: 'redirect' });\n const [loading, setLoading] = useState(false);\n\n if (!project.config.clientTeamCreationEnabled) {\n return <MessageCard title={t(\"Team creation is not enabled\")} />;\n }\n\n const onSubmit = async (data: yup.InferType<typeof teamCreationSchema>) => {\n setLoading(true);\n\n try {\n const team = await user.createTeam({ displayName: data.displayName });\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className='stack-scope flex flex-col items-stretch'>\n <div className=\"mb-6\">\n <form\n className=\"flex flex-col items-stretch stack-scope\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <div className=\"flex items-end gap-4\">\n <div>\n <Label htmlFor=\"email\" className=\"mb-1\">{t(\"Display name\")}</Label>\n <Input\n id=\"email\"\n type=\"email\"\n {...register(\"displayName\")}\n />\n </div>\n <FormWarningText text={errors.displayName?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>{t(\"Create\")}</Button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|