mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-03 12:30:19 +08:00
feat: add "Reset to Default HTML" button
This commit is contained in:
@ -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 {
|
||||||
|
@ -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/")
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
@ -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>`;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user