mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 10:45:47 +08:00
Add user soft deletion.
This commit is contained in:
parent
db892333fe
commit
9e920181d2
@ -152,6 +152,7 @@ func (c *ApiController) Signup() {
|
|||||||
IsAdmin: false,
|
IsAdmin: false,
|
||||||
IsGlobalAdmin: false,
|
IsGlobalAdmin: false,
|
||||||
IsForbidden: false,
|
IsForbidden: false,
|
||||||
|
IsDeleted: false,
|
||||||
SignupApplication: application.Name,
|
SignupApplication: application.Name,
|
||||||
Properties: map[string]string{},
|
Properties: map[string]string{},
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ func (c *ApiController) Login() {
|
|||||||
user = object.GetUserByField(application.Organization, "name", userInfo.Username)
|
user = object.GetUserByField(application.Organization, "name", userInfo.Username)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user != nil {
|
if user != nil && user.IsDeleted == false {
|
||||||
// Sign in via OAuth (want to sign up but already have account)
|
// Sign in via OAuth (want to sign up but already have account)
|
||||||
|
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
@ -293,6 +293,7 @@ func (c *ApiController) Login() {
|
|||||||
IsAdmin: false,
|
IsAdmin: false,
|
||||||
IsGlobalAdmin: false,
|
IsGlobalAdmin: false,
|
||||||
IsForbidden: false,
|
IsForbidden: false,
|
||||||
|
IsDeleted: false,
|
||||||
SignupApplication: application.Name,
|
SignupApplication: application.Name,
|
||||||
Properties: properties,
|
Properties: properties,
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ func CheckPassword(user *User, password string) string {
|
|||||||
|
|
||||||
func CheckUserPassword(organization string, username string, password string) (*User, string) {
|
func CheckUserPassword(organization string, username string, password string) (*User, string) {
|
||||||
user := GetUserByFields(organization, username)
|
user := GetUserByFields(organization, username)
|
||||||
if user == nil {
|
if user == nil || user.IsDeleted == true {
|
||||||
return nil, "the user does not exist, please sign up first"
|
return nil, "the user does not exist, please sign up first"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ func initBuiltInUser() {
|
|||||||
IsAdmin: true,
|
IsAdmin: true,
|
||||||
IsGlobalAdmin: true,
|
IsGlobalAdmin: true,
|
||||||
IsForbidden: false,
|
IsForbidden: false,
|
||||||
|
IsDeleted: false,
|
||||||
Properties: make(map[string]string),
|
Properties: make(map[string]string),
|
||||||
}
|
}
|
||||||
AddUser(user)
|
AddUser(user)
|
||||||
|
@ -24,13 +24,14 @@ type Organization struct {
|
|||||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
|
|
||||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
WebsiteUrl string `xorm:"varchar(100)" json:"websiteUrl"`
|
WebsiteUrl string `xorm:"varchar(100)" json:"websiteUrl"`
|
||||||
Favicon string `xorm:"varchar(100)" json:"favicon"`
|
Favicon string `xorm:"varchar(100)" json:"favicon"`
|
||||||
PasswordType string `xorm:"varchar(100)" json:"passwordType"`
|
PasswordType string `xorm:"varchar(100)" json:"passwordType"`
|
||||||
PasswordSalt string `xorm:"varchar(100)" json:"passwordSalt"`
|
PasswordSalt string `xorm:"varchar(100)" json:"passwordSalt"`
|
||||||
PhonePrefix string `xorm:"varchar(10)" json:"phonePrefix"`
|
PhonePrefix string `xorm:"varchar(10)" json:"phonePrefix"`
|
||||||
DefaultAvatar string `xorm:"varchar(100)" json:"defaultAvatar"`
|
DefaultAvatar string `xorm:"varchar(100)" json:"defaultAvatar"`
|
||||||
|
EnableSoftDeletion bool `json:"enableSoftDeletion"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetOrganizationCount(owner string) int {
|
func GetOrganizationCount(owner string) int {
|
||||||
|
@ -51,6 +51,7 @@ type User struct {
|
|||||||
IsAdmin bool `json:"isAdmin"`
|
IsAdmin bool `json:"isAdmin"`
|
||||||
IsGlobalAdmin bool `json:"isGlobalAdmin"`
|
IsGlobalAdmin bool `json:"isGlobalAdmin"`
|
||||||
IsForbidden bool `json:"isForbidden"`
|
IsForbidden bool `json:"isForbidden"`
|
||||||
|
IsDeleted bool `json:"isDeleted"`
|
||||||
SignupApplication string `xorm:"varchar(100)" json:"signupApplication"`
|
SignupApplication string `xorm:"varchar(100)" json:"signupApplication"`
|
||||||
Hash string `xorm:"varchar(100)" json:"hash"`
|
Hash string `xorm:"varchar(100)" json:"hash"`
|
||||||
PreHash string `xorm:"varchar(100)" json:"preHash"`
|
PreHash string `xorm:"varchar(100)" json:"preHash"`
|
||||||
@ -199,8 +200,8 @@ func UpdateUser(id string, user *User) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).Cols("owner", "display_name", "avatar",
|
affected, err := adapter.Engine.ID(core.PK{owner, name}).Cols("owner", "display_name", "avatar",
|
||||||
"location", "address", "region", "language", "affiliation", "title", "homepage", "bio", "score", "tag", "is_admin", "is_global_admin", "is_forbidden",
|
"location", "address", "region", "language", "affiliation", "title", "homepage", "bio", "score", "tag",
|
||||||
"hash", "properties").Update(user)
|
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "properties").Update(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ func createUserFromOriginalUser(originalUser *User, affiliationMap map[int]strin
|
|||||||
IsAdmin: false,
|
IsAdmin: false,
|
||||||
IsGlobalAdmin: false,
|
IsGlobalAdmin: false,
|
||||||
IsForbidden: originalUser.Deleted != 0,
|
IsForbidden: originalUser.Deleted != 0,
|
||||||
|
IsDeleted: false,
|
||||||
Properties: map[string]string{},
|
Properties: map[string]string{},
|
||||||
}
|
}
|
||||||
return user
|
return user
|
||||||
|
@ -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} from 'antd';
|
import {Button, Card, Col, Input, Row, Select, Switch} from 'antd';
|
||||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||||
import * as LdapBackend from "./backend/LdapBackend";
|
import * as LdapBackend from "./backend/LdapBackend";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
@ -205,6 +205,16 @@ class OrganizationEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: '20px'}} >
|
||||||
|
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("organization:Soft deletion"), i18next.t("organization:Soft deletion - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={1} >
|
||||||
|
<Switch checked={this.state.organization.enableSoftDeletion} onChange={checked => {
|
||||||
|
this.updateOrganizationField('enableSoftDeletion', 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"))} :
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import {Button, Popconfirm, Table} from 'antd';
|
import {Button, Popconfirm, Switch, Table} from 'antd';
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||||
@ -59,6 +59,7 @@ class OrganizationListPage extends React.Component {
|
|||||||
PasswordSalt: "",
|
PasswordSalt: "",
|
||||||
phonePrefix: "86",
|
phonePrefix: "86",
|
||||||
defaultAvatar: "https://casbin.org/img/casbin.svg",
|
defaultAvatar: "https://casbin.org/img/casbin.svg",
|
||||||
|
enableSoftDeletion: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +159,7 @@ class OrganizationListPage extends React.Component {
|
|||||||
title: i18next.t("general:Password type"),
|
title: i18next.t("general:Password type"),
|
||||||
dataIndex: 'passwordType',
|
dataIndex: 'passwordType',
|
||||||
key: 'passwordType',
|
key: 'passwordType',
|
||||||
width: '100px',
|
width: '150px',
|
||||||
sorter: (a, b) => a.passwordType.localeCompare(b.passwordType),
|
sorter: (a, b) => a.passwordType.localeCompare(b.passwordType),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -172,7 +173,7 @@ class OrganizationListPage extends React.Component {
|
|||||||
title: i18next.t("organization:Default avatar"),
|
title: i18next.t("organization:Default avatar"),
|
||||||
dataIndex: 'defaultAvatar',
|
dataIndex: 'defaultAvatar',
|
||||||
key: 'defaultAvatar',
|
key: 'defaultAvatar',
|
||||||
width: '50px',
|
width: '120px',
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<a target="_blank" rel="noreferrer" href={text}>
|
<a target="_blank" rel="noreferrer" href={text}>
|
||||||
@ -181,6 +182,18 @@ class OrganizationListPage extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("organization:Soft deletion"),
|
||||||
|
dataIndex: 'enableSoftDeletion',
|
||||||
|
key: 'enableSoftDeletion',
|
||||||
|
width: '140px',
|
||||||
|
sorter: (a, b) => a.enableSoftDeletion - b.enableSoftDeletion,
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Switch disabled checkedChildren="ON" unCheckedChildren="OFF" checked={text} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("general:Action"),
|
title: i18next.t("general:Action"),
|
||||||
dataIndex: '',
|
dataIndex: '',
|
||||||
|
@ -353,6 +353,16 @@ class UserEditPage extends React.Component {
|
|||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: '20px'}} >
|
||||||
|
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("user:Is deleted"), i18next.t("user:Is deleted - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={(Setting.isMobile()) ? 22 : 2} >
|
||||||
|
<Switch checked={this.state.user.isDeleted} onChange={checked => {
|
||||||
|
this.updateUserField('isDeleted', checked);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ class UserListPage extends React.Component {
|
|||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
type: "normal-user",
|
type: "normal-user",
|
||||||
password: "123",
|
password: "123",
|
||||||
|
passwordSalt: "",
|
||||||
displayName: `New User - ${randomName}`,
|
displayName: `New User - ${randomName}`,
|
||||||
avatar: "https://casbin.org/img/casbin.svg",
|
avatar: "https://casbin.org/img/casbin.svg",
|
||||||
email: "user@example.com",
|
email: "user@example.com",
|
||||||
@ -78,6 +79,7 @@ class UserListPage extends React.Component {
|
|||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
isGlobalAdmin: false,
|
isGlobalAdmin: false,
|
||||||
IsForbidden: false,
|
IsForbidden: false,
|
||||||
|
isDeleted: false,
|
||||||
properties: {},
|
properties: {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +166,7 @@ class UserListPage extends React.Component {
|
|||||||
title: i18next.t("general:Created time"),
|
title: i18next.t("general:Created time"),
|
||||||
dataIndex: 'createdTime',
|
dataIndex: 'createdTime',
|
||||||
key: 'createdTime',
|
key: 'createdTime',
|
||||||
width: '180px',
|
width: '160px',
|
||||||
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
sorter: (a, b) => a.createdTime.localeCompare(b.createdTime),
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return Setting.getFormattedDate(text);
|
return Setting.getFormattedDate(text);
|
||||||
@ -243,7 +245,7 @@ class UserListPage extends React.Component {
|
|||||||
title: i18next.t("user:Is admin"),
|
title: i18next.t("user:Is admin"),
|
||||||
dataIndex: 'isAdmin',
|
dataIndex: 'isAdmin',
|
||||||
key: 'isAdmin',
|
key: 'isAdmin',
|
||||||
width: '100px',
|
width: '110px',
|
||||||
sorter: (a, b) => a.isAdmin - b.isAdmin,
|
sorter: (a, b) => a.isAdmin - b.isAdmin,
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
@ -255,7 +257,7 @@ class UserListPage extends React.Component {
|
|||||||
title: i18next.t("user:Is global admin"),
|
title: i18next.t("user:Is global admin"),
|
||||||
dataIndex: 'isGlobalAdmin',
|
dataIndex: 'isGlobalAdmin',
|
||||||
key: 'isGlobalAdmin',
|
key: 'isGlobalAdmin',
|
||||||
width: '100px',
|
width: '110px',
|
||||||
sorter: (a, b) => a.isGlobalAdmin - b.isGlobalAdmin,
|
sorter: (a, b) => a.isGlobalAdmin - b.isGlobalAdmin,
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
@ -267,7 +269,7 @@ class UserListPage extends React.Component {
|
|||||||
title: i18next.t("user:Is forbidden"),
|
title: i18next.t("user:Is forbidden"),
|
||||||
dataIndex: 'isForbidden',
|
dataIndex: 'isForbidden',
|
||||||
key: 'isForbidden',
|
key: 'isForbidden',
|
||||||
width: '100px',
|
width: '110px',
|
||||||
sorter: (a, b) => a.isForbidden - b.isForbidden,
|
sorter: (a, b) => a.isForbidden - b.isForbidden,
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
@ -275,6 +277,18 @@ class UserListPage extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("user:Is deleted"),
|
||||||
|
dataIndex: 'isDeleted',
|
||||||
|
key: 'isDeleted',
|
||||||
|
width: '110px',
|
||||||
|
sorter: (a, b) => a.isDeleted - b.isDeleted,
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Switch disabled checkedChildren="ON" unCheckedChildren="OFF" checked={text} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("general:Action"),
|
title: i18next.t("general:Action"),
|
||||||
dataIndex: '',
|
dataIndex: '',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user