mirror of
https://github.com/casdoor/casdoor.git
synced 2025-09-09 01:12:55 +08:00
feat: add isProfilePublic setting for accessing user info (#656)
* feat: add isProfilePublic setting for accessing user info Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com> * fix: requested changes Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>
This commit is contained in:
@@ -87,6 +87,17 @@ func (c *ApiController) GetUser() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
owner := c.Input().Get("owner")
|
owner := c.Input().Get("owner")
|
||||||
email := c.Input().Get("email")
|
email := c.Input().Get("email")
|
||||||
|
userOwner, _ := util.GetOwnerAndNameFromId(id)
|
||||||
|
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", userOwner))
|
||||||
|
|
||||||
|
if !organization.IsProfilePublic {
|
||||||
|
requestUserId := c.GetSessionUsername()
|
||||||
|
hasPermission, err := object.CheckUserPermission(requestUserId, id, false)
|
||||||
|
if !hasPermission {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var user *object.User
|
var user *object.User
|
||||||
if email == "" {
|
if email == "" {
|
||||||
@@ -233,39 +244,15 @@ func (c *ApiController) SetPassword() {
|
|||||||
newPassword := c.Ctx.Request.Form.Get("newPassword")
|
newPassword := c.Ctx.Request.Form.Get("newPassword")
|
||||||
|
|
||||||
requestUserId := c.GetSessionUsername()
|
requestUserId := c.GetSessionUsername()
|
||||||
if requestUserId == "" {
|
|
||||||
c.ResponseError("Please login first")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userId := fmt.Sprintf("%s/%s", userOwner, userName)
|
userId := fmt.Sprintf("%s/%s", userOwner, userName)
|
||||||
targetUser := object.GetUser(userId)
|
|
||||||
if targetUser == nil {
|
hasPermission, err := object.CheckUserPermission(requestUserId, userId, true)
|
||||||
c.ResponseError(fmt.Sprintf("The user: %s doesn't exist", userId))
|
if !hasPermission {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPermission := false
|
targetUser := object.GetUser(userId)
|
||||||
if strings.HasPrefix(requestUserId, "app/") {
|
|
||||||
hasPermission = true
|
|
||||||
} else {
|
|
||||||
requestUser := object.GetUser(requestUserId)
|
|
||||||
if requestUser == nil {
|
|
||||||
c.ResponseError("Session outdated. Please login again.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if requestUser.IsGlobalAdmin {
|
|
||||||
hasPermission = true
|
|
||||||
} else if requestUserId == userId {
|
|
||||||
hasPermission = true
|
|
||||||
} else if targetUser.Owner == requestUser.Owner && requestUser.IsAdmin {
|
|
||||||
hasPermission = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !hasPermission {
|
|
||||||
c.ResponseError("You don't have the permission to do this.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if oldPassword != "" {
|
if oldPassword != "" {
|
||||||
msg := object.CheckPassword(targetUser, oldPassword)
|
msg := object.CheckPassword(targetUser, oldPassword)
|
||||||
|
@@ -17,6 +17,7 @@ package object
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/cred"
|
"github.com/casdoor/casdoor/cred"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@@ -195,3 +196,37 @@ func CheckUserPassword(organization string, username string, password string) (*
|
|||||||
func filterField(field string) bool {
|
func filterField(field string) bool {
|
||||||
return reFieldWhiteList.MatchString(field)
|
return reFieldWhiteList.MatchString(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckUserPermission(requestUserId, userId string, strict bool) (bool, error) {
|
||||||
|
if requestUserId == "" {
|
||||||
|
return false, fmt.Errorf("please login first")
|
||||||
|
}
|
||||||
|
|
||||||
|
targetUser := GetUser(userId)
|
||||||
|
if targetUser == nil {
|
||||||
|
return false, fmt.Errorf("the user: %s doesn't exist", userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
hasPermission := false
|
||||||
|
if strings.HasPrefix(requestUserId, "app/") {
|
||||||
|
hasPermission = true
|
||||||
|
} else {
|
||||||
|
requestUser := GetUser(requestUserId)
|
||||||
|
if requestUser == nil {
|
||||||
|
return false, fmt.Errorf("session outdated, please login again")
|
||||||
|
}
|
||||||
|
if requestUser.IsGlobalAdmin {
|
||||||
|
hasPermission = true
|
||||||
|
} else if requestUserId == userId {
|
||||||
|
hasPermission = true
|
||||||
|
} else if targetUser.Owner == requestUser.Owner {
|
||||||
|
if strict {
|
||||||
|
hasPermission = requestUser.IsAdmin
|
||||||
|
} else {
|
||||||
|
hasPermission = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasPermission, fmt.Errorf("you don't have the permission to do this")
|
||||||
|
}
|
@@ -35,6 +35,7 @@ type Organization struct {
|
|||||||
Tags []string `xorm:"mediumtext" json:"tags"`
|
Tags []string `xorm:"mediumtext" json:"tags"`
|
||||||
MasterPassword string `xorm:"varchar(100)" json:"masterPassword"`
|
MasterPassword string `xorm:"varchar(100)" json:"masterPassword"`
|
||||||
EnableSoftDeletion bool `json:"enableSoftDeletion"`
|
EnableSoftDeletion bool `json:"enableSoftDeletion"`
|
||||||
|
IsProfilePublic bool `json:"isProfilePublic"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetOrganizationCount(owner, field, value string) int {
|
func GetOrganizationCount(owner, field, value string) int {
|
||||||
|
@@ -240,6 +240,16 @@ class OrganizationEditPage extends React.Component {
|
|||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: '20px'}} >
|
||||||
|
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("organization:Is profile public"), i18next.t("organization:Is profile public - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={1} >
|
||||||
|
<Switch checked={this.state.organization.isProfilePublic} onChange={checked => {
|
||||||
|
this.updateOrganizationField('isProfilePublic', checked);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: '20px'}}>
|
<Row style={{marginTop: '20px'}}>
|
||||||
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("general:LDAPs"), i18next.t("general:LDAPs - Tooltip"))} :
|
{Setting.getLabel(i18next.t("general:LDAPs"), i18next.t("general:LDAPs - Tooltip"))} :
|
||||||
|
@@ -39,6 +39,7 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
tags: [],
|
tags: [],
|
||||||
masterPassword: "",
|
masterPassword: "",
|
||||||
enableSoftDeletion: false,
|
enableSoftDeletion: false,
|
||||||
|
isProfilePublic: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Card, Col, Input, Row, Select, Switch} from 'antd';
|
import {Button, Card, Col, Input, Result, Row, Select, Spin, Switch} from 'antd';
|
||||||
import * as UserBackend from "./backend/UserBackend";
|
import * as UserBackend from "./backend/UserBackend";
|
||||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
@@ -47,6 +47,7 @@ class UserEditPage extends React.Component {
|
|||||||
organizations: [],
|
organizations: [],
|
||||||
applications: [],
|
applications: [],
|
||||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||||
|
loading: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,9 +60,14 @@ class UserEditPage extends React.Component {
|
|||||||
|
|
||||||
getUser() {
|
getUser() {
|
||||||
UserBackend.getUser(this.state.organizationName, this.state.userName)
|
UserBackend.getUser(this.state.organizationName, this.state.userName)
|
||||||
.then((user) => {
|
.then((data) => {
|
||||||
|
if (data.status === null || data.status !== "error") {
|
||||||
|
this.setState({
|
||||||
|
user: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
user: user,
|
loading: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -423,6 +429,8 @@ class UserEditPage extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,13 +477,24 @@ class UserEditPage extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
this.state.user !== null ? this.renderUser() : null
|
this.state.loading ? <Spin loading={this.state.loading} size="large" /> : (
|
||||||
|
this.state.user !== null ? this.renderUser() :
|
||||||
|
<Result
|
||||||
|
status="404"
|
||||||
|
title="404 NOT FOUND"
|
||||||
|
subTitle={i18next.t("general:Sorry, the user you visited does not exist or you are not authorized to access this user.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
this.state.user === null ? null :
|
||||||
|
<div style={{marginTop: '20px', marginLeft: '40px'}}>
|
||||||
|
<Button size="large" onClick={() => this.submitUserEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||||
|
<Button style={{marginLeft: '20px'}} type="primary" size="large" onClick={() => this.submitUserEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||||
|
{this.state.mode === "add" ? <Button style={{marginLeft: '20px'}} size="large" onClick={() => this.deleteUser()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
<div style={{marginTop: '20px', marginLeft: '40px'}}>
|
|
||||||
<Button size="large" onClick={() => this.submitUserEdit(false)}>{i18next.t("general:Save")}</Button>
|
|
||||||
<Button style={{marginLeft: '20px'}} type="primary" size="large" onClick={() => this.submitUserEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
|
||||||
{this.state.mode === "add" ? <Button style={{marginLeft: '20px'}} size="large" onClick={() => this.deleteUser()}>{i18next.t("general:Cancel")}</Button> : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -171,6 +171,7 @@
|
|||||||
"Signup application": "注册应用",
|
"Signup application": "注册应用",
|
||||||
"Signup application - Tooltip": "表示用户注册时通过哪个应用注册的",
|
"Signup application - Tooltip": "表示用户注册时通过哪个应用注册的",
|
||||||
"Sorry, the page you visited does not exist.": "抱歉,您访问的页面不存在",
|
"Sorry, the page you visited does not exist.": "抱歉,您访问的页面不存在",
|
||||||
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "抱歉,您访问的用户不存在或您无权访问该用户",
|
||||||
"State": "状态",
|
"State": "状态",
|
||||||
"State - Tooltip": "状态",
|
"State - Tooltip": "状态",
|
||||||
"Swagger": "API文档",
|
"Swagger": "API文档",
|
||||||
@@ -252,7 +253,9 @@
|
|||||||
"Tags": "标签集合",
|
"Tags": "标签集合",
|
||||||
"Tags - Tooltip": "可供用户选择的标签的集合",
|
"Tags - Tooltip": "可供用户选择的标签的集合",
|
||||||
"Website URL": "网页地址",
|
"Website URL": "网页地址",
|
||||||
"Website URL - Tooltip": "网页地址"
|
"Website URL - Tooltip": "网页地址",
|
||||||
|
"Is profile public": "公开用户信息",
|
||||||
|
"Is profile public - Tooltip": "关闭后,只有全局管理员或同组织才能访问用户信息"
|
||||||
},
|
},
|
||||||
"payment": {
|
"payment": {
|
||||||
"Currency": "币种",
|
"Currency": "币种",
|
||||||
|
Reference in New Issue
Block a user