Skip to content

Commit 1ba0035

Browse files
authored
Validate spam on save (supabase#30714)
1 parent a731446 commit 1ba0035

File tree

1 file changed

+47
-30
lines changed

1 file changed

+47
-30
lines changed

apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,11 @@ const TemplateEditor = ({ template }: TemplateEditorProps) => {
4141
onSuccess: (res) => setValidationResult(res),
4242
})
4343

44-
const { mutate: updateAuthConfig, isLoading: isUpdatingConfig } = useAuthConfigUpdateMutation({
45-
onError: (error) => toast.error(`Failed to update email templates: ${error.message}`),
44+
const { mutate: updateAuthConfig } = useAuthConfigUpdateMutation({
45+
onError: (error) => {
46+
setIsSavingTemplate(false)
47+
toast.error(`Failed to update email templates: ${error.message}`)
48+
},
4649
})
4750

4851
const { id, properties } = template
@@ -66,31 +69,61 @@ const TemplateEditor = ({ template }: TemplateEditorProps) => {
6669
const [validationResult, setValidationResult] = useState<ValidateSpamResponse>()
6770
const [bodyValue, setBodyValue] = useState((authConfig && authConfig[messageSlug]) ?? '')
6871
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
72+
const [isSavingTemplate, setIsSavingTemplate] = useState(false)
6973

7074
// eslint-disable-next-line react-hooks/exhaustive-deps
71-
const debounceValidateSpam = useCallback(debounce(validateSpam, 1000), [])
7275
const spamRules = (validationResult?.rules ?? []).filter((rule) => rule.score > 0)
7376
const preventSaveFromSpamCheck = builtInSMTP && spamRules.length > 0
7477

7578
const onSubmit = (values: any, { resetForm }: any) => {
79+
if (!projectRef) return console.error('Project ref is required')
80+
81+
setIsSavingTemplate(true)
7682
const payload = { ...values }
7783

7884
// Because the template content uses the code editor which is not a form component
7985
// its state is kept separately from the form state, hence why we manually inject it here
8086
delete payload[messageSlug]
8187
if (messageProperty) payload[messageSlug] = bodyValue
8288

83-
updateAuthConfig(
84-
{ projectRef: projectRef!, config: payload },
89+
const [subjectKey] = Object.keys(properties)
90+
91+
validateSpam(
8592
{
86-
onSuccess: () => {
87-
toast.success('Successfully updated settings')
88-
resetForm({
89-
values: values,
90-
initialValues: values,
91-
})
92-
setHasUnsavedChanges(false) // Reset the unsaved changes state
93+
projectRef,
94+
template: {
95+
subject: payload[subjectKey],
96+
content: payload[messageSlug],
9397
},
98+
},
99+
{
100+
onSuccess: (res) => {
101+
const spamRules = (res?.rules ?? []).filter((rule) => rule.score > 0)
102+
const preventSaveFromSpamCheck = builtInSMTP && spamRules.length > 0
103+
104+
if (preventSaveFromSpamCheck) {
105+
setIsSavingTemplate(false)
106+
toast.error(
107+
'Please rectify all spam warnings before saving while using the built-in email service'
108+
)
109+
} else {
110+
updateAuthConfig(
111+
{ projectRef: projectRef, config: payload },
112+
{
113+
onSuccess: () => {
114+
setIsSavingTemplate(false)
115+
toast.success('Successfully updated settings')
116+
resetForm({
117+
values: values,
118+
initialValues: values,
119+
})
120+
setHasUnsavedChanges(false) // Reset the unsaved changes state
121+
},
122+
}
123+
)
124+
}
125+
},
126+
onError: () => setIsSavingTemplate(false),
94127
}
95128
)
96129
}
@@ -164,14 +197,6 @@ const TemplateEditor = ({ template }: TemplateEditorProps) => {
164197
</ReactMarkdown>
165198
) : null
166199
}
167-
onChange={(e) => {
168-
if (projectRef) {
169-
debounceValidateSpam({
170-
projectRef,
171-
template: { subject: e.target.value, content: bodyValue },
172-
})
173-
}
174-
}}
175200
disabled={!canUpdateConfig}
176201
/>
177202
</div>
@@ -219,14 +244,6 @@ const TemplateEditor = ({ template }: TemplateEditorProps) => {
219244
onInputChange={(e: string | undefined) => {
220245
setBodyValue(e ?? '')
221246
if (bodyValue !== e) setHasUnsavedChanges(true)
222-
223-
if (projectRef) {
224-
const [subjectKey] = Object.keys(values)
225-
debounceValidateSpam({
226-
projectRef,
227-
template: { subject: values[subjectKey], content: e ?? '' },
228-
})
229-
}
230247
}}
231248
options={{ wordWrap: 'on', contextmenu: false }}
232249
value={bodyValue}
@@ -257,9 +274,9 @@ const TemplateEditor = ({ template }: TemplateEditorProps) => {
257274
setBodyValue((authConfig && authConfig[messageSlug]) ?? '')
258275
}}
259276
form={formId}
260-
isSubmitting={isUpdatingConfig}
277+
isSubmitting={isSavingTemplate}
261278
hasChanges={hasChanges}
262-
disabled={preventSaveFromSpamCheck || !canUpdateConfig}
279+
disabled={!canUpdateConfig}
263280
helper={
264281
preventSaveFromSpamCheck
265282
? 'Please rectify all spam warnings before saving while using the built-in email service'

0 commit comments

Comments
 (0)