mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-15 05:43:50 +08:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
a120734bb1 | |||
edd0b30e08 |
@ -140,6 +140,9 @@ func (c *ApiController) SendEmail() {
|
|||||||
}
|
}
|
||||||
content = strings.Replace(content, "%{user.friendlyName}", userString, 1)
|
content = strings.Replace(content, "%{user.friendlyName}", userString, 1)
|
||||||
|
|
||||||
|
matchContent := object.ResetLinkReg.Find([]byte(content))
|
||||||
|
content = strings.Replace(content, string(matchContent), "", -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 {
|
||||||
|
@ -258,7 +258,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, clientIp, vform.Dest)
|
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, clientIp, vform.Dest, vform.Method, c.Ctx.Request.Host, application.Name)
|
||||||
case object.VerifyTypePhone:
|
case object.VerifyTypePhone:
|
||||||
if vform.Method == LoginVerification || vform.Method == ForgetVerification {
|
if vform.Method == LoginVerification || vform.Method == ForgetVerification {
|
||||||
if user != nil && util.GetMaskedPhone(user.Phone) == vform.Dest {
|
if user != nil && util.GetMaskedPhone(user.Phone) == vform.Dest {
|
||||||
|
@ -252,7 +252,7 @@ func CheckPassword(user *User, password string, lang string, options ...bool) er
|
|||||||
|
|
||||||
credManager := cred.GetCredManager(passwordType)
|
credManager := cred.GetCredManager(passwordType)
|
||||||
if credManager == nil {
|
if credManager == nil {
|
||||||
return fmt.Errorf(i18n.Translate(lang, "check:unsupported password type: %s"), organization.PasswordType)
|
return fmt.Errorf(i18n.Translate(lang, "check:unsupported password type: %s"), passwordType)
|
||||||
}
|
}
|
||||||
|
|
||||||
if organization.MasterPassword != "" {
|
if organization.MasterPassword != "" {
|
||||||
@ -265,6 +265,16 @@ func CheckPassword(user *User, password string, lang string, options ...bool) er
|
|||||||
return recordSigninErrorInfo(user, lang, enableCaptcha)
|
return recordSigninErrorInfo(user, lang, enableCaptcha)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isOutdated := passwordType != organization.PasswordType
|
||||||
|
if isOutdated {
|
||||||
|
user.Password = password
|
||||||
|
user.UpdateUserPassword(organization)
|
||||||
|
_, err = UpdateUser(user.GetId(), user, []string{"password", "password_type", "password_salt"}, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return resetUserSigninErrorTimes(user)
|
return resetUserSigninErrorTimes(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -33,6 +35,8 @@ type VerifyResult struct {
|
|||||||
Msg string
|
Msg string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ResetLinkReg *regexp.Regexp
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VerificationSuccess = iota
|
VerificationSuccess = iota
|
||||||
wrongCodeError
|
wrongCodeError
|
||||||
@ -45,6 +49,10 @@ const (
|
|||||||
VerifyTypeEmail = "email"
|
VerifyTypeEmail = "email"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ResetLinkReg = regexp.MustCompile("(?s)<reset-link>(.*?)</reset-link>")
|
||||||
|
}
|
||||||
|
|
||||||
type VerificationRecord struct {
|
type VerificationRecord struct {
|
||||||
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
@ -81,7 +89,7 @@ func IsAllowSend(user *User, remoteAddr, recordType string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string, method string, host string, applicationName string) error {
|
||||||
sender := organization.DisplayName
|
sender := organization.DisplayName
|
||||||
title := provider.Title
|
title := provider.Title
|
||||||
|
|
||||||
@ -93,6 +101,23 @@ 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 := strings.Replace(provider.Content, "%s", code, 1)
|
content := strings.Replace(provider.Content, "%s", code, 1)
|
||||||
|
|
||||||
|
if method == "forget" {
|
||||||
|
originFrontend, _ := getOriginFromHost(host)
|
||||||
|
|
||||||
|
query := url.Values{}
|
||||||
|
query.Add("code", code)
|
||||||
|
query.Add("username", user.Name)
|
||||||
|
query.Add("dest", util.GetMaskedEmail(dest))
|
||||||
|
forgetURL := originFrontend + "/forget/" + applicationName + "?" + query.Encode()
|
||||||
|
|
||||||
|
content = strings.Replace(content, "%link", forgetURL, -1)
|
||||||
|
content = strings.Replace(content, "<reset-link>", "", -1)
|
||||||
|
content = strings.Replace(content, "</reset-link>", "", -1)
|
||||||
|
} else {
|
||||||
|
matchContent := ResetLinkReg.Find([]byte(content))
|
||||||
|
content = strings.Replace(content, string(matchContent), "", -1)
|
||||||
|
}
|
||||||
|
|
||||||
userString := "Hi"
|
userString := "Hi"
|
||||||
if user != nil {
|
if user != nil {
|
||||||
userString = user.GetFriendlyName()
|
userString = user.GetFriendlyName()
|
||||||
|
@ -1227,7 +1227,7 @@ 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"}} 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. <reset-link>Or click %link to reset</reset-link>")} >
|
||||||
{i18next.t("provider:Reset to Default Text")}
|
{i18next.t("provider:Reset to Default Text")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary" onClick={() => this.updateProviderField("content", Setting.getDefaultHtmlEmailContent())} >
|
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary" onClick={() => this.updateProviderField("content", Setting.getDefaultHtmlEmailContent())} >
|
||||||
|
@ -1580,6 +1580,11 @@ export function getDefaultHtmlEmailContent() {
|
|||||||
<div class="code">
|
<div class="code">
|
||||||
%s
|
%s
|
||||||
</div>
|
</div>
|
||||||
|
<reset-link>
|
||||||
|
<div class="link">
|
||||||
|
Or click this <a href="%link">link</a> to reset
|
||||||
|
</div>
|
||||||
|
</reset-link>
|
||||||
<p>Thanks</p>
|
<p>Thanks</p>
|
||||||
<p>Casbin Team</p>
|
<p>Casbin Team</p>
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -31,18 +31,21 @@ const {Option} = Select;
|
|||||||
class ForgetPage extends React.Component {
|
class ForgetPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
const queryParams = new URLSearchParams(location.search);
|
||||||
this.state = {
|
this.state = {
|
||||||
classes: props,
|
classes: props,
|
||||||
applicationName: props.applicationName ?? props.match.params?.applicationName,
|
applicationName: props.applicationName ?? props.match.params?.applicationName,
|
||||||
msg: null,
|
msg: null,
|
||||||
name: props.account ? props.account.name : "",
|
name: props.account ? props.account.name : queryParams.get("username"),
|
||||||
username: props.account ? props.account.name : "",
|
username: props.account ? props.account.name : "",
|
||||||
phone: "",
|
phone: "",
|
||||||
email: "",
|
email: "",
|
||||||
dest: "",
|
dest: "",
|
||||||
isVerifyTypeFixed: false,
|
isVerifyTypeFixed: false,
|
||||||
verifyType: "", // "email", "phone"
|
verifyType: "", // "email", "phone"
|
||||||
current: 0,
|
current: queryParams.get("code") ? 2 : 0,
|
||||||
|
code: queryParams.get("code"),
|
||||||
|
queryParams: queryParams,
|
||||||
};
|
};
|
||||||
this.form = React.createRef();
|
this.form = React.createRef();
|
||||||
}
|
}
|
||||||
@ -148,9 +151,26 @@ class ForgetPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onFinish(values) {
|
async onFinish(values) {
|
||||||
values.username = this.state.name;
|
values.username = this.state.name;
|
||||||
values.userOwner = this.getApplicationObj()?.organizationObj.name;
|
values.userOwner = this.getApplicationObj()?.organizationObj.name;
|
||||||
|
|
||||||
|
if (this.state.queryParams.get("code")) {
|
||||||
|
const res = await UserBackend.verifyCode({
|
||||||
|
application: this.getApplicationObj().name,
|
||||||
|
organization: values.userOwner,
|
||||||
|
username: this.state.queryParams.get("dest"),
|
||||||
|
name: this.state.name,
|
||||||
|
code: this.state.code,
|
||||||
|
type: "login",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.status !== "ok") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UserBackend.setPassword(values.userOwner, values.username, "", values?.newPassword, this.state.code).then(res => {
|
UserBackend.setPassword(values.userOwner, values.username, "", values?.newPassword, this.state.code).then(res => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
const linkInStorage = sessionStorage.getItem("signinUrl");
|
const linkInStorage = sessionStorage.getItem("signinUrl");
|
||||||
|
Reference in New Issue
Block a user