feat: add "Reset to Default HTML" button

This commit is contained in:
Yang Luo
2023-12-30 00:47:10 +08:00
parent 14fcedcc5d
commit 27187b3a54
5 changed files with 85 additions and 7 deletions

View File

@ -54,6 +54,11 @@ type NotificationForm struct {
// @Success 200 {object} controllers.Response The Response object // @Success 200 {object} controllers.Response The Response object
// @router /api/send-email [post] // @router /api/send-email [post]
func (c *ApiController) SendEmail() { func (c *ApiController) SendEmail() {
user, ok := c.RequireSignedInUser()
if !ok {
return
}
var emailForm EmailForm var emailForm EmailForm
err := json.Unmarshal(c.Ctx.Input.RequestBody, &emailForm) err := json.Unmarshal(c.Ctx.Input.RequestBody, &emailForm)
@ -108,8 +113,13 @@ func (c *ApiController) SendEmail() {
} }
code := "123456" code := "123456"
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes." // "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
content := fmt.Sprintf(emailForm.Content, code) content := strings.Replace(provider.Content, "%s", code, 1)
if user != nil {
content = strings.Replace(content, "%{user.friendlyName}", user.GetFriendlyName(), 1)
}
for _, receiver := range emailForm.Receivers { for _, receiver := range emailForm.Receivers {
err = object.SendEmail(provider, emailForm.Title, content, receiver, emailForm.Sender) err = object.SendEmail(provider, emailForm.Title, content, receiver, emailForm.Sender)
if err != nil { if err != nil {

View File

@ -886,6 +886,18 @@ func (user *User) GetId() string {
return fmt.Sprintf("%s/%s", user.Owner, user.Name) return fmt.Sprintf("%s/%s", user.Owner, user.Name)
} }
func (user *User) GetFriendlyName() string {
if user.FirstName != "" && user.LastName != "" {
return fmt.Sprintf("%s, %s", user.FirstName, user.LastName)
} else if user.DisplayName != "" {
return user.DisplayName
} else if user.Name != "" {
return user.Name
} else {
return user.Id
}
}
func isUserIdGlobalAdmin(userId string) bool { func isUserIdGlobalAdmin(userId string) bool {
return strings.HasPrefix(userId, "built-in/") || strings.HasPrefix(userId, "app/") return strings.HasPrefix(userId, "built-in/") || strings.HasPrefix(userId, "app/")
} }

View File

@ -89,7 +89,10 @@ func SendVerificationCodeToEmail(organization *Organization, user *User, provide
} }
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes." // "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
content := fmt.Sprintf(provider.Content, code) content := strings.Replace(provider.Content, "%s", code, 1)
if user != nil {
content = strings.Replace(content, "%{user.friendlyName}", user.GetFriendlyName(), 1)
}
if err := IsAllowSend(user, remoteAddr, provider.Category); err != nil { if err := IsAllowSend(user, remoteAddr, provider.Category); err != nil {
return err return err

View File

@ -488,7 +488,7 @@ class ProviderEditPage extends React.Component {
this.updateProviderField("port", 465); this.updateProviderField("port", 465);
this.updateProviderField("disableSsl", false); this.updateProviderField("disableSsl", false);
this.updateProviderField("title", "Casdoor Verification Code"); this.updateProviderField("title", "Casdoor Verification Code");
this.updateProviderField("content", "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."); this.updateProviderField("content", Setting.getDefaultHtmlEmailContent());
this.updateProviderField("receiver", this.props.account.email); this.updateProviderField("receiver", this.props.account.email);
} else if (value === "SMS") { } else if (value === "SMS") {
this.updateProviderField("type", "Twilio SMS"); this.updateProviderField("type", "Twilio SMS");
@ -975,8 +975,11 @@ class ProviderEditPage extends React.Component {
</Col> </Col>
<Col span={22} > <Col span={22} >
<Row style={{marginTop: "20px"}} > <Row style={{marginTop: "20px"}} >
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary" onClick={() => this.updateProviderField("content", "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes.")} > <Button style={{marginLeft: "10px", marginBottom: "5px"}} onClick={() => this.updateProviderField("content", "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes.")} >
{i18next.t("provider:Reset to Default")} {i18next.t("provider:Reset to Default Text")}
</Button>
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary" onClick={() => this.updateProviderField("content", Setting.getDefaultHtmlEmailContent())} >
{i18next.t("provider:Reset to Default HTML")}
</Button> </Button>
</Row> </Row>
<Row> <Row>
@ -994,7 +997,7 @@ class ProviderEditPage extends React.Component {
<Col span={1} /> <Col span={1} />
<Col span={Setting.isMobile() ? 22 : 11}> <Col span={Setting.isMobile() ? 22 : 11}>
<div style={{margin: "10px"}}> <div style={{margin: "10px"}}>
<div dangerouslySetInnerHTML={{__html: this.state.provider.content.replace("%s", "123456")}} /> <div dangerouslySetInnerHTML={{__html: this.state.provider.content.replace("%s", "123456").replace("%{user.friendlyName}", Setting.getFriendlyUserName(this.props.account))}} />
</div> </div>
</Col> </Col>
</Row> </Row>
@ -1011,7 +1014,7 @@ class ProviderEditPage extends React.Component {
}} /> }} />
</Col> </Col>
{["Azure ACS"].includes(this.state.provider.type) ? null : ( {["Azure ACS"].includes(this.state.provider.type) ? null : (
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary" onClick={() => ProviderEditTestEmail.connectSmtpServer(this.state.provider)} > <Button style={{marginLeft: "10px", marginBottom: "5px"}} onClick={() => ProviderEditTestEmail.connectSmtpServer(this.state.provider)} >
{i18next.t("provider:Test SMTP Connection")} {i18next.t("provider:Test SMTP Connection")}
</Button> </Button>
)} )}

View File

@ -1405,3 +1405,53 @@ export function getCurrencySymbol(currency) {
return currency; return currency;
} }
} }
export function getFriendlyUserName(account) {
if (account.firstName !== "" && account.lastName !== "") {
return `${account.firstName}, ${account.lastName}`;
} else if (account.displayName !== "") {
return account.displayName;
} else if (account.name !== "") {
return account.name;
} else {
return account.id;
}
}
export function getDefaultHtmlEmailContent() {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Verification Code Email</title>
<style>
body { font-family: Arial, sans-serif; }
.email-container { width: 600px; margin: 0 auto; }
.header { text-align: center; }
.code { font-size: 24px; margin: 20px 0; text-align: center; }
.footer { font-size: 12px; text-align: center; margin-top: 50px; }
.footer a { color: #000; text-decoration: none; }
</style>
</head>
<body>
<div class="email-container">
<div class="header">
<h3>Casbin Organization</h3>
<img src="https://cdn.casbin.org/img/casdoor-logo_1185x256.png" alt="Casdoor Logo" width="300">
</div>
<p><strong>%{user.friendlyName}</strong>, here is your verification code</p>
<p>Use this code for your transaction. It's valid for 5 minutes</p>
<div class="code">
%s
</div>
<p>Thanks</p>
<p>Casbin Team</p>
<hr>
<div class="footer">
<p>Casdoor is a brand operated by Casbin organization. For more info please refer to <a href="https://casdoor.org">https://casdoor.org</a></p>
</div>
</div>
</body>
</html>`;
}