Compare commits

...

6 Commits

Author SHA1 Message Date
0b17cb9746 feat: make Organization.EnableSoftDeletion and User.IsDeleted work (#3205)
* feat: make Organization.EnableSoftDeletion and User.IsDeleted work

* fix: add handling of the situation where organization is nil
2024-09-15 14:35:44 +08:00
e2ce9ad625 feat: handle null account item issue in CheckPermissionForUpdateUser() (#3202)
* feat: improve the logic of the permission check code for users to modify account items

* fix: add skip operation for deleted account items in update-user API

* fix: add the function of removing deleted account item
2024-09-14 15:00:10 +08:00
64491abc64 feat: fix CORS issue of /api/acs for SAML IdP (#3200)
* fix: fix CORS problem of /api/acs when login with saml idp

* fix: fix origin get null when receive post with http protocol
2024-09-14 12:48:51 +08:00
934a8947c8 feat: fix CAS logout failure caused by Beego session update problem (#3194)
* feat: fix the cas logout failure caused by beego session update problem

* fix: simplify the implementation of logout timer

* fix: change the location of the login success code

* fix: add i18n to CasLogout.js
2024-09-10 21:31:37 +08:00
943edfb48b feat: support QR login for casdoor app (#3190)
* feat: add MFA devices QR code to UserEditPage

* chore: remove mfa devices
2024-09-08 22:38:13 +08:00
0d02b5e768 feat: remove disabled state in syncer.table 2024-09-07 21:08:21 +08:00
7 changed files with 261 additions and 57 deletions

View File

@ -950,7 +950,17 @@ func DeleteUser(user *User) (bool, error) {
return false, err
}
return deleteUser(user)
organization, err := GetOrganizationByUser(user)
if err != nil {
return false, err
}
if organization != nil && organization.EnableSoftDeletion {
user.IsDeleted = true
user.DeletedTime = util.GetCurrentTime()
return UpdateUser(user.GetId(), user, []string{"is_deleted", "deleted_time"}, false)
} else {
return deleteUser(user)
}
}
func GetUserInfo(user *User, scope string, aud string, host string) (*Userinfo, error) {

View File

@ -271,113 +271,213 @@ func CheckPermissionForUpdateUser(oldUser, newUser *User, isAdmin bool, lang str
if oldUser.Owner != newUser.Owner {
item := GetAccountItemByName("Organization", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Owner = oldUser.Owner
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Name != newUser.Name {
item := GetAccountItemByName("Name", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Name = oldUser.Name
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Id != newUser.Id {
item := GetAccountItemByName("ID", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Id = oldUser.Id
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.DisplayName != newUser.DisplayName {
item := GetAccountItemByName("Display name", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.DisplayName = oldUser.DisplayName
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Avatar != newUser.Avatar {
item := GetAccountItemByName("Avatar", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Avatar = oldUser.Avatar
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Type != newUser.Type {
item := GetAccountItemByName("User type", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Type = oldUser.Type
} else {
itemsChanged = append(itemsChanged, item)
}
}
// The password is *** when not modified
if oldUser.Password != newUser.Password && newUser.Password != "***" {
item := GetAccountItemByName("Password", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Password = oldUser.Password
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Email != newUser.Email {
item := GetAccountItemByName("Email", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Email = oldUser.Email
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Phone != newUser.Phone {
item := GetAccountItemByName("Phone", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Phone = oldUser.Phone
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.CountryCode != newUser.CountryCode {
item := GetAccountItemByName("Country code", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.CountryCode = oldUser.CountryCode
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Region != newUser.Region {
item := GetAccountItemByName("Country/Region", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Region = oldUser.Region
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Location != newUser.Location {
item := GetAccountItemByName("Location", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Location = oldUser.Location
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Affiliation != newUser.Affiliation {
item := GetAccountItemByName("Affiliation", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Affiliation = oldUser.Affiliation
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Title != newUser.Title {
item := GetAccountItemByName("Title", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Title = oldUser.Title
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Homepage != newUser.Homepage {
item := GetAccountItemByName("Homepage", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Homepage = oldUser.Homepage
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Bio != newUser.Bio {
item := GetAccountItemByName("Bio", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Bio = oldUser.Bio
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Tag != newUser.Tag {
item := GetAccountItemByName("Tag", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Tag = oldUser.Tag
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.SignupApplication != newUser.SignupApplication {
item := GetAccountItemByName("Signup application", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.SignupApplication = oldUser.SignupApplication
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Gender != newUser.Gender {
item := GetAccountItemByName("Gender", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Gender = oldUser.Gender
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Birthday != newUser.Birthday {
item := GetAccountItemByName("Birthday", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Birthday = oldUser.Birthday
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Education != newUser.Education {
item := GetAccountItemByName("Education", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Education = oldUser.Education
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.IdCard != newUser.IdCard {
item := GetAccountItemByName("ID card", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.IdCard = oldUser.IdCard
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.IdCardType != newUser.IdCardType {
item := GetAccountItemByName("ID card type", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.IdCardType = oldUser.IdCardType
} else {
itemsChanged = append(itemsChanged, item)
}
}
oldUserPropertiesJson, _ := json.Marshal(oldUser.Properties)
newUserPropertiesJson, _ := json.Marshal(newUser.Properties)
if string(oldUserPropertiesJson) != string(newUserPropertiesJson) {
item := GetAccountItemByName("Properties", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Properties = oldUser.Properties
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.PreferredMfaType != newUser.PreferredMfaType {
item := GetAccountItemByName("Multi-factor authentication", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.PreferredMfaType = oldUser.PreferredMfaType
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Groups == nil {
@ -390,7 +490,11 @@ func CheckPermissionForUpdateUser(oldUser, newUser *User, isAdmin bool, lang str
newUserGroupsJson, _ := json.Marshal(newUser.Groups)
if string(oldUserGroupsJson) != string(newUserGroupsJson) {
item := GetAccountItemByName("Groups", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Groups = oldUser.Groups
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Address == nil {
@ -404,65 +508,117 @@ func CheckPermissionForUpdateUser(oldUser, newUser *User, isAdmin bool, lang str
newUserAddressJson, _ := json.Marshal(newUser.Address)
if string(oldUserAddressJson) != string(newUserAddressJson) {
item := GetAccountItemByName("Address", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Address = oldUser.Address
} else {
itemsChanged = append(itemsChanged, item)
}
}
if newUser.FaceIds != nil {
item := GetAccountItemByName("Face ID", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.FaceIds = oldUser.FaceIds
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.IsAdmin != newUser.IsAdmin {
item := GetAccountItemByName("Is admin", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.IsAdmin = oldUser.IsAdmin
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.IsForbidden != newUser.IsForbidden {
item := GetAccountItemByName("Is forbidden", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.IsForbidden = oldUser.IsForbidden
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.IsDeleted != newUser.IsDeleted {
item := GetAccountItemByName("Is deleted", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.IsDeleted = oldUser.IsDeleted
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.NeedUpdatePassword != newUser.NeedUpdatePassword {
item := GetAccountItemByName("Need update password", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.NeedUpdatePassword = oldUser.NeedUpdatePassword
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Balance != newUser.Balance {
item := GetAccountItemByName("Balance", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Balance = oldUser.Balance
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Score != newUser.Score {
item := GetAccountItemByName("Score", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Score = oldUser.Score
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Karma != newUser.Karma {
item := GetAccountItemByName("Karma", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Karma = oldUser.Karma
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Language != newUser.Language {
item := GetAccountItemByName("Language", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Language = oldUser.Language
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Ranking != newUser.Ranking {
item := GetAccountItemByName("Ranking", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Ranking = oldUser.Ranking
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Currency != newUser.Currency {
item := GetAccountItemByName("Currency", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Currency = oldUser.Currency
} else {
itemsChanged = append(itemsChanged, item)
}
}
if oldUser.Hash != newUser.Hash {
item := GetAccountItemByName("Hash", organization)
itemsChanged = append(itemsChanged, item)
if item == nil {
newUser.Hash = oldUser.Hash
} else {
itemsChanged = append(itemsChanged, item)
}
}
for _, accountItem := range itemsChanged {

View File

@ -48,6 +48,10 @@ func CorsFilter(ctx *context.Context) {
originHostname := getHostname(origin)
host := removePort(ctx.Request.Host)
if origin == "null" {
origin = ""
}
if strings.HasPrefix(origin, "http://localhost") || strings.HasPrefix(origin, "https://localhost") || strings.HasPrefix(origin, "http://127.0.0.1") || strings.HasPrefix(origin, "http://casdoor-app") || strings.Contains(origin, ".chromiumapp.org") {
setCorsHeaders(ctx, origin)
return

View File

@ -434,10 +434,9 @@ class SyncerEditPage extends React.Component {
{Setting.getLabel(i18next.t("syncer:Table"), i18next.t("syncer:Table - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.syncer.table}
disabled={this.state.syncer.type === "Keycloak"} onChange={e => {
this.updateSyncerField("table", e.target.value);
}} />
<Input value={this.state.syncer.table} onChange={e => {
this.updateSyncerField("table", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >

View File

@ -1050,6 +1050,13 @@ class UserEditPage extends React.Component {
<MfaAccountTable
title={i18next.t("user:MFA accounts")}
table={this.state.user.mfaAccounts}
qrUrl={
"casdoor-app://login/into?serverUrl=" + window.location.origin +
"&clientId=" + this.state.application.clientId +
"&organizationName=" + this.state.organizationName +
"&appName=" + this.state.user.signupApplication
}
icon={this.state.user.avatar}
onUpdateTable={(table) => {this.updateUserField("mfaAccounts", table);}}
/>
</Col>

View File

@ -34,25 +34,42 @@ class CasLogout extends React.Component {
UNSAFE_componentWillMount() {
const params = new URLSearchParams(this.props.location.search);
const logoutInterval = 100;
const logoutTimeOut = (redirectUri) => {
setTimeout(() => {
AuthBackend.getAccount().then((accountRes) => {
if (accountRes.status === "ok") {
AuthBackend.logout().then((logoutRes) => {
if (logoutRes.status === "ok") {
logoutTimeOut(logoutRes.data2);
} else {
Setting.showMessage("error", `${i18next.t("login:Failed to log out")}: ${logoutRes.msg}`);
}
});
} else {
Setting.showMessage("success", i18next.t("application:Logged out successfully"));
this.props.onUpdateAccount(null);
if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") {
Setting.goToLink(redirectUri);
} else if (params.has("service")) {
Setting.goToLink(params.get("service"));
} else {
Setting.goToLinkSoft(this, `/cas/${this.state.owner}/${this.state.applicationName}/login`);
}
}
});
}, logoutInterval);
};
AuthBackend.logout()
.then((res) => {
if (res.status === "ok") {
Setting.showMessage("success", "Logged out successfully");
this.props.onUpdateAccount(null);
const redirectUri = res.data2;
if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") {
Setting.goToLink(redirectUri);
} else if (params.has("service")) {
Setting.goToLink(params.get("service"));
} else {
Setting.goToLinkSoft(this, `/cas/${this.state.owner}/${this.state.applicationName}/login`);
}
logoutTimeOut(res.data2);
} else {
Setting.showMessage("error", `Failed to log out: ${res.msg}`);
Setting.showMessage("error", `${i18next.t("login:Failed to log out")}: ${res.msg}`);
}
});
}
render() {

View File

@ -14,7 +14,7 @@
import React from "react";
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
import {Button, Col, Image, Input, Row, Table, Tooltip} from "antd";
import {Button, Col, Image, Input, Popover, QRCode, Row, Table, Tooltip} from "antd";
import * as Setting from "../Setting";
import i18next from "i18next";
@ -23,6 +23,8 @@ class MfaAccountTable extends React.Component {
super(props);
this.state = {
classes: props,
qrUrl: this.props.qrUrl,
icon: this.props.icon,
mfaAccounts: this.props.table !== null ? this.props.table.map((item, index) => {
item.key = index;
return item;
@ -158,6 +160,15 @@ class MfaAccountTable extends React.Component {
<div>
{this.props.title}&nbsp;&nbsp;&nbsp;&nbsp;
<Button style={{marginRight: "5px"}} type="primary" size="small" onClick={() => this.addRow(table)}>{i18next.t("general:Add")}</Button>
<Popover trigger="focus" content={
<QRCode
value={this.state.qrUrl}
icon={this.state.icon}
bordered={false}
/>
}>
<Button style={{marginLeft: "5px"}} type="primary" size="small">{i18next.t("general:QR Code")}</Button>
</Popover>
</div>
)}
/>