mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-02 11:20:18 +08:00
feat: login by code (#344)
Signed-off-by: abingcbc <abingcbc626@gmail.com>
This commit is contained in:
@ -139,53 +139,35 @@ func (c *ApiController) Login() {
|
||||
|
||||
if form.Password == "" {
|
||||
var verificationCodeType string
|
||||
var checkResult string
|
||||
|
||||
// check result through Email or Phone
|
||||
if strings.Contains(form.Email, "@") {
|
||||
if strings.Contains(form.Username, "@") {
|
||||
verificationCodeType = "email"
|
||||
checkResult := object.CheckVerificationCode(form.Email, form.EmailCode)
|
||||
if len(checkResult) != 0 {
|
||||
responseText := fmt.Sprintf("Email%s", checkResult)
|
||||
c.ResponseError(responseText)
|
||||
return
|
||||
}
|
||||
checkResult = object.CheckVerificationCode(form.Username, form.Code)
|
||||
} else {
|
||||
verificationCodeType = "phone"
|
||||
checkPhone := fmt.Sprintf("+%s%s", form.PhonePrefix, form.Email)
|
||||
checkResult := object.CheckVerificationCode(checkPhone, form.EmailCode)
|
||||
if len(checkResult) != 0 {
|
||||
responseText := fmt.Sprintf("Phone%s", checkResult)
|
||||
if len(form.PhonePrefix) == 0 {
|
||||
responseText := fmt.Sprintf("%s%s", verificationCodeType, "No phone prefix")
|
||||
c.ResponseError(responseText)
|
||||
return
|
||||
}
|
||||
checkPhone := fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username)
|
||||
checkResult = object.CheckVerificationCode(checkPhone, form.Code)
|
||||
}
|
||||
|
||||
// get user
|
||||
var userId string
|
||||
if form.Username == "" {
|
||||
userId, _ = c.RequireSignedIn()
|
||||
} else {
|
||||
userId = fmt.Sprintf("%s/%s", form.Organization, form.Username)
|
||||
}
|
||||
|
||||
user = object.GetUser(userId)
|
||||
if user == nil {
|
||||
c.ResponseError("No such user.")
|
||||
if len(checkResult) != 0 {
|
||||
responseText := fmt.Sprintf("%s%s", verificationCodeType, checkResult)
|
||||
c.ResponseError(responseText)
|
||||
return
|
||||
}
|
||||
|
||||
// disable the verification code
|
||||
switch verificationCodeType {
|
||||
case "email":
|
||||
if user.Email != form.Email {
|
||||
c.ResponseError("wrong email!")
|
||||
}
|
||||
object.DisableVerificationCode(form.Email)
|
||||
case "phone":
|
||||
if user.Phone != form.Email {
|
||||
c.ResponseError("wrong phone!")
|
||||
}
|
||||
object.DisableVerificationCode(form.Email)
|
||||
object.DisableVerificationCode(form.Username)
|
||||
|
||||
user = object.GetUserByFields(form.Organization, form.Username)
|
||||
if user == nil {
|
||||
c.ResponseError("No such user.")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
password := form.Password
|
||||
|
@ -45,6 +45,7 @@ func (c *ApiController) SendVerificationCode() {
|
||||
checkType := c.Ctx.Request.Form.Get("checkType")
|
||||
checkId := c.Ctx.Request.Form.Get("checkId")
|
||||
checkKey := c.Ctx.Request.Form.Get("checkKey")
|
||||
checkUser := c.Ctx.Request.Form.Get("checkUser")
|
||||
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
||||
|
||||
if len(destType) == 0 || len(dest) == 0 || len(orgId) == 0 || !strings.Contains(orgId, "/") || len(checkType) == 0 || len(checkId) == 0 || len(checkKey) == 0 {
|
||||
@ -67,6 +68,12 @@ func (c *ApiController) SendVerificationCode() {
|
||||
organization := object.GetOrganization(orgId)
|
||||
application := object.GetApplicationByOrganizationName(organization.Name)
|
||||
|
||||
if checkUser == "true" && user == nil &&
|
||||
object.GetUserByFields(organization.Name, dest) == nil {
|
||||
c.ResponseError("No such user.")
|
||||
return
|
||||
}
|
||||
|
||||
sendResp := errors.New("Invalid dest type.")
|
||||
switch destType {
|
||||
case "email":
|
||||
|
@ -136,10 +136,9 @@ class ForgetPage extends React.Component {
|
||||
AuthBackend.login({
|
||||
application: forms.step2.getFieldValue("application"),
|
||||
organization: forms.step2.getFieldValue("organization"),
|
||||
email: forms.step2.getFieldValue("email"),
|
||||
emailCode: forms.step2.getFieldValue("emailCode"),
|
||||
username: forms.step2.getFieldValue("email"),
|
||||
code: forms.step2.getFieldValue("emailCode"),
|
||||
phonePrefix: this.state.application?.organizationObj.phonePrefix,
|
||||
username: this.state.username,
|
||||
type: "login"
|
||||
}, oAuthParams).then(res => {
|
||||
if (res.status === "ok") {
|
||||
|
@ -49,6 +49,7 @@ class LoginPage extends React.Component {
|
||||
isCodeSignin: false,
|
||||
msg: null,
|
||||
username: null,
|
||||
validEmailOrPhone: false
|
||||
};
|
||||
}
|
||||
|
||||
@ -109,6 +110,7 @@ class LoginPage extends React.Component {
|
||||
const application = this.getApplicationObj();
|
||||
const ths = this;
|
||||
values["type"] = this.state.type;
|
||||
values["phonePrefix"] = this.getApplicationObj()?.organizationObj.phonePrefix;
|
||||
const oAuthParams = Util.getOAuthGetParameters();
|
||||
|
||||
AuthBackend.login(values, oAuthParams)
|
||||
@ -288,11 +290,28 @@ class LoginPage extends React.Component {
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="username"
|
||||
rules={[{ required: true, message: i18next.t("login:Please input your username, Email or phone!") }]}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: i18next.t("login:Please input your username, Email or phone!")
|
||||
},
|
||||
{
|
||||
validator: (_, value) => {
|
||||
if (this.state.isCodeSignin) {
|
||||
if (this.state.email !== "" && !Setting.isValidEmail(this.state.username) && !Setting.isValidPhone(this.state.username)) {
|
||||
this.setState({validEmailOrPhone: false});
|
||||
return Promise.reject(i18next.t("login:The input is not valid Email or Phone!"));
|
||||
}
|
||||
}
|
||||
this.setState({validEmailOrPhone: true});
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
prefix={<UserOutlined className="site-form-item-icon" />}
|
||||
placeholder={i18next.t("login:username, Email or phone")}
|
||||
placeholder={ this.state.isCodeSignin ? i18next.t("login:Email or phone") : i18next.t("login:username, Email or phone") }
|
||||
disabled={!application.enablePassword}
|
||||
onChange={e => {
|
||||
this.setState({
|
||||
@ -308,8 +327,8 @@ class LoginPage extends React.Component {
|
||||
rules={[{ required: true, message: i18next.t("login:Please input your code!") }]}
|
||||
>
|
||||
<CountDownInput
|
||||
disabled={this.state.username?.length === 0}
|
||||
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationOrgName(application)]}
|
||||
disabled={this.state.username?.length === 0 || !this.state.validEmailOrPhone}
|
||||
onButtonClickArgs={[this.state.username, "", Setting.getApplicationOrgName(application), true]}
|
||||
/>
|
||||
</Form.Item>
|
||||
) : (
|
||||
|
@ -88,7 +88,7 @@ export function setPassword(userOwner, userName, oldPassword, newPassword) {
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function sendCode(checkType, checkId, checkKey, dest, type, orgId) {
|
||||
export function sendCode(checkType, checkId, checkKey, dest, type, orgId, checkUser) {
|
||||
let formData = new FormData();
|
||||
formData.append("checkType", checkType);
|
||||
formData.append("checkId", checkId);
|
||||
@ -96,6 +96,7 @@ export function sendCode(checkType, checkId, checkKey, dest, type, orgId) {
|
||||
formData.append("dest", dest);
|
||||
formData.append("type", type);
|
||||
formData.append("organizationId", orgId);
|
||||
formData.append("checkUser", checkUser);
|
||||
return fetch(`${Setting.ServerUrl}/api/send-verification-code`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
|
@ -18,6 +18,8 @@ import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import {SafetyOutlined} from "@ant-design/icons";
|
||||
import * as Util from "../auth/Util";
|
||||
import {isValidEmail, isValidPhone} from "../Setting";
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
@ -40,6 +42,14 @@ export const CountDownInput = (props) => {
|
||||
|
||||
const handleOk = () => {
|
||||
setVisible(false);
|
||||
if (isValidEmail(onButtonClickArgs[0])) {
|
||||
onButtonClickArgs[1] = "email";
|
||||
} else if (isValidPhone(onButtonClickArgs[0])) {
|
||||
onButtonClickArgs[1] = "phone";
|
||||
} else {
|
||||
Util.showMessage("error", i18next.t("login:Invalid Email or phone"))
|
||||
return;
|
||||
}
|
||||
UserBackend.sendCode(checkType, checkId, key, ...onButtonClickArgs).then(res => {
|
||||
setKey("");
|
||||
if (res) {
|
||||
|
@ -177,6 +177,7 @@
|
||||
"Please input your code!": "Please input your code!",
|
||||
"Please input your password!": "Please input your password!",
|
||||
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||
"Please input your Email or phone!": "Please input your Email or phone!",
|
||||
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
|
||||
"Sign In": "Sign In",
|
||||
"Sign in with code": "Sign in with code",
|
||||
@ -185,7 +186,10 @@
|
||||
"Signing in...": "Signing in...",
|
||||
"To access": "To access",
|
||||
"sign up now": "sign up now",
|
||||
"username, Email or phone": "username, Email or phone"
|
||||
"Email or phone": "Email or phone",
|
||||
"username, Email or phone": "username, Email or phone",
|
||||
"Invalid Email or phone": "Invalid Email or phone",
|
||||
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!"
|
||||
},
|
||||
"organization": {
|
||||
"Default avatar": "Default avatar",
|
||||
|
@ -177,6 +177,7 @@
|
||||
"Please input your code!": "Please input your code!",
|
||||
"Please input your password!": "Please input your password!",
|
||||
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||
"Please input your Email or phone!": "Please input your Email or phone!",
|
||||
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
|
||||
"Sign In": "Sign In",
|
||||
"Sign in with code": "Sign in with code",
|
||||
@ -185,7 +186,10 @@
|
||||
"Signing in...": "Signing in...",
|
||||
"To access": "To access",
|
||||
"sign up now": "sign up now",
|
||||
"username, Email or phone": "username, Email or phone"
|
||||
"Email or phone": "Email or phone",
|
||||
"username, Email or phone": "username, Email or phone",
|
||||
"Invalid Email or phone": "Invalid Email or phone",
|
||||
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!"
|
||||
},
|
||||
"organization": {
|
||||
"Default avatar": "Default avatar",
|
||||
|
@ -177,6 +177,7 @@
|
||||
"Please input your code!": "Please input your code!",
|
||||
"Please input your password!": "Please input your password!",
|
||||
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||
"Please input your Email or phone!": "Please input your Email or phone!",
|
||||
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
|
||||
"Sign In": "Sign In",
|
||||
"Sign in with code": "Sign in with code",
|
||||
@ -185,7 +186,10 @@
|
||||
"Signing in...": "Signing in...",
|
||||
"To access": "To access",
|
||||
"sign up now": "sign up now",
|
||||
"username, Email or phone": "username, Email or phone"
|
||||
"Email or phone": "Email or phone",
|
||||
"username, Email or phone": "username, Email or phone",
|
||||
"Invalid Email or phone": "Invalid Email or phone",
|
||||
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!"
|
||||
},
|
||||
"organization": {
|
||||
"Default avatar": "Default avatar",
|
||||
|
@ -177,6 +177,7 @@
|
||||
"Please input your code!": "Please input your code!",
|
||||
"Please input your password!": "Please input your password!",
|
||||
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||
"Please input your Email or phone!": "Please input your Email or phone!",
|
||||
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
|
||||
"Sign In": "Sign In",
|
||||
"Sign in with code": "Sign in with code",
|
||||
@ -185,7 +186,10 @@
|
||||
"Signing in...": "Signing in...",
|
||||
"To access": "To access",
|
||||
"sign up now": "sign up now",
|
||||
"username, Email or phone": "username, Email or phone"
|
||||
"Email or phone": "Email or phone",
|
||||
"username, Email or phone": "username, Email or phone",
|
||||
"Invalid Email or phone": "Invalid Email or phone",
|
||||
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!"
|
||||
},
|
||||
"organization": {
|
||||
"Default avatar": "Default avatar",
|
||||
|
@ -177,6 +177,7 @@
|
||||
"Please input your code!": "Please input your code!",
|
||||
"Please input your password!": "Please input your password!",
|
||||
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||
"Please input your Email or phone!": "Please input your Email or phone!",
|
||||
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
|
||||
"Sign In": "Sign In",
|
||||
"Sign in with code": "Sign in with code",
|
||||
@ -185,7 +186,10 @@
|
||||
"Signing in...": "Signing in...",
|
||||
"To access": "To access",
|
||||
"sign up now": "sign up now",
|
||||
"username, Email or phone": "username, Email or phone"
|
||||
"Email or phone": "Email or phone",
|
||||
"username, Email or phone": "username, Email or phone",
|
||||
"Invalid Email or phone": "Invalid Email or phone",
|
||||
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!"
|
||||
},
|
||||
"organization": {
|
||||
"Default avatar": "Default avatar",
|
||||
|
@ -177,6 +177,7 @@
|
||||
"Please input your code!": "Please input your code!",
|
||||
"Please input your password!": "Please input your password!",
|
||||
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||
"Please input your Email or phone!": "Please input your Email or phone!",
|
||||
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
|
||||
"Sign In": "Sign In",
|
||||
"Sign in with code": "Sign in with code",
|
||||
@ -185,7 +186,10 @@
|
||||
"Signing in...": "Signing in...",
|
||||
"To access": "To access",
|
||||
"sign up now": "sign up now",
|
||||
"username, Email or phone": "username, Email or phone"
|
||||
"Email or phone": "Email or phone",
|
||||
"username, Email or phone": "username, Email or phone",
|
||||
"Invalid Email or phone": "Invalid Email or phone",
|
||||
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!"
|
||||
},
|
||||
"organization": {
|
||||
"Default avatar": "Default avatar",
|
||||
|
@ -177,6 +177,7 @@
|
||||
"Please input your code!": "请输入您的验证码!",
|
||||
"Please input your password!": "请输入您的密码!",
|
||||
"Please input your password, at least 6 characters!": "请输入您的密码,不少于6位",
|
||||
"Please input your Email or phone!": "请输入您的Email或手机号!",
|
||||
"Please input your username, Email or phone!": "请输入您的用户名、Email或手机号!",
|
||||
"Sign In": "登录",
|
||||
"Sign in with code": "验证码登录",
|
||||
@ -185,7 +186,10 @@
|
||||
"Signing in...": "正在登录...",
|
||||
"To access": "访问",
|
||||
"sign up now": "立即注册",
|
||||
"username, Email or phone": "用户名、Email或手机号"
|
||||
"Email or phone": "Email或手机号",
|
||||
"username, Email or phone": "用户名、Email或手机号",
|
||||
"Invalid Email or phone": "无效的Email或手机号",
|
||||
"The input is not valid Email or Phone!": "您输入的电子邮箱格式或手机号有误!"
|
||||
},
|
||||
"organization": {
|
||||
"Default avatar": "默认头像",
|
||||
|
Reference in New Issue
Block a user