mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-11 16:27:49 +08:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bdc5c92ef0 | ||
![]() |
4e3eedf246 | ||
![]() |
8e98fc5a9f | ||
![]() |
6f6159be07 | ||
![]() |
3e4dbc2dcb | ||
![]() |
48b5b27982 | ||
![]() |
1839252c30 | ||
![]() |
1fff1db6a7 | ||
![]() |
a0b0e186b7 | ||
![]() |
8c7f235ee1 | ||
![]() |
a0a762aa6f | ||
![]() |
2eec53a6d0 | ||
![]() |
117dec4542 | ||
![]() |
895cdd024d | ||
![]() |
f0b0891ac9 | ||
![]() |
10449e89ab | ||
![]() |
6e70f0fc58 | ||
![]() |
2bca424370 | ||
![]() |
de49a45e19 |
@@ -78,6 +78,7 @@ p, *, *, POST, /api/get-email-and-phone, *, *
|
|||||||
p, *, *, POST, /api/login, *, *
|
p, *, *, POST, /api/login, *, *
|
||||||
p, *, *, GET, /api/get-app-login, *, *
|
p, *, *, GET, /api/get-app-login, *, *
|
||||||
p, *, *, POST, /api/logout, *, *
|
p, *, *, POST, /api/logout, *, *
|
||||||
|
p, *, *, GET, /api/logout, *, *
|
||||||
p, *, *, GET, /api/get-account, *, *
|
p, *, *, GET, /api/get-account, *, *
|
||||||
p, *, *, GET, /api/userinfo, *, *
|
p, *, *, GET, /api/userinfo, *, *
|
||||||
p, *, *, *, /api/login/oauth, *, *
|
p, *, *, *, /api/login/oauth, *, *
|
||||||
@@ -92,6 +93,7 @@ p, *, *, GET, /api/get-payment, *, *
|
|||||||
p, *, *, POST, /api/update-payment, *, *
|
p, *, *, POST, /api/update-payment, *, *
|
||||||
p, *, *, POST, /api/invoice-payment, *, *
|
p, *, *, POST, /api/invoice-payment, *, *
|
||||||
p, *, *, GET, /api/get-providers, *, *
|
p, *, *, GET, /api/get-providers, *, *
|
||||||
|
p, *, *, POST, /api/notify-payment, *, *
|
||||||
p, *, *, POST, /api/unlink, *, *
|
p, *, *, POST, /api/unlink, *, *
|
||||||
p, *, *, POST, /api/set-password, *, *
|
p, *, *, POST, /api/set-password, *, *
|
||||||
p, *, *, POST, /api/send-verification-code, *, *
|
p, *, *, POST, /api/send-verification-code, *, *
|
||||||
|
@@ -228,7 +228,7 @@ func (c *ApiController) Signup() {
|
|||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
// @Description logout the current user
|
// @Description logout the current user
|
||||||
// @Success 200 {object} controllers.Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /logout [post]
|
// @router /logout [get,post]
|
||||||
func (c *ApiController) Logout() {
|
func (c *ApiController) Logout() {
|
||||||
user := c.GetSessionUsername()
|
user := c.GetSessionUsername()
|
||||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||||
|
@@ -50,6 +50,17 @@ func tokenToResponse(token *object.Token) *Response {
|
|||||||
// HandleLoggedIn ...
|
// HandleLoggedIn ...
|
||||||
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *RequestForm) (resp *Response) {
|
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *RequestForm) (resp *Response) {
|
||||||
userId := user.GetId()
|
userId := user.GetId()
|
||||||
|
|
||||||
|
allowed, err := object.CheckAccessPermission(userId, application)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error(), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !allowed {
|
||||||
|
c.ResponseError("Unauthorized operation")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if form.Type == ResponseTypeLogin {
|
if form.Type == ResponseTypeLogin {
|
||||||
c.SetSessionUsername(userId)
|
c.SetSessionUsername(userId)
|
||||||
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
||||||
|
@@ -85,11 +85,15 @@ func (c *ApiController) GetUsers() {
|
|||||||
// @router /get-user [get]
|
// @router /get-user [get]
|
||||||
func (c *ApiController) GetUser() {
|
func (c *ApiController) GetUser() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
owner := c.Input().Get("owner")
|
|
||||||
email := c.Input().Get("email")
|
email := c.Input().Get("email")
|
||||||
userOwner, _ := util.GetOwnerAndNameFromId(id)
|
userId := c.Input().Get("userId")
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", userOwner))
|
|
||||||
|
|
||||||
|
owner := c.Input().Get("owner")
|
||||||
|
if owner == "" {
|
||||||
|
owner, _ = util.GetOwnerAndNameFromId(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", owner))
|
||||||
if !organization.IsProfilePublic {
|
if !organization.IsProfilePublic {
|
||||||
requestUserId := c.GetSessionUsername()
|
requestUserId := c.GetSessionUsername()
|
||||||
hasPermission, err := object.CheckUserPermission(requestUserId, id, false)
|
hasPermission, err := object.CheckUserPermission(requestUserId, id, false)
|
||||||
@@ -100,10 +104,12 @@ func (c *ApiController) GetUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var user *object.User
|
var user *object.User
|
||||||
if email == "" {
|
if email != "" {
|
||||||
user = object.GetUser(id)
|
|
||||||
} else {
|
|
||||||
user = object.GetUserByEmail(owner, email)
|
user = object.GetUserByEmail(owner, email)
|
||||||
|
} else if userId != "" {
|
||||||
|
user = object.GetUserByUserId(owner, userId)
|
||||||
|
} else {
|
||||||
|
user = object.GetUser(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedUser(user)
|
c.Data["json"] = object.GetMaskedUser(user)
|
||||||
|
@@ -49,8 +49,24 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
||||||
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
||||||
|
|
||||||
if destType == "" || dest == "" || applicationId == "" || !strings.Contains(applicationId, "/") || checkType == "" {
|
if destType == "" {
|
||||||
c.ResponseError("Missing parameter.")
|
c.ResponseError("Missing parameter: type.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if dest == "" {
|
||||||
|
c.ResponseError("Missing parameter: dest.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if applicationId == "" {
|
||||||
|
c.ResponseError("Missing parameter: applicationId.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !strings.Contains(applicationId, "/") {
|
||||||
|
c.ResponseError("Wrong parameter: applicationId.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if checkType == "" {
|
||||||
|
c.ResponseError("Missing parameter: checkType.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,6 +39,7 @@ func readI18nFile(language string) *I18nData {
|
|||||||
func writeI18nFile(language string, data *I18nData) {
|
func writeI18nFile(language string, data *I18nData) {
|
||||||
s := util.StructToJsonFormatted(data)
|
s := util.StructToJsonFormatted(data)
|
||||||
s = strings.ReplaceAll(s, "\\u0026", "&")
|
s = strings.ReplaceAll(s, "\\u0026", "&")
|
||||||
|
s += "\n"
|
||||||
println(s)
|
println(s)
|
||||||
|
|
||||||
util.WriteStringToPath(s, getI18nFilePath(language))
|
util.WriteStringToPath(s, getI18nFilePath(language))
|
||||||
|
@@ -144,7 +144,7 @@ func (idp *BilibiliIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
type BilibiliUserInfo struct {
|
type BilibiliUserInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Face string `json:"face"`
|
Face string `json:"face"`
|
||||||
OpenId string `json:"openid`
|
OpenId string `json:"openid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BilibiliUserInfoResponse struct {
|
type BilibiliUserInfoResponse struct {
|
||||||
|
@@ -139,7 +139,7 @@
|
|||||||
"cryptoAlgorithm": "RS256",
|
"cryptoAlgorithm": "RS256",
|
||||||
"bitSize": 4096,
|
"bitSize": 4096,
|
||||||
"expireInYears": 20,
|
"expireInYears": 20,
|
||||||
"publicKey": "",
|
"certificate": "",
|
||||||
"privateKey": ""
|
"privateKey": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@@ -203,6 +203,11 @@ func (a *Adapter) createTable() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = a.Engine.Sync2(new(PermissionRule))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||||
|
@@ -33,7 +33,7 @@ type Cert struct {
|
|||||||
BitSize int `json:"bitSize"`
|
BitSize int `json:"bitSize"`
|
||||||
ExpireInYears int `json:"expireInYears"`
|
ExpireInYears int `json:"expireInYears"`
|
||||||
|
|
||||||
PublicKey string `xorm:"mediumtext" json:"publicKey"`
|
Certificate string `xorm:"mediumtext" json:"certificate"`
|
||||||
PrivateKey string `xorm:"mediumtext" json:"privateKey"`
|
PrivateKey string `xorm:"mediumtext" json:"privateKey"`
|
||||||
AuthorityPublicKey string `xorm:"mediumtext" json:"authorityPublicKey"`
|
AuthorityPublicKey string `xorm:"mediumtext" json:"authorityPublicKey"`
|
||||||
AuthorityRootPublicKey string `xorm:"mediumtext" json:"authorityRootPublicKey"`
|
AuthorityRootPublicKey string `xorm:"mediumtext" json:"authorityRootPublicKey"`
|
||||||
@@ -123,9 +123,9 @@ func UpdateCert(id string, cert *Cert) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddCert(cert *Cert) bool {
|
func AddCert(cert *Cert) bool {
|
||||||
if cert.PublicKey == "" || cert.PrivateKey == "" {
|
if cert.Certificate == "" || cert.PrivateKey == "" {
|
||||||
publicKey, privateKey := generateRsaKeys(cert.BitSize, cert.ExpireInYears, cert.Name, cert.Owner)
|
certificate, privateKey := generateRsaKeys(cert.BitSize, cert.ExpireInYears, cert.Name, cert.Owner)
|
||||||
cert.PublicKey = publicKey
|
cert.Certificate = certificate
|
||||||
cert.PrivateKey = privateKey
|
cert.PrivateKey = privateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -229,4 +229,30 @@ func CheckUserPermission(requestUserId, userId string, strict bool) (bool, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
return hasPermission, fmt.Errorf("you don't have the permission to do this")
|
return hasPermission, fmt.Errorf("you don't have the permission to do this")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
||||||
|
permissions := GetPermissions(application.Organization)
|
||||||
|
allowed := true
|
||||||
|
var err error
|
||||||
|
for _, permission := range permissions {
|
||||||
|
if !permission.IsEnabled || len(permission.Users) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
isHit := false
|
||||||
|
for _, resource := range permission.Resources {
|
||||||
|
if application.Name == resource {
|
||||||
|
isHit = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isHit {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
allowed, err = enforcer.Enforce(userId, application.Name, "read")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allowed, err
|
||||||
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import (
|
|||||||
func InitDb() {
|
func InitDb() {
|
||||||
existed := initBuiltInOrganization()
|
existed := initBuiltInOrganization()
|
||||||
if !existed {
|
if !existed {
|
||||||
|
initBuiltInPermission()
|
||||||
initBuiltInProvider()
|
initBuiltInProvider()
|
||||||
initBuiltInUser()
|
initBuiltInUser()
|
||||||
initBuiltInApplication()
|
initBuiltInApplication()
|
||||||
@@ -167,7 +168,7 @@ func readTokenFromFile() (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initBuiltInCert() {
|
func initBuiltInCert() {
|
||||||
tokenJwtPublicKey, tokenJwtPrivateKey := readTokenFromFile()
|
tokenJwtCertificate, tokenJwtPrivateKey := readTokenFromFile()
|
||||||
cert := getCert("admin", "cert-built-in")
|
cert := getCert("admin", "cert-built-in")
|
||||||
if cert != nil {
|
if cert != nil {
|
||||||
return
|
return
|
||||||
@@ -183,7 +184,7 @@ func initBuiltInCert() {
|
|||||||
CryptoAlgorithm: "RS256",
|
CryptoAlgorithm: "RS256",
|
||||||
BitSize: 4096,
|
BitSize: 4096,
|
||||||
ExpireInYears: 20,
|
ExpireInYears: 20,
|
||||||
PublicKey: tokenJwtPublicKey,
|
Certificate: tokenJwtCertificate,
|
||||||
PrivateKey: tokenJwtPrivateKey,
|
PrivateKey: tokenJwtPrivateKey,
|
||||||
}
|
}
|
||||||
AddCert(cert)
|
AddCert(cert)
|
||||||
@@ -230,3 +231,25 @@ func initBuiltInProvider() {
|
|||||||
func initWebAuthn() {
|
func initWebAuthn() {
|
||||||
gob.Register(webauthn.SessionData{})
|
gob.Register(webauthn.SessionData{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initBuiltInPermission() {
|
||||||
|
permission := GetPermission("built-in/permission-built-in")
|
||||||
|
if permission != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
permission = &Permission{
|
||||||
|
Owner: "built-in",
|
||||||
|
Name: "permission-built-in",
|
||||||
|
CreatedTime: util.GetCurrentTime(),
|
||||||
|
DisplayName: "Built-in Permission",
|
||||||
|
Users: []string{"built-in/admin"},
|
||||||
|
Roles: []string{},
|
||||||
|
ResourceType: "Application",
|
||||||
|
Resources: []string{"app-built-in"},
|
||||||
|
Actions: []string{"Read", "Write", "Admin"},
|
||||||
|
Effect: "Allow",
|
||||||
|
IsEnabled: true,
|
||||||
|
}
|
||||||
|
AddPermission(permission)
|
||||||
|
}
|
||||||
|
@@ -97,7 +97,7 @@ func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
|
|||||||
//link here: https://self-issued.info/docs/draft-ietf-jose-json-web-key.html
|
//link here: https://self-issued.info/docs/draft-ietf-jose-json-web-key.html
|
||||||
//or https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key
|
//or https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key
|
||||||
for _, cert := range certs {
|
for _, cert := range certs {
|
||||||
certPemBlock := []byte(cert.PublicKey)
|
certPemBlock := []byte(cert.Certificate)
|
||||||
certDerBlock, _ := pem.Decode(certPemBlock)
|
certDerBlock, _ := pem.Decode(certPemBlock)
|
||||||
x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes)
|
x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes)
|
||||||
|
|
||||||
|
@@ -16,7 +16,12 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casbin/casbin/v2"
|
||||||
|
"github.com/casbin/casbin/v2/model"
|
||||||
|
xormadapter "github.com/casbin/xorm-adapter/v2"
|
||||||
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"xorm.io/core"
|
"xorm.io/core"
|
||||||
)
|
)
|
||||||
@@ -39,6 +44,16 @@ type Permission struct {
|
|||||||
IsEnabled bool `json:"isEnabled"`
|
IsEnabled bool `json:"isEnabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PermissionRule struct {
|
||||||
|
PType string `xorm:"varchar(100) index not null default ''"`
|
||||||
|
V0 string `xorm:"varchar(100) index not null default ''"`
|
||||||
|
V1 string `xorm:"varchar(100) index not null default ''"`
|
||||||
|
V2 string `xorm:"varchar(100) index not null default ''"`
|
||||||
|
V3 string `xorm:"varchar(100) index not null default ''"`
|
||||||
|
V4 string `xorm:"varchar(100) index not null default ''"`
|
||||||
|
V5 string `xorm:"varchar(100) index not null default ''"`
|
||||||
|
}
|
||||||
|
|
||||||
func GetPermissionCount(owner, field, value string) int {
|
func GetPermissionCount(owner, field, value string) int {
|
||||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||||
count, err := session.Count(&Permission{})
|
count, err := session.Count(&Permission{})
|
||||||
@@ -95,7 +110,8 @@ func GetPermission(id string) *Permission {
|
|||||||
|
|
||||||
func UpdatePermission(id string, permission *Permission) bool {
|
func UpdatePermission(id string, permission *Permission) bool {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
if getPermission(owner, name) == nil {
|
oldPermission := getPermission(owner, name)
|
||||||
|
if oldPermission == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +120,11 @@ func UpdatePermission(id string, permission *Permission) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
removePolicies(oldPermission)
|
||||||
|
addPolicies(permission)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +134,10 @@ func AddPermission(permission *Permission) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
addPolicies(permission)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,9 +147,85 @@ func DeletePermission(permission *Permission) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
removePolicies(permission)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (permission *Permission) GetId() string {
|
func (permission *Permission) GetId() string {
|
||||||
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
|
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getEnforcer(permission *Permission) *casbin.Enforcer {
|
||||||
|
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||||
|
adapter, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName()+conf.GetConfigString("dbName"), "permission_rule", tableNamePrefix, true)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
modelText := `
|
||||||
|
[request_definition]
|
||||||
|
r = sub, obj, act
|
||||||
|
|
||||||
|
[policy_definition]
|
||||||
|
p = permission, sub, obj, act
|
||||||
|
|
||||||
|
[policy_effect]
|
||||||
|
e = some(where (p.eft == allow))
|
||||||
|
|
||||||
|
[matchers]
|
||||||
|
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`
|
||||||
|
permissionModel := getModel(permission.Owner, permission.Model)
|
||||||
|
if permissionModel != nil {
|
||||||
|
modelText = permissionModel.ModelText
|
||||||
|
}
|
||||||
|
m, err := model.NewModelFromString(modelText)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
enforcer, err := casbin.NewEnforcer(m, adapter)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return enforcer
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPolicies(permission *Permission) [][]string {
|
||||||
|
var policies [][]string
|
||||||
|
for _, user := range permission.Users {
|
||||||
|
for _, resource := range permission.Resources {
|
||||||
|
for _, action := range permission.Actions {
|
||||||
|
policies = append(policies, []string{permission.GetId(), user, resource, strings.ToLower(action)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return policies
|
||||||
|
}
|
||||||
|
|
||||||
|
func addPolicies(permission *Permission) {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
policies := getPolicies(permission)
|
||||||
|
|
||||||
|
_, err := enforcer.AddPolicies(policies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func removePolicies(permission *Permission) {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
|
||||||
|
_, err := enforcer.RemoveFilteredPolicy(0, permission.GetId())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -30,7 +30,7 @@ func TestProduct(t *testing.T) {
|
|||||||
product := GetProduct("admin/product_123")
|
product := GetProduct("admin/product_123")
|
||||||
provider := getProvider(product.Owner, "provider_pay_alipay")
|
provider := getProvider(product.Owner, "provider_pay_alipay")
|
||||||
cert := getCert(product.Owner, "cert-pay-alipay")
|
cert := getCert(product.Owner, "cert-pay-alipay")
|
||||||
pProvider := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.PublicKey, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
pProvider := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.Certificate, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
||||||
|
|
||||||
paymentName := util.GenerateTimeId()
|
paymentName := util.GenerateTimeId()
|
||||||
returnUrl := ""
|
returnUrl := ""
|
||||||
|
@@ -214,7 +214,7 @@ func (p *Provider) getPaymentProvider() (pp.PaymentProvider, *Cert, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pProvider := pp.GetPaymentProvider(p.Type, p.ClientId, p.ClientSecret, p.Host, cert.PublicKey, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
pProvider := pp.GetPaymentProvider(p.Type, p.ClientId, p.ClientSecret, p.Host, cert.Certificate, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
||||||
if pProvider == nil {
|
if pProvider == nil {
|
||||||
return nil, cert, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
return nil, cert, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
||||||
}
|
}
|
||||||
|
@@ -36,7 +36,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//returns a saml2 response
|
//returns a saml2 response
|
||||||
func NewSamlResponse(user *User, host string, publicKey string, destination string, iss string, requestId string, redirectUri []string) (*etree.Element, error) {
|
func NewSamlResponse(user *User, host string, certificate string, destination string, iss string, requestId string, redirectUri []string) (*etree.Element, error) {
|
||||||
samlResponse := &etree.Element{
|
samlResponse := &etree.Element{
|
||||||
Space: "samlp",
|
Space: "samlp",
|
||||||
Tag: "Response",
|
Tag: "Response",
|
||||||
@@ -177,8 +177,8 @@ type Attribute struct {
|
|||||||
func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, error) {
|
func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, error) {
|
||||||
//_, originBackend := getOriginFromHost(host)
|
//_, originBackend := getOriginFromHost(host)
|
||||||
cert := getCertByApplication(application)
|
cert := getCertByApplication(application)
|
||||||
block, _ := pem.Decode([]byte(cert.PublicKey))
|
block, _ := pem.Decode([]byte(cert.Certificate))
|
||||||
publicKey := base64.StdEncoding.EncodeToString(block.Bytes)
|
certificate := base64.StdEncoding.EncodeToString(block.Bytes)
|
||||||
|
|
||||||
origin := beego.AppConfig.String("origin")
|
origin := beego.AppConfig.String("origin")
|
||||||
originFrontend, originBackend := getOriginFromHost(host)
|
originFrontend, originBackend := getOriginFromHost(host)
|
||||||
@@ -199,7 +199,7 @@ func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, e
|
|||||||
KeyInfo: KeyInfo{
|
KeyInfo: KeyInfo{
|
||||||
X509Data: X509Data{
|
X509Data: X509Data{
|
||||||
X509Certificate: X509Certificate{
|
X509Certificate: X509Certificate{
|
||||||
Cert: publicKey,
|
Cert: certificate,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -248,18 +248,18 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
return "", "", fmt.Errorf("err: invalid issuer url")
|
return "", "", fmt.Errorf("err: invalid issuer url")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get public key string
|
// get certificate string
|
||||||
cert := getCertByApplication(application)
|
cert := getCertByApplication(application)
|
||||||
block, _ := pem.Decode([]byte(cert.PublicKey))
|
block, _ := pem.Decode([]byte(cert.Certificate))
|
||||||
publicKey := base64.StdEncoding.EncodeToString(block.Bytes)
|
certificate := base64.StdEncoding.EncodeToString(block.Bytes)
|
||||||
|
|
||||||
_, originBackend := getOriginFromHost(host)
|
_, originBackend := getOriginFromHost(host)
|
||||||
|
|
||||||
// build signedResponse
|
// build signedResponse
|
||||||
samlResponse, _ := NewSamlResponse(user, originBackend, publicKey, authnRequest.AssertionConsumerServiceURL, authnRequest.Issuer.Url, authnRequest.ID, application.RedirectUris)
|
samlResponse, _ := NewSamlResponse(user, originBackend, certificate, authnRequest.AssertionConsumerServiceURL, authnRequest.Issuer.Url, authnRequest.ID, application.RedirectUris)
|
||||||
randomKeyStore := &X509Key{
|
randomKeyStore := &X509Key{
|
||||||
PrivateKey: cert.PrivateKey,
|
PrivateKey: cert.PrivateKey,
|
||||||
X509Certificate: publicKey,
|
X509Certificate: certificate,
|
||||||
}
|
}
|
||||||
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
|
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
|
||||||
ctx.Hash = crypto.SHA1
|
ctx.Hash = crypto.SHA1
|
||||||
|
@@ -17,6 +17,7 @@ package object
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
@@ -42,8 +43,19 @@ func getProviderEndpoint(provider *Provider) string {
|
|||||||
return endpoint
|
return endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func escapePath(path string) string {
|
||||||
|
tokens := strings.Split(path, "/")
|
||||||
|
if len(tokens) > 0 {
|
||||||
|
tokens[len(tokens)-1] = url.QueryEscape(tokens[len(tokens)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
res := strings.Join(tokens, "/")
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool) (string, string) {
|
func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool) (string, string) {
|
||||||
objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), fullFilePath)
|
escapedPath := escapePath(fullFilePath)
|
||||||
|
objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), escapedPath)
|
||||||
|
|
||||||
host := ""
|
host := ""
|
||||||
if provider.Type != "Local File System" {
|
if provider.Type != "Local File System" {
|
||||||
@@ -60,9 +72,9 @@ func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool
|
|||||||
host = fmt.Sprintf("%s/%s", host, provider.Bucket)
|
host = fmt.Sprintf("%s/%s", host, provider.Bucket)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileUrl := util.UrlJoin(host, objectKey)
|
fileUrl := util.UrlJoin(host, escapePath(objectKey))
|
||||||
if hasTimestamp {
|
if hasTimestamp {
|
||||||
fileUrl = fmt.Sprintf("%s?t=%s", util.UrlJoin(host, objectKey), util.GetCurrentUnixTime())
|
fileUrl = fmt.Sprintf("%s?t=%s", fileUrl, util.GetCurrentUnixTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileUrl, objectKey
|
return fileUrl, objectKey
|
||||||
|
@@ -151,6 +151,8 @@ func (syncer *Syncer) initAdapter() {
|
|||||||
var dataSourceName string
|
var dataSourceName string
|
||||||
if syncer.DatabaseType == "mssql" {
|
if syncer.DatabaseType == "mssql" {
|
||||||
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", syncer.User, syncer.Password, syncer.Host, syncer.Port, syncer.Database)
|
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", syncer.User, syncer.Password, syncer.Host, syncer.Port, syncer.Database)
|
||||||
|
} else if syncer.DatabaseType == "postgres" {
|
||||||
|
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s", syncer.User, syncer.Password, syncer.Host, syncer.Port, syncer.Database)
|
||||||
} else {
|
} else {
|
||||||
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/", syncer.User, syncer.Password, syncer.Host, syncer.Port)
|
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/", syncer.User, syncer.Password, syncer.Host, syncer.Port)
|
||||||
}
|
}
|
||||||
|
@@ -173,16 +173,21 @@ func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*Or
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tableColumn := range syncer.TableColumns {
|
for _, tableColumn := range syncer.TableColumns {
|
||||||
|
tableColumnName := tableColumn.Name
|
||||||
|
if syncer.Type == "Keycloak" && syncer.DatabaseType == "postgres" {
|
||||||
|
tableColumnName = strings.ToLower(tableColumnName)
|
||||||
|
}
|
||||||
|
|
||||||
value := ""
|
value := ""
|
||||||
if strings.Contains(tableColumn.Name, "+") {
|
if strings.Contains(tableColumnName, "+") {
|
||||||
names := strings.Split(tableColumn.Name, "+")
|
names := strings.Split(tableColumnName, "+")
|
||||||
var values []string
|
var values []string
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
values = append(values, result[strings.Trim(name, " ")])
|
values = append(values, result[strings.Trim(name, " ")])
|
||||||
}
|
}
|
||||||
value = strings.Join(values, " ")
|
value = strings.Join(values, " ")
|
||||||
} else {
|
} else {
|
||||||
value = result[tableColumn.Name]
|
value = result[tableColumnName]
|
||||||
}
|
}
|
||||||
syncer.setUserByKeyValue(originalUser, tableColumn.CasdoorName, value)
|
syncer.setUserByKeyValue(originalUser, tableColumn.CasdoorName, value)
|
||||||
}
|
}
|
||||||
@@ -198,7 +203,7 @@ func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*Or
|
|||||||
originalUser.PasswordSalt = credential.Salt
|
originalUser.PasswordSalt = credential.Salt
|
||||||
}
|
}
|
||||||
// query and set signup application from user group table
|
// query and set signup application from user group table
|
||||||
sql = fmt.Sprintf("select name from keycloak_group where id = " +
|
sql = fmt.Sprintf("select name from keycloak_group where id = "+
|
||||||
"(select group_id as gid from user_group_membership where user_id = '%s')", originalUser.Id)
|
"(select group_id as gid from user_group_membership where user_id = '%s')", originalUser.Id)
|
||||||
groupResult, _ := syncer.Adapter.Engine.QueryString(sql)
|
groupResult, _ := syncer.Adapter.Engine.QueryString(sql)
|
||||||
if len(groupResult) > 0 {
|
if len(groupResult) > 0 {
|
||||||
@@ -209,7 +214,12 @@ func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*Or
|
|||||||
tm := time.Unix(i/int64(1000), 0)
|
tm := time.Unix(i/int64(1000), 0)
|
||||||
originalUser.CreatedTime = tm.Format("2006-01-02T15:04:05+08:00")
|
originalUser.CreatedTime = tm.Format("2006-01-02T15:04:05+08:00")
|
||||||
// enable
|
// enable
|
||||||
originalUser.IsForbidden = !(result["ENABLED"] == "\x01")
|
value, ok := result["ENABLED"]
|
||||||
|
if ok {
|
||||||
|
originalUser.IsForbidden = !util.ParseBool(value)
|
||||||
|
} else {
|
||||||
|
originalUser.IsForbidden = !util.ParseBool(result["enabled"])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
users = append(users, originalUser)
|
users = append(users, originalUser)
|
||||||
|
@@ -241,11 +241,11 @@ func GetValidationBySaml(samlRequest string, host string) (string, string, error
|
|||||||
samlResponse := NewSamlResponse11(user, request.RequestID, host)
|
samlResponse := NewSamlResponse11(user, request.RequestID, host)
|
||||||
|
|
||||||
cert := getCertByApplication(application)
|
cert := getCertByApplication(application)
|
||||||
block, _ := pem.Decode([]byte(cert.PublicKey))
|
block, _ := pem.Decode([]byte(cert.Certificate))
|
||||||
publicKey := base64.StdEncoding.EncodeToString(block.Bytes)
|
certificate := base64.StdEncoding.EncodeToString(block.Bytes)
|
||||||
randomKeyStore := &X509Key{
|
randomKeyStore := &X509Key{
|
||||||
PrivateKey: cert.PrivateKey,
|
PrivateKey: cert.PrivateKey,
|
||||||
X509Certificate: publicKey,
|
X509Certificate: certificate,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
|
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
|
||||||
|
@@ -129,13 +129,13 @@ func ParseJwtToken(token string, cert *Cert) (*Claims, error) {
|
|||||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSA public key
|
// RSA certificate
|
||||||
publicKey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(cert.PublicKey))
|
certificate, err := jwt.ParseRSAPublicKeyFromPEM([]byte(cert.Certificate))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return publicKey, nil
|
return certificate, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if t != nil {
|
if t != nil {
|
||||||
|
@@ -23,10 +23,10 @@ import (
|
|||||||
|
|
||||||
func TestGenerateRsaKeys(t *testing.T) {
|
func TestGenerateRsaKeys(t *testing.T) {
|
||||||
fileId := "token_jwt_key"
|
fileId := "token_jwt_key"
|
||||||
publicKey, privateKey := generateRsaKeys(4096, 20, "Casdoor Cert", "Casdoor Organization")
|
certificate, privateKey := generateRsaKeys(4096, 20, "Casdoor Cert", "Casdoor Organization")
|
||||||
|
|
||||||
// Write certificate (aka public key) to file.
|
// Write certificate (aka certificate) to file.
|
||||||
util.WriteStringToPath(publicKey, fmt.Sprintf("%s.pem", fileId))
|
util.WriteStringToPath(certificate, fmt.Sprintf("%s.pem", fileId))
|
||||||
|
|
||||||
// Write private key to file.
|
// Write private key to file.
|
||||||
util.WriteStringToPath(privateKey, fmt.Sprintf("%s.key", fileId))
|
util.WriteStringToPath(privateKey, fmt.Sprintf("%s.key", fileId))
|
||||||
|
@@ -97,7 +97,7 @@ type User struct {
|
|||||||
Steam string `xorm:"steam varchar(100)" json:"steam"`
|
Steam string `xorm:"steam varchar(100)" json:"steam"`
|
||||||
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
|
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
|
||||||
Okta string `xorm:"okta varchar(100)" json:"okta"`
|
Okta string `xorm:"okta varchar(100)" json:"okta"`
|
||||||
Douyin string `xorm:"douyin vachar(100)" json:"douyin"`
|
Douyin string `xorm:"douyin varchar(100)" json:"douyin"`
|
||||||
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
||||||
|
|
||||||
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
||||||
@@ -270,6 +270,24 @@ func GetUserByEmail(owner string, email string) *User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetUserByUserId(owner string, userId string) *User {
|
||||||
|
if owner == "" || userId == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{Owner: owner, Id: userId}
|
||||||
|
existed, err := adapter.Engine.Get(&user)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if existed {
|
||||||
|
return &user
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GetUser(id string) *User {
|
func GetUser(id string) *User {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
return getUser(owner, name)
|
return getUser(owner, name)
|
||||||
@@ -329,9 +347,11 @@ func UpdateUser(id string, user *User, columns []string, isGlobalAdmin bool) boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(columns) == 0 {
|
if len(columns) == 0 {
|
||||||
columns = []string{"owner", "display_name", "avatar",
|
columns = []string{
|
||||||
|
"owner", "display_name", "avatar",
|
||||||
"location", "address", "region", "language", "affiliation", "title", "homepage", "bio", "score", "tag", "signup_application",
|
"location", "address", "region", "language", "affiliation", "title", "homepage", "bio", "score", "tag", "signup_application",
|
||||||
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials"}
|
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if isGlobalAdmin {
|
if isGlobalAdmin {
|
||||||
columns = append(columns, "name", "email", "phone")
|
columns = append(columns, "name", "email", "phone")
|
||||||
@@ -398,10 +418,10 @@ func AddUsers(users []*User) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
//organization := GetOrganizationByUser(users[0])
|
// organization := GetOrganizationByUser(users[0])
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
// this function is only used for syncer or batch upload, so no need to encrypt the password
|
// this function is only used for syncer or batch upload, so no need to encrypt the password
|
||||||
//user.UpdateUserPassword(organization)
|
// user.UpdateUserPassword(organization)
|
||||||
|
|
||||||
user.UpdateUserHash()
|
user.UpdateUserHash()
|
||||||
user.PreHash = user.Hash
|
user.PreHash = user.Hash
|
||||||
|
@@ -28,7 +28,7 @@ type AlipayPaymentProvider struct {
|
|||||||
Client *alipay.Client
|
Client *alipay.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAlipayPaymentProvider(appId string, appPublicKey string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string) *AlipayPaymentProvider {
|
func NewAlipayPaymentProvider(appId string, appCertificate string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string) *AlipayPaymentProvider {
|
||||||
pp := &AlipayPaymentProvider{}
|
pp := &AlipayPaymentProvider{}
|
||||||
|
|
||||||
client, err := alipay.NewClient(appId, appPrivateKey, true)
|
client, err := alipay.NewClient(appId, appPrivateKey, true)
|
||||||
@@ -36,7 +36,7 @@ func NewAlipayPaymentProvider(appId string, appPublicKey string, appPrivateKey s
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.SetCertSnByContent([]byte(appPublicKey), []byte(authorityRootPublicKey), []byte(authorityPublicKey))
|
err = client.SetCertSnByContent([]byte(appCertificate), []byte(authorityRootPublicKey), []byte(authorityPublicKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@@ -22,9 +22,9 @@ type PaymentProvider interface {
|
|||||||
GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error)
|
GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPaymentProvider(typ string, appId string, clientSecret string, host string, appPublicKey string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string) PaymentProvider {
|
func GetPaymentProvider(typ string, appId string, clientSecret string, host string, appCertificate string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string) PaymentProvider {
|
||||||
if typ == "Alipay" {
|
if typ == "Alipay" {
|
||||||
return NewAlipayPaymentProvider(appId, appPublicKey, appPrivateKey, authorityPublicKey, authorityRootPublicKey)
|
return NewAlipayPaymentProvider(appId, appCertificate, appPrivateKey, authorityPublicKey, authorityRootPublicKey)
|
||||||
} else if typ == "GC" {
|
} else if typ == "GC" {
|
||||||
return NewGcPaymentProvider(appId, clientSecret, host)
|
return NewGcPaymentProvider(appId, clientSecret, host)
|
||||||
}
|
}
|
||||||
|
@@ -122,6 +122,10 @@ func AuthzFilter(ctx *context.Context) {
|
|||||||
urlPath := getUrlPath(ctx.Request.URL.Path)
|
urlPath := getUrlPath(ctx.Request.URL.Path)
|
||||||
objOwner, objName := getObject(ctx)
|
objOwner, objName := getObject(ctx)
|
||||||
|
|
||||||
|
if strings.HasPrefix(urlPath, "/api/notify-payment") {
|
||||||
|
urlPath = "/api/notify-payment"
|
||||||
|
}
|
||||||
|
|
||||||
isAllowed := authz.IsAllowed(subOwner, subName, method, urlPath, objOwner, objName)
|
isAllowed := authz.IsAllowed(subOwner, subName, method, urlPath, objOwner, objName)
|
||||||
|
|
||||||
result := "deny"
|
result := "deny"
|
||||||
|
@@ -48,7 +48,7 @@ func initAPI() {
|
|||||||
beego.Router("/api/signup", &controllers.ApiController{}, "POST:Signup")
|
beego.Router("/api/signup", &controllers.ApiController{}, "POST:Signup")
|
||||||
beego.Router("/api/login", &controllers.ApiController{}, "POST:Login")
|
beego.Router("/api/login", &controllers.ApiController{}, "POST:Login")
|
||||||
beego.Router("/api/get-app-login", &controllers.ApiController{}, "GET:GetApplicationLogin")
|
beego.Router("/api/get-app-login", &controllers.ApiController{}, "GET:GetApplicationLogin")
|
||||||
beego.Router("/api/logout", &controllers.ApiController{}, "POST:Logout")
|
beego.Router("/api/logout", &controllers.ApiController{}, "GET,POST:Logout")
|
||||||
beego.Router("/api/get-account", &controllers.ApiController{}, "GET:GetAccount")
|
beego.Router("/api/get-account", &controllers.ApiController{}, "GET:GetAccount")
|
||||||
beego.Router("/api/userinfo", &controllers.ApiController{}, "GET:GetUserinfo")
|
beego.Router("/api/userinfo", &controllers.ApiController{}, "GET:GetUserinfo")
|
||||||
beego.Router("/api/unlink", &controllers.ApiController{}, "POST:Unlink")
|
beego.Router("/api/unlink", &controllers.ApiController{}, "POST:Unlink")
|
||||||
|
@@ -2418,6 +2418,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/logout": {
|
"/api/logout": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Login API"
|
||||||
|
],
|
||||||
|
"description": "logout the current user",
|
||||||
|
"operationId": "ApiController.Logout",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
"Login API"
|
"Login API"
|
||||||
@@ -3096,14 +3111,120 @@
|
|||||||
],
|
],
|
||||||
"operationId": "ApiController.VerifyCaptcha"
|
"operationId": "ApiController.VerifyCaptcha"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/api/webauthn/signin/begin": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Login API"
|
||||||
|
],
|
||||||
|
"description": "WebAuthn Login Flow 1st stage",
|
||||||
|
"operationId": "ApiController.WebAuthnSigninBegin",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "owner",
|
||||||
|
"description": "owner",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "name",
|
||||||
|
"description": "name",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The CredentialAssertion object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/protocol.CredentialAssertion"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/webauthn/signin/finish": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Login API"
|
||||||
|
],
|
||||||
|
"description": "WebAuthn Login Flow 2nd stage",
|
||||||
|
"operationId": "ApiController.WebAuthnSigninBegin",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "authenticator assertion Response",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/protocol.CredentialAssertionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "\"The Response object\"",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/webauthn/signup/begin": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"User API"
|
||||||
|
],
|
||||||
|
"description": "WebAuthn Registration Flow 1st stage",
|
||||||
|
"operationId": "ApiController.WebAuthnSignupBegin",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The CredentialCreationOptions object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/protocol.CredentialCreation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/webauthn/signup/finish": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"User API"
|
||||||
|
],
|
||||||
|
"description": "WebAuthn Registration Flow 2nd stage",
|
||||||
|
"operationId": "ApiController.WebAuthnSignupFinish",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "authenticator attestation Response",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/protocol.CredentialCreationResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "\"The Response object\"",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"2127.0xc000398090.false": {
|
"2127.0xc000427560.false": {
|
||||||
"title": "false",
|
"title": "false",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"2161.0xc0003980c0.false": {
|
"2161.0xc000427590.false": {
|
||||||
"title": "false",
|
"title": "false",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
@@ -3221,10 +3342,10 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"data": {
|
"data": {
|
||||||
"$ref": "#/definitions/2127.0xc000398090.false"
|
"$ref": "#/definitions/2127.0xc000427560.false"
|
||||||
},
|
},
|
||||||
"data2": {
|
"data2": {
|
||||||
"$ref": "#/definitions/2161.0xc0003980c0.false"
|
"$ref": "#/definitions/2161.0xc000427590.false"
|
||||||
},
|
},
|
||||||
"msg": {
|
"msg": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -3329,12 +3450,18 @@
|
|||||||
"enablePassword": {
|
"enablePassword": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"enableSamlCompress": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"enableSignUp": {
|
"enableSignUp": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"enableSigninSession": {
|
"enableSigninSession": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"enableWebAuthn": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"expireInHours": {
|
"expireInHours": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64"
|
"format": "int64"
|
||||||
@@ -3444,7 +3571,7 @@
|
|||||||
"privateKey": {
|
"privateKey": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"publicKey": {
|
"certificate": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"scope": {
|
"scope": {
|
||||||
@@ -4507,6 +4634,12 @@
|
|||||||
"updatedTime": {
|
"updatedTime": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"webauthnCredentials": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/webauthn.Credential"
|
||||||
|
}
|
||||||
|
},
|
||||||
"wechat": {
|
"wechat": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@@ -4596,6 +4729,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"protocol.CredentialAssertion": {
|
||||||
|
"title": "CredentialAssertion",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"protocol.CredentialAssertionResponse": {
|
||||||
|
"title": "CredentialAssertionResponse",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"protocol.CredentialCreation": {
|
||||||
|
"title": "CredentialCreation",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"protocol.CredentialCreationResponse": {
|
||||||
|
"title": "CredentialCreationResponse",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"webauthn.Credential": {
|
||||||
|
"title": "Credential",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"xorm.Engine": {
|
"xorm.Engine": {
|
||||||
"title": "Engine",
|
"title": "Engine",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
@@ -1584,6 +1584,16 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.TokenError'
|
$ref: '#/definitions/object.TokenError'
|
||||||
/api/logout:
|
/api/logout:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Login API
|
||||||
|
description: logout the current user
|
||||||
|
operationId: ApiController.Logout
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- Login API
|
- Login API
|
||||||
@@ -2028,11 +2038,80 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Verification API
|
- Verification API
|
||||||
operationId: ApiController.VerifyCaptcha
|
operationId: ApiController.VerifyCaptcha
|
||||||
|
/api/webauthn/signin/begin:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Login API
|
||||||
|
description: WebAuthn Login Flow 1st stage
|
||||||
|
operationId: ApiController.WebAuthnSigninBegin
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: owner
|
||||||
|
description: owner
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: name
|
||||||
|
description: name
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The CredentialAssertion object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/protocol.CredentialAssertion'
|
||||||
|
/api/webauthn/signin/finish:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Login API
|
||||||
|
description: WebAuthn Login Flow 2nd stage
|
||||||
|
operationId: ApiController.WebAuthnSigninBegin
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: authenticator assertion Response
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/protocol.CredentialAssertionResponse'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '"The Response object"'
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Response'
|
||||||
|
/api/webauthn/signup/begin:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- User API
|
||||||
|
description: WebAuthn Registration Flow 1st stage
|
||||||
|
operationId: ApiController.WebAuthnSignupBegin
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The CredentialCreationOptions object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/protocol.CredentialCreation'
|
||||||
|
/api/webauthn/signup/finish:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- User API
|
||||||
|
description: WebAuthn Registration Flow 2nd stage
|
||||||
|
operationId: ApiController.WebAuthnSignupFinish
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: authenticator attestation Response
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/protocol.CredentialCreationResponse'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '"The Response object"'
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Response'
|
||||||
definitions:
|
definitions:
|
||||||
2127.0xc000398090.false:
|
2127.0xc000427560.false:
|
||||||
title: "false"
|
title: "false"
|
||||||
type: object
|
type: object
|
||||||
2161.0xc0003980c0.false:
|
2161.0xc000427590.false:
|
||||||
title: "false"
|
title: "false"
|
||||||
type: object
|
type: object
|
||||||
Response:
|
Response:
|
||||||
@@ -2113,9 +2192,9 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
$ref: '#/definitions/2127.0xc000398090.false'
|
$ref: '#/definitions/2127.0xc000427560.false'
|
||||||
data2:
|
data2:
|
||||||
$ref: '#/definitions/2161.0xc0003980c0.false'
|
$ref: '#/definitions/2161.0xc000427590.false'
|
||||||
msg:
|
msg:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
@@ -2185,10 +2264,14 @@ definitions:
|
|||||||
type: boolean
|
type: boolean
|
||||||
enablePassword:
|
enablePassword:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
enableSamlCompress:
|
||||||
|
type: boolean
|
||||||
enableSignUp:
|
enableSignUp:
|
||||||
type: boolean
|
type: boolean
|
||||||
enableSigninSession:
|
enableSigninSession:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
enableWebAuthn:
|
||||||
|
type: boolean
|
||||||
expireInHours:
|
expireInHours:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
@@ -2263,7 +2346,7 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
privateKey:
|
privateKey:
|
||||||
type: string
|
type: string
|
||||||
publicKey:
|
certificate:
|
||||||
type: string
|
type: string
|
||||||
scope:
|
scope:
|
||||||
type: string
|
type: string
|
||||||
@@ -2977,6 +3060,10 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
updatedTime:
|
updatedTime:
|
||||||
type: string
|
type: string
|
||||||
|
webauthnCredentials:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/webauthn.Credential'
|
||||||
wechat:
|
wechat:
|
||||||
type: string
|
type: string
|
||||||
wecom:
|
wecom:
|
||||||
@@ -3035,6 +3122,21 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
|
protocol.CredentialAssertion:
|
||||||
|
title: CredentialAssertion
|
||||||
|
type: object
|
||||||
|
protocol.CredentialAssertionResponse:
|
||||||
|
title: CredentialAssertionResponse
|
||||||
|
type: object
|
||||||
|
protocol.CredentialCreation:
|
||||||
|
title: CredentialCreation
|
||||||
|
type: object
|
||||||
|
protocol.CredentialCreationResponse:
|
||||||
|
title: CredentialCreationResponse
|
||||||
|
type: object
|
||||||
|
webauthn.Credential:
|
||||||
|
title: Credential
|
||||||
|
type: object
|
||||||
xorm.Engine:
|
xorm.Engine:
|
||||||
title: Engine
|
title: Engine
|
||||||
type: object
|
type: object
|
||||||
|
@@ -52,8 +52,10 @@ func ParseFloat(s string) float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ParseBool(s string) bool {
|
func ParseBool(s string) bool {
|
||||||
if s == "\x01" {
|
if s == "\x01" || s == "true" {
|
||||||
return true
|
return true
|
||||||
|
} else if s == "false" {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
i := ParseInt(s)
|
i := ParseInt(s)
|
||||||
|
@@ -45,6 +45,10 @@
|
|||||||
"curly": ["error", "all"],
|
"curly": ["error", "all"],
|
||||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
||||||
"no-mixed-spaces-and-tabs": "error",
|
"no-mixed-spaces-and-tabs": "error",
|
||||||
|
"sort-imports": ["error", {
|
||||||
|
"ignoreDeclarationSort": true
|
||||||
|
}],
|
||||||
|
|
||||||
|
|
||||||
"react/prop-types": "off",
|
"react/prop-types": "off",
|
||||||
"react/display-name": "off",
|
"react/display-name": "off",
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DownOutlined, DeleteOutlined, UpOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||||
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@@ -17,7 +17,7 @@ import "./App.less";
|
|||||||
import {Helmet} from "react-helmet";
|
import {Helmet} from "react-helmet";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import {DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
import {DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
||||||
import {Avatar, BackTop, Dropdown, Layout, Menu, Card, Result, Button} from "antd";
|
import {Avatar, BackTop, Button, Card, Dropdown, Layout, Menu, Result} from "antd";
|
||||||
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
||||||
import OrganizationListPage from "./OrganizationListPage";
|
import OrganizationListPage from "./OrganizationListPage";
|
||||||
import OrganizationEditPage from "./OrganizationEditPage";
|
import OrganizationEditPage from "./OrganizationEditPage";
|
||||||
@@ -669,7 +669,8 @@ class App extends Component {
|
|||||||
<Route exact path="/signup" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} />)} />
|
<Route exact path="/signup" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/signup/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />)} />
|
<Route exact path="/signup/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />)} />
|
||||||
<Route exact path="/login" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
|
<Route exact path="/login" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/signup/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signup"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
<Route exact path="/auto-signup/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signup"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
||||||
|
<Route exact path="/signup/oauth/authorize" render={(props) => <SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
||||||
<Route exact path="/login/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
<Route exact path="/login/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
||||||
<Route exact path="/login/saml/authorize/:owner/:applicationName" render={(props) => <LoginPage account={this.state.account} type={"saml"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
<Route exact path="/login/saml/authorize/:owner/:applicationName" render={(props) => <LoginPage account={this.state.account} type={"saml"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
||||||
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout clearAccount={() => this.setState({account: null})} {...props} />)} />
|
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout clearAccount={() => this.setState({account: null})} {...props} />)} />
|
||||||
|
@@ -30,6 +30,7 @@ class BaseListPage extends React.Component {
|
|||||||
loading: false,
|
loading: false,
|
||||||
searchText: "",
|
searchText: "",
|
||||||
searchedColumn: "",
|
searchedColumn: "",
|
||||||
|
isAuthorized: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -164,25 +164,25 @@ class CertEditPage extends React.Component {
|
|||||||
</Row>
|
</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("cert:Public key"), i18next.t("cert:Public key - Tooltip"))} :
|
{Setting.getLabel(i18next.t("cert:Certificate"), i18next.t("cert:Certificate - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={9} >
|
<Col span={9} >
|
||||||
<Button style={{marginRight: "10px", marginBottom: "10px"}} onClick={() => {
|
<Button style={{marginRight: "10px", marginBottom: "10px"}} onClick={() => {
|
||||||
copy(this.state.cert.publicKey);
|
copy(this.state.cert.certificate);
|
||||||
Setting.showMessage("success", i18next.t("cert:Public key copied to clipboard successfully"));
|
Setting.showMessage("success", i18next.t("cert:Certificate copied to clipboard successfully"));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18next.t("cert:Copy public key")}
|
{i18next.t("cert:Copy certificate")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="primary" onClick={() => {
|
<Button type="primary" onClick={() => {
|
||||||
const blob = new Blob([this.state.cert.publicKey], {type: "text/plain;charset=utf-8"});
|
const blob = new Blob([this.state.cert.certificate], {type: "text/plain;charset=utf-8"});
|
||||||
FileSaver.saveAs(blob, "token_jwt_key.pem");
|
FileSaver.saveAs(blob, "token_jwt_key.pem");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18next.t("cert:Download public key")}
|
{i18next.t("cert:Download certificate")}
|
||||||
</Button>
|
</Button>
|
||||||
<TextArea autoSize={{minRows: 30, maxRows: 30}} value={this.state.cert.publicKey} onChange={e => {
|
<TextArea autoSize={{minRows: 30, maxRows: 30}} value={this.state.cert.certificate} onChange={e => {
|
||||||
this.updateCertField("publicKey", e.target.value);
|
this.updateCertField("certificate", e.target.value);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={1} />
|
<Col span={1} />
|
||||||
|
@@ -34,7 +34,7 @@ class CertListPage extends BaseListPage {
|
|||||||
cryptoAlgorithm: "RS256",
|
cryptoAlgorithm: "RS256",
|
||||||
bitSize: 4096,
|
bitSize: 4096,
|
||||||
expireInYears: 20,
|
expireInYears: 20,
|
||||||
publicKey: "",
|
certificate: "",
|
||||||
privateKey: "",
|
privateKey: "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@ import React, {useState} from "react";
|
|||||||
import Cropper from "react-cropper";
|
import Cropper from "react-cropper";
|
||||||
import "cropperjs/dist/cropper.css";
|
import "cropperjs/dist/cropper.css";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import {Button, Row, Col, Modal} from "antd";
|
import {Button, Col, Modal, Row} from "antd";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import * as ResourceBackend from "./backend/ResourceBackend";
|
import * as ResourceBackend from "./backend/ResourceBackend";
|
||||||
|
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Col, Row, Table, Popconfirm} from "antd";
|
import {Button, Col, Popconfirm, Row, Table} from "antd";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import * as LdapBackend from "./backend/LdapBackend";
|
import * as LdapBackend from "./backend/LdapBackend";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@@ -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, Switch, Table} from "antd";
|
import {Button, Popconfirm, Result, 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";
|
||||||
@@ -235,6 +235,17 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!this.state.isAuthorized) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="403"
|
||||||
|
title="403 Unauthorized"
|
||||||
|
subTitle={i18next.t("general:Sorry, you do not have permission to access this page.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={organizations} rowKey="name" size="middle" bordered pagination={paginationProps}
|
||||||
@@ -272,6 +283,13 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import {Button, Col, Modal, Row, Input} from "antd";
|
import {Button, Col, Input, Modal, Row} from "antd";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import * as UserBackend from "./backend/UserBackend";
|
import * as UserBackend from "./backend/UserBackend";
|
||||||
|
@@ -21,6 +21,7 @@ import * as Setting from "./Setting";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import * as RoleBackend from "./backend/RoleBackend";
|
import * as RoleBackend from "./backend/RoleBackend";
|
||||||
import * as ModelBackend from "./backend/ModelBackend";
|
import * as ModelBackend from "./backend/ModelBackend";
|
||||||
|
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ class PermissionEditPage extends React.Component {
|
|||||||
users: [],
|
users: [],
|
||||||
roles: [],
|
roles: [],
|
||||||
models: [],
|
models: [],
|
||||||
|
resources: [],
|
||||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -55,6 +57,7 @@ class PermissionEditPage extends React.Component {
|
|||||||
this.getUsers(permission.owner);
|
this.getUsers(permission.owner);
|
||||||
this.getRoles(permission.owner);
|
this.getRoles(permission.owner);
|
||||||
this.getModels(permission.owner);
|
this.getModels(permission.owner);
|
||||||
|
this.getResources(permission.owner);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +97,15 @@ class PermissionEditPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getResources(organizationName) {
|
||||||
|
ApplicationBackend.getApplicationsByOrganization("admin", organizationName)
|
||||||
|
.then((res) => {
|
||||||
|
this.setState({
|
||||||
|
resources: (res.msg === undefined) ? res : [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
parsePermissionField(key, value) {
|
parsePermissionField(key, value) {
|
||||||
if ([""].includes(key)) {
|
if ([""].includes(key)) {
|
||||||
value = Setting.myParseInt(value);
|
value = Setting.myParseInt(value);
|
||||||
@@ -131,6 +143,8 @@ class PermissionEditPage extends React.Component {
|
|||||||
|
|
||||||
this.getUsers(owner);
|
this.getUsers(owner);
|
||||||
this.getRoles(owner);
|
this.getRoles(owner);
|
||||||
|
this.getModels(owner);
|
||||||
|
this.getResources(owner);
|
||||||
})}>
|
})}>
|
||||||
{
|
{
|
||||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||||
@@ -212,6 +226,18 @@ class PermissionEditPage extends React.Component {
|
|||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("permission:Resources"), i18next.t("permission:Resources - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Select virtual={false} mode="tags" style={{width: "100%"}} value={this.state.permission.resources} onChange={(value => {this.updatePermissionField("resources", value);})}>
|
||||||
|
{
|
||||||
|
this.state.resources.map((resource, index) => <Option key={index} value={`${resource.name}`}>{`${resource.name}`}</Option>)
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
</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("permission:Actions"), i18next.t("permission:Actions - Tooltip"))} :
|
{Setting.getLabel(i18next.t("permission:Actions"), i18next.t("permission:Actions - Tooltip"))} :
|
||||||
|
@@ -33,7 +33,7 @@ class PermissionListPage extends BaseListPage {
|
|||||||
roles: [],
|
roles: [],
|
||||||
resourceType: "Application",
|
resourceType: "Application",
|
||||||
resources: ["app-built-in"],
|
resources: ["app-built-in"],
|
||||||
action: "Read",
|
actions: ["Read"],
|
||||||
effect: "Allow",
|
effect: "Allow",
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
};
|
};
|
||||||
|
@@ -622,7 +622,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
</Row>
|
</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("provider:IdP"), i18next.t("provider:IdP public key"))} :
|
{Setting.getLabel(i18next.t("provider:IdP"), i18next.t("provider:IdP certificate"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.provider.idP} onChange={e => {
|
<Input value={this.state.provider.idP} onChange={e => {
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DownOutlined, DeleteOutlined, UpOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||||
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import {Button, Col, Modal, Row, Input} from "antd";
|
import {Button, Col, Input, Modal, Row} from "antd";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import {Menu, Dropdown} from "antd";
|
import {Dropdown, Menu} from "antd";
|
||||||
import {createFromIconfontCN} from "@ant-design/icons";
|
import {createFromIconfontCN} from "@ant-design/icons";
|
||||||
import "./App.less";
|
import "./App.less";
|
||||||
|
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import {message, Tag, Tooltip} from "antd";
|
import {Tag, Tooltip, message} from "antd";
|
||||||
import {QuestionCircleTwoTone} from "@ant-design/icons";
|
import {QuestionCircleTwoTone} from "@ant-design/icons";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {isMobile as isMobileDevice} from "react-device-detect";
|
import {isMobile as isMobileDevice} from "react-device-detect";
|
||||||
@@ -662,8 +662,8 @@ export function goToLogin(ths, application) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!application.enablePassword && window.location.pathname.includes("/signup/oauth/authorize")) {
|
if (!application.enablePassword && window.location.pathname.includes("/auto-signup/oauth/authorize")) {
|
||||||
const link = window.location.href.replace("/signup/oauth/authorize", "/login/oauth/authorize");
|
const link = window.location.href.replace("/auto-signup/oauth/authorize", "/login/oauth/authorize");
|
||||||
goToLink(link);
|
goToLink(link);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -685,7 +685,7 @@ export function goToSignup(ths, application) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!application.enablePassword && window.location.pathname.includes("/login/oauth/authorize")) {
|
if (!application.enablePassword && window.location.pathname.includes("/login/oauth/authorize")) {
|
||||||
const link = window.location.href.replace("/login/oauth/authorize", "/signup/oauth/authorize");
|
const link = window.location.href.replace("/login/oauth/authorize", "/auto-signup/oauth/authorize");
|
||||||
goToLink(link);
|
goToLink(link);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DownOutlined, DeleteOutlined, UpOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||||
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DownOutlined, DeleteOutlined, UpOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||||
import {Button, Col, Input, Row, Select, Switch, Table, Tooltip} from "antd";
|
import {Button, Col, Input, Row, Select, Switch, Table, Tooltip} from "antd";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DownOutlined, DeleteOutlined, UpOutlined, LinkOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, DownOutlined, LinkOutlined, UpOutlined} from "@ant-design/icons";
|
||||||
import {Button, Col, Input, Row, Table, Tooltip} from "antd";
|
import {Button, Col, Input, Row, Table, Tooltip} from "antd";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DownOutlined, DeleteOutlined, UpOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||||
import {Button, Col, Input, Row, Table, Tooltip} from "antd";
|
import {Button, Col, Input, Row, Table, Tooltip} from "antd";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@@ -62,7 +62,7 @@ class ForgetPage extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
Util.showMessage(
|
Util.showMessage(
|
||||||
"error",
|
"error",
|
||||||
i18next.t("forget:Unknown forgot type: ") + this.state.type
|
i18next.t("forget:Unknown forget type: ") + this.state.type
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -638,13 +638,13 @@ class LoginPage extends React.Component {
|
|||||||
throw credentialRequestOptions.status.msg;
|
throw credentialRequestOptions.status.msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
credentialRequestOptions.publicKey.challenge = UserWebauthnBackend.webAuthnBufferDecode(credentialRequestOptions.publicKey.challenge);
|
credentialRequestOptions.certificate.challenge = UserWebauthnBackend.webAuthnBufferDecode(credentialRequestOptions.certificate.challenge);
|
||||||
credentialRequestOptions.publicKey.allowCredentials.forEach(function(listItem) {
|
credentialRequestOptions.certificate.allowCredentials.forEach(function(listItem) {
|
||||||
listItem.id = UserWebauthnBackend.webAuthnBufferDecode(listItem.id);
|
listItem.id = UserWebauthnBackend.webAuthnBufferDecode(listItem.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
return navigator.credentials.get({
|
return navigator.credentials.get({
|
||||||
publicKey: credentialRequestOptions.publicKey
|
certificate: credentialRequestOptions.certificate
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((assertion) => {
|
.then((assertion) => {
|
||||||
@@ -692,7 +692,7 @@ class LoginPage extends React.Component {
|
|||||||
>
|
>
|
||||||
<CountDownInput
|
<CountDownInput
|
||||||
disabled={this.state.username?.length === 0 || !this.state.validEmailOrPhone}
|
disabled={this.state.username?.length === 0 || !this.state.validEmailOrPhone}
|
||||||
onButtonClickArgs={[this.state.username, "", Setting.getApplicationOrgName(application), true]}
|
onButtonClickArgs={[this.state.username, this.state.validEmail ? "email" : "phone", Setting.getApplicationName(application)]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
) : (
|
) : (
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Result, Button} from "antd";
|
import {Button, Result} from "antd";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import {authConfig} from "./Auth";
|
import {authConfig} from "./Auth";
|
||||||
import * as Util from "./Util";
|
import * as Util from "./Util";
|
||||||
|
@@ -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 {Form, Input, Checkbox, Button, Row, Col, Result, Modal} from "antd";
|
import {Button, Checkbox, Col, Form, Input, Modal, Result, Row} from "antd";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
import * as AuthBackend from "./AuthBackend";
|
import * as AuthBackend from "./AuthBackend";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
@@ -79,19 +79,28 @@ class SignupPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
UNSAFE_componentWillMount() {
|
||||||
if (this.state.applicationName !== undefined) {
|
let applicationName = this.state.applicationName;
|
||||||
this.getApplication();
|
const oAuthParams = Util.getOAuthGetParameters();
|
||||||
|
if (oAuthParams !== null) {
|
||||||
|
applicationName = oAuthParams.state;
|
||||||
|
this.setState({applicationName: oAuthParams.state});
|
||||||
|
const signinUrl = window.location.href.replace("/signup/oauth/authorize", "/login/oauth/authorize");
|
||||||
|
sessionStorage.setItem("signinUrl", signinUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applicationName !== undefined) {
|
||||||
|
this.getApplication(applicationName);
|
||||||
} else {
|
} else {
|
||||||
Util.showMessage("error", `Unknown application name: ${this.state.applicationName}`);
|
Util.showMessage("error", `Unknown application name: ${applicationName}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getApplication() {
|
getApplication(applicationName) {
|
||||||
if (this.state.applicationName === undefined) {
|
if (applicationName === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", applicationName)
|
||||||
.then((application) => {
|
.then((application) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: application,
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Alert, Button, message, Result} from "antd";
|
import {Alert, Button, Result, message} from "antd";
|
||||||
|
|
||||||
export function showMessage(type, text) {
|
export function showMessage(type, text) {
|
||||||
if (type === "success") {
|
if (type === "success") {
|
||||||
|
@@ -21,15 +21,15 @@ export function registerWebauthnCredential() {
|
|||||||
})
|
})
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then((credentialCreationOptions) => {
|
.then((credentialCreationOptions) => {
|
||||||
credentialCreationOptions.publicKey.challenge = webAuthnBufferDecode(credentialCreationOptions.publicKey.challenge);
|
credentialCreationOptions.certificate.challenge = webAuthnBufferDecode(credentialCreationOptions.certificate.challenge);
|
||||||
credentialCreationOptions.publicKey.user.id = webAuthnBufferDecode(credentialCreationOptions.publicKey.user.id);
|
credentialCreationOptions.certificate.user.id = webAuthnBufferDecode(credentialCreationOptions.certificate.user.id);
|
||||||
if (credentialCreationOptions.publicKey.excludeCredentials) {
|
if (credentialCreationOptions.certificate.excludeCredentials) {
|
||||||
for (var i = 0; i < credentialCreationOptions.publicKey.excludeCredentials.length; i++) {
|
for (var i = 0; i < credentialCreationOptions.certificate.excludeCredentials.length; i++) {
|
||||||
credentialCreationOptions.publicKey.excludeCredentials[i].id = webAuthnBufferDecode(credentialCreationOptions.publicKey.excludeCredentials[i].id);
|
credentialCreationOptions.certificate.excludeCredentials[i].id = webAuthnBufferDecode(credentialCreationOptions.certificate.excludeCredentials[i].id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return navigator.credentials.create({
|
return navigator.credentials.create({
|
||||||
publicKey: credentialCreationOptions.publicKey
|
certificate: credentialCreationOptions.certificate
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((credential) => {
|
.then((credential) => {
|
||||||
|
@@ -51,11 +51,11 @@
|
|||||||
"Bit size": "Bitgröße",
|
"Bit size": "Bitgröße",
|
||||||
"Bit size - Tooltip": "Bit Größe - Tooltip",
|
"Bit size - Tooltip": "Bit Größe - Tooltip",
|
||||||
"Copy private key": "Privaten Schlüssel kopieren",
|
"Copy private key": "Privaten Schlüssel kopieren",
|
||||||
"Copy public key": "Öffentlichen Schlüssel kopieren",
|
"Copy certificate": "Kopieren des Zertifikats",
|
||||||
"Crypto algorithm": "Crypto-Algorithmus",
|
"Crypto algorithm": "Crypto-Algorithmus",
|
||||||
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
||||||
"Download private key": "Privaten Schlüssel herunterladen",
|
"Download private key": "Privaten Schlüssel herunterladen",
|
||||||
"Download public key": "Öffentlichen Schlüssel herunterladen",
|
"Download certificate": "Zertifikat herunterladen",
|
||||||
"Edit Cert": "Zitat bearbeiten",
|
"Edit Cert": "Zitat bearbeiten",
|
||||||
"Expire in years": "Gültig in Jahren",
|
"Expire in years": "Gültig in Jahren",
|
||||||
"Expire in years - Tooltip": "Verfällt in Jahren - Tooltip",
|
"Expire in years - Tooltip": "Verfällt in Jahren - Tooltip",
|
||||||
@@ -63,9 +63,9 @@
|
|||||||
"Private key": "Privater Schlüssel",
|
"Private key": "Privater Schlüssel",
|
||||||
"Private key - Tooltip": "Privater Schlüssel - Tooltip",
|
"Private key - Tooltip": "Privater Schlüssel - Tooltip",
|
||||||
"Private key copied to clipboard successfully": "Privater Schlüssel erfolgreich in die Zwischenablage kopiert",
|
"Private key copied to clipboard successfully": "Privater Schlüssel erfolgreich in die Zwischenablage kopiert",
|
||||||
"Public key": "Öffentlicher Schlüssel",
|
"Certificate": "Zertifikat",
|
||||||
"Public key - Tooltip": "Öffentlicher Schlüssel - Tooltip",
|
"Certificate - Tooltip": "Zertifikat - Tooltip",
|
||||||
"Public key copied to clipboard successfully": "Öffentlicher Schlüssel erfolgreich in die Zwischenablage kopiert",
|
"Certificate copied to clipboard successfully": "Das Zertifikat wurde erfolgreich in die Zwischenablage kopiert",
|
||||||
"Scope": "Bereich",
|
"Scope": "Bereich",
|
||||||
"Scope - Tooltip": "Bereich - Tooltip",
|
"Scope - Tooltip": "Bereich - Tooltip",
|
||||||
"Type": "Typ",
|
"Type": "Typ",
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
"Please input your username!": "Bitte geben Sie Ihren Benutzernamen ein!",
|
"Please input your username!": "Bitte geben Sie Ihren Benutzernamen ein!",
|
||||||
"Reset": "Reset",
|
"Reset": "Reset",
|
||||||
"Retrieve password": "Passwort abrufen",
|
"Retrieve password": "Passwort abrufen",
|
||||||
|
"Unknown forget type": "Unknown forget type",
|
||||||
"Verify": "Überprüfen"
|
"Verify": "Überprüfen"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
@@ -187,6 +188,7 @@
|
|||||||
"Signup application - Tooltip": "Signup application - Tooltip",
|
"Signup application - Tooltip": "Signup application - Tooltip",
|
||||||
"Sorry, the page you visited does not exist.": "Die von Ihnen besuchte Seite existiert leider nicht.",
|
"Sorry, the page you visited does not exist.": "Die von Ihnen besuchte Seite existiert leider nicht.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
|
"Sorry, you do not have permission to access this page.": "Sorry, you do not have permission to access this page.",
|
||||||
"State": "State",
|
"State": "State",
|
||||||
"State - Tooltip": "State - Tooltip",
|
"State - Tooltip": "State - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
@@ -345,7 +347,8 @@
|
|||||||
"New Permission": "New Permission",
|
"New Permission": "New Permission",
|
||||||
"Resource type": "Ressourcentyp",
|
"Resource type": "Ressourcentyp",
|
||||||
"Resource type - Tooltip": "Ressourcentyp - Tooltip",
|
"Resource type - Tooltip": "Ressourcentyp - Tooltip",
|
||||||
"Resources": "Ressourcen"
|
"Resources": "Ressourcen",
|
||||||
|
"Resources - Tooltip": "Resources - Tooltip"
|
||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
@@ -423,7 +426,7 @@
|
|||||||
"Host": "Host",
|
"Host": "Host",
|
||||||
"Host - Tooltip": "Unique string-style identifier",
|
"Host - Tooltip": "Unique string-style identifier",
|
||||||
"IdP": "IdP",
|
"IdP": "IdP",
|
||||||
"IdP public key": "IdP-öffentlicher Schlüssel",
|
"IdP certificate": "IdP-öffentlicher Schlüssel",
|
||||||
"Issuer URL": "Ausgabe-URL",
|
"Issuer URL": "Ausgabe-URL",
|
||||||
"Issuer URL - Tooltip": "Ausgabe-URL - Tooltip",
|
"Issuer URL - Tooltip": "Ausgabe-URL - Tooltip",
|
||||||
"Link copied to clipboard successfully": "Link erfolgreich in die Zwischenablage kopiert",
|
"Link copied to clipboard successfully": "Link erfolgreich in die Zwischenablage kopiert",
|
||||||
@@ -663,4 +666,4 @@
|
|||||||
"URL - Tooltip": "URL - Tooltip",
|
"URL - Tooltip": "URL - Tooltip",
|
||||||
"Value": "Wert"
|
"Value": "Wert"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,11 +51,11 @@
|
|||||||
"Bit size": "Bit size",
|
"Bit size": "Bit size",
|
||||||
"Bit size - Tooltip": "Bit size - Tooltip",
|
"Bit size - Tooltip": "Bit size - Tooltip",
|
||||||
"Copy private key": "Copy private key",
|
"Copy private key": "Copy private key",
|
||||||
"Copy public key": "Copy public key",
|
"Copy certificate": "Copy certificate",
|
||||||
"Crypto algorithm": "Crypto algorithm",
|
"Crypto algorithm": "Crypto algorithm",
|
||||||
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
||||||
"Download private key": "Download private key",
|
"Download private key": "Download private key",
|
||||||
"Download public key": "Download public key",
|
"Download certificate": "Download certificate",
|
||||||
"Edit Cert": "Edit Cert",
|
"Edit Cert": "Edit Cert",
|
||||||
"Expire in years": "Expire in years",
|
"Expire in years": "Expire in years",
|
||||||
"Expire in years - Tooltip": "Expire in years - Tooltip",
|
"Expire in years - Tooltip": "Expire in years - Tooltip",
|
||||||
@@ -63,9 +63,9 @@
|
|||||||
"Private key": "Private key",
|
"Private key": "Private key",
|
||||||
"Private key - Tooltip": "Private key - Tooltip",
|
"Private key - Tooltip": "Private key - Tooltip",
|
||||||
"Private key copied to clipboard successfully": "Private key copied to clipboard successfully",
|
"Private key copied to clipboard successfully": "Private key copied to clipboard successfully",
|
||||||
"Public key": "Public key",
|
"Certificate": "Certificate",
|
||||||
"Public key - Tooltip": "Public key - Tooltip",
|
"Certificate - Tooltip": "Certificate - Tooltip",
|
||||||
"Public key copied to clipboard successfully": "Public key copied to clipboard successfully",
|
"Certificate copied to clipboard successfully": "Certificate copied to clipboard successfully",
|
||||||
"Scope": "Scope",
|
"Scope": "Scope",
|
||||||
"Scope - Tooltip": "Scope - Tooltip",
|
"Scope - Tooltip": "Scope - Tooltip",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
"Please input your username!": "Please input your username!",
|
"Please input your username!": "Please input your username!",
|
||||||
"Reset": "Reset",
|
"Reset": "Reset",
|
||||||
"Retrieve password": "Retrieve password",
|
"Retrieve password": "Retrieve password",
|
||||||
|
"Unknown forget type": "Unknown forget type",
|
||||||
"Verify": "Verify"
|
"Verify": "Verify"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
@@ -187,6 +188,7 @@
|
|||||||
"Signup application - Tooltip": "Signup application - Tooltip",
|
"Signup application - Tooltip": "Signup application - Tooltip",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
|
"Sorry, you do not have permission to access this page.": "Sorry, you do not have permission to access this page.",
|
||||||
"State": "State",
|
"State": "State",
|
||||||
"State - Tooltip": "State - Tooltip",
|
"State - Tooltip": "State - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
@@ -345,7 +347,8 @@
|
|||||||
"New Permission": "New Permission",
|
"New Permission": "New Permission",
|
||||||
"Resource type": "Resource type",
|
"Resource type": "Resource type",
|
||||||
"Resource type - Tooltip": "Resource type - Tooltip",
|
"Resource type - Tooltip": "Resource type - Tooltip",
|
||||||
"Resources": "Resources"
|
"Resources": "Resources",
|
||||||
|
"Resources - Tooltip": "Resources - Tooltip"
|
||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
@@ -423,7 +426,7 @@
|
|||||||
"Host": "Host",
|
"Host": "Host",
|
||||||
"Host - Tooltip": "Host - Tooltip",
|
"Host - Tooltip": "Host - Tooltip",
|
||||||
"IdP": "IdP",
|
"IdP": "IdP",
|
||||||
"IdP public key": "IdP public key",
|
"IdP certificate": "IdP certificate",
|
||||||
"Issuer URL": "Issuer URL",
|
"Issuer URL": "Issuer URL",
|
||||||
"Issuer URL - Tooltip": "Issuer URL - Tooltip",
|
"Issuer URL - Tooltip": "Issuer URL - Tooltip",
|
||||||
"Link copied to clipboard successfully": "Link copied to clipboard successfully",
|
"Link copied to clipboard successfully": "Link copied to clipboard successfully",
|
||||||
@@ -663,4 +666,4 @@
|
|||||||
"URL - Tooltip": "URL - Tooltip",
|
"URL - Tooltip": "URL - Tooltip",
|
||||||
"Value": "Value"
|
"Value": "Value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,21 +51,21 @@
|
|||||||
"Bit size": "Taille du bit",
|
"Bit size": "Taille du bit",
|
||||||
"Bit size - Tooltip": "Taille du bit - Infobulle",
|
"Bit size - Tooltip": "Taille du bit - Infobulle",
|
||||||
"Copy private key": "Copier la clé privée",
|
"Copy private key": "Copier la clé privée",
|
||||||
"Copy public key": "Copier la clé publique",
|
"Copy certificate": "Copier le certificate",
|
||||||
"Crypto algorithm": "Algorithme de cryptomonnaie",
|
"Crypto algorithm": "Algorithme de cryptomonnaie",
|
||||||
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
||||||
"Download private key": "Télécharger la clé privée",
|
"Download private key": "Télécharger la clé privée",
|
||||||
"Download public key": "Télécharger la clé publique",
|
"Download certificate": "Télécharger le certificate",
|
||||||
"Edit Cert": "Modifier le certificat",
|
"Edit Cert": "Modifier le certificate",
|
||||||
"Expire in years": "Expire dans les années",
|
"Expire in years": "Expire dans les années",
|
||||||
"Expire in years - Tooltip": "Expire dans les années - infobulle",
|
"Expire in years - Tooltip": "Expire dans les années - infobulle",
|
||||||
"New Cert": "New Cert",
|
"New Cert": "New Cert",
|
||||||
"Private key": "Clé privée",
|
"Private key": "Clé privée",
|
||||||
"Private key - Tooltip": "Clé privée - Infobulle",
|
"Private key - Tooltip": "Clé privée - Infobulle",
|
||||||
"Private key copied to clipboard successfully": "Clé privée copiée dans le presse-papiers avec succès",
|
"Private key copied to clipboard successfully": "Clé privée copiée dans le presse-papiers avec succès",
|
||||||
"Public key": "Clé publique",
|
"Certificate": "certificate",
|
||||||
"Public key - Tooltip": "Clé publique - Infobulle",
|
"Certificate - Tooltip": "certificate - Infobulle",
|
||||||
"Public key copied to clipboard successfully": "Clé publique copiée dans le presse-papiers avec succès",
|
"Certificate copied to clipboard successfully": "Le certificate a été copié avec succès dans le presse-papiers",
|
||||||
"Scope": "Périmètre d'application",
|
"Scope": "Périmètre d'application",
|
||||||
"Scope - Tooltip": "Scope - Infobulle",
|
"Scope - Tooltip": "Scope - Infobulle",
|
||||||
"Type": "Type de texte",
|
"Type": "Type de texte",
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
"Please input your username!": "Veuillez entrer votre nom d'utilisateur !",
|
"Please input your username!": "Veuillez entrer votre nom d'utilisateur !",
|
||||||
"Reset": "Reset",
|
"Reset": "Reset",
|
||||||
"Retrieve password": "Récupérer le mot de passe",
|
"Retrieve password": "Récupérer le mot de passe",
|
||||||
|
"Unknown forget type": "Unknown forget type",
|
||||||
"Verify": "Vérifier"
|
"Verify": "Vérifier"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
@@ -187,6 +188,7 @@
|
|||||||
"Signup application - Tooltip": "Signup application - Tooltip",
|
"Signup application - Tooltip": "Signup application - Tooltip",
|
||||||
"Sorry, the page you visited does not exist.": "Désolé, la page que vous avez visitée n'existe pas.",
|
"Sorry, the page you visited does not exist.": "Désolé, la page que vous avez visitée n'existe pas.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
|
"Sorry, you do not have permission to access this page.": "Désolé, vous n'avez pas la permission d'accéder à cette page.",
|
||||||
"State": "State",
|
"State": "State",
|
||||||
"State - Tooltip": "State - Tooltip",
|
"State - Tooltip": "State - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
@@ -345,7 +347,8 @@
|
|||||||
"New Permission": "New Permission",
|
"New Permission": "New Permission",
|
||||||
"Resource type": "Type de ressource",
|
"Resource type": "Type de ressource",
|
||||||
"Resource type - Tooltip": "Type de ressource - infobulle",
|
"Resource type - Tooltip": "Type de ressource - infobulle",
|
||||||
"Resources": "Ressource"
|
"Resources": "Ressource",
|
||||||
|
"Resources - Tooltip": "Resources - Tooltip"
|
||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
@@ -423,7 +426,7 @@
|
|||||||
"Host": "Hôte",
|
"Host": "Hôte",
|
||||||
"Host - Tooltip": "Unique string-style identifier",
|
"Host - Tooltip": "Unique string-style identifier",
|
||||||
"IdP": "IDP",
|
"IdP": "IDP",
|
||||||
"IdP public key": "Clé publique IdP",
|
"IdP certificate": "Clé publique IdP",
|
||||||
"Issuer URL": "URL de l'émetteur",
|
"Issuer URL": "URL de l'émetteur",
|
||||||
"Issuer URL - Tooltip": "URL de l'émetteur - infobulle",
|
"Issuer URL - Tooltip": "URL de l'émetteur - infobulle",
|
||||||
"Link copied to clipboard successfully": "Lien copié dans le presse-papiers avec succès",
|
"Link copied to clipboard successfully": "Lien copié dans le presse-papiers avec succès",
|
||||||
@@ -663,4 +666,4 @@
|
|||||||
"URL - Tooltip": "URL - Info-bulle",
|
"URL - Tooltip": "URL - Info-bulle",
|
||||||
"Value": "Valeur"
|
"Value": "Valeur"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,11 +51,11 @@
|
|||||||
"Bit size": "ビットサイズ",
|
"Bit size": "ビットサイズ",
|
||||||
"Bit size - Tooltip": "ビットサイズ - ツールチップ",
|
"Bit size - Tooltip": "ビットサイズ - ツールチップ",
|
||||||
"Copy private key": "秘密鍵をコピー",
|
"Copy private key": "秘密鍵をコピー",
|
||||||
"Copy public key": "公開鍵をコピー",
|
"Copy certificate": "証明書をコピーします",
|
||||||
"Crypto algorithm": "暗号化アルゴリズム",
|
"Crypto algorithm": "暗号化アルゴリズム",
|
||||||
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
||||||
"Download private key": "秘密鍵をダウンロード",
|
"Download private key": "秘密鍵をダウンロード",
|
||||||
"Download public key": "公開鍵をダウンロード",
|
"Download certificate": "証明書をダウンロードします",
|
||||||
"Edit Cert": "Certを編集",
|
"Edit Cert": "Certを編集",
|
||||||
"Expire in years": "有効期限",
|
"Expire in years": "有効期限",
|
||||||
"Expire in years - Tooltip": "年間有効期限 - ツールチップ",
|
"Expire in years - Tooltip": "年間有効期限 - ツールチップ",
|
||||||
@@ -63,9 +63,9 @@
|
|||||||
"Private key": "Private key",
|
"Private key": "Private key",
|
||||||
"Private key - Tooltip": "Private key - Tooltip",
|
"Private key - Tooltip": "Private key - Tooltip",
|
||||||
"Private key copied to clipboard successfully": "秘密鍵を正常にクリップボードにコピーしました",
|
"Private key copied to clipboard successfully": "秘密鍵を正常にクリップボードにコピーしました",
|
||||||
"Public key": "公開キー",
|
"Certificate": "Certificate",
|
||||||
"Public key - Tooltip": "Public key - Tooltip",
|
"Certificate - Tooltip": "Certificate - Tooltip",
|
||||||
"Public key copied to clipboard successfully": "公開鍵を正常にクリップボードにコピーしました",
|
"Certificate copied to clipboard successfully": "証明書はクリップボードに正常にコピーされました",
|
||||||
"Scope": "スコープ",
|
"Scope": "スコープ",
|
||||||
"Scope - Tooltip": "スコープ → ツールチップ",
|
"Scope - Tooltip": "スコープ → ツールチップ",
|
||||||
"Type": "タイプ",
|
"Type": "タイプ",
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
"Please input your username!": "ユーザー名を入力してください!",
|
"Please input your username!": "ユーザー名を入力してください!",
|
||||||
"Reset": "Reset",
|
"Reset": "Reset",
|
||||||
"Retrieve password": "パスワードの取得",
|
"Retrieve password": "パスワードの取得",
|
||||||
|
"Unknown forget type": "Unknown forget type",
|
||||||
"Verify": "確認する"
|
"Verify": "確認する"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
@@ -187,6 +188,7 @@
|
|||||||
"Signup application - Tooltip": "Signup application - Tooltip",
|
"Signup application - Tooltip": "Signup application - Tooltip",
|
||||||
"Sorry, the page you visited does not exist.": "申し訳ありませんが、訪問したページは存在しません。",
|
"Sorry, the page you visited does not exist.": "申し訳ありませんが、訪問したページは存在しません。",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
|
"Sorry, you do not have permission to access this page.": "申し訳ありませんが、このページにアクセスする権限がありません。",
|
||||||
"State": "State",
|
"State": "State",
|
||||||
"State - Tooltip": "State - Tooltip",
|
"State - Tooltip": "State - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
@@ -345,7 +347,8 @@
|
|||||||
"New Permission": "New Permission",
|
"New Permission": "New Permission",
|
||||||
"Resource type": "リソースタイプ",
|
"Resource type": "リソースタイプ",
|
||||||
"Resource type - Tooltip": "リソースタイプ - ツールチップ",
|
"Resource type - Tooltip": "リソースタイプ - ツールチップ",
|
||||||
"Resources": "リソース"
|
"Resources": "リソース",
|
||||||
|
"Resources - Tooltip": "Resources - Tooltip"
|
||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
@@ -423,7 +426,7 @@
|
|||||||
"Host": "ホスト",
|
"Host": "ホスト",
|
||||||
"Host - Tooltip": "Unique string-style identifier",
|
"Host - Tooltip": "Unique string-style identifier",
|
||||||
"IdP": "IdP",
|
"IdP": "IdP",
|
||||||
"IdP public key": "IdP public key",
|
"IdP certificate": "IdP certificate",
|
||||||
"Issuer URL": "Issuer URL",
|
"Issuer URL": "Issuer URL",
|
||||||
"Issuer URL - Tooltip": "Issuer URL - ツールチップ",
|
"Issuer URL - Tooltip": "Issuer URL - ツールチップ",
|
||||||
"Link copied to clipboard successfully": "リンクをクリップボードにコピーしました",
|
"Link copied to clipboard successfully": "リンクをクリップボードにコピーしました",
|
||||||
@@ -663,4 +666,4 @@
|
|||||||
"URL - Tooltip": "URL → ツールチップ",
|
"URL - Tooltip": "URL → ツールチップ",
|
||||||
"Value": "値"
|
"Value": "値"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,11 +51,11 @@
|
|||||||
"Bit size": "Bit size",
|
"Bit size": "Bit size",
|
||||||
"Bit size - Tooltip": "Bit size - Tooltip",
|
"Bit size - Tooltip": "Bit size - Tooltip",
|
||||||
"Copy private key": "Copy private key",
|
"Copy private key": "Copy private key",
|
||||||
"Copy public key": "Copy public key",
|
"Copy certificate": "Copy certificate",
|
||||||
"Crypto algorithm": "Crypto algorithm",
|
"Crypto algorithm": "Crypto algorithm",
|
||||||
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
||||||
"Download private key": "Download private key",
|
"Download private key": "Download private key",
|
||||||
"Download public key": "Download public key",
|
"Download certificate": "Download certificate",
|
||||||
"Edit Cert": "Edit Cert",
|
"Edit Cert": "Edit Cert",
|
||||||
"Expire in years": "Expire in years",
|
"Expire in years": "Expire in years",
|
||||||
"Expire in years - Tooltip": "Expire in years - Tooltip",
|
"Expire in years - Tooltip": "Expire in years - Tooltip",
|
||||||
@@ -63,9 +63,9 @@
|
|||||||
"Private key": "Private key",
|
"Private key": "Private key",
|
||||||
"Private key - Tooltip": "Private key - Tooltip",
|
"Private key - Tooltip": "Private key - Tooltip",
|
||||||
"Private key copied to clipboard successfully": "Private key copied to clipboard successfully",
|
"Private key copied to clipboard successfully": "Private key copied to clipboard successfully",
|
||||||
"Public key": "Public key",
|
"Certificate": "Certificate",
|
||||||
"Public key - Tooltip": "Public key - Tooltip",
|
"Certificate - Tooltip": "Certificate - Tooltip",
|
||||||
"Public key copied to clipboard successfully": "Public key copied to clipboard successfully",
|
"Certificate copied to clipboard successfully": "Certificate copied to clipboard successfully",
|
||||||
"Scope": "Scope",
|
"Scope": "Scope",
|
||||||
"Scope - Tooltip": "Scope - Tooltip",
|
"Scope - Tooltip": "Scope - Tooltip",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
"Please input your username!": "Please input your username!",
|
"Please input your username!": "Please input your username!",
|
||||||
"Reset": "Reset",
|
"Reset": "Reset",
|
||||||
"Retrieve password": "Retrieve password",
|
"Retrieve password": "Retrieve password",
|
||||||
|
"Unknown forget type": "Unknown forget type",
|
||||||
"Verify": "Verify"
|
"Verify": "Verify"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
@@ -187,6 +188,7 @@
|
|||||||
"Signup application - Tooltip": "Signup application - Tooltip",
|
"Signup application - Tooltip": "Signup application - Tooltip",
|
||||||
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
|
"Sorry, you do not have permission to access this page.": "Sorry, you do not have permission to access this page.",
|
||||||
"State": "State",
|
"State": "State",
|
||||||
"State - Tooltip": "State - Tooltip",
|
"State - Tooltip": "State - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
@@ -345,7 +347,8 @@
|
|||||||
"New Permission": "New Permission",
|
"New Permission": "New Permission",
|
||||||
"Resource type": "Resource type",
|
"Resource type": "Resource type",
|
||||||
"Resource type - Tooltip": "Resource type - Tooltip",
|
"Resource type - Tooltip": "Resource type - Tooltip",
|
||||||
"Resources": "Resources"
|
"Resources": "Resources",
|
||||||
|
"Resources - Tooltip": "Resources - Tooltip"
|
||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
@@ -423,7 +426,7 @@
|
|||||||
"Host": "Host",
|
"Host": "Host",
|
||||||
"Host - Tooltip": "Unique string-style identifier",
|
"Host - Tooltip": "Unique string-style identifier",
|
||||||
"IdP": "IdP",
|
"IdP": "IdP",
|
||||||
"IdP public key": "IdP public key",
|
"IdP certificate": "IdP certificate",
|
||||||
"Issuer URL": "Issuer URL",
|
"Issuer URL": "Issuer URL",
|
||||||
"Issuer URL - Tooltip": "Issuer URL - Tooltip",
|
"Issuer URL - Tooltip": "Issuer URL - Tooltip",
|
||||||
"Link copied to clipboard successfully": "Link copied to clipboard successfully",
|
"Link copied to clipboard successfully": "Link copied to clipboard successfully",
|
||||||
@@ -663,4 +666,4 @@
|
|||||||
"URL - Tooltip": "URL - Tooltip",
|
"URL - Tooltip": "URL - Tooltip",
|
||||||
"Value": "Value"
|
"Value": "Value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,11 +51,11 @@
|
|||||||
"Bit size": "Размер бита",
|
"Bit size": "Размер бита",
|
||||||
"Bit size - Tooltip": "Размер бита - Подсказка",
|
"Bit size - Tooltip": "Размер бита - Подсказка",
|
||||||
"Copy private key": "Копировать закрытый ключ",
|
"Copy private key": "Копировать закрытый ключ",
|
||||||
"Copy public key": "Копировать открытый ключ",
|
"Copy certificate": "Копирование сертификата",
|
||||||
"Crypto algorithm": "Алгоритм крипто",
|
"Crypto algorithm": "Алгоритм крипто",
|
||||||
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
||||||
"Download private key": "Скачать закрытый ключ",
|
"Download private key": "Скачать закрытый ключ",
|
||||||
"Download public key": "Скачать открытый ключ",
|
"Download certificate": "Скачать сертификат",
|
||||||
"Edit Cert": "Изменить сертификат",
|
"Edit Cert": "Изменить сертификат",
|
||||||
"Expire in years": "Истекает через годы",
|
"Expire in years": "Истекает через годы",
|
||||||
"Expire in years - Tooltip": "Истекает через годы - Подсказка",
|
"Expire in years - Tooltip": "Истекает через годы - Подсказка",
|
||||||
@@ -63,9 +63,9 @@
|
|||||||
"Private key": "Приватный ключ",
|
"Private key": "Приватный ключ",
|
||||||
"Private key - Tooltip": "Приватный ключ - Подсказка",
|
"Private key - Tooltip": "Приватный ключ - Подсказка",
|
||||||
"Private key copied to clipboard successfully": "Приватный ключ скопирован в буфер обмена",
|
"Private key copied to clipboard successfully": "Приватный ключ скопирован в буфер обмена",
|
||||||
"Public key": "Публичный ключ",
|
"Certificate": "сертификат",
|
||||||
"Public key - Tooltip": "Открытый ключ - Подсказка",
|
"Certificate - Tooltip": "сертификат - Подсказка",
|
||||||
"Public key copied to clipboard successfully": "Открытый ключ успешно скопирован в буфер обмена",
|
"Certificate copied to clipboard successfully": "Сертификат успешно скопирован в буфер обмена",
|
||||||
"Scope": "Сфера охвата",
|
"Scope": "Сфера охвата",
|
||||||
"Scope - Tooltip": "Область применения - Подсказка",
|
"Scope - Tooltip": "Область применения - Подсказка",
|
||||||
"Type": "Тип",
|
"Type": "Тип",
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
"Please input your username!": "Пожалуйста, введите ваше имя пользователя!",
|
"Please input your username!": "Пожалуйста, введите ваше имя пользователя!",
|
||||||
"Reset": "Reset",
|
"Reset": "Reset",
|
||||||
"Retrieve password": "Получить пароль",
|
"Retrieve password": "Получить пароль",
|
||||||
|
"Unknown forget type": "Unknown forget type",
|
||||||
"Verify": "Подтвердить"
|
"Verify": "Подтвердить"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
@@ -187,6 +188,7 @@
|
|||||||
"Signup application - Tooltip": "Signup application - Tooltip",
|
"Signup application - Tooltip": "Signup application - Tooltip",
|
||||||
"Sorry, the page you visited does not exist.": "Извините, посещенная вами страница не существует.",
|
"Sorry, the page you visited does not exist.": "Извините, посещенная вами страница не существует.",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
|
"Sorry, you do not have permission to access this page.": "Извините, вы не имеете права доступа к этой странице.",
|
||||||
"State": "State",
|
"State": "State",
|
||||||
"State - Tooltip": "State - Tooltip",
|
"State - Tooltip": "State - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
@@ -345,7 +347,8 @@
|
|||||||
"New Permission": "New Permission",
|
"New Permission": "New Permission",
|
||||||
"Resource type": "Тип ресурса",
|
"Resource type": "Тип ресурса",
|
||||||
"Resource type - Tooltip": "Тип ресурса - Подсказка",
|
"Resource type - Tooltip": "Тип ресурса - Подсказка",
|
||||||
"Resources": "Ресурсы"
|
"Resources": "Ресурсы",
|
||||||
|
"Resources - Tooltip": "Resources - Tooltip"
|
||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
@@ -423,7 +426,7 @@
|
|||||||
"Host": "Хост",
|
"Host": "Хост",
|
||||||
"Host - Tooltip": "Unique string-style identifier",
|
"Host - Tooltip": "Unique string-style identifier",
|
||||||
"IdP": "ИдП",
|
"IdP": "ИдП",
|
||||||
"IdP public key": "Публичный ключ IdP",
|
"IdP certificate": "Публичный ключ IdP",
|
||||||
"Issuer URL": "URL эмитента",
|
"Issuer URL": "URL эмитента",
|
||||||
"Issuer URL - Tooltip": "URL эмитента - Tooltip",
|
"Issuer URL - Tooltip": "URL эмитента - Tooltip",
|
||||||
"Link copied to clipboard successfully": "Ссылка скопирована в буфер обмена",
|
"Link copied to clipboard successfully": "Ссылка скопирована в буфер обмена",
|
||||||
@@ -663,4 +666,4 @@
|
|||||||
"URL - Tooltip": "URL - Подсказка",
|
"URL - Tooltip": "URL - Подсказка",
|
||||||
"Value": "Значение"
|
"Value": "Значение"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,11 +51,11 @@
|
|||||||
"Bit size": "位大小",
|
"Bit size": "位大小",
|
||||||
"Bit size - Tooltip": "位大小 - 工具提示",
|
"Bit size - Tooltip": "位大小 - 工具提示",
|
||||||
"Copy private key": "复制私钥",
|
"Copy private key": "复制私钥",
|
||||||
"Copy public key": "复制公钥",
|
"Copy certificate": "复制证书",
|
||||||
"Crypto algorithm": "加密算法",
|
"Crypto algorithm": "加密算法",
|
||||||
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
||||||
"Download private key": "下载私钥",
|
"Download private key": "下载私钥",
|
||||||
"Download public key": "下载公钥",
|
"Download certificate": "下载证书",
|
||||||
"Edit Cert": "编辑证书",
|
"Edit Cert": "编辑证书",
|
||||||
"Expire in years": "有效期(年)",
|
"Expire in years": "有效期(年)",
|
||||||
"Expire in years - Tooltip": "到期年份-工具提示",
|
"Expire in years - Tooltip": "到期年份-工具提示",
|
||||||
@@ -63,9 +63,9 @@
|
|||||||
"Private key": "私钥",
|
"Private key": "私钥",
|
||||||
"Private key - Tooltip": "私钥 - 工具提示",
|
"Private key - Tooltip": "私钥 - 工具提示",
|
||||||
"Private key copied to clipboard successfully": "私钥已成功复制到剪贴板",
|
"Private key copied to clipboard successfully": "私钥已成功复制到剪贴板",
|
||||||
"Public key": "公钥",
|
"Certificate": "证书",
|
||||||
"Public key - Tooltip": "公钥 - 工具提示",
|
"Certificate - Tooltip": "证书 - 工具提示",
|
||||||
"Public key copied to clipboard successfully": "公钥已成功复制到剪贴板",
|
"Certificate copied to clipboard successfully": "证书已成功复制到剪贴板",
|
||||||
"Scope": "用途",
|
"Scope": "用途",
|
||||||
"Scope - Tooltip": "范围 - 工具提示",
|
"Scope - Tooltip": "范围 - 工具提示",
|
||||||
"Type": "类型",
|
"Type": "类型",
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
"Please input your username!": "请输入您的用户名!",
|
"Please input your username!": "请输入您的用户名!",
|
||||||
"Reset": "重置",
|
"Reset": "重置",
|
||||||
"Retrieve password": "找回密码",
|
"Retrieve password": "找回密码",
|
||||||
|
"Unknown forget type": "未知的忘记密码类型",
|
||||||
"Verify": "验证"
|
"Verify": "验证"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
@@ -187,6 +188,7 @@
|
|||||||
"Signup application - Tooltip": "表示用户注册时通过哪个应用注册的",
|
"Signup application - Tooltip": "表示用户注册时通过哪个应用注册的",
|
||||||
"Sorry, the page you visited does not exist.": "抱歉,您访问的页面不存在",
|
"Sorry, the page you visited does not exist.": "抱歉,您访问的页面不存在",
|
||||||
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "抱歉,您访问的用户不存在或您无权访问该用户",
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "抱歉,您访问的用户不存在或您无权访问该用户",
|
||||||
|
"Sorry, you do not have permission to access this page.": "抱歉,您无权访问该页面",
|
||||||
"State": "状态",
|
"State": "状态",
|
||||||
"State - Tooltip": "状态",
|
"State - Tooltip": "状态",
|
||||||
"Swagger": "API文档",
|
"Swagger": "API文档",
|
||||||
@@ -345,7 +347,8 @@
|
|||||||
"New Permission": "添加权限",
|
"New Permission": "添加权限",
|
||||||
"Resource type": "资源类型",
|
"Resource type": "资源类型",
|
||||||
"Resource type - Tooltip": "授权资源的类型",
|
"Resource type - Tooltip": "授权资源的类型",
|
||||||
"Resources": "资源"
|
"Resources": "资源",
|
||||||
|
"Resources - Tooltip": "被授权的资源"
|
||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "支付宝",
|
"Alipay": "支付宝",
|
||||||
@@ -423,7 +426,7 @@
|
|||||||
"Host": "主机",
|
"Host": "主机",
|
||||||
"Host - Tooltip": "主机",
|
"Host - Tooltip": "主机",
|
||||||
"IdP": "IdP",
|
"IdP": "IdP",
|
||||||
"IdP public key": "IdP 公钥",
|
"IdP certificate": "IdP 公钥",
|
||||||
"Issuer URL": "发行者网址",
|
"Issuer URL": "发行者网址",
|
||||||
"Issuer URL - Tooltip": "发行者URL - 工具提示",
|
"Issuer URL - Tooltip": "发行者URL - 工具提示",
|
||||||
"Link copied to clipboard successfully": "链接已成功复制到剪贴板",
|
"Link copied to clipboard successfully": "链接已成功复制到剪贴板",
|
||||||
@@ -663,4 +666,4 @@
|
|||||||
"URL - Tooltip": "URL",
|
"URL - Tooltip": "URL",
|
||||||
"Value": "值"
|
"Value": "值"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user