mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-10 01:56:49 +08:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
75e917a070 | |||
e1182bb635 | |||
2b70698c2a |
@ -87,6 +87,7 @@ Edit `conf/app.conf`, set `runmode=dev`. Firstly build front-end files:
|
|||||||
```bash
|
```bash
|
||||||
cd web/ && npm install && npm run start
|
cd web/ && npm install && npm run start
|
||||||
```
|
```
|
||||||
|
*❗ A word of caution ❗: the `npm` commands above need a recommended system RAM of at least 4GB. It has a potential failure during building the files if your RAM is not sufficient.*
|
||||||
|
|
||||||
Then build back-end binary file, change directory to root(Relative to casdoor):
|
Then build back-end binary file, change directory to root(Relative to casdoor):
|
||||||
|
|
||||||
|
230
idp/gitlab.go
Normal file
230
idp/gitlab.go
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package idp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GitlabIdProvider struct {
|
||||||
|
Client *http.Client
|
||||||
|
Config *oauth2.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGitlabIdProvider(clientId string, clientSecret string, redirectUrl string) *GitlabIdProvider {
|
||||||
|
idp := &GitlabIdProvider{}
|
||||||
|
|
||||||
|
config := idp.getConfig(clientId, clientSecret, redirectUrl)
|
||||||
|
idp.Config = config
|
||||||
|
|
||||||
|
return idp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *GitlabIdProvider) SetHttpClient(client *http.Client) {
|
||||||
|
idp.Client = client
|
||||||
|
}
|
||||||
|
|
||||||
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
|
func (idp *GitlabIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
|
var endpoint = oauth2.Endpoint{
|
||||||
|
TokenURL: "https://gitlab.com/oauth/token",
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = &oauth2.Config{
|
||||||
|
Scopes: []string{"read_user+profile"},
|
||||||
|
Endpoint: endpoint,
|
||||||
|
ClientID: clientId,
|
||||||
|
ClientSecret: clientSecret,
|
||||||
|
RedirectURL: redirectUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitlabProviderToken struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
RefreshToken string `json:"refresh_token"`
|
||||||
|
CreatedAt int `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetToken use code get access_token (*operation of getting code ought to be done in front)
|
||||||
|
// get more detail via: https://docs.gitlab.com/ee/api/oauth2.html
|
||||||
|
func (idp *GitlabIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||||
|
params := url.Values{}
|
||||||
|
params.Add("grant_type", "authorization_code")
|
||||||
|
params.Add("client_id", idp.Config.ClientID)
|
||||||
|
params.Add("client_secret", idp.Config.ClientSecret)
|
||||||
|
params.Add("code", code)
|
||||||
|
params.Add("redirect_uri", idp.Config.RedirectURL)
|
||||||
|
|
||||||
|
accessTokenUrl := fmt.Sprintf("%s?%s", idp.Config.Endpoint.TokenURL, params.Encode())
|
||||||
|
resp, err := idp.Client.Post(accessTokenUrl, "application/json;charset=UTF-8", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gtoken := &GitlabProviderToken{}
|
||||||
|
if err = json.Unmarshal(data, gtoken); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// gtoken.ExpiresIn always returns 0, so we set Expiry=7200 to avoid verification errors.
|
||||||
|
token := &oauth2.Token{
|
||||||
|
AccessToken: gtoken.AccessToken,
|
||||||
|
TokenType: gtoken.TokenType,
|
||||||
|
RefreshToken: gtoken.RefreshToken,
|
||||||
|
Expiry: time.Unix(time.Now().Unix()+int64(7200), 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"id":5162115,
|
||||||
|
"name":"shiluo",
|
||||||
|
"username":"shiluo",
|
||||||
|
"state":"active",
|
||||||
|
"avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5162115/avatar.png",
|
||||||
|
"web_url":"https://gitlab.com/shiluo",
|
||||||
|
"created_at":"2019-12-23T02:50:10.348Z",
|
||||||
|
"bio":"",
|
||||||
|
"bio_html":"",
|
||||||
|
"location":"China",
|
||||||
|
"public_email":"silo1999@163.com",
|
||||||
|
"skype":"",
|
||||||
|
"linkedin":"",
|
||||||
|
"twitter":"",
|
||||||
|
"website_url":"",
|
||||||
|
"organization":"",
|
||||||
|
"job_title":"",
|
||||||
|
"pronouns":null,
|
||||||
|
"bot":false,
|
||||||
|
"work_information":null,
|
||||||
|
"followers":0,
|
||||||
|
"following":0,
|
||||||
|
"last_sign_in_at":"2019-12-26T13:24:42.941Z",
|
||||||
|
"confirmed_at":"2019-12-23T02:52:10.778Z",
|
||||||
|
"last_activity_on":"2021-08-19",
|
||||||
|
"email":"silo1999@163.com",
|
||||||
|
"theme_id":1,
|
||||||
|
"color_scheme_id":1,
|
||||||
|
"projects_limit":100000,
|
||||||
|
"current_sign_in_at":"2021-08-19T09:46:46.004Z",
|
||||||
|
"identities":[
|
||||||
|
{
|
||||||
|
"provider":"github",
|
||||||
|
"extern_uid":"51157931",
|
||||||
|
"saml_provider_id":null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"can_create_group":true,
|
||||||
|
"can_create_project":true,
|
||||||
|
"two_factor_enabled":false,
|
||||||
|
"external":false,
|
||||||
|
"private_profile":false,
|
||||||
|
"commit_email":"silo1999@163.com",
|
||||||
|
"shared_runners_minutes_limit":null,
|
||||||
|
"extra_shared_runners_minutes_limit":null
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
type GitlabUserInfo struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
State string `json:"state"`
|
||||||
|
AvatarUrl string `json:"avatar_url"`
|
||||||
|
WebUrl string `json:"web_url"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
Bio string `json:"bio"`
|
||||||
|
BioHtml string `json:"bio_html"`
|
||||||
|
Location string `json:"location"`
|
||||||
|
PublicEmail string `json:"public_email"`
|
||||||
|
Skype string `json:"skype"`
|
||||||
|
Linkedin string `json:"linkedin"`
|
||||||
|
Twitter string `json:"twitter"`
|
||||||
|
WebsiteUrl string `json:"website_url"`
|
||||||
|
Organization string `json:"organization"`
|
||||||
|
JobTitle string `json:"job_title"`
|
||||||
|
Pronouns interface{} `json:"pronouns"`
|
||||||
|
Bot bool `json:"bot"`
|
||||||
|
WorkInformation interface{} `json:"work_information"`
|
||||||
|
Followers int `json:"followers"`
|
||||||
|
Following int `json:"following"`
|
||||||
|
LastSignInAt time.Time `json:"last_sign_in_at"`
|
||||||
|
ConfirmedAt time.Time `json:"confirmed_at"`
|
||||||
|
LastActivityOn string `json:"last_activity_on"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
ThemeId int `json:"theme_id"`
|
||||||
|
ColorSchemeId int `json:"color_scheme_id"`
|
||||||
|
ProjectsLimit int `json:"projects_limit"`
|
||||||
|
CurrentSignInAt time.Time `json:"current_sign_in_at"`
|
||||||
|
Identities []struct {
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
ExternUid string `json:"extern_uid"`
|
||||||
|
SamlProviderId interface{} `json:"saml_provider_id"`
|
||||||
|
} `json:"identities"`
|
||||||
|
CanCreateGroup bool `json:"can_create_group"`
|
||||||
|
CanCreateProject bool `json:"can_create_project"`
|
||||||
|
TwoFactorEnabled bool `json:"two_factor_enabled"`
|
||||||
|
External bool `json:"external"`
|
||||||
|
PrivateProfile bool `json:"private_profile"`
|
||||||
|
CommitEmail string `json:"commit_email"`
|
||||||
|
SharedRunnersMinutesLimit interface{} `json:"shared_runners_minutes_limit"`
|
||||||
|
ExtraSharedRunnersMinutesLimit interface{} `json:"extra_shared_runners_minutes_limit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserInfo use GitlabProviderToken gotten before return GitlabUserInfo
|
||||||
|
func (idp *GitlabIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
|
resp, err := idp.Client.Get("https://gitlab.com/api/v4/user?access_token="+token.AccessToken)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
guser := GitlabUserInfo{}
|
||||||
|
if err = json.Unmarshal(data, &guser);err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userInfo := UserInfo{
|
||||||
|
Id: strconv.Itoa(guser.Id),
|
||||||
|
Username: guser.Username,
|
||||||
|
DisplayName: guser.Name,
|
||||||
|
AvatarUrl: guser.AvatarUrl,
|
||||||
|
Email: guser.Email,
|
||||||
|
}
|
||||||
|
return &userInfo, nil
|
||||||
|
}
|
@ -57,6 +57,8 @@ func GetIdProvider(providerType string, clientId string, clientSecret string, re
|
|||||||
return NewWeComIdProvider(clientId, clientSecret, redirectUrl)
|
return NewWeComIdProvider(clientId, clientSecret, redirectUrl)
|
||||||
} else if providerType == "Lark" {
|
} else if providerType == "Lark" {
|
||||||
return NewLarkIdProvider(clientId, clientSecret, redirectUrl)
|
return NewLarkIdProvider(clientId, clientSecret, redirectUrl)
|
||||||
|
} else if providerType == "GitLab" {
|
||||||
|
return NewGitlabIdProvider(clientId, clientSecret, redirectUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
func SendCodeToPhone(provider *Provider, phone, code string) string {
|
func SendCodeToPhone(provider *Provider, phone, code string) string {
|
||||||
client := go_sms_sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.RegionId, provider.TemplateCode, provider.AppId)
|
client := go_sms_sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.RegionId, provider.TemplateCode, provider.AppId)
|
||||||
if client == nil {
|
if client == nil {
|
||||||
return fmt.Sprintf("Unsupported provide type: %s", provider.Type)
|
return fmt.Sprintf("Unsupported provider type: %s", provider.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
param := make(map[string]string)
|
param := make(map[string]string)
|
||||||
|
@ -58,6 +58,7 @@ type User struct {
|
|||||||
LinkedIn string `xorm:"linkedin varchar(100)" json:"linkedin"`
|
LinkedIn string `xorm:"linkedin varchar(100)" json:"linkedin"`
|
||||||
Wecom string `xorm:"wecom varchar(100)" json:"wecom"`
|
Wecom string `xorm:"wecom varchar(100)" json:"wecom"`
|
||||||
Lark string `xorm:"lark varchar(100)" json:"lark"`
|
Lark string `xorm:"lark varchar(100)" json:"lark"`
|
||||||
|
Gitlab string `xorm:"gitlab varchar(100)" json:"gitlab"`
|
||||||
|
|
||||||
Ldap string `xorm:"ldap varchar(100)" json:"ldap"`
|
Ldap string `xorm:"ldap varchar(100)" json:"ldap"`
|
||||||
Properties map[string]string `json:"properties"`
|
Properties map[string]string `json:"properties"`
|
||||||
|
@ -77,6 +77,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
{id: 'LinkedIn', name: 'LinkedIn'},
|
{id: 'LinkedIn', name: 'LinkedIn'},
|
||||||
{id: 'WeCom', name: 'WeCom'},
|
{id: 'WeCom', name: 'WeCom'},
|
||||||
{id: 'Lark', name: 'Lark'},
|
{id: 'Lark', name: 'Lark'},
|
||||||
|
{id: 'GitLab', name: 'GitLab'},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
} else if (provider.category === "Email") {
|
} else if (provider.category === "Email") {
|
||||||
|
32
web/src/auth/GitLabLoginButton.js
Normal file
32
web/src/auth/GitLabLoginButton.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2021 The casbin Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import {createButton} from "react-social-login-buttons";
|
||||||
|
import {StaticBaseUrl} from "../Setting";
|
||||||
|
|
||||||
|
function Icon({ width = 24, height = 24, color }) {
|
||||||
|
return <img src={`${StaticBaseUrl}/buttons/gitlab.svg`} alt="Sign in with GitLab" style={{width: 24, height: 24}} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
text: "Sign in with GitLab",
|
||||||
|
icon: Icon,
|
||||||
|
iconFormat: name => `fa fa-${name}`,
|
||||||
|
style: {background: "rgb(255,255,255)", color: "#000000"},
|
||||||
|
activeStyle: {background: "rgb(100,150,250)"},
|
||||||
|
};
|
||||||
|
|
||||||
|
const GitLabLoginButton = createButton(config);
|
||||||
|
|
||||||
|
export default GitLabLoginButton;
|
@ -32,6 +32,7 @@ import i18next from "i18next";
|
|||||||
import LinkedInLoginButton from "./LinkedInLoginButton";
|
import LinkedInLoginButton from "./LinkedInLoginButton";
|
||||||
import WeComLoginButton from "./WeComLoginButton";
|
import WeComLoginButton from "./WeComLoginButton";
|
||||||
import LarkLoginButton from "./LarkLoginButton";
|
import LarkLoginButton from "./LarkLoginButton";
|
||||||
|
import GitLabLoginButton from "./GitLabLoginButton";
|
||||||
|
|
||||||
class LoginPage extends React.Component {
|
class LoginPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -170,6 +171,8 @@ class LoginPage extends React.Component {
|
|||||||
return <WeComLoginButton text={text} align={"center"} />
|
return <WeComLoginButton text={text} align={"center"} />
|
||||||
} else if (type === "Lark") {
|
} else if (type === "Lark") {
|
||||||
return <LarkLoginButton text={text} align={"center"} />
|
return <LarkLoginButton text={text} align={"center"} />
|
||||||
|
} else if (type === "GitLab") {
|
||||||
|
return <GitLabLoginButton text={text} align={"center"} />
|
||||||
}
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
@ -55,10 +55,14 @@ const LinkedInAuthLogo = `${StaticBaseUrl}/img/social_linkedin.png`;
|
|||||||
const WeComAuthUri = "https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect";
|
const WeComAuthUri = "https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect";
|
||||||
const WeComAuthLogo = `${StaticBaseUrl}/img/social_wecom.png`;
|
const WeComAuthLogo = `${StaticBaseUrl}/img/social_wecom.png`;
|
||||||
|
|
||||||
// const WeComAuthScope = "";
|
// const LarkAuthScope = "";
|
||||||
const LarkAuthUri = "https://open.feishu.cn/open-apis/authen/v1/index";
|
const LarkAuthUri = "https://open.feishu.cn/open-apis/authen/v1/index";
|
||||||
const LarkAuthLogo = `${StaticBaseUrl}/img/social_lark.png`;
|
const LarkAuthLogo = `${StaticBaseUrl}/img/social_lark.png`;
|
||||||
|
|
||||||
|
const GitLabAuthScope = "read_user+profile";
|
||||||
|
const GitLabAuthUri = "https://gitlab.com/oauth/authorize";
|
||||||
|
const GitLabAuthLogo = `${StaticBaseUrl}/img/social_gitlab.png`;
|
||||||
|
|
||||||
export function getAuthLogo(provider) {
|
export function getAuthLogo(provider) {
|
||||||
if (provider.type === "Google") {
|
if (provider.type === "Google") {
|
||||||
return GoogleAuthLogo;
|
return GoogleAuthLogo;
|
||||||
@ -82,6 +86,8 @@ export function getAuthLogo(provider) {
|
|||||||
return WeComAuthLogo;
|
return WeComAuthLogo;
|
||||||
} else if (provider.type === "Lark") {
|
} else if (provider.type === "Lark") {
|
||||||
return LarkAuthLogo;
|
return LarkAuthLogo;
|
||||||
|
} else if (provider.type === "GitLab") {
|
||||||
|
return GitLabAuthLogo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,5 +120,7 @@ export function getAuthUrl(application, provider, method) {
|
|||||||
return `${WeComAuthUri}?appid=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&usertype=member`
|
return `${WeComAuthUri}?appid=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&usertype=member`
|
||||||
} else if (provider.type === "Lark") {
|
} else if (provider.type === "Lark") {
|
||||||
return `${LarkAuthUri}?app_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}`
|
return `${LarkAuthUri}?app_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}`
|
||||||
|
} else if (provider.type === "GitLab") {
|
||||||
|
return `${GitLabAuthUri}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${GitLabAuthScope}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,12 @@
|
|||||||
"Signin URL": "Signin URL",
|
"Signin URL": "Signin URL",
|
||||||
"Signin URL - Tooltip": "sign in url",
|
"Signin URL - Tooltip": "sign in url",
|
||||||
"ID - Tooltip": "random string",
|
"ID - Tooltip": "random string",
|
||||||
"Favicon - Tooltip": "Application icon"
|
"Favicon - Tooltip": "Application icon",
|
||||||
|
"Uploading": "Uploading",
|
||||||
|
"Start Upload": "Start Upload",
|
||||||
|
"Upload success": "Upload success",
|
||||||
|
"Back Home": "Back Home",
|
||||||
|
"Sorry, the page you visited does not exist": "Sorry, the page you visited does not exist"
|
||||||
},
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"Username": "Username",
|
"Username": "Username",
|
||||||
@ -186,7 +191,13 @@
|
|||||||
"Domain": "Domain",
|
"Domain": "Domain",
|
||||||
"Domain - Tooltip": "Storage endpoint custom domain",
|
"Domain - Tooltip": "Storage endpoint custom domain",
|
||||||
"Region": "Region",
|
"Region": "Region",
|
||||||
"Region - Tooltip": "Storage region"
|
"Region - Tooltip": "Storage region",
|
||||||
|
"Access key": "Access key",
|
||||||
|
"Access key - Tooltip": "Access key - Tooltip",
|
||||||
|
"Secret access key": "Secret access key",
|
||||||
|
"Secret access key - Tooltip": "Secret access key - Tooltip",
|
||||||
|
"SMS account": "SMS account",
|
||||||
|
"SMS account - Tooltip": "SMS account - Tooltip"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Edit User": "Edit User",
|
"Edit User": "Edit User",
|
||||||
|
@ -79,7 +79,12 @@
|
|||||||
"Signin URL": "Signin URL",
|
"Signin URL": "Signin URL",
|
||||||
"Signin URL - Tooltip": "sign in url",
|
"Signin URL - Tooltip": "sign in url",
|
||||||
"ID - Tooltip": "random string",
|
"ID - Tooltip": "random string",
|
||||||
"Favicon - Tooltip": "Application icon"
|
"Favicon - Tooltip": "Application icon",
|
||||||
|
"Uploading": "Uploading",
|
||||||
|
"Start Upload": "Start Upload",
|
||||||
|
"Upload success": "Upload success",
|
||||||
|
"Back Home": "Back Home",
|
||||||
|
"Sorry, the page you visited does not exist": "Sorry, the page you visited does not exist"
|
||||||
},
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"Username": "Username",
|
"Username": "Username",
|
||||||
@ -186,7 +191,13 @@
|
|||||||
"Domain": "Domain",
|
"Domain": "Domain",
|
||||||
"Domain - Tooltip": "Storage endpoint custom domain",
|
"Domain - Tooltip": "Storage endpoint custom domain",
|
||||||
"Region": "Region",
|
"Region": "Region",
|
||||||
"Region - Tooltip": "Storage region"
|
"Region - Tooltip": "Storage region",
|
||||||
|
"Access key": "Access key",
|
||||||
|
"Access key - Tooltip": "Access key - Tooltip",
|
||||||
|
"Secret access key": "Secret access key",
|
||||||
|
"Secret access key - Tooltip": "Secret access key - Tooltip",
|
||||||
|
"SMS account": "SMS account",
|
||||||
|
"SMS account - Tooltip": "SMS account - Tooltip"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Edit User": "Edit User",
|
"Edit User": "Edit User",
|
||||||
|
@ -79,7 +79,12 @@
|
|||||||
"Signin URL": "Signin URL",
|
"Signin URL": "Signin URL",
|
||||||
"Signin URL - Tooltip": "sign in url",
|
"Signin URL - Tooltip": "sign in url",
|
||||||
"ID - Tooltip": "random string",
|
"ID - Tooltip": "random string",
|
||||||
"Favicon - Tooltip": "Application icon"
|
"Favicon - Tooltip": "Application icon",
|
||||||
|
"Uploading": "Uploading",
|
||||||
|
"Start Upload": "Start Upload",
|
||||||
|
"Upload success": "Upload success",
|
||||||
|
"Back Home": "Back Home",
|
||||||
|
"Sorry, the page you visited does not exist": "Sorry, the page you visited does not exist"
|
||||||
},
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"Username": "Username",
|
"Username": "Username",
|
||||||
@ -186,7 +191,13 @@
|
|||||||
"Domain": "Domain",
|
"Domain": "Domain",
|
||||||
"Domain - Tooltip": "Storage endpoint custom domain",
|
"Domain - Tooltip": "Storage endpoint custom domain",
|
||||||
"Region": "Region",
|
"Region": "Region",
|
||||||
"Region - Tooltip": "Storage region"
|
"Region - Tooltip": "Storage region",
|
||||||
|
"Access key": "Access key",
|
||||||
|
"Access key - Tooltip": "Access key - Tooltip",
|
||||||
|
"Secret access key": "Secret access key",
|
||||||
|
"Secret access key - Tooltip": "Secret access key - Tooltip",
|
||||||
|
"SMS account": "SMS account",
|
||||||
|
"SMS account - Tooltip": "SMS account - Tooltip"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Edit User": "Edit User",
|
"Edit User": "Edit User",
|
||||||
|
@ -79,7 +79,12 @@
|
|||||||
"Signin URL": "Signin URL",
|
"Signin URL": "Signin URL",
|
||||||
"Signin URL - Tooltip": "sign in url",
|
"Signin URL - Tooltip": "sign in url",
|
||||||
"ID - Tooltip": "random string",
|
"ID - Tooltip": "random string",
|
||||||
"Favicon - Tooltip": "Application icon"
|
"Favicon - Tooltip": "Application icon",
|
||||||
|
"Uploading": "Uploading",
|
||||||
|
"Start Upload": "Start Upload",
|
||||||
|
"Upload success": "Upload success",
|
||||||
|
"Back Home": "Back Home",
|
||||||
|
"Sorry, the page you visited does not exist": "Sorry, the page you visited does not exist"
|
||||||
},
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"Username": "Username",
|
"Username": "Username",
|
||||||
@ -186,7 +191,13 @@
|
|||||||
"Domain": "Domain",
|
"Domain": "Domain",
|
||||||
"Domain - Tooltip": "Storage endpoint custom domain",
|
"Domain - Tooltip": "Storage endpoint custom domain",
|
||||||
"Region": "Region",
|
"Region": "Region",
|
||||||
"Region - Tooltip": "Storage region"
|
"Region - Tooltip": "Storage region",
|
||||||
|
"Access key": "Access key",
|
||||||
|
"Access key - Tooltip": "Access key - Tooltip",
|
||||||
|
"Secret access key": "Secret access key",
|
||||||
|
"Secret access key - Tooltip": "Secret access key - Tooltip",
|
||||||
|
"SMS account": "SMS account",
|
||||||
|
"SMS account - Tooltip": "SMS account - Tooltip"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Edit User": "Edit User",
|
"Edit User": "Edit User",
|
||||||
|
@ -79,7 +79,12 @@
|
|||||||
"Signin URL": "Signin URL",
|
"Signin URL": "Signin URL",
|
||||||
"Signin URL - Tooltip": "sign in url",
|
"Signin URL - Tooltip": "sign in url",
|
||||||
"ID - Tooltip": "random string",
|
"ID - Tooltip": "random string",
|
||||||
"Favicon - Tooltip": "Application icon"
|
"Favicon - Tooltip": "Application icon",
|
||||||
|
"Uploading": "Uploading",
|
||||||
|
"Start Upload": "Start Upload",
|
||||||
|
"Upload success": "Upload success",
|
||||||
|
"Back Home": "Back Home",
|
||||||
|
"Sorry, the page you visited does not exist": "Sorry, the page you visited does not exist"
|
||||||
},
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"Username": "Username",
|
"Username": "Username",
|
||||||
@ -186,7 +191,13 @@
|
|||||||
"Domain": "Domain",
|
"Domain": "Domain",
|
||||||
"Domain - Tooltip": "Storage endpoint custom domain",
|
"Domain - Tooltip": "Storage endpoint custom domain",
|
||||||
"Region": "Region",
|
"Region": "Region",
|
||||||
"Region - Tooltip": "Storage region"
|
"Region - Tooltip": "Storage region",
|
||||||
|
"Access key": "Access key",
|
||||||
|
"Access key - Tooltip": "Access key - Tooltip",
|
||||||
|
"Secret access key": "Secret access key",
|
||||||
|
"Secret access key - Tooltip": "Secret access key - Tooltip",
|
||||||
|
"SMS account": "SMS account",
|
||||||
|
"SMS account - Tooltip": "SMS account - Tooltip"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Edit User": "Edit User",
|
"Edit User": "Edit User",
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
"User": "用户",
|
"User": "用户",
|
||||||
"Applications": "应用",
|
"Applications": "应用",
|
||||||
"Application": "应用",
|
"Application": "应用",
|
||||||
"Records": "Records",
|
"Records": "日志",
|
||||||
"Client ip": "Client ip",
|
"Client ip": "客户端地址",
|
||||||
"Timestamp": "Timestamp",
|
"Timestamp": "时间戳",
|
||||||
"Username": "用户名",
|
"Username": "用户名",
|
||||||
"Request uri": "Request uri",
|
"Request uri": "请求地址",
|
||||||
"LDAPs": "LDAPs",
|
"LDAPs": "LDAPs",
|
||||||
"Save": "保存",
|
"Save": "保存",
|
||||||
"Add": "添加",
|
"Add": "添加",
|
||||||
@ -79,7 +79,12 @@
|
|||||||
"Signin URL": "登录URL",
|
"Signin URL": "登录URL",
|
||||||
"Signin URL - Tooltip": "用户的登录地址",
|
"Signin URL - Tooltip": "用户的登录地址",
|
||||||
"ID - Tooltip": "唯一的随机字符串",
|
"ID - Tooltip": "唯一的随机字符串",
|
||||||
"Favicon - Tooltip": "网站的图标"
|
"Favicon - Tooltip": "网站的图标",
|
||||||
|
"Uploading": "上传中",
|
||||||
|
"Start Upload": "开始上传",
|
||||||
|
"Upload success": "上传成功",
|
||||||
|
"Back Home": "返回到首页",
|
||||||
|
"Sorry, the page you visited does not exist": "很抱歉,你访问的页面不存在"
|
||||||
},
|
},
|
||||||
"signup": {
|
"signup": {
|
||||||
"Username": "用户名",
|
"Username": "用户名",
|
||||||
@ -87,7 +92,7 @@
|
|||||||
"Please input your personal name!": "请输入您的姓名!",
|
"Please input your personal name!": "请输入您的姓名!",
|
||||||
"Please input your address!": "请输入您的地址!",
|
"Please input your address!": "请输入您的地址!",
|
||||||
"Please input your affiliation!": "请输入您所在的工作单位!",
|
"Please input your affiliation!": "请输入您所在的工作单位!",
|
||||||
"Please select your country/region!": "Please select your country/region!",
|
"Please select your country/region!": "请选择您的国家/地区",
|
||||||
"The input is not valid Email!": "您输入的电子邮箱格式错误!",
|
"The input is not valid Email!": "您输入的电子邮箱格式错误!",
|
||||||
"Please input your Email!": "请输入您的电子邮箱!",
|
"Please input your Email!": "请输入您的电子邮箱!",
|
||||||
"Confirm": "确认密码",
|
"Confirm": "确认密码",
|
||||||
@ -179,14 +184,20 @@
|
|||||||
"Provider URL": "提供商URL",
|
"Provider URL": "提供商URL",
|
||||||
"Provider URL - Tooltip": "唯一的、字符串式的ID",
|
"Provider URL - Tooltip": "唯一的、字符串式的ID",
|
||||||
"Edit Provider": "修改提供商",
|
"Edit Provider": "修改提供商",
|
||||||
"Endpoint": "Endpoint",
|
"Endpoint": "节点",
|
||||||
"Endpoint - Tooltip": "Storage bucket endpoint",
|
"Endpoint - Tooltip": "Storage bucket endpoint",
|
||||||
"Bucket": "Bucket",
|
"Bucket": "存储桶",
|
||||||
"Bucket - Tooltip": "Storage bucket name",
|
"Bucket - Tooltip": "存储桶名称",
|
||||||
"Domain": "Domain",
|
"Domain": "域名",
|
||||||
"Domain - Tooltip": "Storage endpoint custom domain",
|
"Domain - Tooltip": "存储节点自定义域名",
|
||||||
"Region": "Region",
|
"Region": "地区",
|
||||||
"Region - Tooltip": "Storage region"
|
"Region - Tooltip": "存储区域",
|
||||||
|
"Access key": "Access key",
|
||||||
|
"Access key - Tooltip": "Access key - Tooltip",
|
||||||
|
"Secret access key": "Secret access key",
|
||||||
|
"Secret access key - Tooltip": "Secret access key - Tooltip",
|
||||||
|
"SMS account": "SMS账号",
|
||||||
|
"SMS account - Tooltip": "SMS account - Tooltip"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Edit User": "修改用户",
|
"Edit User": "修改用户",
|
||||||
@ -199,8 +210,8 @@
|
|||||||
"Address - Tooltip": "唯一的、字符串式的ID",
|
"Address - Tooltip": "唯一的、字符串式的ID",
|
||||||
"Affiliation": "工作单位",
|
"Affiliation": "工作单位",
|
||||||
"Affiliation - Tooltip": "唯一的、字符串式的ID",
|
"Affiliation - Tooltip": "唯一的、字符串式的ID",
|
||||||
"Country/Region": "Country/Region",
|
"Country/Region": "国家/地区",
|
||||||
"Country/Region - Tooltip": "Country/Region",
|
"Country/Region - Tooltip": "国家/地区",
|
||||||
"Modify affiliation": "修改工作单位",
|
"Modify affiliation": "修改工作单位",
|
||||||
"Tag": "标签",
|
"Tag": "标签",
|
||||||
"Tag - Tooltip": "唯一的、字符串式的ID",
|
"Tag - Tooltip": "唯一的、字符串式的ID",
|
||||||
|
Reference in New Issue
Block a user