mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-04 20:10:35 +08:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0639564d27 | ||
![]() |
6c647818ca | ||
![]() |
8bc73d17aa | ||
![]() |
1f37c80177 | ||
![]() |
7924fca403 | ||
![]() |
bd06996bab | ||
![]() |
19ab168b12 | ||
![]() |
854a74b73e | ||
![]() |
beefb0b432 | ||
![]() |
d8969e6652 | ||
![]() |
666ff48837 | ||
![]() |
0a0c1b4788 | ||
![]() |
438c999e11 | ||
![]() |
a193ceb33d | ||
![]() |
caec1d1bac | ||
![]() |
0d48da24dc | ||
![]() |
de9eeaa1ef | ||
![]() |
ae6e35ee73 | ||
![]() |
a58df645bf |
2
ai/ai.go
2
ai/ai.go
@@ -129,7 +129,7 @@ func QueryAnswerStream(authToken string, question string, writer io.Writer, buil
|
|||||||
fmt.Printf("%s", data)
|
fmt.Printf("%s", data)
|
||||||
|
|
||||||
// Write the streamed data as Server-Sent Events
|
// Write the streamed data as Server-Sent Events
|
||||||
if _, err = fmt.Fprintf(writer, "data: %s\n\n", data); err != nil {
|
if _, err = fmt.Fprintf(writer, "event: message\ndata: %s\n\n", data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flusher.Flush()
|
flusher.Flush()
|
||||||
|
@@ -368,9 +368,11 @@ func (c *ApiController) GetAccount() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Permissions = object.GetMaskedPermissions(user.Permissions)
|
if user != nil {
|
||||||
user.Roles = object.GetMaskedRoles(user.Roles)
|
user.Permissions = object.GetMaskedPermissions(user.Permissions)
|
||||||
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
user.Roles = object.GetMaskedRoles(user.Roles)
|
||||||
|
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
||||||
|
}
|
||||||
|
|
||||||
organization, err := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
|
organization, err := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -123,6 +123,11 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp = &Response{Status: "ok", Msg: "", Data: res, Data2: map[string]string{"redirectUrl": redirectUrl, "method": method}}
|
resp = &Response{Status: "ok", Msg: "", Data: res, Data2: map[string]string{"redirectUrl": redirectUrl, "method": method}}
|
||||||
|
|
||||||
|
if application.EnableSigninSession || application.HasPromptPage() {
|
||||||
|
// The prompt page needs the user to be signed in
|
||||||
|
c.SetSessionUsername(userId)
|
||||||
|
}
|
||||||
} else if form.Type == ResponseTypeCas {
|
} else if form.Type == ResponseTypeCas {
|
||||||
// not oauth but CAS SSO protocol
|
// not oauth but CAS SSO protocol
|
||||||
service := c.Input().Get("service")
|
service := c.Input().Get("service")
|
||||||
@@ -135,11 +140,11 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
resp.Data = st
|
resp.Data = st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.EnableSigninSession || application.HasPromptPage() {
|
if application.EnableSigninSession || application.HasPromptPage() {
|
||||||
// The prompt page needs the user to be signed in
|
// The prompt page needs the user to be signed in
|
||||||
c.SetSessionUsername(userId)
|
c.SetSessionUsername(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type))
|
resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type))
|
||||||
}
|
}
|
||||||
|
@@ -100,7 +100,7 @@ func (c *ApiController) GetLdapUsers() {
|
|||||||
func (c *ApiController) GetLdaps() {
|
func (c *ApiController) GetLdaps() {
|
||||||
owner := c.Input().Get("owner")
|
owner := c.Input().Get("owner")
|
||||||
|
|
||||||
c.ResponseOk(object.GetLdaps(owner))
|
c.ResponseOk(object.GetMaskedLdaps(object.GetLdaps(owner)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLdap
|
// GetLdap
|
||||||
@@ -116,7 +116,7 @@ func (c *ApiController) GetLdap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, name := util.GetOwnerAndNameFromId(id)
|
_, name := util.GetOwnerAndNameFromId(id)
|
||||||
c.ResponseOk(object.GetLdap(name))
|
c.ResponseOk(object.GetMaskedLdap(object.GetLdap(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddLdap
|
// AddLdap
|
||||||
@@ -226,8 +226,9 @@ func (c *ApiController) DeleteLdap() {
|
|||||||
// @Title SyncLdapUsers
|
// @Title SyncLdapUsers
|
||||||
// @router /sync-ldap-users [post]
|
// @router /sync-ldap-users [post]
|
||||||
func (c *ApiController) SyncLdapUsers() {
|
func (c *ApiController) SyncLdapUsers() {
|
||||||
owner := c.Input().Get("owner")
|
id := c.Input().Get("id")
|
||||||
ldapId := c.Input().Get("ldapId")
|
|
||||||
|
owner, ldapId := util.GetOwnerAndNameFromId(id)
|
||||||
var users []object.LdapUser
|
var users []object.LdapUser
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -198,7 +198,10 @@ func (c *ApiController) GetUser() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
if user != nil {
|
||||||
|
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
||||||
|
}
|
||||||
|
|
||||||
err = object.ExtendUserWithRolesAndPermissions(user)
|
err = object.ExtendUserWithRolesAndPermissions(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
|
@@ -25,6 +25,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestDeployStaticFiles(t *testing.T) {
|
func TestDeployStaticFiles(t *testing.T) {
|
||||||
provider := object.GetProvider(util.GetId("admin", "provider_storage_aliyun_oss"))
|
object.InitConfig()
|
||||||
|
|
||||||
|
provider, err := object.GetProvider(util.GetId("admin", "provider_storage_aliyun_oss"))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
deployStaticFiles(provider)
|
deployStaticFiles(provider)
|
||||||
}
|
}
|
||||||
|
@@ -107,6 +107,11 @@ func UpdateGroup(id string, group *Group) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = checkGroupName(group.Name)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
if name != group.Name {
|
if name != group.Name {
|
||||||
err := GroupChangeTrigger(name, group.Name)
|
err := GroupChangeTrigger(name, group.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -123,6 +128,11 @@ func UpdateGroup(id string, group *Group) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddGroup(group *Group) (bool, error) {
|
func AddGroup(group *Group) (bool, error) {
|
||||||
|
err := checkGroupName(group.Name)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := adapter.Engine.Insert(group)
|
affected, err := adapter.Engine.Insert(group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -168,6 +178,17 @@ func DeleteGroup(group *Group) (bool, error) {
|
|||||||
return affected != 0, nil
|
return affected != 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkGroupName(name string) error {
|
||||||
|
exist, err := adapter.Engine.Exist(&Organization{Owner: "admin", Name: name})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if exist {
|
||||||
|
return errors.New("group name can't be same as the organization name")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (group *Group) GetId() string {
|
func (group *Group) GetId() string {
|
||||||
return fmt.Sprintf("%s/%s", group.Owner, group.Name)
|
return fmt.Sprintf("%s/%s", group.Owner, group.Name)
|
||||||
}
|
}
|
||||||
@@ -225,7 +246,7 @@ func GetGroupUserCount(groupName string, field, value string) (int64, error) {
|
|||||||
func GetPaginationGroupUsers(groupName string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
|
func GetPaginationGroupUsers(groupName string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
|
||||||
users := []*User{}
|
users := []*User{}
|
||||||
session := adapter.Engine.Table("user").
|
session := adapter.Engine.Table("user").
|
||||||
Where(builder.Like{"`groups`", groupName})
|
Where(builder.Like{"`groups`", groupName + "\""})
|
||||||
|
|
||||||
if offset != -1 && limit != -1 {
|
if offset != -1 && limit != -1 {
|
||||||
session.Limit(limit, offset)
|
session.Limit(limit, offset)
|
||||||
@@ -255,7 +276,7 @@ func GetPaginationGroupUsers(groupName string, offset, limit int, field, value,
|
|||||||
func GetGroupUsers(groupName string) ([]*User, error) {
|
func GetGroupUsers(groupName string) ([]*User, error) {
|
||||||
users := []*User{}
|
users := []*User{}
|
||||||
err := adapter.Engine.Table("user").
|
err := adapter.Engine.Table("user").
|
||||||
Where(builder.Like{"`groups`", groupName}).
|
Where(builder.Like{"`groups`", groupName + "\""}).
|
||||||
Find(&users)
|
Find(&users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -61,7 +61,7 @@ func getBuiltInAccountItems() []*AccountItem {
|
|||||||
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
{Name: "Groups", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
{Name: "Groups", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
|
@@ -103,6 +103,37 @@ func GetLdap(id string) (*Ldap, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetMaskedLdap(ldap *Ldap, errs ...error) (*Ldap, error) {
|
||||||
|
if len(errs) > 0 && errs[0] != nil {
|
||||||
|
return nil, errs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if ldap == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if ldap.Password != "" {
|
||||||
|
ldap.Password = "***"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ldap, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMaskedLdaps(ldaps []*Ldap, errs ...error) ([]*Ldap, error) {
|
||||||
|
if len(errs) > 0 && errs[0] != nil {
|
||||||
|
return nil, errs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
for _, ldap := range ldaps {
|
||||||
|
ldap, err = GetMaskedLdap(ldap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ldaps, nil
|
||||||
|
}
|
||||||
|
|
||||||
func UpdateLdap(ldap *Ldap) (bool, error) {
|
func UpdateLdap(ldap *Ldap) (bool, error) {
|
||||||
if l, err := GetLdap(ldap.Id); err != nil {
|
if l, err := GetLdap(ldap.Id); err != nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@@ -123,6 +123,10 @@ 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 {
|
||||||
|
if cert.Type != "x509" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
certPemBlock := []byte(cert.Certificate)
|
certPemBlock := []byte(cert.Certificate)
|
||||||
certDerBlock, _ := pem.Decode(certPemBlock)
|
certDerBlock, _ := pem.Decode(certPemBlock)
|
||||||
x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes)
|
x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes)
|
||||||
|
@@ -229,7 +229,7 @@ func UpdateProvider(id string, provider *Provider) (bool, error) {
|
|||||||
session = session.Omit("client_secret2")
|
session = session.Omit("client_secret2")
|
||||||
}
|
}
|
||||||
|
|
||||||
if provider.Type != "Keycloak" {
|
if provider.Type == "Tencent Cloud COS" {
|
||||||
provider.Endpoint = util.GetEndPoint(provider.Endpoint)
|
provider.Endpoint = util.GetEndPoint(provider.Endpoint)
|
||||||
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
|
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ func UpdateProvider(id string, provider *Provider) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddProvider(provider *Provider) (bool, error) {
|
func AddProvider(provider *Provider) (bool, error) {
|
||||||
if provider.Type != "Keycloak" {
|
if provider.Type == "Tencent Cloud COS" {
|
||||||
provider.Endpoint = util.GetEndPoint(provider.Endpoint)
|
provider.Endpoint = util.GetEndPoint(provider.Endpoint)
|
||||||
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
|
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,11 @@ func SendSms(provider *Provider, content string, phoneNumbers ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if provider.Type == sender.Aliyun {
|
if provider.Type == sender.Twilio {
|
||||||
|
if provider.AppId != "" {
|
||||||
|
phoneNumbers = append([]string{provider.AppId}, phoneNumbers...)
|
||||||
|
}
|
||||||
|
} else if provider.Type == sender.Aliyun {
|
||||||
for i, number := range phoneNumbers {
|
for i, number := range phoneNumbers {
|
||||||
phoneNumbers[i] = strings.TrimPrefix(number, "+86")
|
phoneNumbers[i] = strings.TrimPrefix(number, "+86")
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
"github.com/casdoor/casdoor/storage"
|
"github.com/casdoor/casdoor/storage"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"github.com/casdoor/oss"
|
||||||
)
|
)
|
||||||
|
|
||||||
var isCloudIntranet bool
|
var isCloudIntranet bool
|
||||||
@@ -102,11 +103,11 @@ func GetUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool
|
|||||||
return fileUrl, objectKey
|
return fileUrl, objectKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadFile(provider *Provider, fullFilePath string, fileBuffer *bytes.Buffer, lang string) (string, string, error) {
|
func getStorageProvider(provider *Provider, lang string) (oss.StorageInterface, error) {
|
||||||
endpoint := getProviderEndpoint(provider)
|
endpoint := getProviderEndpoint(provider)
|
||||||
storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, endpoint)
|
storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, endpoint)
|
||||||
if storageProvider == nil {
|
if storageProvider == nil {
|
||||||
return "", "", fmt.Errorf(i18n.Translate(lang, "storage:The provider type: %s is not supported"), provider.Type)
|
return nil, fmt.Errorf(i18n.Translate(lang, "storage:The provider type: %s is not supported"), provider.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
if provider.Domain == "" {
|
if provider.Domain == "" {
|
||||||
@@ -114,9 +115,18 @@ func uploadFile(provider *Provider, fullFilePath string, fileBuffer *bytes.Buffe
|
|||||||
UpdateProvider(provider.GetId(), provider)
|
UpdateProvider(provider.GetId(), provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return storageProvider, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func uploadFile(provider *Provider, fullFilePath string, fileBuffer *bytes.Buffer, lang string) (string, string, error) {
|
||||||
|
storageProvider, err := getStorageProvider(provider, lang)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
fileUrl, objectKey := GetUploadFileUrl(provider, fullFilePath, true)
|
fileUrl, objectKey := GetUploadFileUrl(provider, fullFilePath, true)
|
||||||
|
|
||||||
_, err := storageProvider.Put(objectKey, fileBuffer)
|
_, err = storageProvider.Put(objectKey, fileBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
@@ -154,15 +164,9 @@ func DeleteFile(provider *Provider, objectKey string, lang string) error {
|
|||||||
return fmt.Errorf(i18n.Translate(lang, "storage:The objectKey: %s is not allowed"), objectKey)
|
return fmt.Errorf(i18n.Translate(lang, "storage:The objectKey: %s is not allowed"), objectKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint := getProviderEndpoint(provider)
|
storageProvider, err := getStorageProvider(provider, lang)
|
||||||
storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, endpoint)
|
if err != nil {
|
||||||
if storageProvider == nil {
|
return err
|
||||||
return fmt.Errorf(i18n.Translate(lang, "storage:The provider type: %s is not supported"), provider.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
if provider.Domain == "" {
|
|
||||||
provider.Domain = storageProvider.GetEndpoint()
|
|
||||||
UpdateProvider(provider.GetId(), provider)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return storageProvider.Delete(objectKey)
|
return storageProvider.Delete(objectKey)
|
||||||
|
@@ -293,7 +293,13 @@ func CheckPermissionForUpdateUser(oldUser, newUser *User, isAdmin bool, lang str
|
|||||||
itemsChanged = append(itemsChanged, item)
|
itemsChanged = append(itemsChanged, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if oldUser.Groups == nil {
|
||||||
|
oldUser.Groups = []string{}
|
||||||
|
}
|
||||||
oldUserGroupsJson, _ := json.Marshal(oldUser.Groups)
|
oldUserGroupsJson, _ := json.Marshal(oldUser.Groups)
|
||||||
|
if newUser.Groups == nil {
|
||||||
|
newUser.Groups = []string{}
|
||||||
|
}
|
||||||
newUserGroupsJson, _ := json.Marshal(newUser.Groups)
|
newUserGroupsJson, _ := json.Marshal(newUser.Groups)
|
||||||
if string(oldUserGroupsJson) != string(newUserGroupsJson) {
|
if string(oldUserGroupsJson) != string(newUserGroupsJson) {
|
||||||
item := GetAccountItemByName("Groups", organization)
|
item := GetAccountItemByName("Groups", organization)
|
||||||
|
@@ -33,6 +33,13 @@ func CorsFilter(ctx *context.Context) {
|
|||||||
origin := ctx.Input.Header(headerOrigin)
|
origin := ctx.Input.Header(headerOrigin)
|
||||||
originConf := conf.GetConfigString("origin")
|
originConf := conf.GetConfigString("origin")
|
||||||
|
|
||||||
|
if ctx.Request.Method == "POST" && ctx.Request.RequestURI == "/api/login/oauth/access_token" {
|
||||||
|
ctx.Output.Header(headerAllowOrigin, origin)
|
||||||
|
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS, DELETE")
|
||||||
|
ctx.Output.Header(headerAllowHeaders, "Content-Type, Authorization")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if origin != "" && originConf != "" && origin != originConf {
|
if origin != "" && originConf != "" && origin != originConf {
|
||||||
ok, err := object.IsOriginAllowed(origin)
|
ok, err := object.IsOriginAllowed(origin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -130,10 +130,8 @@ class App extends Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
requiredEnableMfa: requiredEnableMfa,
|
requiredEnableMfa: requiredEnableMfa,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.requiredEnableMfa !== prevState.requiredEnableMfa || this.state.account !== prevState.account) {
|
if (requiredEnableMfa === true) {
|
||||||
if (this.state.requiredEnableMfa === true) {
|
|
||||||
const mfaType = Setting.getMfaItemsByRules(this.state.account, this.state.account?.organization, [MfaRuleRequired])
|
const mfaType = Setting.getMfaItemsByRules(this.state.account, this.state.account?.organization, [MfaRuleRequired])
|
||||||
.find((item) => item.rule === MfaRuleRequired)?.name;
|
.find((item) => item.rule === MfaRuleRequired)?.name;
|
||||||
if (mfaType !== undefined) {
|
if (mfaType !== undefined) {
|
||||||
@@ -144,7 +142,6 @@ class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateMenuKey() {
|
updateMenuKey() {
|
||||||
// eslint-disable-next-line no-restricted-globals
|
|
||||||
const uri = location.pathname;
|
const uri = location.pathname;
|
||||||
this.setState({
|
this.setState({
|
||||||
uri: uri,
|
uri: uri,
|
||||||
@@ -636,7 +633,7 @@ class App extends Component {
|
|||||||
<Route exact path="/payments/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/payments/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/payments/:paymentName/result" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentResultPage account={this.state.account} {...props} />)} />
|
<Route exact path="/payments/:paymentName/result" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentResultPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/mfa/setup" render={(props) => this.renderLoginIfNotLoggedIn(<MfaSetupPage account={this.state.account} onfinish={result => this.setState({requiredEnableMfa: result})} {...props} />)} />
|
<Route exact path="/mfa/setup" render={(props) => this.renderLoginIfNotLoggedIn(<MfaSetupPage account={this.state.account} onfinish={() => this.setState({requiredEnableMfa: false})} {...props} />)} />
|
||||||
<Route exact path="/.well-known/openid-configuration" render={(props) => <OdicDiscoveryPage />} />
|
<Route exact path="/.well-known/openid-configuration" render={(props) => <OdicDiscoveryPage />} />
|
||||||
<Route exact path="/sysinfo" render={(props) => this.renderLoginIfNotLoggedIn(<SystemInfo account={this.state.account} {...props} />)} />
|
<Route exact path="/sysinfo" render={(props) => this.renderLoginIfNotLoggedIn(<SystemInfo account={this.state.account} {...props} />)} />
|
||||||
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
||||||
|
@@ -158,6 +158,7 @@ class CertEditPage extends React.Component {
|
|||||||
{
|
{
|
||||||
[
|
[
|
||||||
{id: "x509", name: "x509"},
|
{id: "x509", name: "x509"},
|
||||||
|
{id: "Payment", name: "Payment"},
|
||||||
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
|
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
|
@@ -151,6 +151,7 @@ class CertListPage extends BaseListPage {
|
|||||||
filterMultiple: false,
|
filterMultiple: false,
|
||||||
filters: [
|
filters: [
|
||||||
{text: "x509", value: "x509"},
|
{text: "x509", value: "x509"},
|
||||||
|
{text: "Payment", value: "Payment"},
|
||||||
],
|
],
|
||||||
width: "110px",
|
width: "110px",
|
||||||
sorter: true,
|
sorter: true,
|
||||||
@@ -213,7 +214,7 @@ class CertListPage extends BaseListPage {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={certs} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={certs} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{i18next.t("general:Certs")}
|
{i18next.t("general:Certs")}
|
||||||
|
@@ -41,7 +41,7 @@ class EntryPage extends React.Component {
|
|||||||
|
|
||||||
renderHomeIfLoggedIn(component) {
|
renderHomeIfLoggedIn(component) {
|
||||||
if (this.props.account !== null && this.props.account !== undefined) {
|
if (this.props.account !== null && this.props.account !== undefined) {
|
||||||
return <Redirect to="/" />;
|
return <Redirect to={{pathname: "/", state: {from: "/login"}}} />;
|
||||||
} else {
|
} else {
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
@@ -74,7 +74,7 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
{name: "Ranking", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
{name: "Ranking", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
{name: "Signup application", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
{name: "Signup application", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
{name: "API key", label: i18next.t("general:API key"), modifyRule: "Self"},
|
{name: "API key", label: i18next.t("general:API key"), modifyRule: "Self"},
|
||||||
{name: "Groups", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
{name: "Groups", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
{name: "Roles", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
{name: "Roles", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
||||||
{name: "Permissions", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
{name: "Permissions", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
||||||
{name: "3rd-party logins", visible: true, viewRule: "Self", modifyRule: "Self"},
|
{name: "3rd-party logins", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||||
|
@@ -196,7 +196,7 @@ class PlanListPage extends BaseListPage {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={plans} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={plans} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{i18next.t("general:Plans")}
|
{i18next.t("general:Plans")}
|
||||||
|
@@ -165,7 +165,7 @@ class PricingListPage extends BaseListPage {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={pricings} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={pricings} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{i18next.t("general:Pricings")}
|
{i18next.t("general:Pricings")}
|
||||||
|
@@ -236,7 +236,10 @@ class ProviderEditPage extends React.Component {
|
|||||||
tooltip = i18next.t("provider:Agent ID - Tooltip");
|
tooltip = i18next.t("provider:Agent ID - Tooltip");
|
||||||
}
|
}
|
||||||
} else if (provider.category === "SMS") {
|
} else if (provider.category === "SMS") {
|
||||||
if (provider.type === "Tencent Cloud SMS") {
|
if (provider.type === "Twilio SMS") {
|
||||||
|
text = i18next.t("provider:Sender number");
|
||||||
|
tooltip = i18next.t("provider:Sender number - Tooltip");
|
||||||
|
} else if (provider.type === "Tencent Cloud SMS") {
|
||||||
text = i18next.t("provider:App ID");
|
text = i18next.t("provider:App ID");
|
||||||
tooltip = i18next.t("provider:App ID - Tooltip");
|
tooltip = i18next.t("provider:App ID - Tooltip");
|
||||||
} else if (provider.type === "Volc Engine SMS") {
|
} else if (provider.type === "Volc Engine SMS") {
|
||||||
@@ -674,6 +677,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
{this.getAppIdRow(this.state.provider)}
|
||||||
{
|
{
|
||||||
this.state.provider.category === "Email" ? (
|
this.state.provider.category === "Email" ? (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@@ -919,7 +923,6 @@ class ProviderEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
{this.getAppIdRow(this.state.provider)}
|
|
||||||
<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:Provider URL"), i18next.t("provider:Provider URL - Tooltip"))} :
|
{Setting.getLabel(i18next.t("provider:Provider URL"), i18next.t("provider:Provider URL - Tooltip"))} :
|
||||||
|
@@ -215,7 +215,7 @@ class SubscriptionListPage extends BaseListPage {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={subscriptions} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={subscriptions} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{i18next.t("general:Subscriptions")}
|
{i18next.t("general:Subscriptions")}
|
||||||
|
@@ -82,6 +82,10 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||||
|
if (prevState.loginMethod === undefined && this.state.loginMethod === undefined) {
|
||||||
|
const application = this.getApplicationObj();
|
||||||
|
this.setState({loginMethod: this.getDefaultLoginMethod(application)});
|
||||||
|
}
|
||||||
if (prevProps.application !== this.props.application) {
|
if (prevProps.application !== this.props.application) {
|
||||||
this.setState({loginMethod: this.getDefaultLoginMethod(this.props.application)});
|
this.setState({loginMethod: this.getDefaultLoginMethod(this.props.application)});
|
||||||
|
|
||||||
|
@@ -190,7 +190,7 @@ class MfaSetupPage extends React.Component {
|
|||||||
<MfaEnableForm user={this.getUser()} mfaType={this.state.mfaType} recoveryCodes={this.state.mfaProps.recoveryCodes}
|
<MfaEnableForm user={this.getUser()} mfaType={this.state.mfaType} recoveryCodes={this.state.mfaProps.recoveryCodes}
|
||||||
onSuccess={() => {
|
onSuccess={() => {
|
||||||
Setting.showMessage("success", i18next.t("general:Enabled successfully"));
|
Setting.showMessage("success", i18next.t("general:Enabled successfully"));
|
||||||
this.props.onfinish(true);
|
this.props.onfinish();
|
||||||
if (localStorage.getItem("mfaRedirectUrl") !== null) {
|
if (localStorage.getItem("mfaRedirectUrl") !== null) {
|
||||||
Setting.goToLink(localStorage.getItem("mfaRedirectUrl"));
|
Setting.goToLink(localStorage.getItem("mfaRedirectUrl"));
|
||||||
localStorage.removeItem("mfaRedirectUrl");
|
localStorage.removeItem("mfaRedirectUrl");
|
||||||
|
@@ -17,7 +17,7 @@ import ThemePicker from "./ThemePicker";
|
|||||||
import ColorPicker, {GREEN_COLOR, PINK_COLOR} from "./ColorPicker";
|
import ColorPicker, {GREEN_COLOR, PINK_COLOR} from "./ColorPicker";
|
||||||
import RadiusPicker from "./RadiusPicker";
|
import RadiusPicker from "./RadiusPicker";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {useEffect} from "react";
|
import {useEffect, useLayoutEffect} from "react";
|
||||||
import {Content} from "antd/es/layout/layout";
|
import {Content} from "antd/es/layout/layout";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import * as Conf from "../../Conf";
|
import * as Conf from "../../Conf";
|
||||||
@@ -58,6 +58,11 @@ export default function ThemeEditor(props) {
|
|||||||
}, [isLight, isCompact]);
|
}, [isLight, isCompact]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
onThemeChange(null, themeData);
|
||||||
|
form.setFieldsValue(themeData);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
const mergedData = Object.assign(Object.assign(Object.assign({}, Conf.ThemeDefault), {themeType}), ThemesInfo[themeType]);
|
const mergedData = Object.assign(Object.assign(Object.assign({}, Conf.ThemeDefault), {themeType}), ThemesInfo[themeType]);
|
||||||
onThemeChange(null, mergedData);
|
onThemeChange(null, mergedData);
|
||||||
form.setFieldsValue(mergedData);
|
form.setFieldsValue(mergedData);
|
||||||
|
Reference in New Issue
Block a user