Compare commits

...

10 Commits

Author SHA1 Message Date
61c2fd5412 feat: fix the issue of jumping back to the login page after resetting password (#1288)
* fix: redirect to login page

* fix: front end router

* fix: front end router

* fix: signup page router

* fix: redirect to login page
2022-11-13 12:16:49 +08:00
d542208eb8 feat: fix select language box overlay (#1289)
* fix: select language box overlay

* fix: select language box position

* fix: select language box position

* fix: select language box position
2022-11-13 10:52:22 +08:00
f818200c95 feat: fix empty organization in adapter edit page (#1274) 2022-11-08 21:03:15 +08:00
5bc2e91344 fix: fix typo (#1264) 2022-11-06 21:14:26 +08:00
295f732b18 Show tag in i18n 2022-11-06 20:19:31 +08:00
770ae47471 feat: fix memory leak problem (#1257) 2022-11-06 01:43:27 +08:00
2ce4f96355 fix: forget page mobile view (#1263) 2022-11-05 22:54:22 +08:00
07ed834b27 fix: system info mobile view (#1261) 2022-11-05 22:46:52 +08:00
8d686411ee feat: support add providers inside the Organization scope (#1250)
* feat: support add providers inside the Organization scope

Signed-off-by: magicwind <2814461814@qq.com>

* Update ProviderListPage.js

* fix: gloabal admin can see all providers

* fix: table fixed column warning

* fix: edit application page can get all providers

Signed-off-by: magicwind <2814461814@qq.com>
Co-authored-by: hsluoyz <hsluoyz@qq.com>
2022-11-04 21:31:08 +08:00
ce722897f1 feat: support prefix path for storage files (#1258) 2022-11-04 21:08:39 +08:00
37 changed files with 503 additions and 304 deletions

View File

@ -142,7 +142,7 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
userId := fmt.Sprintf("%s/%s", subOwner, subName)
user := object.GetUser(userId)
if user != nil && user.IsAdmin && subOwner == objOwner {
if user != nil && user.IsAdmin && (subOwner == objOwner || (objOwner == "admin" && subOwner == objName)) {
return true
}

View File

@ -48,6 +48,30 @@ func (c *ApiController) GetProviders() {
}
}
// GetGlobalProviders
// @Title GetGlobalProviders
// @Tag Provider API
// @Description get Global providers
// @Success 200 {array} object.Provider The Response object
// @router /get-global-providers [get]
func (c *ApiController) GetGlobalProviders() {
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedProviders(object.GetGlobalProviders())
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalProviderCount(field, value)))
providers := object.GetMaskedProviders(object.GetPaginationGlobalProviders(paginator.Offset(), limit, field, value, sortField, sortOrder))
c.ResponseOk(providers, paginator.Nums())
}
}
// GetProvider
// @Title GetProvider
// @Tag Provider API

View File

@ -60,6 +60,7 @@ type Provider struct {
IntranetEndpoint string `xorm:"varchar(100)" json:"intranetEndpoint"`
Domain string `xorm:"varchar(100)" json:"domain"`
Bucket string `xorm:"varchar(100)" json:"bucket"`
PathPrefix string `xorm:"varchar(100)" json:"pathPrefix"`
Metadata string `xorm:"mediumtext" json:"metadata"`
IdP string `xorm:"mediumtext" json:"idP"`
@ -101,6 +102,16 @@ func GetProviderCount(owner, field, value string) int {
return int(count)
}
func GetGlobalProviderCount(field, value string) int {
session := GetSession("", -1, -1, field, value, "", "")
count, err := session.Count(&Provider{})
if err != nil {
panic(err)
}
return int(count)
}
func GetProviders(owner string) []*Provider {
providers := []*Provider{}
err := adapter.Engine.Desc("created_time").Find(&providers, &Provider{Owner: owner})
@ -111,8 +122,18 @@ func GetProviders(owner string) []*Provider {
return providers
}
func GetPaginationProviders(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Provider {
func GetGlobalProviders() []*Provider {
providers := []*Provider{}
err := adapter.Engine.Desc("created_time").Find(&providers)
if err != nil {
panic(err)
}
return providers
}
func GetPaginationProviders(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Provider {
var providers []*Provider
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&providers)
if err != nil {
@ -122,6 +143,17 @@ func GetPaginationProviders(owner string, offset, limit int, field, value, sortF
return providers
}
func GetPaginationGlobalProviders(offset, limit int, field, value, sortField, sortOrder string) []*Provider {
var providers []*Provider
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
err := session.Find(&providers)
if err != nil {
panic(err)
}
return providers
}
func getProvider(owner string, name string) *Provider {
if owner == "" || name == "" {
return nil

View File

@ -55,7 +55,7 @@ func escapePath(path string) string {
}
func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool) (string, string) {
escapedPath := escapePath(fullFilePath)
escapedPath := util.UrlJoin(provider.PathPrefix, escapePath(fullFilePath))
objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), escapedPath)
host := ""
@ -70,7 +70,7 @@ func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool
host = util.UrlJoin(provider.Domain, "/files")
}
if provider.Type == "Azure Blob" {
host = fmt.Sprintf("%s/%s", host, provider.Bucket)
host = util.UrlJoin(host, provider.Bucket)
}
fileUrl := util.UrlJoin(host, escapePath(objectKey))

View File

@ -37,7 +37,16 @@ func (syncer *Syncer) getOriginalUsers() ([]*OriginalUser, error) {
return nil, err
}
return syncer.getOriginalUsersFromMap(results), nil
// Memory leak problem handling
// https://github.com/casdoor/casdoor/issues/1256
users := syncer.getOriginalUsersFromMap(results)
for _, m := range results {
for k := range m {
delete(m, k)
}
}
return users, nil
}
func (syncer *Syncer) getOriginalUserMap() ([]*OriginalUser, map[string]*OriginalUser, error) {

View File

@ -123,6 +123,7 @@ func initAPI() {
beego.Router("/api/get-providers", &controllers.ApiController{}, "GET:GetProviders")
beego.Router("/api/get-provider", &controllers.ApiController{}, "GET:GetProvider")
beego.Router("/api/get-global-providers", &controllers.ApiController{}, "GET:GetGlobalProviders")
beego.Router("/api/update-provider", &controllers.ApiController{}, "POST:UpdateProvider")
beego.Router("/api/add-provider", &controllers.ApiController{}, "POST:AddProvider")
beego.Router("/api/delete-provider", &controllers.ApiController{}, "POST:DeleteProvider")

View File

@ -120,7 +120,7 @@ class AccountTable extends React.Component {
},
},
{
title: i18next.t("provider:visible"),
title: i18next.t("organization:Visible"),
dataIndex: "visible",
key: "visible",
width: "120px",
@ -133,7 +133,7 @@ class AccountTable extends React.Component {
},
},
{
title: i18next.t("organization:viewRule"),
title: i18next.t("organization:View rule"),
dataIndex: "viewRule",
key: "viewRule",
width: "155px",
@ -160,7 +160,7 @@ class AccountTable extends React.Component {
},
},
{
title: i18next.t("organization:modifyRule"),
title: i18next.t("organization:Modify rule"),
dataIndex: "modifyRule",
key: "modifyRule",
width: "155px",

View File

@ -59,7 +59,7 @@ class AdapterEditPage extends React.Component {
}
getOrganizations() {
OrganizationBackend.getOrganizations(this.state.organizationName)
OrganizationBackend.getOrganizations("admin")
.then((res) => {
this.setState({
organizations: (res.msg === undefined) ? res : [],
@ -195,7 +195,7 @@ class AdapterEditPage extends React.Component {
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.adapter.organization} onChange={(value => {this.updateadapterField("organization", value);})}>
<Select virtual={false} style={{width: "100%"}} value={this.state.adapter.organization} onChange={(value => {this.updateAdapterField("organization", value);})}>
{
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
}

View File

@ -70,21 +70,6 @@ class AdapterListPage extends BaseListPage {
renderTable(adapters) {
const columns = [
{
title: i18next.t("general:Organization"),
dataIndex: "organization",
key: "organization",
width: "120px",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Name"),
dataIndex: "name",
@ -101,6 +86,21 @@ class AdapterListPage extends BaseListPage {
);
},
},
{
title: i18next.t("general:Organization"),
dataIndex: "organization",
key: "organization",
width: "120px",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Created time"),
dataIndex: "createdTime",

View File

@ -420,13 +420,6 @@ class App extends Component {
</Link>
</Menu.Item>
);
res.push(
<Menu.Item key="/providers">
<Link to="/providers">
{i18next.t("general:Providers")}
</Link>
</Menu.Item>
);
res.push(
<Menu.Item key="/applications">
<Link to="/applications">
@ -437,6 +430,13 @@ class App extends Component {
}
if (Setting.isLocalAdminUser(this.state.account)) {
res.push(
<Menu.Item key="/providers">
<Link to="/providers">
{i18next.t("general:Providers")}
</Link>
</Menu.Item>
);
res.push(
<Menu.Item key="/resources">
<Link to="/resources">
@ -566,6 +566,7 @@ class App extends Component {
<Route exact path="/adapters/:organizationName/:adapterName" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterEditPage account={this.state.account} {...props} />)} />
<Route exact path="/providers" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderListPage account={this.state.account} {...props} />)} />
<Route exact path="/providers/:providerName" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderEditPage account={this.state.account} {...props} />)} />
<Route exact path="/providers/:organizationName/:providerName" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderEditPage account={this.state.account} {...props} />)} />
<Route exact path="/applications" render={(props) => this.renderLoginIfNotLoggedIn(<ApplicationListPage account={this.state.account} {...props} />)} />
<Route exact path="/applications/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<ApplicationEditPage account={this.state.account} {...props} />)} />
<Route exact path="/resources" render={(props) => this.renderLoginIfNotLoggedIn(<ResourceListPage account={this.state.account} {...props} />)} />

View File

@ -123,7 +123,7 @@
.login-form {
text-align: center;
padding: 10px;
padding: 30px;
}
.login-content {

View File

@ -91,6 +91,7 @@ class ApplicationEditPage extends React.Component {
super(props);
this.state = {
classes: props,
owner: props.account.owner,
applicationName: props.match.params.applicationName,
application: null,
organizations: [],
@ -141,12 +142,21 @@ class ApplicationEditPage extends React.Component {
}
getProviders() {
ProviderBackend.getProviders("admin")
.then((res) => {
this.setState({
providers: res,
if (Setting.isAdminUser(this.props.account)) {
ProviderBackend.getGlobalProviders()
.then((res) => {
this.setState({
providers: res,
});
});
});
} else {
ProviderBackend.getProviders(this.state.owner)
.then((res) => {
this.setState({
providers: res,
});
});
}
}
getSamlMetadata() {

View File

@ -63,21 +63,6 @@ class ModelListPage extends BaseListPage {
renderTable(models) {
const columns = [
{
title: i18next.t("general:Organization"),
dataIndex: "owner",
key: "owner",
width: "120px",
sorter: true,
...this.getColumnSearchProps("owner"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Name"),
dataIndex: "name",
@ -94,6 +79,21 @@ class ModelListPage extends BaseListPage {
);
},
},
{
title: i18next.t("general:Organization"),
dataIndex: "owner",
key: "owner",
width: "120px",
sorter: true,
...this.getColumnSearchProps("owner"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Created time"),
dataIndex: "createdTime",

View File

@ -76,6 +76,38 @@ class PaymentListPage extends BaseListPage {
renderTable(payments) {
const columns = [
{
title: i18next.t("general:Name"),
dataIndex: "name",
key: "name",
width: "180px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("name"),
render: (text, record, index) => {
return (
<Link to={`/payments/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Provider"),
dataIndex: "provider",
key: "provider",
width: "150px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("provider"),
render: (text, record, index) => {
return (
<Link to={`/providers/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Organization"),
dataIndex: "organization",
@ -106,22 +138,7 @@ class PaymentListPage extends BaseListPage {
);
},
},
{
title: i18next.t("general:Name"),
dataIndex: "name",
key: "name",
width: "180px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("name"),
render: (text, record, index) => {
return (
<Link to={`/payments/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Created time"),
dataIndex: "createdTime",
@ -140,22 +157,6 @@ class PaymentListPage extends BaseListPage {
// sorter: true,
// ...this.getColumnSearchProps('displayName'),
// },
{
title: i18next.t("general:Provider"),
dataIndex: "provider",
key: "provider",
width: "150px",
fixed: "left",
sorter: true,
...this.getColumnSearchProps("provider"),
render: (text, record, index) => {
return (
<Link to={`/providers/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("payment:Type"),
dataIndex: "type",

View File

@ -77,21 +77,7 @@ class PermissionListPage extends BaseListPage {
renderTable(permissions) {
const columns = [
{
title: i18next.t("general:Organization"),
dataIndex: "owner",
key: "owner",
width: "120px",
sorter: true,
...this.getColumnSearchProps("owner"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
// https://github.com/ant-design/ant-design/issues/22184
{
title: i18next.t("general:Name"),
dataIndex: "name",
@ -108,6 +94,21 @@ class PermissionListPage extends BaseListPage {
);
},
},
{
title: i18next.t("general:Organization"),
dataIndex: "owner",
key: "owner",
width: "120px",
sorter: true,
...this.getColumnSearchProps("owner"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Created time"),
dataIndex: "createdTime",

View File

@ -32,6 +32,7 @@ class ProviderEditPage extends React.Component {
this.state = {
classes: props,
providerName: props.match.params.providerName,
owner: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
provider: null,
mode: props.location.mode !== undefined ? props.location.mode : "edit",
};
@ -42,7 +43,7 @@ class ProviderEditPage extends React.Component {
}
getProvider() {
ProviderBackend.getProvider("admin", this.state.providerName)
ProviderBackend.getProvider(this.state.owner, this.state.providerName)
.then((provider) => {
this.setState({
provider: provider,
@ -469,6 +470,16 @@ class ProviderEditPage extends React.Component {
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Path prefix"), i18next.t("provider:The prefix path of the file - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.pathPrefix} onChange={e => {
this.updateProviderField("pathPrefix", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :

View File

@ -23,10 +23,25 @@ import i18next from "i18next";
import BaseListPage from "./BaseListPage";
class ProviderListPage extends BaseListPage {
constructor(props) {
super(props);
this.state = {
classes: props,
owner: Setting.isAdminUser(props.account) ? "admin" : props.account.organization.name,
data: [],
pagination: {
current: 1,
pageSize: 10,
},
loading: false,
searchText: "",
searchedColumn: "",
};
}
newProvider() {
const randomName = Setting.getRandomName();
return {
owner: "admin", // this.props.account.providername,
owner: this.state.owner,
name: `provider_${randomName}`,
createdTime: moment().format(),
displayName: `New Provider - ${randomName}`,
@ -46,7 +61,7 @@ class ProviderListPage extends BaseListPage {
const newProvider = this.newProvider();
ProviderBackend.addProvider(newProvider)
.then((res) => {
this.props.history.push({pathname: `/providers/${newProvider.name}`, mode: "add"});
this.props.history.push({pathname: `/providers/${newProvider.owner}/${newProvider.name}`, mode: "add"});
}
)
.catch(error => {
@ -177,7 +192,7 @@ class ProviderListPage extends BaseListPage {
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/providers/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/providers/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<Popconfirm
title={`Sure to delete provider: ${record.name} ?`}
onConfirm={() => this.deleteProvider(index)}
@ -224,7 +239,8 @@ class ProviderListPage extends BaseListPage {
value = params.type;
}
this.setState({loading: true});
ProviderBackend.getProviders("admin", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
(Setting.isAdminUser(this.props.account) ? ProviderBackend.getGlobalProviders(params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
: ProviderBackend.getProviders(this.state.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder))
.then((res) => {
if (res.status === "ok") {
this.setState({

View File

@ -105,7 +105,7 @@ class ProviderTable extends React.Component {
},
},
{
title: i18next.t("provider:canSignUp"),
title: i18next.t("provider:Can signup"),
dataIndex: "canSignUp",
key: "canSignUp",
width: "120px",
@ -122,7 +122,7 @@ class ProviderTable extends React.Component {
},
},
{
title: i18next.t("provider:canSignIn"),
title: i18next.t("provider:Can signin"),
dataIndex: "canSignIn",
key: "canSignIn",
width: "120px",
@ -139,7 +139,7 @@ class ProviderTable extends React.Component {
},
},
{
title: i18next.t("provider:canUnlink"),
title: i18next.t("provider:Can unlink"),
dataIndex: "canUnlink",
key: "canUnlink",
width: "120px",
@ -156,7 +156,7 @@ class ProviderTable extends React.Component {
},
},
{
title: i18next.t("provider:prompted"),
title: i18next.t("provider:Prompted"),
dataIndex: "prompted",
key: "prompted",
width: "120px",

View File

@ -65,21 +65,6 @@ class RoleListPage extends BaseListPage {
renderTable(roles) {
const columns = [
{
title: i18next.t("general:Organization"),
dataIndex: "owner",
key: "owner",
width: "120px",
sorter: true,
...this.getColumnSearchProps("owner"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Name"),
dataIndex: "name",
@ -96,6 +81,21 @@ class RoleListPage extends BaseListPage {
);
},
},
{
title: i18next.t("general:Organization"),
dataIndex: "owner",
key: "owner",
width: "120px",
sorter: true,
...this.getColumnSearchProps("owner"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Created time"),
dataIndex: "createdTime",

View File

@ -13,7 +13,7 @@
// limitations under the License.
import React from "react";
import {Link, useHistory} from "react-router-dom";
import {Link} from "react-router-dom";
import {Tag, Tooltip, message} from "antd";
import {QuestionCircleTwoTone} from "@ant-design/icons";
import {isMobile as isMobileDevice} from "react-device-detect";
@ -752,7 +752,7 @@ export function getLoginLink(application) {
} else if (authConfig.appName === application.name) {
url = "/login";
} else if (application.signinUrl === "") {
url = path.join(application.homepageUrl, "login");
url = path.join(application.homepageUrl, "/login");
} else {
url = application.signinUrl;
}
@ -764,9 +764,8 @@ export function renderLoginLink(application, text) {
return renderLink(url, text, null);
}
export function redirectToLoginPage(application) {
export function redirectToLoginPage(application, history) {
const loginLink = getLoginLink(application);
const history = useHistory();
history.push(loginLink);
}

View File

@ -104,7 +104,7 @@ class SignupTable extends React.Component {
},
},
{
title: i18next.t("provider:visible"),
title: i18next.t("provider:Visible"),
dataIndex: "visible",
key: "visible",
width: "120px",
@ -126,7 +126,7 @@ class SignupTable extends React.Component {
},
},
{
title: i18next.t("provider:required"),
title: i18next.t("provider:Required"),
dataIndex: "required",
key: "required",
width: "120px",
@ -143,7 +143,7 @@ class SignupTable extends React.Component {
},
},
{
title: i18next.t("provider:prompted"),
title: i18next.t("provider:Prompted"),
dataIndex: "prompted",
key: "prompted",
width: "120px",

View File

@ -88,21 +88,6 @@ class SyncerListPage extends BaseListPage {
renderTable(syncers) {
const columns = [
{
title: i18next.t("general:Organization"),
dataIndex: "organization",
key: "organization",
width: "120px",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Name"),
dataIndex: "name",
@ -119,6 +104,21 @@ class SyncerListPage extends BaseListPage {
);
},
},
{
title: i18next.t("general:Organization"),
dataIndex: "organization",
key: "organization",
width: "120px",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Created time"),
dataIndex: "createdTime",

View File

@ -90,37 +90,66 @@ class SystemInfo extends React.Component {
</div> : i18next.t("system:Get Memory Usage Failed")
);
return (
<Row>
<Col span={6}></Col>
<Col span={12}>
<Row gutter={[10, 10]}>
<Col span={12}>
<Card title={i18next.t("system:CPU Usage")} bordered={true} style={{textAlign: "center"}}>
{this.state.loading ? <Spin size="large" /> : CPUInfo}
</Card>
</Col>
<Col span={12}>
<Card title={i18next.t("system:Memory Usage")} bordered={true} style={{textAlign: "center"}}>
{this.state.loading ? <Spin size="large" /> : MemInfo}
</Card>
</Col>
</Row>
<Divider />
<Card title={i18next.t("system:About Casdoor")} bordered={true} style={{textAlign: "center"}}>
<div>{i18next.t("system:An Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML and CAS")}</div>
GitHub: <a href="https://github.com/casdoor/casdoor">casdoor</a>
<br />
{i18next.t("system:Version")}: <a href={this.state.href}>{this.state.latestVersion}</a>
<br />
{i18next.t("system:Official Website")}: <a href="https://casdoor.org/">casdoor.org</a>
<br />
{i18next.t("system:Community")}: <a href="https://casdoor.org/#:~:text=Casdoor%20API-,Community,-GitHub">contact us</a>
</Card>
</Col>
<Col span={6}></Col>
</Row>
);
if (!Setting.isMobile()) {
return (
<Row>
<Col span={6}></Col>
<Col span={12}>
<Row gutter={[10, 10]}>
<Col span={12}>
<Card title={i18next.t("system:CPU Usage")} bordered={true} style={{textAlign: "center", height: "100%"}}>
{this.state.loading ? <Spin size="large" /> : CPUInfo}
</Card>
</Col>
<Col span={12}>
<Card title={i18next.t("system:Memory Usage")} bordered={true} style={{textAlign: "center", height: "100%"}}>
{this.state.loading ? <Spin size="large" /> : MemInfo}
</Card>
</Col>
</Row>
<Divider />
<Card title={i18next.t("system:About Casdoor")} bordered={true} style={{textAlign: "center"}}>
<div>{i18next.t("system:An Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML and CAS")}</div>
GitHub: <a href="https://github.com/casdoor/casdoor">casdoor</a>
<br />
{i18next.t("system:Version")}: <a href={this.state.href}>{this.state.latestVersion}</a>
<br />
{i18next.t("system:Official Website")}: <a href="https://casdoor.org/">casdoor.org</a>
<br />
{i18next.t("system:Community")}: <a href="https://casdoor.org/#:~:text=Casdoor%20API-,Community,-GitHub">contact us</a>
</Card>
</Col>
<Col span={6}></Col>
</Row>
);
} else {
return (
<Row gutter={[16, 0]}>
<Col span={24}>
<Card title={i18next.t("system:CPU Usage")} bordered={true} style={{textAlign: "center", width: "100%"}}>
{this.state.loading ? <Spin size="large" /> : CPUInfo}
</Card>
</Col>
<Col span={24}>
<Card title={i18next.t("system:Memory Usage")} bordered={true} style={{textAlign: "center", width: "100%"}}>
{this.state.loading ? <Spin size="large" /> : MemInfo}
</Card>
</Col>
<Col span={24}>
<Card title={i18next.t("system:About Casdoor")} bordered={true} style={{textAlign: "center"}}>
<div>{i18next.t("system:An Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML and CAS")}</div>
GitHub: <a href="https://github.com/casdoor/casdoor">casdoor</a>
<br />
{i18next.t("system:Version")}: <a href={this.state.href}>{this.state.latestVersion}</a>
<br />
{i18next.t("system:Official Website")}: <a href="https://casdoor.org/">casdoor.org</a>
<br />
{i18next.t("system:Community")}: <a href="https://casdoor.org/#:~:text=Casdoor%20API-,Community,-GitHub">contact us</a>
</Card>
</Col>
</Row>
);
}
}
}

View File

@ -17,6 +17,7 @@ import {Link} from "react-router-dom";
import {Button, Popconfirm, Switch, Table, Upload} from "antd";
import {UploadOutlined} from "@ant-design/icons";
import moment from "moment";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting";
import * as UserBackend from "./backend/UserBackend";
import i18next from "i18next";
@ -28,6 +29,7 @@ class UserListPage extends BaseListPage {
this.state = {
classes: props,
organizationName: props.match.params.organizationName,
organization: null,
data: [],
pagination: {
current: 1,
@ -271,6 +273,15 @@ class UserListPage extends BaseListPage {
width: "110px",
sorter: true,
...this.getColumnSearchProps("tag"),
render: (text, record, index) => {
const tagMap = {};
this.state.organization?.tags?.map((tag, index) => {
const tokens = tag.split("|");
const displayValue = Setting.getLanguage() !== "zh" ? tokens[0] : tokens[1];
tagMap[tokens[0]] = displayValue;
});
return tagMap[text];
},
},
{
title: i18next.t("user:Is admin"),
@ -387,6 +398,11 @@ class UserListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
const users = res.data;
if (users.length > 0) {
this.getOrganization(users[0].owner);
}
}
});
} else {
@ -403,10 +419,24 @@ class UserListPage extends BaseListPage {
searchText: params.searchText,
searchedColumn: params.searchedColumn,
});
const users = res.data;
if (users.length > 0) {
this.getOrganization(users[0].owner);
}
}
});
}
};
getOrganization(organizationName) {
OrganizationBackend.getOrganization("admin", organizationName)
.then((organization) => {
this.setState({
organization: organization,
});
});
}
}
export default UserListPage;

View File

@ -67,21 +67,6 @@ class WebhookListPage extends BaseListPage {
renderTable(webhooks) {
const columns = [
{
title: i18next.t("general:Organization"),
dataIndex: "organization",
key: "organization",
width: "110px",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Name"),
dataIndex: "name",
@ -98,6 +83,21 @@ class WebhookListPage extends BaseListPage {
);
},
},
{
title: i18next.t("general:Organization"),
dataIndex: "organization",
key: "organization",
width: "110px",
sorter: true,
...this.getColumnSearchProps("organization"),
render: (text, record, index) => {
return (
<Link to={`/organizations/${text}`}>
{text}
</Link>
);
},
},
{
title: i18next.t("general:Created time"),
dataIndex: "createdTime",

View File

@ -23,6 +23,7 @@ import {CountDownInput} from "../common/CountDownInput";
import * as UserBackend from "../backend/UserBackend";
import {CheckCircleOutlined, KeyOutlined, LockOutlined, SolutionOutlined, UserOutlined} from "@ant-design/icons";
import CustomGithubCorner from "../CustomGithubCorner";
import {withRouter} from "react-router-dom";
const {Step} = Steps;
const {Option} = Select;
@ -166,7 +167,7 @@ class ForgetPage extends React.Component {
values.userOwner = this.state.application?.organizationObj.name;
UserBackend.setPassword(values.userOwner, values.username, "", values?.newPassword).then(res => {
if (res.status === "ok") {
Setting.redirectToLoginPage(this.state.application);
Setting.redirectToLoginPage(this.state.application, this.props.history);
} else {
Setting.showMessage("error", i18next.t(`signup:${res.msg}`));
}
@ -489,7 +490,7 @@ class ForgetPage extends React.Component {
return (
<div className="loginBackground" style={{backgroundImage: Setting.inIframe() || Setting.isMobile() ? null : `url(${application.formBackgroundUrl})`}}>
<CustomGithubCorner />
<div className="login-content forget-content">
<div className="login-content forget-content" style={{padding: Setting.isMobile() ? "0" : null, boxShadow: Setting.isMobile() ? "none" : null}}>
<Row>
<Col span={24} style={{justifyContent: "center"}}>
<Row>
@ -550,4 +551,4 @@ class ForgetPage extends React.Component {
}
}
export default ForgetPage;
export default withRouter(ForgetPage);

View File

@ -30,6 +30,7 @@ import {CountDownInput} from "../common/CountDownInput";
import SelectLanguageBox from "../SelectLanguageBox";
import {withTranslation} from "react-i18next";
import {CaptchaModal} from "../common/CaptchaModal";
import {withRouter} from "react-router-dom";
const {TabPane} = Tabs;
@ -339,7 +340,7 @@ class LoginPage extends React.Component {
title="Sign Up Error"
subTitle={"The application does not allow to sign up new account"}
extra={[
<Button type="primary" key="signin" onClick={() => Setting.redirectToLoginPage(application)}>
<Button type="primary" key="signin" onClick={() => Setting.redirectToLoginPage(application, this.props.history)}>
{
i18next.t("login:Sign In")
}
@ -784,7 +785,6 @@ class LoginPage extends React.Component {
<div className="login-content" style={{margin: this.parseOffset(application.formOffset)}}>
{Setting.inIframe() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
<div className="login-panel">
<SelectLanguageBox id="language-box-corner" style={{top: "50px"}} />
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
</div>
@ -800,6 +800,7 @@ class LoginPage extends React.Component {
{/* {*/}
{/* this.state.clientId !== null ? "Redirect" : null*/}
{/* }*/}
<SelectLanguageBox id="language-box-corner" style={{top: "55px", right: "5px", position: "absolute"}} />
{
this.renderSignedInBox()
}
@ -816,4 +817,4 @@ class LoginPage extends React.Component {
}
}
export default withTranslation()(LoginPage);
export default withTranslation()(withRouter(LoginPage));

View File

@ -22,6 +22,7 @@ import i18next from "i18next";
import AffiliationSelect from "../common/AffiliationSelect";
import OAuthWidget from "../common/OAuthWidget";
import SelectRegionBox from "../SelectRegionBox";
import {withRouter} from "react-router-dom";
class PromptPage extends React.Component {
constructor(props) {
@ -190,7 +191,7 @@ class PromptPage extends React.Component {
if (redirectUrl !== "" && redirectUrl !== null) {
Setting.goToLink(redirectUrl);
} else {
Setting.redirectToLoginPage(this.getApplicationObj());
Setting.redirectToLoginPage(this.getApplicationObj(), this.props.history);
}
} else {
Setting.showMessage("error", `Failed to log out: ${res.msg}`);
@ -234,7 +235,7 @@ class PromptPage extends React.Component {
title="Sign Up Error"
subTitle={"You are unexpected to see this prompt page"}
extra={[
<Button type="primary" key="signin" onClick={() => Setting.redirectToLoginPage(application)}>
<Button type="primary" key="signin" onClick={() => Setting.redirectToLoginPage(application, this.props.history)}>
{
i18next.t("login:Sign In")
}
@ -272,4 +273,4 @@ class PromptPage extends React.Component {
}
}
export default PromptPage;
export default withRouter(PromptPage);

View File

@ -26,6 +26,7 @@ import {CountDownInput} from "../common/CountDownInput";
import SelectRegionBox from "../SelectRegionBox";
import CustomGithubCorner from "../CustomGithubCorner";
import SelectLanguageBox from "../SelectLanguageBox";
import {withRouter} from "react-router-dom";
const formItemLayout = {
labelCol: {
@ -541,7 +542,7 @@ class SignupPage extends React.Component {
title="Sign Up Error"
subTitle={"The application does not allow to sign up new account"}
extra={[
<Button type="primary" key="signin" onClick={() => Setting.redirectToLoginPage(application)}>
<Button type="primary" key="signin" onClick={() => Setting.redirectToLoginPage(application, this.props.history)}>
{
i18next.t("login:Sign In")
}
@ -562,7 +563,7 @@ class SignupPage extends React.Component {
application: application.name,
organization: application.organization,
}}
style={{width: !Setting.isMobile() ? "400px" : "250px"}}
style={{width: !Setting.isMobile() ? "400px" : "300px"}}
size="large"
>
<Form.Item
@ -600,7 +601,7 @@ class SignupPage extends React.Component {
if (linkInStorage !== null && linkInStorage !== "") {
Setting.goToLink(linkInStorage);
} else {
Setting.redirectToLoginPage(application);
Setting.redirectToLoginPage(application, this.props.history);
}
}}>
{i18next.t("signup:sign in now")}
@ -633,7 +634,6 @@ class SignupPage extends React.Component {
<div className="login-content" style={{margin: this.parseOffset(application.formOffset)}}>
{Setting.inIframe() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
<div className="login-panel" >
<SelectLanguageBox id="language-box-corner" style={{top: "50px"}} />
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
</div>
@ -645,6 +645,7 @@ class SignupPage extends React.Component {
{
Setting.renderLogo(application)
}
<SelectLanguageBox id="language-box-corner" style={{top: "55px", right: "5px", position: "absolute"}} />
{
this.renderForm(application)
}
@ -660,4 +661,4 @@ class SignupPage extends React.Component {
}
}
export default SignupPage;
export default withRouter(SignupPage);

View File

@ -24,6 +24,16 @@ export function getProviders(owner, page = "", pageSize = "", field = "", value
}).then(res => res.json());
}
export function getGlobalProviders(page = "", pageSize = "", field = "", value = "", sortField = "", sortOrder = "") {
return fetch(`${Setting.ServerUrl}/api/get-global-providers?p=${page}&pageSize=${pageSize}&field=${field}&value=${value}&sortField=${sortField}&sortOrder=${sortOrder}`, {
method: "GET",
credentials: "include",
headers: {
"Accept-Language": Setting.getAcceptLanguage(),
},
}).then(res => res.json());
}
export function getProvider(owner, name) {
return fetch(`${Setting.ServerUrl}/api/get-provider?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET",

View File

@ -13,6 +13,7 @@
"Sync": "Sync"
},
"application": {
"Always": "Always",
"Auto signin": "Auto signin",
"Auto signin - Tooltip": "Auto signin - Tooltip",
"Background URL": "Background URL",
@ -43,6 +44,7 @@
"Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left",
"New Application": "New Application",
"None": "None",
"Password ON": "Passwort AN",
"Password ON - Tooltip": "Whether to allow password login",
"Please select a HTML file": "Bitte wählen Sie eine HTML-Datei",
@ -53,6 +55,7 @@
"Refresh token expire": "Aktualisierungs-Token läuft ab",
"Refresh token expire - Tooltip": "Aktualisierungs-Token läuft ab - Tooltip",
"Right": "Right",
"Rule": "Rule",
"SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -67,10 +70,7 @@
"Token expire": "Token läuft ab",
"Token expire - Tooltip": "Token läuft ab - Tooltip",
"Token format": "Token-Format",
"Token format - Tooltip": "Token-Format - Tooltip",
"Rule": "Rule",
"None": "None",
"Always": "Always"
"Token format - Tooltip": "Token-Format - Tooltip"
},
"cert": {
"Bit size": "Bitgröße",
@ -311,15 +311,16 @@
"Favicon": "Févicon",
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule",
"New Organization": "New Organization",
"Soft deletion": "Weiche Löschung",
"Soft deletion - Tooltip": "Weiche Löschung - Tooltip",
"Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "Website-URL",
"Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
"Website URL - Tooltip": "Unique string-style identifier"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -452,6 +453,9 @@
"Bucket": "Eimer",
"Bucket - Tooltip": "Storage bucket name",
"Can not parse Metadata": "Metadaten können nicht analysiert werden",
"Can signin": "Can signin",
"Can signup": "Can signup",
"Can unlink": "Can unlink",
"Category": "Kategorie",
"Category - Tooltip": "Unique string-style identifier",
"Channel No.": "Channel No.",
@ -491,14 +495,17 @@
"New Provider": "New Provider",
"Parse": "Parse",
"Parse Metadata successfully": "Metadaten erfolgreich analysieren",
"Path prefix": "Path prefix",
"Port": "Port",
"Port - Tooltip": "Unique string-style identifier",
"Prompted": "Prompted",
"Provider URL": "Provider-URL",
"Provider URL - Tooltip": "Unique string-style identifier",
"Region ID": "Region ID",
"Region ID - Tooltip": "Region ID - Tooltip",
"Region endpoint for Internet": "Region Endpunkt für Internet",
"Region endpoint for Intranet": "Region Endpunkt für Intranet",
"Required": "Required",
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
"SMS account": "SMS account",
"SMS account - Tooltip": "SMS account - Tooltip",
@ -535,19 +542,15 @@
"Test Connection": "Test Smtp Connection",
"Test Email": "Test email config",
"Test Email - Tooltip": "Email Address",
"The prefix path of the file - Tooltip": "The prefix path of the file - Tooltip",
"Token URL": "Token URL",
"Token URL - Tooltip": "Token URL - Tooltip",
"Type": "Typ",
"Type - Tooltip": "Unique string-style identifier",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"alertType": "alarmtyp",
"canSignIn": "canSignIn",
"canSignUp": "canSignUp",
"canUnlink": "canUnlink",
"prompted": "gefragt",
"required": "benötigt",
"visible": "sichtbar"
"Visible": "Visible",
"alertType": "alarmtyp"
},
"record": {
"Is Triggered": "Wird ausgelöst"

View File

@ -13,6 +13,7 @@
"Sync": "Sync"
},
"application": {
"Always": "Always",
"Auto signin": "Auto signin",
"Auto signin - Tooltip": "Auto signin - Tooltip",
"Background URL": "Background URL",
@ -43,6 +44,7 @@
"Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left",
"New Application": "New Application",
"None": "None",
"Password ON": "Password ON",
"Password ON - Tooltip": "Password ON - Tooltip",
"Please select a HTML file": "Please select a HTML file",
@ -53,6 +55,7 @@
"Refresh token expire": "Refresh token expire",
"Refresh token expire - Tooltip": "Refresh token expire - Tooltip",
"Right": "Right",
"Rule": "Rule",
"SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -67,10 +70,7 @@
"Token expire": "Token expire",
"Token expire - Tooltip": "Token expire - Tooltip",
"Token format": "Token format",
"Token format - Tooltip": "Token format - Tooltip",
"Rule": "Rule",
"None": "None",
"Always": "Always"
"Token format - Tooltip": "Token format - Tooltip"
},
"cert": {
"Bit size": "Bit size",
@ -311,15 +311,16 @@
"Favicon": "Favicon",
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule",
"New Organization": "New Organization",
"Soft deletion": "Soft deletion",
"Soft deletion - Tooltip": "Soft deletion - Tooltip",
"Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "Website URL",
"Website URL - Tooltip": "Website URL - Tooltip",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
"Website URL - Tooltip": "Website URL - Tooltip"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -452,6 +453,9 @@
"Bucket": "Bucket",
"Bucket - Tooltip": "Bucket - Tooltip",
"Can not parse Metadata": "Can not parse Metadata",
"Can signin": "Can signin",
"Can signup": "Can signup",
"Can unlink": "Can unlink",
"Category": "Category",
"Category - Tooltip": "Category - Tooltip",
"Channel No.": "Channel No.",
@ -491,14 +495,17 @@
"New Provider": "New Provider",
"Parse": "Parse",
"Parse Metadata successfully": "Parse Metadata successfully",
"Path prefix": "Path prefix",
"Port": "Port",
"Port - Tooltip": "Port - Tooltip",
"Prompted": "Prompted",
"Provider URL": "Provider URL",
"Provider URL - Tooltip": "Provider URL - Tooltip",
"Region ID": "Region ID",
"Region ID - Tooltip": "Region ID - Tooltip",
"Region endpoint for Internet": "Region endpoint for Internet",
"Region endpoint for Intranet": "Region endpoint for Intranet",
"Required": "Required",
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
"SMS account": "SMS account",
"SMS account - Tooltip": "SMS account - Tooltip",
@ -535,19 +542,15 @@
"Test Connection": "Test Connection",
"Test Email": "Test Email",
"Test Email - Tooltip": "Test Email - Tooltip",
"The prefix path of the file - Tooltip": "The prefix path of the file - Tooltip",
"Token URL": "Token URL",
"Token URL - Tooltip": "Token URL - Tooltip",
"Type": "Type",
"Type - Tooltip": "Type - Tooltip",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"alertType": "alertType",
"canSignIn": "canSignIn",
"canSignUp": "canSignUp",
"canUnlink": "canUnlink",
"prompted": "prompted",
"required": "required",
"visible": "visible"
"Visible": "Visible",
"alertType": "alertType"
},
"record": {
"Is Triggered": "Is Triggered"

View File

@ -13,6 +13,7 @@
"Sync": "Sync"
},
"application": {
"Always": "Always",
"Auto signin": "Auto signin",
"Auto signin - Tooltip": "Auto signin - Tooltip",
"Background URL": "Background URL",
@ -43,6 +44,7 @@
"Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left",
"New Application": "New Application",
"None": "None",
"Password ON": "Mot de passe activé",
"Password ON - Tooltip": "Whether to allow password login",
"Please select a HTML file": "Veuillez sélectionner un fichier HTML",
@ -53,6 +55,7 @@
"Refresh token expire": "Expiration du jeton d'actualisation",
"Refresh token expire - Tooltip": "Expiration du jeton d'actualisation - infobulle",
"Right": "Right",
"Rule": "Rule",
"SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -67,10 +70,7 @@
"Token expire": "Expiration du jeton",
"Token expire - Tooltip": "Expiration du jeton - Info-bulle",
"Token format": "Format du jeton",
"Token format - Tooltip": "Format du jeton - infobulle",
"Rule": "Rule",
"None": "None",
"Always": "Always"
"Token format - Tooltip": "Format du jeton - infobulle"
},
"cert": {
"Bit size": "Taille du bit",
@ -311,15 +311,16 @@
"Favicon": "Favicon",
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule",
"New Organization": "New Organization",
"Soft deletion": "Suppression du logiciel",
"Soft deletion - Tooltip": "Suppression de soft - infobulle",
"Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "URL du site web",
"Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
"Website URL - Tooltip": "Unique string-style identifier"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -452,6 +453,9 @@
"Bucket": "Seau",
"Bucket - Tooltip": "Storage bucket name",
"Can not parse Metadata": "Impossible d'analyser les métadonnées",
"Can signin": "Can signin",
"Can signup": "Can signup",
"Can unlink": "Can unlink",
"Category": "Catégorie",
"Category - Tooltip": "Unique string-style identifier",
"Channel No.": "Channel No.",
@ -491,14 +495,17 @@
"New Provider": "New Provider",
"Parse": "Parse",
"Parse Metadata successfully": "Analyse des métadonnées réussie",
"Path prefix": "Path prefix",
"Port": "Port",
"Port - Tooltip": "Unique string-style identifier",
"Prompted": "Prompted",
"Provider URL": "URL du fournisseur",
"Provider URL - Tooltip": "Unique string-style identifier",
"Region ID": "ID de la région",
"Region ID - Tooltip": "ID de région - infobulle",
"Region endpoint for Internet": "Point de terminaison de la région pour Internet",
"Region endpoint for Intranet": "Point de terminaison de la région pour Intranet",
"Required": "Required",
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
"SMS account": "SMS account",
"SMS account - Tooltip": "SMS account - Tooltip",
@ -535,19 +542,15 @@
"Test Connection": "Test Smtp Connection",
"Test Email": "Test email config",
"Test Email - Tooltip": "Email Address",
"The prefix path of the file - Tooltip": "The prefix path of the file - Tooltip",
"Token URL": "Token URL",
"Token URL - Tooltip": "Token URL - Tooltip",
"Type": "Type de texte",
"Type - Tooltip": "Unique string-style identifier",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"alertType": "Type d'alerte",
"canSignIn": "canSignIn",
"canSignUp": "canSignUp",
"canUnlink": "canUnlink",
"prompted": "invitée",
"required": "Obligatoire",
"visible": "Visible"
"Visible": "Visible",
"alertType": "Type d'alerte"
},
"record": {
"Is Triggered": "Est déclenché"

View File

@ -13,6 +13,7 @@
"Sync": "Sync"
},
"application": {
"Always": "Always",
"Auto signin": "Auto signin",
"Auto signin - Tooltip": "Auto signin - Tooltip",
"Background URL": "Background URL",
@ -43,6 +44,7 @@
"Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left",
"New Application": "New Application",
"None": "None",
"Password ON": "パスワードON",
"Password ON - Tooltip": "Whether to allow password login",
"Please select a HTML file": "HTMLファイルを選択してください",
@ -53,6 +55,7 @@
"Refresh token expire": "トークンの更新の期限が切れます",
"Refresh token expire - Tooltip": "トークンの有効期限を更新する - ツールチップ",
"Right": "Right",
"Rule": "Rule",
"SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -67,10 +70,7 @@
"Token expire": "トークンの有効期限",
"Token expire - Tooltip": "トークンの有効期限 - ツールチップ",
"Token format": "トークンのフォーマット",
"Token format - Tooltip": "トークンフォーマット - ツールチップ",
"Rule": "Rule",
"None": "None",
"Always": "Always"
"Token format - Tooltip": "トークンフォーマット - ツールチップ"
},
"cert": {
"Bit size": "ビットサイズ",
@ -311,15 +311,16 @@
"Favicon": "ファビコン",
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule",
"New Organization": "New Organization",
"Soft deletion": "ソフト削除",
"Soft deletion - Tooltip": "ソフト削除 - ツールチップ",
"Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "Website URL",
"Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
"Website URL - Tooltip": "Unique string-style identifier"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -452,6 +453,9 @@
"Bucket": "バケツ入りバケツ",
"Bucket - Tooltip": "Storage bucket name",
"Can not parse Metadata": "メタデータをパースできません",
"Can signin": "Can signin",
"Can signup": "Can signup",
"Can unlink": "Can unlink",
"Category": "カテゴリ",
"Category - Tooltip": "Unique string-style identifier",
"Channel No.": "Channel No.",
@ -491,14 +495,17 @@
"New Provider": "New Provider",
"Parse": "Parse",
"Parse Metadata successfully": "メタデータの解析に成功",
"Path prefix": "Path prefix",
"Port": "ポート",
"Port - Tooltip": "Unique string-style identifier",
"Prompted": "Prompted",
"Provider URL": "プロバイダー URL",
"Provider URL - Tooltip": "Unique string-style identifier",
"Region ID": "地域ID",
"Region ID - Tooltip": "リージョンID - ツールチップ",
"Region endpoint for Internet": "インターネットのリージョンエンドポイント",
"Region endpoint for Intranet": "イントラネットのリージョンエンドポイント",
"Required": "Required",
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
"SMS account": "SMS account",
"SMS account - Tooltip": "SMS account - Tooltip",
@ -535,19 +542,15 @@
"Test Connection": "Test Smtp Connection",
"Test Email": "Test email config",
"Test Email - Tooltip": "Email Address",
"The prefix path of the file - Tooltip": "The prefix path of the file - Tooltip",
"Token URL": "Token URL",
"Token URL - Tooltip": "Token URL - Tooltip",
"Type": "タイプ",
"Type - Tooltip": "Unique string-style identifier",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"alertType": "alertType",
"canSignIn": "canSignIn",
"canSignUp": "canSignUp",
"canUnlink": "canUnlink",
"prompted": "プロンプトされた",
"required": "必須",
"visible": "表示"
"Visible": "Visible",
"alertType": "alertType"
},
"record": {
"Is Triggered": "トリガーされます"

View File

@ -13,6 +13,7 @@
"Sync": "Sync"
},
"application": {
"Always": "Always",
"Auto signin": "Auto signin",
"Auto signin - Tooltip": "Auto signin - Tooltip",
"Background URL": "Background URL",
@ -43,6 +44,7 @@
"Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left",
"New Application": "New Application",
"None": "None",
"Password ON": "Password ON",
"Password ON - Tooltip": "Whether to allow password login",
"Please select a HTML file": "Please select a HTML file",
@ -53,6 +55,7 @@
"Refresh token expire": "Refresh token expire",
"Refresh token expire - Tooltip": "Refresh token expire - Tooltip",
"Right": "Right",
"Rule": "Rule",
"SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -67,10 +70,7 @@
"Token expire": "Token expire",
"Token expire - Tooltip": "Token expire - Tooltip",
"Token format": "Token format",
"Token format - Tooltip": "Token format - Tooltip",
"Rule": "Rule",
"None": "None",
"Always": "Always"
"Token format - Tooltip": "Token format - Tooltip"
},
"cert": {
"Bit size": "Bit size",
@ -311,15 +311,16 @@
"Favicon": "Favicon",
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule",
"New Organization": "New Organization",
"Soft deletion": "Soft deletion",
"Soft deletion - Tooltip": "Soft deletion - Tooltip",
"Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "Website URL",
"Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
"Website URL - Tooltip": "Unique string-style identifier"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -452,6 +453,9 @@
"Bucket": "Bucket",
"Bucket - Tooltip": "Storage bucket name",
"Can not parse Metadata": "Can not parse Metadata",
"Can signin": "Can signin",
"Can signup": "Can signup",
"Can unlink": "Can unlink",
"Category": "Category",
"Category - Tooltip": "Unique string-style identifier",
"Channel No.": "Channel No.",
@ -491,14 +495,17 @@
"New Provider": "New Provider",
"Parse": "Parse",
"Parse Metadata successfully": "Parse Metadata successfully",
"Path prefix": "Path prefix",
"Port": "Port",
"Port - Tooltip": "Unique string-style identifier",
"Prompted": "Prompted",
"Provider URL": "Provider URL",
"Provider URL - Tooltip": "Unique string-style identifier",
"Region ID": "Region ID",
"Region ID - Tooltip": "Region ID - Tooltip",
"Region endpoint for Internet": "Region endpoint for Internet",
"Region endpoint for Intranet": "Region endpoint for Intranet",
"Required": "Required",
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
"SMS account": "SMS account",
"SMS account - Tooltip": "SMS account - Tooltip",
@ -535,19 +542,15 @@
"Test Connection": "Test Smtp Connection",
"Test Email": "Test email config",
"Test Email - Tooltip": "Email Address",
"The prefix path of the file - Tooltip": "The prefix path of the file - Tooltip",
"Token URL": "Token URL",
"Token URL - Tooltip": "Token URL - Tooltip",
"Type": "Type",
"Type - Tooltip": "Unique string-style identifier",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"alertType": "alertType",
"canSignIn": "canSignIn",
"canSignUp": "canSignUp",
"canUnlink": "canUnlink",
"prompted": "prompted",
"required": "required",
"visible": "visible"
"Visible": "Visible",
"alertType": "alertType"
},
"record": {
"Is Triggered": "Is Triggered"

View File

@ -13,6 +13,7 @@
"Sync": "Sync"
},
"application": {
"Always": "Always",
"Auto signin": "Auto signin",
"Auto signin - Tooltip": "Auto signin - Tooltip",
"Background URL": "Background URL",
@ -43,6 +44,7 @@
"Grant types - Tooltip": "Виды грантов - Подсказка",
"Left": "Left",
"New Application": "Новое приложение",
"None": "None",
"Password ON": "Пароль ВКЛ",
"Password ON - Tooltip": "Whether to allow password login",
"Please select a HTML file": "Пожалуйста, выберите HTML-файл",
@ -53,6 +55,7 @@
"Refresh token expire": "Срок действия обновления токена истекает",
"Refresh token expire - Tooltip": "Срок обновления токена истекает - Подсказка",
"Right": "Right",
"Rule": "правило",
"SAML metadata": "Метаданные SAML",
"SAML metadata - Tooltip": "Метаданные SAML - Подсказка",
"SAML metadata URL copied to clipboard successfully": "Адрес метаданных SAML скопирован в буфер обмена",
@ -67,10 +70,7 @@
"Token expire": "Токен истекает",
"Token expire - Tooltip": "Истек токен - Подсказка",
"Token format": "Формат токена",
"Token format - Tooltip": "Формат токена - Подсказка",
"Rule": "правило",
"None": "None",
"Always": "Always"
"Token format - Tooltip": "Формат токена - Подсказка"
},
"cert": {
"Bit size": "Размер бита",
@ -311,15 +311,16 @@
"Favicon": "Иконка",
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule",
"New Organization": "New Organization",
"Soft deletion": "Мягкое удаление",
"Soft deletion - Tooltip": "Мягкое удаление - Подсказка",
"Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "URL сайта",
"Website URL - Tooltip": "Unique string-style identifier",
"modifyRule": "modifyRule",
"viewRule": "viewRule"
"Website URL - Tooltip": "Unique string-style identifier"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -452,6 +453,9 @@
"Bucket": "Ведро",
"Bucket - Tooltip": "Storage bucket name",
"Can not parse Metadata": "Невозможно разобрать метаданные",
"Can signin": "Can signin",
"Can signup": "Can signup",
"Can unlink": "Can unlink",
"Category": "Категория",
"Category - Tooltip": "Unique string-style identifier",
"Channel No.": "Channel No.",
@ -491,14 +495,17 @@
"New Provider": "New Provider",
"Parse": "Parse",
"Parse Metadata successfully": "Анализ метаданных успешно завершен",
"Path prefix": "Path prefix",
"Port": "Порт",
"Port - Tooltip": "Unique string-style identifier",
"Prompted": "Prompted",
"Provider URL": "URL провайдера",
"Provider URL - Tooltip": "Unique string-style identifier",
"Region ID": "ID региона",
"Region ID - Tooltip": "Идентификатор региона - Подсказка",
"Region endpoint for Internet": "Конечная точка региона для Интернета",
"Region endpoint for Intranet": "Конечная точка региона Интранета",
"Required": "Required",
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
"SMS account": "SMS account",
"SMS account - Tooltip": "SMS account - Tooltip",
@ -535,19 +542,15 @@
"Test Connection": "Test Smtp Connection",
"Test Email": "Test email config",
"Test Email - Tooltip": "Email Address",
"The prefix path of the file - Tooltip": "The prefix path of the file - Tooltip",
"Token URL": "Token URL",
"Token URL - Tooltip": "Token URL - Tooltip",
"Type": "Тип",
"Type - Tooltip": "Unique string-style identifier",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
"alertType": "тип оповещения",
"canSignIn": "canSignIn",
"canSignUp": "canSignUp",
"canUnlink": "canUnlink",
"prompted": "запрошено",
"required": "обязательный",
"visible": "видимый"
"Visible": "Visible",
"alertType": "тип оповещения"
},
"record": {
"Is Triggered": "Срабатывает"

View File

@ -13,6 +13,7 @@
"Sync": "同步"
},
"application": {
"Always": "始终开启",
"Auto signin": "启用自动登录",
"Auto signin - Tooltip": "当Casdoor存在已登录会话时自动采用该会话进行应用端的登录",
"Background URL": "背景图URL",
@ -43,6 +44,7 @@
"Grant types - Tooltip": "选择允许哪些OAuth协议中的Grant types",
"Left": "居左",
"New Application": "添加应用",
"None": "关闭",
"Password ON": "开启密码",
"Password ON - Tooltip": "是否允许密码登录",
"Please select a HTML file": "请选择一个HTML文件",
@ -53,6 +55,7 @@
"Refresh token expire": "Refresh Token过期",
"Refresh token expire - Tooltip": "Refresh Token过期时间",
"Right": "居右",
"Rule": "规则",
"SAML metadata": "SAML元数据",
"SAML metadata - Tooltip": "SAML协议的元数据Metadata信息",
"SAML metadata URL copied to clipboard successfully": "SAML元数据URL已成功复制到剪贴板",
@ -67,10 +70,7 @@
"Token expire": "Access Token过期",
"Token expire - Tooltip": "Access Token过期时间",
"Token format": "Access Token格式",
"Token format - Tooltip": "Access Token格式",
"Rule": "规则",
"None": "关闭",
"Always": "始终开启"
"Token format - Tooltip": "Access Token格式"
},
"cert": {
"Bit size": "位大小",
@ -311,15 +311,16 @@
"Favicon": "图标",
"Is profile public": "用户个人页公开",
"Is profile public - Tooltip": "关闭后,只有全局管理员或同组织用户才能访问用户主页",
"Modify rule": "修改规则",
"New Organization": "添加组织",
"Soft deletion": "软删除",
"Soft deletion - Tooltip": "启用后,删除用户信息时不会在数据库彻底清除,只会标记为已删除状态",
"Tags": "标签集合",
"Tags - Tooltip": "可供用户选择的标签的集合",
"View rule": "查看规则",
"Visible": "是否可见",
"Website URL": "网页地址",
"Website URL - Tooltip": "网页地址",
"modifyRule": "修改规则",
"viewRule": "查看规则"
"Website URL - Tooltip": "网页地址"
},
"payment": {
"Confirm your invoice information": "确认您的发票信息",
@ -452,6 +453,9 @@
"Bucket": "存储桶",
"Bucket - Tooltip": "Bucket名称",
"Can not parse Metadata": "无法解析元数据",
"Can signin": "可用于登录",
"Can signup": "可用于注册",
"Can unlink": "可解绑定",
"Category": "分类",
"Category - Tooltip": "分类",
"Channel No.": "Channel No.",
@ -491,14 +495,17 @@
"New Provider": "添加提供商",
"Parse": "Parse",
"Parse Metadata successfully": "解析元数据成功",
"Path prefix": "路径前缀",
"Port": "端口",
"Port - Tooltip": "端口号",
"Prompted": "注册后提醒绑定",
"Provider URL": "提供商URL",
"Provider URL - Tooltip": "提供商URL",
"Region ID": "地域ID",
"Region ID - Tooltip": "地域ID",
"Region endpoint for Internet": "地域节点 (外网)",
"Region endpoint for Intranet": "地域节点 (内网)",
"Required": "是否必填项",
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
"SMS account": "SMS account",
"SMS account - Tooltip": "SMS account - Tooltip",
@ -535,19 +542,15 @@
"Test Connection": "测试SMTP连接",
"Test Email": "测试Email配置",
"Test Email - Tooltip": "邮箱地址",
"The prefix path of the file - Tooltip": "文件的路径前缀 - 工具提示",
"Token URL": "Token URL",
"Token URL - Tooltip": "Token URL - 工具提示",
"Type": "类型",
"Type - Tooltip": "类型",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL - 工具提示",
"alertType": "警报类型",
"canSignIn": "可用于登录",
"canSignUp": "可用于注册",
"canUnlink": "可解绑定",
"prompted": "注册后提醒绑定",
"required": "是否必填项",
"visible": "是否可见"
"Visible": "是否可见",
"alertType": "警报类型"
},
"record": {
"Is Triggered": "已触发"