mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-21 11:30:34 +08:00
Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4468859795 | ||
![]() |
914128a78a | ||
![]() |
e5a189e0f4 | ||
![]() |
a07216d0e1 | ||
![]() |
fec54944dd | ||
![]() |
a2db61cc1a | ||
![]() |
134541acde | ||
![]() |
59fca0342e | ||
![]() |
abfc464155 | ||
![]() |
a41f6880a2 | ||
![]() |
d12117324c | ||
![]() |
1a6c9fbf69 | ||
![]() |
dd60d79af9 | ||
![]() |
73d314c7fe | ||
![]() |
27959e0f6f | ||
![]() |
47f40c5b24 | ||
![]() |
2ff9020884 | ||
![]() |
abaf4ca8d9 | ||
![]() |
8ff0cfd6ec | ||
![]() |
7a2a40edcc | ||
![]() |
b7a001ea39 | ||
![]() |
891e8e21d8 | ||
![]() |
80b0d26813 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
||||
with:
|
||||
start: yarn start
|
||||
wait-on: 'http://localhost:7001'
|
||||
wait-on-timeout: 180
|
||||
wait-on-timeout: 210
|
||||
working-directory: ./web
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
|
10
README.md
10
README.md
@@ -11,7 +11,7 @@
|
||||
<img alt="GitHub Workflow Status (branch)" src="https://github.com/casdoor/casdoor/workflows/Build/badge.svg?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/releases/latest">
|
||||
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/casbin/casdoor.svg">
|
||||
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/casdoor/casdoor.svg">
|
||||
</a>
|
||||
<a href="https://hub.docker.com/repository/docker/casbin/casdoor">
|
||||
<img alt="Docker Image Version (latest semver)" src="https://img.shields.io/badge/Docker%20Hub-latest-brightgreen">
|
||||
@@ -23,16 +23,16 @@
|
||||
<img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/casbin/casdoor?style=flat-square" alt="license">
|
||||
<img src="https://img.shields.io/github/license/casdoor/casdoor?style=flat-square" alt="license">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/issues">
|
||||
<img alt="GitHub issues" src="https://img.shields.io/github/issues/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub issues" src="https://img.shields.io/github/issues/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="#">
|
||||
<img alt="GitHub stars" src="https://img.shields.io/github/stars/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub stars" src="https://img.shields.io/github/stars/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/network">
|
||||
<img alt="GitHub forks" src="https://img.shields.io/github/forks/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub forks" src="https://img.shields.io/github/forks/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://crowdin.com/project/casdoor-site">
|
||||
<img alt="Crowdin" src="https://badges.crowdin.net/casdoor-site/localized.svg">
|
||||
|
@@ -171,7 +171,6 @@ func (c *ApiController) Signup() {
|
||||
Region: authForm.Region,
|
||||
Score: initScore,
|
||||
IsAdmin: false,
|
||||
IsGlobalAdmin: false,
|
||||
IsForbidden: false,
|
||||
IsDeleted: false,
|
||||
SignupApplication: application.Name,
|
||||
|
@@ -20,7 +20,6 @@ import (
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
// GetAdapters
|
||||
@@ -144,92 +143,3 @@ func (c *ApiController) DeleteAdapter() {
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteAdapter(&adapter))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetPolicies() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
policies, err := object.GetPolicies(adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(policies)
|
||||
}
|
||||
|
||||
func (c *ApiController) UpdatePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var policies []xormadapter.CasbinRule
|
||||
err = json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.UpdatePolicy(util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]), adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) AddPolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var policy xormadapter.CasbinRule
|
||||
err = json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.AddPolicy(util.CasbinToSlice(policy), adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) RemovePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var policy xormadapter.CasbinRule
|
||||
err = json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.RemovePolicy(util.CasbinToSlice(policy), adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@@ -70,7 +70,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
}
|
||||
|
||||
// check user's tag
|
||||
if !user.IsGlobalAdmin && !user.IsAdmin && len(application.Tags) > 0 {
|
||||
if !user.IsGlobalAdmin() && !user.IsAdmin && len(application.Tags) > 0 {
|
||||
// only users with the tag that is listed in the application tags can login
|
||||
if !util.InSlice(application.Tags, user.Tag) {
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:User's tag: %s is not listed in the application's tags"), user.Tag))
|
||||
@@ -187,12 +187,35 @@ func (c *ApiController) GetApplicationLogin() {
|
||||
redirectUri := c.Input().Get("redirectUri")
|
||||
scope := c.Input().Get("scope")
|
||||
state := c.Input().Get("state")
|
||||
id := c.Input().Get("id")
|
||||
loginType := c.Input().Get("type")
|
||||
|
||||
msg, application, err := object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
|
||||
var application *object.Application
|
||||
var msg string
|
||||
var err error
|
||||
if loginType == "code" {
|
||||
msg, application, err = object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else if loginType == "cas" {
|
||||
application, err = object.GetApplication(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), id))
|
||||
return
|
||||
}
|
||||
|
||||
err = object.CheckCasLogin(application, c.GetAcceptLanguage(), redirectUri)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
application = object.GetMaskedApplication(application, "")
|
||||
if msg != "" {
|
||||
@@ -566,7 +589,6 @@ func (c *ApiController) Login() {
|
||||
Region: userInfo.CountryCode,
|
||||
Score: initScore,
|
||||
IsAdmin: false,
|
||||
IsGlobalAdmin: false,
|
||||
IsForbidden: false,
|
||||
IsDeleted: false,
|
||||
SignupApplication: application.Name,
|
||||
|
@@ -79,7 +79,7 @@ func (c *ApiController) isGlobalAdmin() (bool, *object.User) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return user.Owner == "built-in" || user.IsGlobalAdmin, user
|
||||
return user.IsGlobalAdmin(), user
|
||||
}
|
||||
|
||||
func (c *ApiController) getCurrentUser() *object.User {
|
||||
|
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
// GetEnforcers
|
||||
@@ -74,6 +75,7 @@ func (c *ApiController) GetEnforcers() {
|
||||
// @router /get-enforcer [get]
|
||||
func (c *ApiController) GetEnforcer() {
|
||||
id := c.Input().Get("id")
|
||||
loadModelCfg := c.Input().Get("loadModelCfg")
|
||||
|
||||
enforcer, err := object.GetEnforcer(id)
|
||||
if err != nil {
|
||||
@@ -81,6 +83,13 @@ func (c *ApiController) GetEnforcer() {
|
||||
return
|
||||
}
|
||||
|
||||
if loadModelCfg == "true" {
|
||||
err := enforcer.LoadModelCfg()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.ResponseOk(enforcer)
|
||||
}
|
||||
|
||||
@@ -143,3 +152,88 @@ func (c *ApiController) DeleteEnforcer() {
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteEnforcer(&enforcer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetPolicies() {
|
||||
id := c.Input().Get("id")
|
||||
adapterId := c.Input().Get("adapterId")
|
||||
|
||||
if adapterId != "" {
|
||||
adapter, err := object.GetAdapter(adapterId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
err = adapter.InitAdapter()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.ResponseOk()
|
||||
return
|
||||
}
|
||||
|
||||
policies, err := object.GetPolicies(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(policies)
|
||||
}
|
||||
|
||||
func (c *ApiController) UpdatePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var policies []xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.UpdatePolicy(id, util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) AddPolicy() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var policy xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.AddPolicy(id, util.CasbinToSlice(policy))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) RemovePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var policy xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.RemovePolicy(id, util.CasbinToSlice(policy))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
33
controllers/get-dashboard.go
Normal file
33
controllers/get-dashboard.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import "github.com/casdoor/casdoor/object"
|
||||
|
||||
// GetDashboard
|
||||
// @Title GetDashboard
|
||||
// @Tag GetDashboard API
|
||||
// @Description get information of dashboard
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /get-dashboard [get]
|
||||
func (c *ApiController) GetDashboard() {
|
||||
data, err := object.GetDashboard()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(data)
|
||||
}
|
@@ -45,13 +45,13 @@ func (c *ApiController) Unlink() {
|
||||
// the user will be unlinked from the provider
|
||||
unlinkedUser := form.User
|
||||
|
||||
if user.Id != unlinkedUser.Id && !user.IsGlobalAdmin {
|
||||
if user.Id != unlinkedUser.Id && !user.IsGlobalAdmin() {
|
||||
// if the user is not the same as the one we are unlinking, we need to make sure the user is the global admin.
|
||||
c.ResponseError(c.T("link:You are not the global admin, you can't unlink other users"))
|
||||
return
|
||||
}
|
||||
|
||||
if user.Id == unlinkedUser.Id && !user.IsGlobalAdmin {
|
||||
if user.Id == unlinkedUser.Id && !user.IsGlobalAdmin() {
|
||||
// if the user is unlinking themselves, should check the provider can be unlinked, if not, we should return an error.
|
||||
application, err := object.GetApplicationByUser(user)
|
||||
if err != nil {
|
||||
|
@@ -183,8 +183,6 @@ func (c *ApiController) DeleteOrganization() {
|
||||
func (c *ApiController) GetDefaultApplication() {
|
||||
userId := c.GetSessionUsername()
|
||||
id := c.Input().Get("id")
|
||||
redirectUri := c.Input().Get("redirectUri")
|
||||
typ := c.Input().Get("type")
|
||||
|
||||
application, err := object.GetDefaultApplication(id)
|
||||
if err != nil {
|
||||
@@ -192,14 +190,6 @@ func (c *ApiController) GetDefaultApplication() {
|
||||
return
|
||||
}
|
||||
|
||||
if typ == "cas" {
|
||||
err = object.CheckCasRestrict(application, c.GetAcceptLanguage(), redirectUri)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
maskedApplication := object.GetMaskedApplication(application, userId)
|
||||
c.ResponseOk(maskedApplication)
|
||||
}
|
||||
|
@@ -361,6 +361,9 @@ func (c *ApiController) UploadResource() {
|
||||
return
|
||||
}
|
||||
|
||||
if user.Properties == nil {
|
||||
user.Properties = map[string]string{}
|
||||
}
|
||||
user.Properties[tag] = fileUrl
|
||||
user.Properties["isIdCardVerified"] = "false"
|
||||
_, err = object.UpdateUser(user.GetId(), user, []string{"properties"}, false)
|
||||
|
@@ -40,6 +40,10 @@ type SmsForm struct {
|
||||
OrgId string `json:"organizationId"` // e.g. "admin/built-in"
|
||||
}
|
||||
|
||||
type NotificationForm struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// SendEmail
|
||||
// @Title SendEmail
|
||||
// @Tag Service API
|
||||
@@ -156,3 +160,33 @@ func (c *ApiController) SendSms() {
|
||||
|
||||
c.ResponseOk()
|
||||
}
|
||||
|
||||
// SendNotification
|
||||
// @Title SendNotification
|
||||
// @Tag Service API
|
||||
// @Description This API is not for Casdoor frontend to call, it is for Casdoor SDKs.
|
||||
// @Param from body controllers.NotificationForm true "Details of the notification request"
|
||||
// @Success 200 {object} Response object
|
||||
// @router /api/send-notification [post]
|
||||
func (c *ApiController) SendNotification() {
|
||||
provider, err := c.GetProviderFromContext("Notification")
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var notificationForm NotificationForm
|
||||
err = json.Unmarshal(c.Ctx.Input.RequestBody, ¬ificationForm)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = object.SendNotification(provider, notificationForm.Content)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk()
|
||||
}
|
||||
|
8
go.mod
8
go.mod
@@ -26,16 +26,17 @@ require (
|
||||
github.com/go-mysql-org/go-mysql v1.7.0
|
||||
github.com/go-pay/gopay v1.5.72
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
|
||||
github.com/go-webauthn/webauthn v0.6.0
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/mux v1.7.3 // indirect
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/lestrrat-go/jwx v1.2.21
|
||||
github.com/lib/pq v1.10.2
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
||||
github.com/markbates/goth v1.75.2
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nikoksr/notify v0.41.0 // indirect
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||
github.com/nyaruka/phonenumbers v1.1.5
|
||||
github.com/pquerna/otp v1.4.0
|
||||
@@ -50,7 +51,8 @@ require (
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/stretchr/testify v1.8.3
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/stripe/stripe-go/v74 v74.29.0 // indirect
|
||||
github.com/tealeg/xlsx v1.0.5
|
||||
github.com/thanhpk/randstr v1.0.4
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
|
174
go.sum
174
go.sum
@@ -783,6 +783,8 @@ github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzS
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
|
||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
|
||||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
||||
@@ -796,6 +798,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0A
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b h1:EgJ6N2S0h1WfFIjU5/VVHWbMSVYXAluop97Qxpr/lfQ=
|
||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b/go.mod h1:3SAoF0F5EbcOuBD5WT9nYkbIJieBS84cUQXADbXeBsU=
|
||||
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20221121042443-a3fd332d56d9/go.mod h1:rjP7sIipbZcagro/6TCk6X0ZeFT2eyudH5+fve/cbBA=
|
||||
github.com/SherClockHolmes/webpush-go v1.2.0/go.mod h1:w6X47YApe/B9wUz2Wh8xukxlyupaxSSEbu6yKJcHN2w=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
|
||||
@@ -810,7 +814,9 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5
|
||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387 h1:loy0fjI90vF44BPW4ZYOkE3tDkGTy7yHURusOJimt+I=
|
||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387/go.mod h1:GuR5j/NW7AU7tDAQUDGCtpiPxWIOy/c3kiRDnlwiCHc=
|
||||
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
|
||||
github.com/alicebob/miniredis/v2 v2.30.0/go.mod h1:84TWKZlxYkfgMucPBf5SOQBYJceZeQRFIaQgNMiCX6Q=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1075/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.62.188 h1:8lIVcOlHW+fKCGMEf6nuGTTEFOt/EZJPZ8oq0kTlhGk=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.62.188/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs=
|
||||
@@ -824,13 +830,29 @@ github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0I
|
||||
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
|
||||
github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg=
|
||||
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
|
||||
github.com/appleboy/go-fcm v0.1.5/go.mod h1:MSxZ4LqGRsnywOjnlXJXMqbjZrG4vf+0oHitfC9HRH0=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/atc0005/go-teams-notify/v2 v2.6.1/go.mod h1:xo6GejLDHn3tWBA181F8LrllIL0xC1uRsRxq7YNXaaY=
|
||||
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
github.com/aws/aws-sdk-go v1.37.1/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.44.4 h1:ePN0CVJMdiz2vYUcJH96eyxRrtKGSDMgyhP6rah2OgE=
|
||||
github.com/aws/aws-sdk-go v1.44.4/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.27/go.mod h1:0My+YgmkGxeqjXZb5BYme5pc4drjTnM+x1GJ3zv42Nw=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.26/go.mod h1:GoXt2YC8jHUBbA4jr+W3JiemnIbkXOfxSXcisUsZ3os=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4/go.mod h1:E1hLXN/BL2e6YizK1zFlYd8vsfi2GTjbjBazinMmeaM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34/go.mod h1:wZpTEecJe0Btj3IYnDx/VlUzor9wm3fJHyvLpQF0VwY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28/go.mod h1:7VRpKQQedkfIEXb4k52I7swUnZP0wohVajJMRn3vsUw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35/go.mod h1:0Eg1YjxE0Bhn56lx+SHJwCzhW+2JGtizsrx+lCqrfm0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28/go.mod h1:jj7znCIg05jXlaGBlFMGP8+7UN3VtCkRBG2spnmRQkU=
|
||||
github.com/aws/aws-sdk-go-v2/service/ses v1.15.11/go.mod h1:iI3tHe16kyXcYA6fcoct3hW1uB/XSoe46w29wupWwho=
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.20.13/go.mod h1:rWrvp9i8y/lX94lS7Kn/0iu9RY6vXzeKRqS/knVX8/c=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.12.12/go.mod h1:HuCOxYsF21eKrerARYO6HapNeh9GBNq7fius2AcwodY=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12/go.mod h1:E4VrHCPzmVB/KFXtqBGKb3c8zpbNBgKe3fisDNLAW5w=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.19.2/go.mod h1:dp0yLPsLBOi++WTxzCjA/oZqi6NPIhoR+uF7GeMU9eg=
|
||||
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
github.com/baidubce/bce-sdk-go v0.9.153 h1:h5l2EXehe4C4/bdlAPBaULrbnEDgIu5HOYgniN7bjGM=
|
||||
github.com/baidubce/bce-sdk-go v0.9.153/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
|
||||
@@ -847,12 +869,15 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blinkbean/dingtalk v0.0.0-20210905093040-7d935c0f7e19/go.mod h1:9BaLuGSBqY3vT5hstValh48DbsKO7vaHaJnG9pXwbto=
|
||||
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
|
||||
github.com/casbin/casbin v1.9.1 h1:ucjbS5zTrmSLtH4XogqOG920Poe6QatdXtz1FEbApeM=
|
||||
github.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZllfog=
|
||||
@@ -868,12 +893,14 @@ github.com/casdoor/oss v1.3.0 h1:D5pcz65tJRqJrWY11Ks7D9LUsmlhqqMHugjDhSxWTvk=
|
||||
github.com/casdoor/oss v1.3.0/go.mod h1:YOi6KpG1pZHTkiy9AYaqI0UaPfE7YkaA07d89f1idqY=
|
||||
github.com/casdoor/xorm-adapter/v3 v3.0.4 h1:vB04Ao8n2jA7aFBI9F+gGXo9+Aa1IQP6mTdo50913DM=
|
||||
github.com/casdoor/xorm-adapter/v3 v3.0.4/go.mod h1:4WTcUw+bTgBylGHeGHzTtBvuTXRS23dtwzFLl9tsgFM=
|
||||
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
@@ -902,6 +929,8 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
|
||||
github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
|
||||
@@ -909,6 +938,7 @@ github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401/go.mod h1:BQwMFl
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cschomburg/go-pushbullet v0.0.0-20171206132031-67759df45fbb/go.mod h1:RfQ9wji3fjcSEsQ+uFCtIh3+BXgcZum8Kt3JxvzYzlk=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
|
||||
github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
|
||||
@@ -918,14 +948,19 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M=
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
|
||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
|
||||
github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=
|
||||
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dghubble/oauth1 v0.7.2/go.mod h1:9erQdIhqhOHG/7K9s/tgh9Ks/AfoyrO5mW/43Lu2+kE=
|
||||
github.com/dghubble/sling v1.4.0/go.mod h1:0r40aNsU9EdDUVBNhfCstAtFgutjgJGYbO1oNzkMoM8=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/drswork/go-twitter v0.0.0-20221107160839-dea1b6ed53d7/go.mod h1:ncTaGuXc5v7AuiVekeJ0Nwh8Bf4cudukoj0qM/15UZE=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
@@ -953,6 +988,10 @@ github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J
|
||||
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
|
||||
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
|
||||
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
@@ -960,7 +999,10 @@ github.com/forestmgy/ldapserver v1.1.0 h1:gvil4nuLhqPEL8SugCkFhRyA0/lIvRdwZSqlrw
|
||||
github.com/forestmgy/ldapserver v1.1.0/go.mod h1:1RZ8lox1QSY7rmbjdmy+sYQXY4Lp7SpGzpdE3+j3IyM=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
|
||||
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
@@ -989,6 +1031,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-lark/lark v1.7.4/go.mod h1:6ltbSztPZRT6IaO9ZIQyVaY5pVp/KeMizDYtfZkU+vM=
|
||||
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
|
||||
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
|
||||
github.com/go-ldap/ldap/v3 v3.3.0 h1:lwx+SJpgOHd8tG6SumBQZXCmNX51zM8B1cfxJ5gv4tQ=
|
||||
@@ -1011,11 +1054,18 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
|
||||
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/go-redis/redis/v8 v8.11.6-0.20220405070650-99c79f7041fc/go.mod h1:25mL1NKxbJhB63ihiK8MnNeTRd+xAizd6bOdydrTLUQ=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
||||
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/go-webauthn/revoke v0.1.6 h1:3tv+itza9WpX5tryRQx4GwxCCBrCIiJ8GIkOhxiAmmU=
|
||||
github.com/go-webauthn/revoke v0.1.6/go.mod h1:TB4wuW4tPlwgF3znujA96F70/YSQXHPPWl7vgY09Iy8=
|
||||
github.com/go-webauthn/webauthn v0.6.0 h1:uLInMApSvBfP+vEFasNE0rnVPG++fjp7lmAIvNhe+UU=
|
||||
@@ -1023,6 +1073,8 @@ github.com/go-webauthn/webauthn v0.6.0/go.mod h1:7edMRZXwuM6JIVjN68G24Bzt+bPCvTm
|
||||
github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
|
||||
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||
@@ -1032,6 +1084,7 @@ github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw
|
||||
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0-rc.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
@@ -1101,6 +1154,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
|
||||
github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
|
||||
github.com/google/go-tpm v0.3.3 h1:P/ZFNBZYXRxc+z7i5uyd8VP7MaDteuLZInzrH2idRGo=
|
||||
@@ -1128,6 +1183,7 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
@@ -1136,6 +1192,7 @@ github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JV
|
||||
github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
|
||||
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
|
||||
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
|
||||
github.com/google/uuid v0.0.0-20171113160352-8c31c18f31ed/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
@@ -1166,35 +1223,40 @@ github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4/go.mod h1:lEO7XoHJ/xNRBCxrn4h/CEB67h0kW1B0t4ooP2yrjUA=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY=
|
||||
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregdel/pushover v1.2.0/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER1PthX7to=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||
github.com/inconshreveable/log15 v0.0.0-20201112154412-8562bdadbbac/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk=
|
||||
github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4=
|
||||
@@ -1209,15 +1271,19 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/jmoiron/sqlx v1.3.3/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
|
||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
@@ -1229,8 +1295,12 @@ github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uia
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinburke/go-types v0.0.0-20210723172823-2deba1f80ba7/go.mod h1:/Pk5i/SqYdYv1cie5wGwoZ4P6TpgMi+Yf58mtJSHdOw=
|
||||
github.com/kevinburke/handlers v0.0.0-20220416175136-cbf86af60bb5/go.mod h1:wOuHsUtSfRb2irqcjH8V3/hrPZq9wKy+NxX+hbfY0uI=
|
||||
github.com/kevinburke/rest v0.0.0-20210506044642-5611499aa33c/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kevinburke/twilio-go v0.0.0-20221122012537-65f3dd7539e2/go.mod h1:PDdDH7RSKjjy9iFyoMzfeChOSmXpXuMEUqmAJSihxx4=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
|
||||
@@ -1271,14 +1341,16 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/line/line-bot-sdk-go v7.8.0+incompatible/go.mod h1:0RjLjJEAU/3GIcHkC3av6O4jInAbt25nnZVmOFUgDBg=
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A=
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
|
||||
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
|
||||
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
|
||||
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailgun/mailgun-go/v4 v4.9.1/go.mod h1:FJlF9rI5cQT+mrwujtJjPMbIVy3Ebor9bKTVsJ0QU40=
|
||||
github.com/markbates/going v1.0.0 h1:DQw0ZP7NbNlFGcKbcE/IVSOAFzScxRtLpd0rLMzLhq0=
|
||||
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
|
||||
github.com/markbates/goth v1.75.2 h1:C7KloBMMk50JyXaHhzfqWYLW6+bDcSVIvUGHXneLWro=
|
||||
@@ -1287,9 +1359,11 @@ github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
|
||||
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
@@ -1297,10 +1371,12 @@ github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mileusna/viber v1.0.1/go.mod h1:Pxu/iPMnYjnHgu+bEp3SiKWHWmlf/kDp/yOX8XUdYrQ=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
@@ -1312,25 +1388,43 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA=
|
||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nikoksr/notify v0.41.0 h1:4LGE41GpWdHX5M3Xo6DlWRwS2WLDbOq1Rk7IzY4vjmQ=
|
||||
github.com/nikoksr/notify v0.41.0/go.mod h1:FoE0UVPeopz1Vy5nm9vQZ+JVmYjEIjQgbFstbkw+cRE=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/nyaruka/phonenumbers v1.1.5 h1:vYy2DI+z5hdaemqVzXYJ4CVyK92IG484CirEY+40GTo=
|
||||
github.com/nyaruka/phonenumbers v1.1.5/go.mod h1:yShPJHDSH3aTKzCbXyVxNpbl2kA+F+Ne5Pun/MvFRos=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
||||
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
@@ -1353,11 +1447,13 @@ github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1-0.20161029093637-248dadf4e906/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/plivo/plivo-go/v7 v7.31.0/go.mod h1:BohwA5tHmqajNPtohh55VIIF0AZA88vapm4jv00MFOE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||
@@ -1404,8 +1500,12 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
|
||||
github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU=
|
||||
github.com/russellhaering/gosaml2 v0.9.0 h1:CNMnH42z/GirrKjdmNrSS6bAAs47F9bPdl4PfRmVOIk=
|
||||
github.com/russellhaering/gosaml2 v0.9.0/go.mod h1:byViER/1YPUa0Puj9ROZblpoq2jsE7h/CJmitzX0geU=
|
||||
github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg=
|
||||
@@ -1416,6 +1516,8 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE=
|
||||
github.com/sendgrid/sendgrid-go v3.12.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
||||
@@ -1434,25 +1536,31 @@ github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed h1:KMgQoLJGCq1Io
|
||||
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed/go.mod h1:yFdBgwXP24JziuRl2NMUahT7nGLNOKi1SIiFxMttVD4=
|
||||
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
github.com/silenceper/wechat/v2 v2.1.5/go.mod h1:7Iu3EhQYVtDUJAj+ZVRy8yom75ga7aDWv8RurLkVm0s=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
|
||||
github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
@@ -1474,24 +1582,38 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stripe/stripe-go/v74 v74.29.0 h1:ffJ+1Ta1Ccg7yDDz+SfjixX0KizEEJ/wNVRoFYkdwFY=
|
||||
github.com/stripe/stripe-go/v74 v74.29.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw=
|
||||
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
|
||||
github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
|
||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.639 h1:Ubmf093flFkCvCUuVwFo+jgBdDh7RXZQ4pGcenLFP6M=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.639/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.639 h1:98cUzYW9tzSvY4weN/Ke2ZJfX5e/5/Tb6Z259cSgHZw=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.639/go.mod h1:JX7a56foe9SsC6mCYOPGFx4YdRLBP/PJWQFuZQuhCt4=
|
||||
github.com/textmagic/textmagic-rest-go-v2/v2 v2.0.4420/go.mod h1:PbP69y7uRiNdwtPE3/bVGDaPYA1sr4vuHaGLQAGzeW8=
|
||||
github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo=
|
||||
github.com/thanhpk/randstr v1.0.4/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
|
||||
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2/go.mod h1:4kyMkleCiLkgY6z8gK5BkI01ChBtxR0ro3I1ZDcGM3w=
|
||||
github.com/ttacon/libphonenumber v1.2.1/go.mod h1:E0TpmdVMq5dyVlQ7oenAkhsLu86OkUl+yR4OAxyEg/M=
|
||||
github.com/twilio/twilio-go v0.26.0 h1:wFW4oTe3/LKt6bvByP7eio8JsjtaLHjMQKOUEzQry7U=
|
||||
github.com/twilio/twilio-go v0.26.0/go.mod h1:lz62Hopu4vicpQ056H5TJ0JE4AP0rS3sQ35/ejmgOwE=
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
|
||||
@@ -1503,6 +1625,8 @@ github.com/ucloud/ucloud-sdk-go v0.22.4/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzF
|
||||
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/utahta/go-linenotify v0.5.0/go.mod h1:KsvBXil2wx+ByaCR0e+IZKTbp4pDesc7yjzRigLf6pE=
|
||||
github.com/vartanbeno/go-reddit/v2 v2.0.1/go.mod h1:758/S10hwZSLm43NPtwoNQdZFSg3sjB5745Mwjb0ANI=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.19 h1:jJp+aJgK0e//rZ9I0K2Y7ufJwvuZRo/AQsYDynXMNgA=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF0Ui9vIInTojMM0IfSS4=
|
||||
github.com/wendal/errors v0.0.0-20181209125328-7f31f4b264ec/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||
@@ -1525,13 +1649,16 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
|
||||
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.mau.fi/zeroconfig v0.1.2/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
@@ -1562,6 +1689,7 @@ go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@@ -1609,6 +1737,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
@@ -1656,6 +1785,7 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20171115151908-9dfe39835686/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1684,10 +1814,12 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
@@ -1698,7 +1830,9 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
@@ -1709,6 +1843,7 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220614195744-fb05da6f9022/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
@@ -1726,6 +1861,7 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
|
||||
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
@@ -1761,6 +1897,7 @@ golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4
|
||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/sync v0.0.0-20171101214715-fd80eb99c8f6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1786,6 +1923,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1795,8 +1933,10 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1815,6 +1955,7 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1825,6 +1966,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1848,6 +1990,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1978,6 +2121,7 @@ golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
@@ -2327,15 +2471,16 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
|
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
@@ -2369,6 +2514,9 @@ honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
|
||||
maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho=
|
||||
maunium.net/go/mautrix v0.15.3/go.mod h1:zLrQqdxJlLkurRCozTc9CL6FySkgZlO/kpCYxBILSLE=
|
||||
modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
|
||||
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
|
||||
modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
|
||||
|
@@ -36,6 +36,9 @@ func TestGenerateI18nFrontend(t *testing.T) {
|
||||
applyToOtherLanguage("frontend", "it", data)
|
||||
applyToOtherLanguage("frontend", "ms", data)
|
||||
applyToOtherLanguage("frontend", "tr", data)
|
||||
applyToOtherLanguage("frontend", "ar", data)
|
||||
applyToOtherLanguage("frontend", "he", data)
|
||||
applyToOtherLanguage("frontend", "fi", data)
|
||||
}
|
||||
|
||||
func TestGenerateI18nBackend(t *testing.T) {
|
||||
@@ -55,4 +58,7 @@ func TestGenerateI18nBackend(t *testing.T) {
|
||||
applyToOtherLanguage("backend", "it", data)
|
||||
applyToOtherLanguage("backend", "ms", data)
|
||||
applyToOtherLanguage("backend", "tr", data)
|
||||
applyToOtherLanguage("backend", "ar", data)
|
||||
applyToOtherLanguage("backend", "he", data)
|
||||
applyToOtherLanguage("backend", "fi", data)
|
||||
}
|
||||
|
142
i18n/locales/ar/data.json
Normal file
142
i18n/locales/ar/data.json
Normal file
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/fi/data.json
Normal file
142
i18n/locales/fi/data.json
Normal file
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/he/data.json
Normal file
142
i18n/locales/he/data.json
Normal file
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
@@ -24,20 +24,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const Web3AuthTokenKey = "web3AuthToken"
|
||||
|
||||
type MetaMaskIdProvider struct {
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
type Web3AuthToken struct {
|
||||
Address string `json:"address"`
|
||||
Nonce string `json:"nonce"`
|
||||
CreateAt uint64 `json:"createAt"`
|
||||
TypedData string `json:"typedData"`
|
||||
Signature string `json:"signature"` // signature for typed data
|
||||
}
|
||||
|
||||
func NewMetaMaskIdProvider() *MetaMaskIdProvider {
|
||||
idp := &MetaMaskIdProvider{}
|
||||
return idp
|
||||
|
@@ -111,6 +111,8 @@ func GetIdProvider(idpInfo *ProviderInfo, redirectUrl string) IdProvider {
|
||||
return NewBilibiliIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||
case "MetaMask":
|
||||
return NewMetaMaskIdProvider()
|
||||
case "Web3Onboard":
|
||||
return NewWeb3OnboardIdProvider()
|
||||
default:
|
||||
if isGothSupport(idpInfo.Type) {
|
||||
return NewGothIdProvider(idpInfo.Type, idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
||||
|
103
idp/web3onboard.go
Normal file
103
idp/web3onboard.go
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package idp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const Web3AuthTokenKey = "web3AuthToken"
|
||||
|
||||
type Web3AuthToken struct {
|
||||
Address string `json:"address"`
|
||||
Nonce string `json:"nonce"`
|
||||
CreateAt uint64 `json:"createAt"`
|
||||
TypedData string `json:"typedData"` // typed data use for application
|
||||
Signature string `json:"signature"` // signature for typed data
|
||||
WalletType string `json:"walletType"` // e.g."MetaMask", "Coinbase"
|
||||
}
|
||||
|
||||
type Web3OnboardIdProvider struct {
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
func NewWeb3OnboardIdProvider() *Web3OnboardIdProvider {
|
||||
idp := &Web3OnboardIdProvider{}
|
||||
return idp
|
||||
}
|
||||
|
||||
func (idp *Web3OnboardIdProvider) SetHttpClient(client *http.Client) {
|
||||
idp.Client = client
|
||||
}
|
||||
|
||||
func (idp *Web3OnboardIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
web3AuthToken := Web3AuthToken{}
|
||||
if err := json.Unmarshal([]byte(code), &web3AuthToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
token := &oauth2.Token{
|
||||
AccessToken: fmt.Sprintf("%v:%v", Web3AuthTokenKey, web3AuthToken.Address),
|
||||
TokenType: "Bearer",
|
||||
Expiry: time.Now().AddDate(0, 1, 0),
|
||||
}
|
||||
|
||||
token = token.WithExtra(map[string]interface{}{
|
||||
Web3AuthTokenKey: web3AuthToken,
|
||||
})
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (idp *Web3OnboardIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
web3AuthToken, ok := token.Extra(Web3AuthTokenKey).(Web3AuthToken)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid web3AuthToken")
|
||||
}
|
||||
|
||||
fmtAddress := fmt.Sprintf("%v_%v",
|
||||
strings.ReplaceAll(strings.TrimSpace(web3AuthToken.WalletType), " ", "_"),
|
||||
web3AuthToken.Address,
|
||||
)
|
||||
userInfo := &UserInfo{
|
||||
Id: fmtAddress,
|
||||
Username: fmtAddress,
|
||||
DisplayName: fmtAddress,
|
||||
AvatarUrl: fmt.Sprintf("metamask:%v", forceEthereumAddress(web3AuthToken.Address)),
|
||||
}
|
||||
return userInfo, nil
|
||||
}
|
||||
|
||||
func forceEthereumAddress(address string) string {
|
||||
// The required address to general MetaMask avatar is a string of length 42 that represents an Ethereum address.
|
||||
// This function is used to force any address as an Ethereum address
|
||||
address = strings.TrimSpace(address)
|
||||
var builder strings.Builder
|
||||
for _, ch := range address {
|
||||
builder.WriteRune(ch)
|
||||
}
|
||||
for len(builder.String()) < 42 {
|
||||
builder.WriteString("0")
|
||||
}
|
||||
if len(builder.String()) > 42 {
|
||||
return builder.String()[:42]
|
||||
}
|
||||
return builder.String()
|
||||
}
|
@@ -9,11 +9,11 @@
|
||||
"passwordType": "plain",
|
||||
"passwordSalt": "",
|
||||
"passwordOptions": ["AtLeast6"],
|
||||
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN", "IT", "MY", "TR"],
|
||||
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN", "IT", "MY", "TR", "DZ", "IL", "PH"],
|
||||
"defaultAvatar": "",
|
||||
"defaultApplication": "",
|
||||
"tags": [],
|
||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr"],
|
||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr","ar", "he", "fi"],
|
||||
"masterPassword": "",
|
||||
"initScore": 2000,
|
||||
"enableSoftDeletion": false,
|
||||
@@ -123,7 +123,6 @@
|
||||
"score": 2000,
|
||||
"ranking": 1,
|
||||
"isAdmin": true,
|
||||
"isGlobalAdmin": true,
|
||||
"isForbidden": false,
|
||||
"isDeleted": false,
|
||||
"signupApplication": "",
|
||||
|
@@ -62,7 +62,7 @@ func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
return
|
||||
}
|
||||
|
||||
if bindOrg == "built-in" || bindUser.IsGlobalAdmin {
|
||||
if bindOrg == "built-in" || bindUser.IsGlobalAdmin() {
|
||||
m.Client.IsGlobalAdmin, m.Client.IsOrgAdmin = true, true
|
||||
} else if bindUser.IsAdmin {
|
||||
m.Client.IsOrgAdmin = true
|
||||
|
25
notification/provider.go
Normal file
25
notification/provider.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import "github.com/nikoksr/notify"
|
||||
|
||||
func GetNotificationProvider(typ string, appId string, receiver string) (notify.Notifier, error) {
|
||||
if typ == "Telegram" {
|
||||
return NewTelegramProvider(appId, receiver)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
42
notification/telegram.go
Normal file
42
notification/telegram.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
api "github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"github.com/nikoksr/notify"
|
||||
"github.com/nikoksr/notify/service/telegram"
|
||||
)
|
||||
|
||||
func NewTelegramProvider(apiToken string, chatIdStr string) (notify.Notifier, error) {
|
||||
client, err := api.NewBotAPIWithClient(apiToken, proxy.ProxyHttpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t := &telegram.Telegram{}
|
||||
t.SetClient(client)
|
||||
|
||||
chatId, err := strconv.ParseInt(chatIdStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.AddReceivers(chatId)
|
||||
|
||||
return t, nil
|
||||
}
|
@@ -18,7 +18,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
@@ -41,8 +40,6 @@ type Adapter struct {
|
||||
Table string `xorm:"varchar(100)" json:"table"`
|
||||
TableNamePrefix string `xorm:"varchar(100)" json:"tableNamePrefix"`
|
||||
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
*xormadapter.Adapter `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
@@ -150,7 +147,7 @@ func (adapter *Adapter) getTable() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (adapter *Adapter) initAdapter() error {
|
||||
func (adapter *Adapter) InitAdapter() error {
|
||||
if adapter.Adapter == nil {
|
||||
var dataSourceName string
|
||||
|
||||
@@ -214,119 +211,6 @@ func adapterChangeTrigger(oldName string, newName string) error {
|
||||
return session.Commit()
|
||||
}
|
||||
|
||||
func safeReturn(policy []string, i int) string {
|
||||
if len(policy) > i {
|
||||
return policy[i]
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.CasbinRule {
|
||||
res := []*xormadapter.CasbinRule{}
|
||||
|
||||
for _, policy := range policies {
|
||||
line := xormadapter.CasbinRule{
|
||||
Ptype: Ptype,
|
||||
V0: safeReturn(policy, 0),
|
||||
V1: safeReturn(policy, 1),
|
||||
V2: safeReturn(policy, 2),
|
||||
V3: safeReturn(policy, 3),
|
||||
V4: safeReturn(policy, 4),
|
||||
V5: safeReturn(policy, 5),
|
||||
}
|
||||
res = append(res, &line)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func GetPolicies(adapter *Adapter) ([]*xormadapter.CasbinRule, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policies := matrixToCasbinRules("p", casbinModel.GetPolicy("p", "p"))
|
||||
policies = append(policies, matrixToCasbinRules("g", casbinModel.GetPolicy("g", "g"))...)
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
func UpdatePolicy(oldPolicy, newPolicy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected := casbinModel.UpdatePolicy("p", "p", oldPolicy, newPolicy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
err = adapter.SavePolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func AddPolicy(policy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel.AddPolicy("p", "p", policy)
|
||||
err = adapter.SavePolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func RemovePolicy(policy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected := casbinModel.RemovePolicy("p", "p", policy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
err = adapter.SavePolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func (adapter *Adapter) builtInAdapter() bool {
|
||||
if adapter.Owner != "built-in" {
|
||||
return false
|
||||
@@ -334,10 +218,3 @@ func (adapter *Adapter) builtInAdapter() bool {
|
||||
|
||||
return adapter.Name == "user-adapter-built-in" || adapter.Name == "api-adapter-built-in"
|
||||
}
|
||||
|
||||
func getModelDef() model.Model {
|
||||
casbinModel := model.NewModel()
|
||||
casbinModel.AddDef("p", "p", "_, _, _, _, _, _")
|
||||
casbinModel.AddDef("g", "g", "_, _, _, _, _, _")
|
||||
return casbinModel
|
||||
}
|
||||
|
@@ -141,7 +141,7 @@ func checkSigninErrorTimes(user *User, lang string) string {
|
||||
// reset the error times
|
||||
user.SigninWrongTimes = 0
|
||||
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times"}, user.IsGlobalAdmin)
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times"}, false)
|
||||
}
|
||||
|
||||
return ""
|
||||
@@ -319,7 +319,7 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
|
||||
if requestUser == nil {
|
||||
return false, fmt.Errorf(i18n.Translate(lang, "check:Session outdated, please login again"))
|
||||
}
|
||||
if requestUser.IsGlobalAdmin {
|
||||
if requestUser.IsGlobalAdmin() {
|
||||
hasPermission = true
|
||||
} else if requestUserId == userId {
|
||||
hasPermission = true
|
||||
|
@@ -42,7 +42,7 @@ func resetUserSigninErrorTimes(user *User) {
|
||||
return
|
||||
}
|
||||
user.SigninWrongTimes = 0
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, false)
|
||||
}
|
||||
|
||||
func recordSigninErrorInfo(user *User, lang string, options ...bool) string {
|
||||
@@ -61,7 +61,7 @@ func recordSigninErrorInfo(user *User, lang string, options ...bool) string {
|
||||
}
|
||||
|
||||
// update user
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, false)
|
||||
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
||||
if leftChances == 0 && enableCaptcha {
|
||||
return fmt.Sprint(i18n.Translate(lang, "check:password or code is incorrect"))
|
||||
|
@@ -18,7 +18,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/config"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
@@ -32,8 +34,8 @@ type Enforcer struct {
|
||||
|
||||
Model string `xorm:"varchar(100)" json:"model"`
|
||||
Adapter string `xorm:"varchar(100)" json:"adapter"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
ModelCfg map[string]string `xorm:"-" json:"modelCfg"`
|
||||
*casbin.Enforcer
|
||||
}
|
||||
|
||||
@@ -120,8 +122,8 @@ func DeleteEnforcer(enforcer *Enforcer) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (p *Enforcer) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
||||
func (enforcer *Enforcer) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", enforcer.Owner, enforcer.Name)
|
||||
}
|
||||
|
||||
func (enforcer *Enforcer) InitEnforcer() error {
|
||||
@@ -154,7 +156,7 @@ func (enforcer *Enforcer) InitEnforcer() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = a.initAdapter()
|
||||
err = a.InitAdapter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -182,3 +184,70 @@ func GetInitializedEnforcer(enforcerId string) (*Enforcer, error) {
|
||||
}
|
||||
return enforcer, nil
|
||||
}
|
||||
|
||||
func GetPolicies(id string) ([]*xormadapter.CasbinRule, error) {
|
||||
enforcer, err := GetInitializedEnforcer(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policies := util.MatrixToCasbinRules("p", enforcer.GetPolicy())
|
||||
if enforcer.GetModel()["g"] != nil {
|
||||
policies = append(policies, util.MatrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
|
||||
}
|
||||
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
func UpdatePolicy(id string, oldPolicy, newPolicy []string) (bool, error) {
|
||||
enforcer, err := GetInitializedEnforcer(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return enforcer.UpdatePolicy(oldPolicy, newPolicy)
|
||||
}
|
||||
|
||||
func AddPolicy(id string, policy []string) (bool, error) {
|
||||
enforcer, err := GetInitializedEnforcer(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return enforcer.AddPolicy(policy)
|
||||
}
|
||||
|
||||
func RemovePolicy(id string, policy []string) (bool, error) {
|
||||
enforcer, err := GetInitializedEnforcer(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return enforcer.RemovePolicy(policy)
|
||||
}
|
||||
|
||||
func (enforcer *Enforcer) LoadModelCfg() error {
|
||||
if enforcer.ModelCfg != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
model, err := GetModel(enforcer.Model)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if model == nil {
|
||||
return fmt.Errorf("the model: %s for enforcer: %s is not found", enforcer.Model, enforcer.GetId())
|
||||
}
|
||||
|
||||
cfg, err := config.NewConfigFromText(model.ModelText)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enforcer.ModelCfg = make(map[string]string)
|
||||
enforcer.ModelCfg["p"] = cfg.String("policy_definition::p")
|
||||
if cfg.String("role_definition::g") != "" {
|
||||
enforcer.ModelCfg["g"] = cfg.String("role_definition::g")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
140
object/get-dashboard.go
Normal file
140
object/get-dashboard.go
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Dashboard struct {
|
||||
OrganizationCounts []int `json:"organizationCounts"`
|
||||
UserCounts []int `json:"userCounts"`
|
||||
ProviderCounts []int `json:"providerCounts"`
|
||||
ApplicationCounts []int `json:"applicationCounts"`
|
||||
SubscriptionCounts []int `json:"subscriptionCounts"`
|
||||
}
|
||||
|
||||
func GetDashboard() (*Dashboard, error) {
|
||||
dashboard := &Dashboard{
|
||||
OrganizationCounts: make([]int, 31),
|
||||
UserCounts: make([]int, 31),
|
||||
ProviderCounts: make([]int, 31),
|
||||
ApplicationCounts: make([]int, 31),
|
||||
SubscriptionCounts: make([]int, 31),
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
organizations := []Organization{}
|
||||
users := []User{}
|
||||
providers := []Provider{}
|
||||
applications := []Application{}
|
||||
subscriptions := []Subscription{}
|
||||
|
||||
wg.Add(5)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := ormer.Engine.Find(&organizations); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&users); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&providers); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&applications); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&subscriptions); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
nowTime := time.Now()
|
||||
for i := 30; i >= 0; i-- {
|
||||
cutTime := nowTime.AddDate(0, 0, -i)
|
||||
dashboard.OrganizationCounts[30-i] = countCreatedBefore(organizations, cutTime)
|
||||
dashboard.UserCounts[30-i] = countCreatedBefore(users, cutTime)
|
||||
dashboard.ProviderCounts[30-i] = countCreatedBefore(providers, cutTime)
|
||||
dashboard.ApplicationCounts[30-i] = countCreatedBefore(applications, cutTime)
|
||||
dashboard.SubscriptionCounts[30-i] = countCreatedBefore(subscriptions, cutTime)
|
||||
}
|
||||
return dashboard, nil
|
||||
}
|
||||
|
||||
func countCreatedBefore(objects interface{}, before time.Time) int {
|
||||
count := 0
|
||||
switch obj := objects.(type) {
|
||||
case []Organization:
|
||||
for _, o := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", o.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []User:
|
||||
for _, u := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", u.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Provider:
|
||||
for _, p := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", p.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Application:
|
||||
for _, a := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", a.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Subscription:
|
||||
for _, s := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", s.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
@@ -73,7 +73,6 @@ func getBuiltInAccountItems() []*AccountItem {
|
||||
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is global admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is forbidden", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Multi-factor authentication", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
@@ -145,7 +144,6 @@ func initBuiltInUser() {
|
||||
Score: 2000,
|
||||
Ranking: 1,
|
||||
IsAdmin: true,
|
||||
IsGlobalAdmin: true,
|
||||
IsForbidden: false,
|
||||
IsDeleted: false,
|
||||
SignupApplication: "app-built-in",
|
||||
@@ -318,7 +316,6 @@ func initBuiltInUserModel() {
|
||||
Name: "user-model-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: "Built-in Model",
|
||||
IsEnabled: true,
|
||||
ModelText: `[request_definition]
|
||||
r = sub, obj, act
|
||||
|
||||
@@ -376,7 +373,6 @@ m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
|
||||
Name: "api-model-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: "API Model",
|
||||
IsEnabled: true,
|
||||
ModelText: modelText,
|
||||
}
|
||||
_, err = AddModel(model)
|
||||
@@ -435,7 +431,6 @@ func initBuiltInUserAdapter() {
|
||||
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
|
||||
Database: conf.GetConfigString("dbName"),
|
||||
Table: "casbin_user_rule",
|
||||
IsEnabled: true,
|
||||
}
|
||||
_, err = AddAdapter(adapter)
|
||||
if err != nil {
|
||||
@@ -462,7 +457,6 @@ func initBuiltInApiAdapter() {
|
||||
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
|
||||
Database: conf.GetConfigString("dbName"),
|
||||
Table: "casbin_api_rule",
|
||||
IsEnabled: true,
|
||||
}
|
||||
_, err = AddAdapter(adapter)
|
||||
if err != nil {
|
||||
@@ -487,7 +481,6 @@ func initBuiltInUserEnforcer() {
|
||||
DisplayName: "User Enforcer",
|
||||
Model: "built-in/user-model-built-in",
|
||||
Adapter: "built-in/user-adapter-built-in",
|
||||
IsEnabled: true,
|
||||
}
|
||||
|
||||
_, err = AddEnforcer(enforcer)
|
||||
@@ -513,7 +506,6 @@ func initBuiltInApiEnforcer() {
|
||||
DisplayName: "API Enforcer",
|
||||
Model: "built-in/api-model-built-in",
|
||||
Adapter: "built-in/api-adapter-built-in",
|
||||
IsEnabled: true,
|
||||
}
|
||||
|
||||
_, err = AddEnforcer(enforcer)
|
||||
|
@@ -84,7 +84,7 @@ func MfaRecover(user *User, recoveryCode string) error {
|
||||
return fmt.Errorf("recovery code not found")
|
||||
}
|
||||
|
||||
_, err := UpdateUser(user.GetId(), user, []string{"recovery_codes"}, user.IsAdminUser())
|
||||
_, err := UpdateUser(user.GetId(), user, []string{"recovery_codes"}, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -181,7 +181,7 @@ func DisabledMultiFactorAuth(user *User) error {
|
||||
func SetPreferredMultiFactorAuth(user *User, mfaType string) error {
|
||||
user.PreferredMfaType = mfaType
|
||||
|
||||
_, err := UpdateUser(user.GetId(), user, []string{"preferred_mfa_type"}, user.IsAdminUser())
|
||||
_, err := UpdateUser(user.GetId(), user, []string{"preferred_mfa_type"}, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ package object
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego"
|
||||
"github.com/beego/beego/context"
|
||||
@@ -25,7 +26,10 @@ import (
|
||||
"github.com/pquerna/otp/totp"
|
||||
)
|
||||
|
||||
const MfaTotpSecretSession = "mfa_totp_secret"
|
||||
const (
|
||||
MfaTotpSecretSession = "mfa_totp_secret"
|
||||
MfaTotpPeriodInSeconds = 30
|
||||
)
|
||||
|
||||
type TotpMfa struct {
|
||||
Config *MfaProps
|
||||
@@ -76,7 +80,13 @@ func (mfa *TotpMfa) SetupVerify(ctx *context.Context, passcode string) error {
|
||||
if secret == nil {
|
||||
return errors.New("totp secret is missing")
|
||||
}
|
||||
result := totp.Validate(passcode, secret.(string))
|
||||
|
||||
result, _ := totp.ValidateCustom(passcode, secret.(string), time.Now().UTC(), totp.ValidateOpts{
|
||||
Period: MfaTotpPeriodInSeconds,
|
||||
Skew: 1,
|
||||
Digits: otp.DigitsSix,
|
||||
Algorithm: otp.AlgorithmSHA1,
|
||||
})
|
||||
|
||||
if result {
|
||||
return nil
|
||||
@@ -133,7 +143,7 @@ func NewTotpMfaUtil(config *MfaProps) *TotpMfa {
|
||||
|
||||
return &TotpMfa{
|
||||
Config: config,
|
||||
period: 30,
|
||||
period: MfaTotpPeriodInSeconds,
|
||||
secretSize: 20,
|
||||
digits: otp.DigitsSix,
|
||||
}
|
||||
|
@@ -30,7 +30,6 @@ type Model struct {
|
||||
Description string `xorm:"varchar(100)" json:"description"`
|
||||
|
||||
ModelText string `xorm:"mediumtext" json:"modelText"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
model.Model `xorm:"-" json:"-"`
|
||||
}
|
||||
|
42
object/notification.go
Normal file
42
object/notification.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/casdoor/casdoor/notification"
|
||||
"github.com/nikoksr/notify"
|
||||
)
|
||||
|
||||
func getNotificationClient(provider *Provider) (notify.Notifier, error) {
|
||||
var client notify.Notifier
|
||||
client, err := notification.GetNotificationProvider(provider.Type, provider.AppId, provider.Receiver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func SendNotification(provider *Provider, content string) error {
|
||||
client, err := getNotificationClient(provider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.Send(context.Background(), "", content)
|
||||
return err
|
||||
}
|
@@ -103,7 +103,7 @@ func GetOidcDiscovery(host string) OidcDiscovery {
|
||||
SubjectTypesSupported: []string{"public"},
|
||||
IdTokenSigningAlgValuesSupported: []string{"RS256"},
|
||||
ScopesSupported: []string{"openid", "email", "profile", "address", "phone", "offline_access"},
|
||||
ClaimsSupported: []string{"iss", "ver", "sub", "aud", "iat", "exp", "id", "type", "displayName", "avatar", "permanentAvatar", "email", "phone", "location", "affiliation", "title", "homepage", "bio", "tag", "region", "language", "score", "ranking", "isOnline", "isAdmin", "isGlobalAdmin", "isForbidden", "signupApplication", "ldap"},
|
||||
ClaimsSupported: []string{"iss", "ver", "sub", "aud", "iat", "exp", "id", "type", "displayName", "avatar", "permanentAvatar", "email", "phone", "location", "affiliation", "title", "homepage", "bio", "tag", "region", "language", "score", "ranking", "isOnline", "isAdmin", "isForbidden", "signupApplication", "ldap"},
|
||||
RequestParameterSupported: true,
|
||||
RequestObjectSigningAlgValuesSupported: []string{"HS256", "HS384", "HS512"},
|
||||
EndSessionEndpoint: fmt.Sprintf("%s/api/logout", originBackend),
|
||||
|
@@ -309,8 +309,7 @@ func GetAllRoles(userId string) []string {
|
||||
|
||||
func GetBuiltInModel(modelText string) (model.Model, error) {
|
||||
if modelText == "" {
|
||||
modelText = `
|
||||
[request_definition]
|
||||
modelText = `[request_definition]
|
||||
r = sub, obj, act
|
||||
|
||||
[policy_definition]
|
||||
|
@@ -36,7 +36,7 @@ type Provider struct {
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
SubType string `xorm:"varchar(100)" json:"subType"`
|
||||
Method string `xorm:"varchar(100)" json:"method"`
|
||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||
ClientId string `xorm:"varchar(200)" json:"clientId"`
|
||||
ClientSecret string `xorm:"varchar(2000)" json:"clientSecret"`
|
||||
ClientId2 string `xorm:"varchar(100)" json:"clientId2"`
|
||||
ClientSecret2 string `xorm:"varchar(100)" json:"clientSecret2"`
|
||||
|
@@ -45,7 +45,6 @@ type Syncer struct {
|
||||
DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
|
||||
Database string `xorm:"varchar(100)" json:"database"`
|
||||
Table string `xorm:"varchar(100)" json:"table"`
|
||||
TablePrimaryKey string `xorm:"varchar(100)" json:"tablePrimaryKey"`
|
||||
TableColumns []*TableColumn `xorm:"mediumtext" json:"tableColumns"`
|
||||
AffiliationTable string `xorm:"varchar(100)" json:"affiliationTable"`
|
||||
AvatarBaseUrl string `xorm:"varchar(100)" json:"avatarBaseUrl"`
|
||||
@@ -230,6 +229,27 @@ func (syncer *Syncer) getTable() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (syncer *Syncer) getKey() string {
|
||||
key := "id"
|
||||
hasKey := false
|
||||
hasId := false
|
||||
for _, tableColumn := range syncer.TableColumns {
|
||||
if tableColumn.IsKey {
|
||||
hasKey = true
|
||||
key = tableColumn.Name
|
||||
}
|
||||
if tableColumn.Name == "id" {
|
||||
hasId = true
|
||||
}
|
||||
}
|
||||
|
||||
if !hasKey && !hasId {
|
||||
key = syncer.TableColumns[0].Name
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
func RunSyncer(syncer *Syncer) {
|
||||
syncer.initAdapter()
|
||||
syncer.syncUsers()
|
||||
|
@@ -20,16 +20,24 @@ import (
|
||||
)
|
||||
|
||||
func (syncer *Syncer) syncUsers() {
|
||||
if len(syncer.TableColumns) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Running syncUsers()..\n")
|
||||
|
||||
users, userMap, userNameMap := syncer.getUserMap()
|
||||
users, _, _ := syncer.getUserMap()
|
||||
oUsers, oUserMap, err := syncer.getOriginalUserMap()
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
|
||||
timestamp := time.Now().Format("2006-01-02 15:04:05")
|
||||
line := fmt.Sprintf("[%s] %s\n", timestamp, err.Error())
|
||||
updateSyncerErrorText(syncer, line)
|
||||
_, err = updateSyncerErrorText(syncer, line)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -40,48 +48,68 @@ func (syncer *Syncer) syncUsers() {
|
||||
_, affiliationMap, err = syncer.getAffiliationMap()
|
||||
}
|
||||
|
||||
key := syncer.getKey()
|
||||
|
||||
myUsers := map[string]*User{}
|
||||
for _, m := range users {
|
||||
myUsers[syncer.getUserValue(m, key)] = m
|
||||
}
|
||||
|
||||
newUsers := []*User{}
|
||||
for _, oUser := range oUsers {
|
||||
id := oUser.Id
|
||||
if _, ok := userMap[id]; !ok {
|
||||
if _, ok := userNameMap[oUser.Name]; !ok {
|
||||
primary := syncer.getUserValue(oUser, key)
|
||||
|
||||
if _, ok := myUsers[primary]; !ok {
|
||||
newUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
|
||||
fmt.Printf("New user: %v\n", newUser)
|
||||
newUsers = append(newUsers, newUser)
|
||||
}
|
||||
} else {
|
||||
user := userMap[id]
|
||||
user := myUsers[primary]
|
||||
oHash := syncer.calculateHash(oUser)
|
||||
|
||||
if user.Hash == user.PreHash {
|
||||
if user.Hash != oHash {
|
||||
updatedUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
|
||||
updatedUser.Hash = oHash
|
||||
updatedUser.PreHash = oHash
|
||||
syncer.updateUserForOriginalFields(updatedUser)
|
||||
_, err = syncer.updateUserForOriginalByFields(updatedUser, key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("Update from oUser to user: %v\n", updatedUser)
|
||||
}
|
||||
} else {
|
||||
if user.PreHash == oHash {
|
||||
if !syncer.IsReadOnly {
|
||||
updatedOUser := syncer.createOriginalUserFromUser(user)
|
||||
syncer.updateUser(updatedOUser)
|
||||
_, err = syncer.updateUser(updatedOUser)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("Update from user to oUser: %v\n", updatedOUser)
|
||||
}
|
||||
|
||||
// update preHash
|
||||
user.PreHash = user.Hash
|
||||
SetUserField(user, "pre_hash", user.PreHash)
|
||||
_, err = SetUserField(user, "pre_hash", user.PreHash)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
if user.Hash == oHash {
|
||||
// update preHash
|
||||
user.PreHash = user.Hash
|
||||
SetUserField(user, "pre_hash", user.PreHash)
|
||||
_, err = SetUserField(user, "pre_hash", user.PreHash)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
updatedUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
|
||||
updatedUser.Hash = oHash
|
||||
updatedUser.PreHash = oHash
|
||||
syncer.updateUserForOriginalFields(updatedUser)
|
||||
_, err = syncer.updateUserForOriginalByFields(updatedUser, key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("Update from oUser to user (2nd condition): %v\n", updatedUser)
|
||||
}
|
||||
}
|
||||
|
@@ -80,16 +80,6 @@ func (syncer *Syncer) addUser(user *OriginalUser) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
/*func (syncer *Syncer) getOriginalColumns() []string {
|
||||
res := []string{}
|
||||
for _, tableColumn := range syncer.TableColumns {
|
||||
if tableColumn.CasdoorName != "Id" {
|
||||
res = append(res, tableColumn.Name)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}*/
|
||||
|
||||
func (syncer *Syncer) getCasdoorColumns() []string {
|
||||
res := []string{}
|
||||
for _, tableColumn := range syncer.TableColumns {
|
||||
@@ -102,12 +92,14 @@ func (syncer *Syncer) getCasdoorColumns() []string {
|
||||
}
|
||||
|
||||
func (syncer *Syncer) updateUser(user *OriginalUser) (bool, error) {
|
||||
key := syncer.getKey()
|
||||
|
||||
m := syncer.getMapFromOriginalUser(user)
|
||||
pkValue := m[syncer.TablePrimaryKey]
|
||||
delete(m, syncer.TablePrimaryKey)
|
||||
pkValue := m[key]
|
||||
delete(m, key)
|
||||
setString := syncer.getSqlSetStringFromMap(m)
|
||||
|
||||
sql := fmt.Sprintf("update %s set %s where %s = %s", syncer.getTable(), setString, syncer.TablePrimaryKey, pkValue)
|
||||
sql := fmt.Sprintf("update %s set %s where %s = %s", syncer.getTable(), setString, key, pkValue)
|
||||
res, err := syncer.Ormer.Engine.Exec(sql)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -142,6 +134,34 @@ func (syncer *Syncer) updateUserForOriginalFields(user *User) (bool, error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) updateUserForOriginalByFields(user *User, key string) (bool, error) {
|
||||
var err error
|
||||
oldUser := User{}
|
||||
|
||||
existed, err := ormer.Engine.Where(key+" = ? and owner = ?", syncer.getUserValue(user, key), user.Owner).Get(&oldUser)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !existed {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if user.Avatar != oldUser.Avatar && user.Avatar != "" {
|
||||
user.PermanentAvatar, err = getPermanentAvatarUrl(user.Owner, user.Name, user.Avatar, true)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
columns := syncer.getCasdoorColumns()
|
||||
columns = append(columns, "affiliation", "hash", "pre_hash")
|
||||
affected, err := ormer.Engine.Where(key+" = ? and owner = ?", syncer.getUserValue(&oldUser, key), oldUser.Owner).Cols(columns...).Update(user)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ package object
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -153,8 +154,6 @@ func (syncer *Syncer) setUserByKeyValue(user *User, key string, value string) {
|
||||
user.IsOnline = util.ParseBool(value)
|
||||
case "IsAdmin":
|
||||
user.IsAdmin = util.ParseBool(value)
|
||||
case "IsGlobalAdmin":
|
||||
user.IsGlobalAdmin = util.ParseBool(value)
|
||||
case "IsForbidden":
|
||||
user.IsForbidden = util.ParseBool(value)
|
||||
case "IsDeleted":
|
||||
@@ -164,6 +163,33 @@ func (syncer *Syncer) setUserByKeyValue(user *User, key string, value string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (syncer *Syncer) getUserValue(user *User, key string) string {
|
||||
jsonData, _ := json.Marshal(user)
|
||||
var mapData map[string]interface{}
|
||||
if err := json.Unmarshal(jsonData, &mapData); err != nil {
|
||||
fmt.Println("conversion failed:", err)
|
||||
return user.Id
|
||||
}
|
||||
value := mapData[util.SnakeToCamel(key)]
|
||||
|
||||
if str, ok := value.(string); ok {
|
||||
return str
|
||||
} else {
|
||||
if value != nil {
|
||||
valType := reflect.TypeOf(value)
|
||||
|
||||
typeName := valType.Name()
|
||||
switch typeName {
|
||||
case "bool":
|
||||
return strconv.FormatBool(value.(bool))
|
||||
case "int":
|
||||
return strconv.Itoa(value.(int))
|
||||
}
|
||||
}
|
||||
return user.Id
|
||||
}
|
||||
}
|
||||
|
||||
func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*OriginalUser {
|
||||
users := []*OriginalUser{}
|
||||
for _, result := range results {
|
||||
@@ -261,7 +287,6 @@ func (syncer *Syncer) getMapFromOriginalUser(user *OriginalUser) map[string]stri
|
||||
m["IsDefaultAvatar"] = util.BoolToString(user.IsDefaultAvatar)
|
||||
m["IsOnline"] = util.BoolToString(user.IsOnline)
|
||||
m["IsAdmin"] = util.BoolToString(user.IsAdmin)
|
||||
m["IsGlobalAdmin"] = util.BoolToString(user.IsGlobalAdmin)
|
||||
m["IsForbidden"] = util.BoolToString(user.IsForbidden)
|
||||
m["IsDeleted"] = util.BoolToString(user.IsDeleted)
|
||||
m["CreatedIp"] = user.CreatedIp
|
||||
|
@@ -824,7 +824,6 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
|
||||
Type: "normal-user",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
IsAdmin: false,
|
||||
IsGlobalAdmin: false,
|
||||
IsForbidden: false,
|
||||
IsDeleted: false,
|
||||
Properties: map[string]string{
|
||||
|
@@ -123,7 +123,7 @@ var stToServiceResponse sync.Map
|
||||
// pgt is short for proxy granting ticket
|
||||
var pgtToServiceResponse sync.Map
|
||||
|
||||
func CheckCasRestrict(application *Application, lang string, service string) error {
|
||||
func CheckCasLogin(application *Application, lang string, service string) error {
|
||||
if len(application.RedirectUris) > 0 && !application.IsRedirectUriValid(service) {
|
||||
return fmt.Errorf(i18n.Translate(lang, "token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), service)
|
||||
}
|
||||
|
@@ -73,7 +73,6 @@ type UserWithoutThirdIdp struct {
|
||||
IsDefaultAvatar bool `json:"isDefaultAvatar"`
|
||||
IsOnline bool `json:"isOnline"`
|
||||
IsAdmin bool `json:"isAdmin"`
|
||||
IsGlobalAdmin bool `json:"isGlobalAdmin"`
|
||||
IsForbidden bool `json:"isForbidden"`
|
||||
IsDeleted bool `json:"isDeleted"`
|
||||
SignupApplication string `xorm:"varchar(100)" json:"signupApplication"`
|
||||
@@ -154,7 +153,6 @@ func getUserWithoutThirdIdp(user *User) *UserWithoutThirdIdp {
|
||||
IsDefaultAvatar: user.IsDefaultAvatar,
|
||||
IsOnline: user.IsOnline,
|
||||
IsAdmin: user.IsAdmin,
|
||||
IsGlobalAdmin: user.IsGlobalAdmin,
|
||||
IsForbidden: user.IsForbidden,
|
||||
IsDeleted: user.IsDeleted,
|
||||
SignupApplication: user.SignupApplication,
|
||||
|
@@ -83,7 +83,6 @@ type User struct {
|
||||
IsDefaultAvatar bool `json:"isDefaultAvatar"`
|
||||
IsOnline bool `json:"isOnline"`
|
||||
IsAdmin bool `json:"isAdmin"`
|
||||
IsGlobalAdmin bool `json:"isGlobalAdmin"`
|
||||
IsForbidden bool `json:"isForbidden"`
|
||||
IsDeleted bool `json:"isDeleted"`
|
||||
SignupApplication string `xorm:"varchar(100)" json:"signupApplication"`
|
||||
@@ -170,6 +169,7 @@ type User struct {
|
||||
Yandex string `xorm:"yandex varchar(100)" json:"yandex"`
|
||||
Zoom string `xorm:"zoom varchar(100)" json:"zoom"`
|
||||
MetaMask string `xorm:"metamask varchar(100)" json:"metamask"`
|
||||
Web3Onboard string `xorm:"web3onboard varchar(100)" json:"web3onboard"`
|
||||
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
||||
|
||||
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
||||
@@ -529,7 +529,7 @@ func UpdateUser(id string, user *User, columns []string, isAdmin bool) (bool, er
|
||||
columns = []string{
|
||||
"owner", "display_name", "avatar",
|
||||
"location", "address", "country_code", "region", "language", "affiliation", "title", "homepage", "bio", "tag", "language", "gender", "birthday", "education", "score", "karma", "ranking", "signup_application",
|
||||
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials", "managedAccounts",
|
||||
"is_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials", "managedAccounts",
|
||||
"signin_wrong_times", "last_signin_wrong_time", "groups", "access_key", "access_secret",
|
||||
"github", "google", "qq", "wechat", "facebook", "dingtalk", "weibo", "gitee", "linkedin", "wecom", "lark", "gitlab", "adfs",
|
||||
"baidu", "alipay", "casdoor", "infoflow", "apple", "azuread", "slack", "steam", "bilibili", "okta", "douyin", "line", "amazon",
|
||||
@@ -890,5 +890,13 @@ func (user *User) IsApplicationAdmin(application *Application) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return (user.Owner == application.Organization && user.IsAdmin) || user.IsGlobalAdmin
|
||||
return (user.Owner == application.Organization && user.IsAdmin) || user.IsGlobalAdmin()
|
||||
}
|
||||
|
||||
func (user *User) IsGlobalAdmin() bool {
|
||||
if user == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return user.Owner == "built-in"
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -58,22 +59,15 @@ func downloadImage(client *http.Client, url string) (*bytes.Buffer, string, erro
|
||||
if strings.Contains(contentType, "text/html") {
|
||||
fileExtension = ".html"
|
||||
} else {
|
||||
switch contentType {
|
||||
case "image/jpeg":
|
||||
fileExtension = ".jpg"
|
||||
case "image/png":
|
||||
fileExtension = ".png"
|
||||
case "image/gif":
|
||||
fileExtension = ".gif"
|
||||
case "image/vnd.microsoft.icon":
|
||||
fileExtension = ".ico"
|
||||
case "image/x-icon":
|
||||
fileExtension = ".ico"
|
||||
case "image/svg+xml":
|
||||
fileExtension = ".svg"
|
||||
default:
|
||||
return nil, "", fmt.Errorf("unsupported content type: %s", contentType)
|
||||
fileExtensions, err := mime.ExtensionsByType(contentType)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if fileExtensions == nil {
|
||||
return nil, "", fmt.Errorf("fileExtensions is nil")
|
||||
}
|
||||
|
||||
fileExtension = fileExtensions[0]
|
||||
}
|
||||
|
||||
// Save the image to a bytes.Buffer
|
||||
|
@@ -124,15 +124,14 @@ func UploadUsers(owner string, fileId string) (bool, error) {
|
||||
IsDefaultAvatar: false,
|
||||
IsOnline: parseLineItemBool(&line, 31),
|
||||
IsAdmin: parseLineItemBool(&line, 32),
|
||||
IsGlobalAdmin: parseLineItemBool(&line, 33),
|
||||
IsForbidden: parseLineItemBool(&line, 34),
|
||||
IsDeleted: parseLineItemBool(&line, 35),
|
||||
SignupApplication: parseLineItem(&line, 36),
|
||||
IsForbidden: parseLineItemBool(&line, 33),
|
||||
IsDeleted: parseLineItemBool(&line, 34),
|
||||
SignupApplication: parseLineItem(&line, 35),
|
||||
Hash: "",
|
||||
PreHash: "",
|
||||
CreatedIp: parseLineItem(&line, 37),
|
||||
LastSigninTime: parseLineItem(&line, 38),
|
||||
LastSigninIp: parseLineItem(&line, 39),
|
||||
CreatedIp: parseLineItem(&line, 36),
|
||||
LastSigninTime: parseLineItem(&line, 37),
|
||||
LastSigninIp: parseLineItem(&line, 38),
|
||||
Ldap: "",
|
||||
Properties: map[string]string{},
|
||||
}
|
||||
|
@@ -310,10 +310,7 @@ func CheckPermissionForUpdateUser(oldUser, newUser *User, isAdmin bool, lang str
|
||||
item := GetAccountItemByName("Is admin", organization)
|
||||
itemsChanged = append(itemsChanged, item)
|
||||
}
|
||||
if oldUser.IsGlobalAdmin != newUser.IsGlobalAdmin {
|
||||
item := GetAccountItemByName("Is global admin", organization)
|
||||
itemsChanged = append(itemsChanged, item)
|
||||
}
|
||||
|
||||
if oldUser.IsForbidden != newUser.IsForbidden {
|
||||
item := GetAccountItemByName("Is forbidden", organization)
|
||||
itemsChanged = append(itemsChanged, item)
|
||||
@@ -351,5 +348,5 @@ func (user *User) IsAdminUser() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return user.IsAdmin || user.IsGlobalAdmin
|
||||
return user.IsAdmin || user.IsGlobalAdmin()
|
||||
}
|
||||
|
@@ -90,7 +90,7 @@ func (pp *AlipayPaymentProvider) Notify(request *http.Request, body []byte, auth
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
OrderId: orderId,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
Price: price,
|
||||
PaymentName: paymentName,
|
||||
|
2
pp/gc.go
2
pp/gc.go
@@ -255,7 +255,7 @@ func (pp *GcPaymentProvider) Notify(request *http.Request, body []byte, authorit
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
OrderId: orderId,
|
||||
Price: price,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
PaymentName: paymentName,
|
||||
|
@@ -52,13 +52,12 @@ func NewPaypalPaymentProvider(clientID string, secret string) (*PaypalPaymentPro
|
||||
|
||||
func (pp *PaypalPaymentProvider) Pay(providerName string, productName string, payerName string, paymentName string, productDisplayName string, price float64, currency string, returnUrl string, notifyUrl string) (string, string, error) {
|
||||
// https://github.com/go-pay/gopay/blob/main/doc/paypal.md
|
||||
priceStr := strconv.FormatFloat(price, 'f', 2, 64)
|
||||
units := make([]*paypal.PurchaseUnit, 0, 1)
|
||||
unit := &paypal.PurchaseUnit{
|
||||
ReferenceId: util.GetRandomString(16),
|
||||
Amount: &paypal.Amount{
|
||||
CurrencyCode: currency, // e.g."USD"
|
||||
Value: priceStr, // e.g."100.00"
|
||||
Value: priceFloat64ToString(price), // e.g."100.00"
|
||||
},
|
||||
Description: joinAttachString([]string{productDisplayName, productName, providerName}),
|
||||
}
|
||||
@@ -149,14 +148,13 @@ func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, auth
|
||||
notifyResult = &NotifyResult{
|
||||
PaymentStatus: paymentStatus,
|
||||
PaymentName: paymentName,
|
||||
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
Price: price,
|
||||
Currency: currency,
|
||||
|
||||
OutOrderId: orderId,
|
||||
OrderId: orderId,
|
||||
}
|
||||
return notifyResult, nil
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ const (
|
||||
PaymentStatePaid PaymentState = "Paid"
|
||||
PaymentStateCreated PaymentState = "Created"
|
||||
PaymentStateCanceled PaymentState = "Canceled"
|
||||
PaymentStateTimeout PaymentState = "Timeout"
|
||||
PaymentStateError PaymentState = "Error"
|
||||
)
|
||||
|
||||
@@ -32,13 +33,13 @@ type NotifyResult struct {
|
||||
PaymentStatus PaymentState
|
||||
NotifyMessage string
|
||||
|
||||
ProviderName string
|
||||
ProductName string
|
||||
ProductDisplayName string
|
||||
ProviderName string
|
||||
Price float64
|
||||
Currency string
|
||||
|
||||
OutOrderId string
|
||||
OrderId string
|
||||
}
|
||||
|
||||
type PaymentProvider interface {
|
||||
@@ -75,6 +76,12 @@ func GetPaymentProvider(typ string, clientId string, clientSecret string, host s
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else if typ == "Stripe" {
|
||||
pp, err := NewStripePaymentProvider(clientId, clientSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
166
pp/stripe.go
Normal file
166
pp/stripe.go
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package pp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/stripe/stripe-go/v74"
|
||||
stripeCheckout "github.com/stripe/stripe-go/v74/checkout/session"
|
||||
stripeIntent "github.com/stripe/stripe-go/v74/paymentintent"
|
||||
stripePrice "github.com/stripe/stripe-go/v74/price"
|
||||
stripeProduct "github.com/stripe/stripe-go/v74/product"
|
||||
)
|
||||
|
||||
type StripePaymentProvider struct {
|
||||
PublishableKey string
|
||||
SecretKey string
|
||||
isProd bool
|
||||
}
|
||||
|
||||
func NewStripePaymentProvider(PublishableKey, SecretKey string) (*StripePaymentProvider, error) {
|
||||
isProd := false
|
||||
if conf.GetConfigString("runmode") == "prod" {
|
||||
isProd = true
|
||||
}
|
||||
pp := &StripePaymentProvider{
|
||||
PublishableKey: PublishableKey,
|
||||
SecretKey: SecretKey,
|
||||
isProd: isProd,
|
||||
}
|
||||
stripe.Key = pp.SecretKey
|
||||
return pp, nil
|
||||
}
|
||||
|
||||
func (pp *StripePaymentProvider) Pay(providerName string, productName string, payerName string, paymentName string, productDisplayName string, price float64, currency string, returnUrl string, notifyUrl string) (payUrl string, orderId string, err error) {
|
||||
// Create a temp product
|
||||
description := joinAttachString([]string{productName, productDisplayName, providerName})
|
||||
productParams := &stripe.ProductParams{
|
||||
Name: stripe.String(productDisplayName),
|
||||
Description: stripe.String(description),
|
||||
DefaultPriceData: &stripe.ProductDefaultPriceDataParams{
|
||||
UnitAmount: stripe.Int64(priceFloat64ToInt64(price)),
|
||||
Currency: stripe.String(currency),
|
||||
},
|
||||
}
|
||||
sProduct, err := stripeProduct.New(productParams)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
// Create a price for an existing product
|
||||
priceParams := &stripe.PriceParams{
|
||||
Currency: stripe.String(currency),
|
||||
UnitAmount: stripe.Int64(priceFloat64ToInt64(price)),
|
||||
Product: stripe.String(sProduct.ID),
|
||||
}
|
||||
sPrice, err := stripePrice.New(priceParams)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
// Create a Checkout Session
|
||||
checkoutParams := &stripe.CheckoutSessionParams{
|
||||
LineItems: []*stripe.CheckoutSessionLineItemParams{
|
||||
{
|
||||
Price: stripe.String(sPrice.ID),
|
||||
Quantity: stripe.Int64(1),
|
||||
},
|
||||
},
|
||||
Mode: stripe.String(string(stripe.CheckoutSessionModePayment)),
|
||||
SuccessURL: stripe.String(returnUrl),
|
||||
CancelURL: stripe.String(returnUrl),
|
||||
ClientReferenceID: stripe.String(paymentName),
|
||||
ExpiresAt: stripe.Int64(time.Now().Add(30 * time.Minute).Unix()),
|
||||
}
|
||||
checkoutParams.AddMetadata("product_description", description)
|
||||
sCheckout, err := stripeCheckout.New(checkoutParams)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return sCheckout.URL, sCheckout.ID, nil
|
||||
}
|
||||
|
||||
func (pp *StripePaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
||||
notifyResult := &NotifyResult{}
|
||||
sCheckout, err := stripeCheckout.Get(orderId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch sCheckout.Status {
|
||||
case "open":
|
||||
// The checkout session is still in progress. Payment processing has not started
|
||||
notifyResult.PaymentStatus = PaymentStateCreated
|
||||
return notifyResult, nil
|
||||
case "complete":
|
||||
// The checkout session is complete. Payment processing may still be in progress
|
||||
case "expired":
|
||||
// The checkout session has expired. No further processing will occur
|
||||
notifyResult.PaymentStatus = PaymentStateTimeout
|
||||
return notifyResult, nil
|
||||
default:
|
||||
notifyResult.PaymentStatus = PaymentStateError
|
||||
notifyResult.NotifyMessage = fmt.Sprintf("unexpected stripe checkout status: %v", sCheckout.Status)
|
||||
return notifyResult, nil
|
||||
}
|
||||
switch sCheckout.PaymentStatus {
|
||||
case "paid":
|
||||
// Skip
|
||||
case "unpaid":
|
||||
notifyResult.PaymentStatus = PaymentStateCreated
|
||||
return notifyResult, nil
|
||||
default:
|
||||
notifyResult.PaymentStatus = PaymentStateError
|
||||
notifyResult.NotifyMessage = fmt.Sprintf("unexpected stripe checkout payment status: %v", sCheckout.PaymentStatus)
|
||||
return notifyResult, nil
|
||||
}
|
||||
// Once payment is successful, the Checkout Session will contain a reference to the successful `PaymentIntent`
|
||||
sIntent, err := stripeIntent.Get(sCheckout.PaymentIntent.ID, nil)
|
||||
var (
|
||||
productName string
|
||||
productDisplayName string
|
||||
providerName string
|
||||
)
|
||||
if description, ok := sCheckout.Metadata["product_description"]; ok {
|
||||
productName, productDisplayName, providerName, _ = parseAttachString(description)
|
||||
}
|
||||
notifyResult = &NotifyResult{
|
||||
PaymentName: sCheckout.ClientReferenceID,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
|
||||
Price: priceInt64ToFloat64(sIntent.Amount),
|
||||
Currency: string(sIntent.Currency),
|
||||
|
||||
OrderId: orderId,
|
||||
}
|
||||
return notifyResult, nil
|
||||
}
|
||||
|
||||
func (pp *StripePaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (pp *StripePaymentProvider) GetResponseError(err error) string {
|
||||
if err == nil {
|
||||
return "success"
|
||||
} else {
|
||||
return "fail"
|
||||
}
|
||||
}
|
14
pp/util.go
14
pp/util.go
@@ -16,6 +16,8 @@ package pp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -35,3 +37,15 @@ func parseAttachString(s string) (string, string, string, error) {
|
||||
}
|
||||
return tokens[0], tokens[1], tokens[2], nil
|
||||
}
|
||||
|
||||
func priceInt64ToFloat64(price int64) float64 {
|
||||
return float64(price) / 100
|
||||
}
|
||||
|
||||
func priceFloat64ToInt64(price float64) int64 {
|
||||
return int64(math.Round(price * 100))
|
||||
}
|
||||
|
||||
func priceFloat64ToString(price float64) string {
|
||||
return strconv.FormatFloat(price, 'f', 2, 64)
|
||||
}
|
||||
|
@@ -113,7 +113,7 @@ func (pp *WechatPaymentProvider) Notify(request *http.Request, body []byte, auth
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
OrderId: orderId,
|
||||
Price: price,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
PaymentName: paymentName,
|
||||
|
@@ -51,6 +51,7 @@ func initAPI() {
|
||||
beego.Router("/api/signup", &controllers.ApiController{}, "POST:Signup")
|
||||
beego.Router("/api/login", &controllers.ApiController{}, "POST:Login")
|
||||
beego.Router("/api/get-app-login", &controllers.ApiController{}, "GET:GetApplicationLogin")
|
||||
beego.Router("/api/get-dashboard", &controllers.ApiController{}, "GET:GetDashboard")
|
||||
beego.Router("/api/logout", &controllers.ApiController{}, "GET,POST:Logout")
|
||||
beego.Router("/api/get-account", &controllers.ApiController{}, "GET:GetAccount")
|
||||
beego.Router("/api/userinfo", &controllers.ApiController{}, "GET:GetUserinfo")
|
||||
@@ -247,6 +248,7 @@ func initAPI() {
|
||||
|
||||
beego.Router("/api/send-email", &controllers.ApiController{}, "POST:SendEmail")
|
||||
beego.Router("/api/send-sms", &controllers.ApiController{}, "POST:SendSms")
|
||||
beego.Router("/api/send-notification", &controllers.ApiController{}, "POST:SendNotification")
|
||||
|
||||
beego.Router("/api/webauthn/signup/begin", &controllers.ApiController{}, "Get:WebAuthnSignupBegin")
|
||||
beego.Router("/api/webauthn/signup/finish", &controllers.ApiController{}, "Post:WebAuthnSignupFinish")
|
||||
|
@@ -131,34 +131,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-chat": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Chat API"
|
||||
],
|
||||
"description": "add chat",
|
||||
"operationId": "ApiController.AddChat",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the chat",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Chat"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -243,34 +215,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-message": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Message API"
|
||||
],
|
||||
"description": "add message",
|
||||
"operationId": "ApiController.AddMessage",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the message",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Message"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-model": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -1077,34 +1021,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-chat": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Chat API"
|
||||
],
|
||||
"description": "delete chat",
|
||||
"operationId": "ApiController.DeleteChat",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the chat",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Chat"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -1189,34 +1105,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-message": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Message API"
|
||||
],
|
||||
"description": "delete message",
|
||||
"operationId": "ApiController.DeleteMessage",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the message",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Message"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-mfa/": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -1964,56 +1852,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-chat": {
|
||||
"/api/get-dashboard": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Chat API"
|
||||
],
|
||||
"description": "get chat",
|
||||
"operationId": "ApiController.GetChat",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the chat",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
"GetDashboard API"
|
||||
],
|
||||
"description": "get information of dashboard",
|
||||
"operationId": "ApiController.GetDashboard",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Chat"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-chats": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Chat API"
|
||||
],
|
||||
"description": "get chats",
|
||||
"operationId": "ApiController.GetChats",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "owner",
|
||||
"description": "The owner of chats",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.Chat"
|
||||
}
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2319,87 +2169,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-message": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Message API"
|
||||
],
|
||||
"description": "get message",
|
||||
"operationId": "ApiController.GetMessage",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the message",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-message-answer": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Message API"
|
||||
],
|
||||
"description": "get message answer",
|
||||
"operationId": "ApiController.GetMessageAnswer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the message",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-messages": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Message API"
|
||||
],
|
||||
"description": "get messages",
|
||||
"operationId": "ApiController.GetMessages",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "owner",
|
||||
"description": "The owner of messages",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-model": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -4481,41 +4250,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-chat": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Chat API"
|
||||
],
|
||||
"description": "update chat",
|
||||
"operationId": "ApiController.UpdateChat",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the chat",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the chat",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Chat"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -4614,41 +4348,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-message": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Message API"
|
||||
],
|
||||
"description": "update message",
|
||||
"operationId": "ApiController.UpdateMessage",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the message",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The details of the message",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Message"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controllers.Response"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-model": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -5431,6 +5130,14 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"1183.0xc000639290.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
"1217.0xc0006392c0.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
"LaravelResponse": {
|
||||
"title": "LaravelResponse",
|
||||
"type": "object"
|
||||
@@ -5484,16 +5191,10 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"additionalProperties": {
|
||||
"description": "support string, struct or []struct",
|
||||
"type": "string"
|
||||
}
|
||||
"$ref": "#/definitions/1183.0xc000639290.false"
|
||||
},
|
||||
"data2": {
|
||||
"additionalProperties": {
|
||||
"description": "support string, struct or []struct",
|
||||
"type": "string"
|
||||
}
|
||||
"$ref": "#/definitions/1217.0xc0006392c0.false"
|
||||
},
|
||||
"msg": {
|
||||
"type": "string"
|
||||
@@ -5531,10 +5232,18 @@
|
||||
"title": "JSONWebKey",
|
||||
"type": "object"
|
||||
},
|
||||
"model.Model": {
|
||||
"title": "Model",
|
||||
"type": "object"
|
||||
},
|
||||
"object": {
|
||||
"title": "object",
|
||||
"type": "object"
|
||||
},
|
||||
"object.\u0026{197049 0xc000a2cd50 false}": {
|
||||
"title": "\u0026{197049 0xc000a2cd50 false}",
|
||||
"type": "object"
|
||||
},
|
||||
"object.AccountItem": {
|
||||
"title": "AccountItem",
|
||||
"type": "object",
|
||||
@@ -5557,16 +5266,41 @@
|
||||
"title": "Adapter",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Engine": {
|
||||
"$ref": "#/definitions/xorm.Engine"
|
||||
},
|
||||
"dataSourceName": {
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"dbName": {
|
||||
"database": {
|
||||
"type": "string"
|
||||
},
|
||||
"driverName": {
|
||||
"databaseType": {
|
||||
"type": "string"
|
||||
},
|
||||
"host": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"table": {
|
||||
"type": "string"
|
||||
},
|
||||
"tableNamePrefix": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"user": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -5728,7 +5462,7 @@
|
||||
"title": "CasbinRequest",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.CasbinRequest"
|
||||
"$ref": "#/definitions/object.\u0026{197049 0xc000a2cd50 false}"
|
||||
}
|
||||
},
|
||||
"object.Cert": {
|
||||
@@ -5778,52 +5512,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Chat": {
|
||||
"title": "Chat",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"messageCount": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"user1": {
|
||||
"type": "string"
|
||||
},
|
||||
"user2": {
|
||||
"type": "string"
|
||||
},
|
||||
"users": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Enforce": {
|
||||
"title": "Enforce",
|
||||
"type": "object"
|
||||
@@ -5844,12 +5532,14 @@
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"isEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"modelCfg": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -6084,36 +5774,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Message": {
|
||||
"title": "Message",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"author": {
|
||||
"type": "string"
|
||||
},
|
||||
"chat": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"replyTo": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.MfaItem": {
|
||||
"title": "MfaItem",
|
||||
"type": "object",
|
||||
@@ -6169,9 +5829,6 @@
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"isEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"modelText": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -6349,6 +6006,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Ormer": {
|
||||
"title": "Ormer",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Engine": {
|
||||
"$ref": "#/definitions/xorm.Engine"
|
||||
},
|
||||
"dataSourceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"dbName": {
|
||||
"type": "string"
|
||||
},
|
||||
"driverName": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Payment": {
|
||||
"title": "Payment",
|
||||
"type": "object",
|
||||
@@ -6386,7 +6061,7 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"organization": {
|
||||
"outOrderId": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
@@ -6424,7 +6099,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"state": {
|
||||
"type": "string"
|
||||
"$ref": "#/definitions/pp.PaymentState"
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
@@ -7124,9 +6799,6 @@
|
||||
"$ref": "#/definitions/object.TableColumn"
|
||||
}
|
||||
},
|
||||
"tablePrimaryKey": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -7145,6 +6817,9 @@
|
||||
"isHashed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isKey": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -7464,9 +7139,6 @@
|
||||
"isForbidden": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isGlobalAdmin": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isOnline": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -7692,6 +7364,9 @@
|
||||
"vk": {
|
||||
"type": "string"
|
||||
},
|
||||
"web3onboard": {
|
||||
"type": "string"
|
||||
},
|
||||
"webauthnCredentials": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -7811,6 +7486,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"pp.PaymentState": {
|
||||
"title": "PaymentState",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"PaymentStatePaid = \"Paid\"",
|
||||
"PaymentStateCreated = \"Created\"",
|
||||
"PaymentStateCanceled = \"Canceled\"",
|
||||
"PaymentStateTimeout = \"Timeout\"",
|
||||
"PaymentStateError = \"Error\""
|
||||
],
|
||||
"example": "Paid"
|
||||
},
|
||||
"protocol.CredentialAssertion": {
|
||||
"title": "CredentialAssertion",
|
||||
"type": "object"
|
||||
@@ -7871,6 +7558,10 @@
|
||||
"xorm.Engine": {
|
||||
"title": "Engine",
|
||||
"type": "object"
|
||||
},
|
||||
"xormadapter.Adapter": {
|
||||
"title": "Adapter",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
@@ -7879,9 +7570,5 @@
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
"description": "Find out more about Casdoor",
|
||||
"url": "https://casdoor.org/"
|
||||
}
|
||||
}
|
@@ -85,24 +85,6 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/add-chat:
|
||||
post:
|
||||
tags:
|
||||
- Chat API
|
||||
description: add chat
|
||||
operationId: ApiController.AddChat
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the chat
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Chat'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/add-enforcer:
|
||||
post:
|
||||
tags:
|
||||
@@ -157,24 +139,6 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/add-message:
|
||||
post:
|
||||
tags:
|
||||
- Message API
|
||||
description: add message
|
||||
operationId: ApiController.AddMessage
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the message
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Message'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/add-model:
|
||||
post:
|
||||
tags:
|
||||
@@ -696,24 +660,6 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/delete-chat:
|
||||
post:
|
||||
tags:
|
||||
- Chat API
|
||||
description: delete chat
|
||||
operationId: ApiController.DeleteChat
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the chat
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Chat'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/delete-enforcer:
|
||||
post:
|
||||
tags:
|
||||
@@ -768,24 +714,6 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/delete-message:
|
||||
post:
|
||||
tags:
|
||||
- Message API
|
||||
description: delete message
|
||||
operationId: ApiController.DeleteMessage
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the message
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Message'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/delete-mfa/:
|
||||
post:
|
||||
tags:
|
||||
@@ -1271,42 +1199,17 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Cert'
|
||||
/api/get-chat:
|
||||
/api/get-dashboard:
|
||||
get:
|
||||
tags:
|
||||
- Chat API
|
||||
description: get chat
|
||||
operationId: ApiController.GetChat
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of the chat
|
||||
required: true
|
||||
type: string
|
||||
- GetDashboard API
|
||||
description: get information of dashboard
|
||||
operationId: ApiController.GetDashboard
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/object.Chat'
|
||||
/api/get-chats:
|
||||
get:
|
||||
tags:
|
||||
- Chat API
|
||||
description: get chats
|
||||
operationId: ApiController.GetChats
|
||||
parameters:
|
||||
- in: query
|
||||
name: owner
|
||||
description: The owner of chats
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Chat'
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/get-default-application:
|
||||
get:
|
||||
tags:
|
||||
@@ -1503,59 +1406,6 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Ldap'
|
||||
/api/get-message:
|
||||
get:
|
||||
tags:
|
||||
- Message API
|
||||
description: get message
|
||||
operationId: ApiController.GetMessage
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of the message
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/object.Message'
|
||||
/api/get-message-answer:
|
||||
get:
|
||||
tags:
|
||||
- Message API
|
||||
description: get message answer
|
||||
operationId: ApiController.GetMessageAnswer
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of the message
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/object.Message'
|
||||
/api/get-messages:
|
||||
get:
|
||||
tags:
|
||||
- Message API
|
||||
description: get messages
|
||||
operationId: ApiController.GetMessages
|
||||
parameters:
|
||||
- in: query
|
||||
name: owner
|
||||
description: The owner of messages
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Message'
|
||||
/api/get-model:
|
||||
get:
|
||||
tags:
|
||||
@@ -2925,29 +2775,6 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/update-chat:
|
||||
post:
|
||||
tags:
|
||||
- Chat API
|
||||
description: update chat
|
||||
operationId: ApiController.UpdateChat
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of the chat
|
||||
required: true
|
||||
type: string
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the chat
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Chat'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/update-enforcer:
|
||||
post:
|
||||
tags:
|
||||
@@ -3012,29 +2839,6 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/update-message:
|
||||
post:
|
||||
tags:
|
||||
- Message API
|
||||
description: update message
|
||||
operationId: ApiController.UpdateMessage
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of the message
|
||||
required: true
|
||||
type: string
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the message
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Message'
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/update-model:
|
||||
post:
|
||||
tags:
|
||||
@@ -3549,6 +3353,12 @@ paths:
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
definitions:
|
||||
1183.0xc000639290.false:
|
||||
title: "false"
|
||||
type: object
|
||||
1217.0xc0006392c0.false:
|
||||
title: "false"
|
||||
type: object
|
||||
LaravelResponse:
|
||||
title: LaravelResponse
|
||||
type: object
|
||||
@@ -3588,13 +3398,9 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
additionalProperties:
|
||||
description: support string, struct or []struct
|
||||
type: string
|
||||
$ref: '#/definitions/1183.0xc000639290.false'
|
||||
data2:
|
||||
additionalProperties:
|
||||
description: support string, struct or []struct
|
||||
type: string
|
||||
$ref: '#/definitions/1217.0xc0006392c0.false'
|
||||
msg:
|
||||
type: string
|
||||
name:
|
||||
@@ -3618,9 +3424,15 @@ definitions:
|
||||
jose.JSONWebKey:
|
||||
title: JSONWebKey
|
||||
type: object
|
||||
model.Model:
|
||||
title: Model
|
||||
type: object
|
||||
object:
|
||||
title: object
|
||||
type: object
|
||||
object.&{197049 0xc000a2cd50 false}:
|
||||
title: '&{197049 0xc000a2cd50 false}'
|
||||
type: object
|
||||
object.AccountItem:
|
||||
title: AccountItem
|
||||
type: object
|
||||
@@ -3637,13 +3449,30 @@ definitions:
|
||||
title: Adapter
|
||||
type: object
|
||||
properties:
|
||||
Engine:
|
||||
$ref: '#/definitions/xorm.Engine'
|
||||
dataSourceName:
|
||||
createdTime:
|
||||
type: string
|
||||
dbName:
|
||||
database:
|
||||
type: string
|
||||
driverName:
|
||||
databaseType:
|
||||
type: string
|
||||
host:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
port:
|
||||
type: integer
|
||||
format: int64
|
||||
table:
|
||||
type: string
|
||||
tableNamePrefix:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
object.Application:
|
||||
title: Application
|
||||
@@ -3752,7 +3581,7 @@ definitions:
|
||||
title: CasbinRequest
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.CasbinRequest'
|
||||
$ref: '#/definitions/object.&{197049 0xc000a2cd50 false}'
|
||||
object.Cert:
|
||||
title: Cert
|
||||
type: object
|
||||
@@ -3785,37 +3614,6 @@ definitions:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
object.Chat:
|
||||
title: Chat
|
||||
type: object
|
||||
properties:
|
||||
category:
|
||||
type: string
|
||||
createdTime:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
messageCount:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
organization:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
updatedTime:
|
||||
type: string
|
||||
user1:
|
||||
type: string
|
||||
user2:
|
||||
type: string
|
||||
users:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
object.Enforce:
|
||||
title: Enforce
|
||||
type: object
|
||||
@@ -3831,10 +3629,11 @@ definitions:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
isEnabled:
|
||||
type: boolean
|
||||
model:
|
||||
type: string
|
||||
modelCfg:
|
||||
additionalProperties:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
owner:
|
||||
@@ -3992,26 +3791,6 @@ definitions:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
object.Message:
|
||||
title: Message
|
||||
type: object
|
||||
properties:
|
||||
author:
|
||||
type: string
|
||||
chat:
|
||||
type: string
|
||||
createdTime:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
organization:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
replyTo:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
object.MfaItem:
|
||||
title: MfaItem
|
||||
type: object
|
||||
@@ -4050,8 +3829,6 @@ definitions:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
isEnabled:
|
||||
type: boolean
|
||||
modelText:
|
||||
type: string
|
||||
name:
|
||||
@@ -4169,6 +3946,18 @@ definitions:
|
||||
$ref: '#/definitions/object.ThemeData'
|
||||
websiteUrl:
|
||||
type: string
|
||||
object.Ormer:
|
||||
title: Ormer
|
||||
type: object
|
||||
properties:
|
||||
Engine:
|
||||
$ref: '#/definitions/xorm.Engine'
|
||||
dataSourceName:
|
||||
type: string
|
||||
dbName:
|
||||
type: string
|
||||
driverName:
|
||||
type: string
|
||||
object.Payment:
|
||||
title: Payment
|
||||
type: object
|
||||
@@ -4195,7 +3984,7 @@ definitions:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
organization:
|
||||
outOrderId:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
@@ -4221,7 +4010,7 @@ definitions:
|
||||
returnUrl:
|
||||
type: string
|
||||
state:
|
||||
type: string
|
||||
$ref: '#/definitions/pp.PaymentState'
|
||||
tag:
|
||||
type: string
|
||||
type:
|
||||
@@ -4692,8 +4481,6 @@ definitions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.TableColumn'
|
||||
tablePrimaryKey:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
user:
|
||||
@@ -4706,6 +4493,8 @@ definitions:
|
||||
type: string
|
||||
isHashed:
|
||||
type: boolean
|
||||
isKey:
|
||||
type: boolean
|
||||
name:
|
||||
type: string
|
||||
type:
|
||||
@@ -4920,8 +4709,6 @@ definitions:
|
||||
type: boolean
|
||||
isForbidden:
|
||||
type: boolean
|
||||
isGlobalAdmin:
|
||||
type: boolean
|
||||
isOnline:
|
||||
type: boolean
|
||||
kakao:
|
||||
@@ -5073,6 +4860,8 @@ definitions:
|
||||
type: string
|
||||
vk:
|
||||
type: string
|
||||
web3onboard:
|
||||
type: string
|
||||
webauthnCredentials:
|
||||
type: array
|
||||
items:
|
||||
@@ -5151,6 +4940,16 @@ definitions:
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
pp.PaymentState:
|
||||
title: PaymentState
|
||||
type: string
|
||||
enum:
|
||||
- PaymentStatePaid = "Paid"
|
||||
- PaymentStateCreated = "Created"
|
||||
- PaymentStateCanceled = "Canceled"
|
||||
- PaymentStateTimeout = "Timeout"
|
||||
- PaymentStateError = "Error"
|
||||
example: Paid
|
||||
protocol.CredentialAssertion:
|
||||
title: CredentialAssertion
|
||||
type: object
|
||||
@@ -5195,11 +4994,11 @@ definitions:
|
||||
xorm.Engine:
|
||||
title: Engine
|
||||
type: object
|
||||
xormadapter.Adapter:
|
||||
title: Adapter
|
||||
type: object
|
||||
securityDefinitions:
|
||||
AccessToken:
|
||||
type: apiKey
|
||||
name: Authorization
|
||||
in: header
|
||||
externalDocs:
|
||||
description: Find out more about Casdoor
|
||||
url: https://casdoor.org/
|
||||
|
@@ -34,3 +34,30 @@ func CasbinToSlice(casbinRule xormadapter.CasbinRule) []string {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func safeReturn(policy []string, i int) string {
|
||||
if len(policy) > i {
|
||||
return policy[i]
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func MatrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.CasbinRule {
|
||||
res := []*xormadapter.CasbinRule{}
|
||||
|
||||
for _, policy := range policies {
|
||||
line := xormadapter.CasbinRule{
|
||||
Ptype: Ptype,
|
||||
V0: safeReturn(policy, 0),
|
||||
V1: safeReturn(policy, 1),
|
||||
V2: safeReturn(policy, 2),
|
||||
V3: safeReturn(policy, 3),
|
||||
V4: safeReturn(policy, 4),
|
||||
V5: safeReturn(policy, 5),
|
||||
}
|
||||
res = append(res, &line)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
@@ -88,6 +88,17 @@ func CamelToSnakeCase(camel string) string {
|
||||
return strings.ReplaceAll(buf.String(), " ", "")
|
||||
}
|
||||
|
||||
func SnakeToCamel(snake string) string {
|
||||
words := strings.Split(snake, "_")
|
||||
for i := range words {
|
||||
words[i] = strings.ToLower(words[i])
|
||||
if i > 0 {
|
||||
words[i] = strings.Title(words[i])
|
||||
}
|
||||
}
|
||||
return strings.Join(words, "")
|
||||
}
|
||||
|
||||
func GetOwnerAndNameFromId(id string) (string, string) {
|
||||
tokens := strings.Split(id, "/")
|
||||
if len(tokens) != 2 {
|
||||
|
@@ -51,11 +51,24 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
webpack: {
|
||||
configure: {
|
||||
// ignore webpack warnings by source-map-loader
|
||||
// https://github.com/facebook/create-react-app/pull/11752#issuecomment-1345231546
|
||||
ignoreWarnings: [
|
||||
function ignoreSourcemapsloaderWarnings(warning) {
|
||||
return (
|
||||
warning.module &&
|
||||
warning.module.resource.includes('node_modules') &&
|
||||
warning.details &&
|
||||
warning.details.includes('source-map-loader')
|
||||
)
|
||||
},
|
||||
],
|
||||
// use polyfill Buffer with Webpack 5
|
||||
// https://viglucci.io/articles/how-to-polyfill-buffer-with-webpack-5
|
||||
// https://craco.js.org/docs/configuration/webpack/
|
||||
configure: (webpackConfig, { env, paths }) => {
|
||||
webpackConfig.resolve.fallback = {
|
||||
resolve: {
|
||||
fallback: {
|
||||
// "process": require.resolve('process/browser'),
|
||||
// "util": require.resolve("util/"),
|
||||
// "url": require.resolve("url/"),
|
||||
@@ -74,8 +87,10 @@ module.exports = {
|
||||
"https": false,
|
||||
"assert": false,
|
||||
"buffer": false,
|
||||
};
|
||||
return webpackConfig;
|
||||
"crypto": false,
|
||||
"os": false,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
@@ -10,9 +10,16 @@
|
||||
"@ctrl/tinycolor": "^3.5.0",
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@metamask/eth-sig-util": "^6.0.0",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
"@web3-onboard/coinbase": "^2.2.5",
|
||||
"@web3-onboard/core": "^2.20.5",
|
||||
"@web3-onboard/frontier": "^2.0.4",
|
||||
"@web3-onboard/gnosis": "^2.1.10",
|
||||
"@web3-onboard/infinity-wallet": "^2.0.4",
|
||||
"@web3-onboard/injected-wallets": "^2.10.4",
|
||||
"@web3-onboard/react": "^2.8.10",
|
||||
"@web3-onboard/sequence": "^2.0.8",
|
||||
"@web3-onboard/taho": "^2.0.5",
|
||||
"@web3-onboard/trust": "^2.0.4",
|
||||
"antd": "5.2.3",
|
||||
"antd-token-previewer": "^1.1.0-22",
|
||||
"buffer": "^6.0.3",
|
||||
@@ -20,7 +27,8 @@
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"core-js": "^3.25.0",
|
||||
"craco-less": "^2.0.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"echarts": "^5.4.3",
|
||||
"ethers": "5.6.9",
|
||||
"file-saver": "^2.0.5",
|
||||
"i18n-iso-countries": "^7.0.0",
|
||||
"i18next": "^19.8.9",
|
||||
@@ -44,7 +52,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "cross-env PORT=7001 craco start",
|
||||
"build": "craco build",
|
||||
"build": "craco --max_old_space_size=4096 build",
|
||||
"test": "craco test",
|
||||
"eject": "craco eject",
|
||||
"crowdin:sync": "crowdin upload && crowdin download",
|
||||
@@ -72,16 +80,21 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.18.13",
|
||||
"@babel/eslint-parser": "^7.18.9",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"cross-env": "^7.0.3",
|
||||
"cypress": "^12.5.1",
|
||||
"eslint": "8.22.0",
|
||||
"eslint-plugin-react": "^7.31.1",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"husky": "^4.3.8",
|
||||
"lint-staged": "^13.0.3",
|
||||
"stylelint": "^14.11.0",
|
||||
"stylelint-config-recommended-less": "^1.0.4",
|
||||
"stylelint-config-standard": "^28.0.0"
|
||||
"stylelint-config-standard": "^28.0.0",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2"
|
||||
},
|
||||
"lint-staged": {
|
||||
"src/**/*.{css,less}": [
|
||||
|
@@ -13,17 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||
import {Button, Card, Col, Input, InputNumber, Row, Select} from "antd";
|
||||
import * as AdapterBackend from "./backend/AdapterBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
import "codemirror/lib/codemirror.css";
|
||||
import PolicyTable from "./table/PoliciyTable";
|
||||
require("codemirror/theme/material-darker.css");
|
||||
require("codemirror/mode/javascript/javascript");
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
class AdapterEditPage extends React.Component {
|
||||
@@ -232,20 +227,23 @@ class AdapterEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("adapter:Policies"), i18next.t("adapter:Policies - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("provider:DB Test"), i18next.t("provider:DB Test - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<PolicyTable owner={this.state.organizationName} name={this.state.adapterName} mode={this.state.mode} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Is enabled"), i18next.t("general:Is enabled - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.adapter.isEnabled} onChange={checked => {
|
||||
this.updateAdapterField("isEnabled", checked);
|
||||
}} />
|
||||
<Col span={2} >
|
||||
<Button type={"primary"} onClick={() => {
|
||||
AdapterBackend.getPolicies("", "", `${this.state.organizationName}/${this.state.adapterName}`)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("syncer:Connect successfully"));
|
||||
} else {
|
||||
Setting.showMessage("error", i18next.t("syncer:Failed to connect") + ": " + res.msg);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
}>{i18next.t("syncer:Test DB Connection")}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import {Button, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as AdapterBackend from "./backend/AdapterBackend";
|
||||
@@ -38,7 +38,6 @@ class AdapterListPage extends BaseListPage {
|
||||
databaseType: "mysql",
|
||||
database: "dbName",
|
||||
table: "tableName",
|
||||
isEnabled: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -183,18 +182,6 @@ class AdapterListPage extends BaseListPage {
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Is enabled"),
|
||||
dataIndex: "isEnabled",
|
||||
key: "isEnabled",
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Switch disabled checkedChildren="ON" unCheckedChildren="OFF" checked={text} />
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
|
@@ -351,7 +351,7 @@ class App extends Component {
|
||||
}
|
||||
|
||||
|
||||
{Setting.isMobile() ? null : Setting.getNameAtLeast(this.state.account.displayName)} <DownOutlined />
|
||||
{Setting.isMobile() ? null : Setting.getShortText(Setting.getNameAtLeast(this.state.account.displayName), 30)} <DownOutlined />
|
||||
|
||||
|
||||
|
||||
|
@@ -13,11 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select, Switch} from "antd";
|
||||
import {Button, Card, Col, Input, Row, Select} from "antd";
|
||||
import * as AdapterBackend from "./backend/AdapterBackend";
|
||||
import * as EnforcerBackend from "./backend/EnforcerBackend";
|
||||
import * as ModelBackend from "./backend/ModelBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import PolicyTable from "./table/PolicyTable";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
@@ -42,7 +43,7 @@ class EnforcerEditPage extends React.Component {
|
||||
}
|
||||
|
||||
getEnforcer() {
|
||||
EnforcerBackend.getEnforcer(this.state.organizationName, this.state.enforcerName)
|
||||
EnforcerBackend.getEnforcer(this.state.organizationName, this.state.enforcerName, true)
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
@@ -169,7 +170,7 @@ class EnforcerEditPage extends React.Component {
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.enforcer)} style={{width: "100%"}} value={this.state.enforcer.model} onChange={(model => {
|
||||
this.updateEnforcerField("model", model);
|
||||
})}
|
||||
options={this.state.models.map((model) => Setting.getOption(model.displayName, `${model.owner}/${model.name}`))
|
||||
options={this.state.models.map((model) => Setting.getOption(`${model.owner}/${model.name}`, `${model.owner}/${model.name}`))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -181,18 +182,16 @@ class EnforcerEditPage extends React.Component {
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.enforcer)} style={{width: "100%"}} value={this.state.enforcer.adapter} onChange={(adapter => {
|
||||
this.updateEnforcerField("adapter", adapter);
|
||||
})}
|
||||
options={this.state.adapters.map((adapter) => Setting.getOption(adapter.name, `${adapter.owner}/${adapter.name}`))
|
||||
options={this.state.adapters.map((adapter) => Setting.getOption(`${adapter.owner}/${adapter.name}`, `${adapter.owner}/${adapter.name}`))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Is enabled"), i18next.t("general:Is enabled - Tooltip"))} :
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("adapter:Policies"), i18next.t("adapter:Policies - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.enforcer.isEnabled} onChange={checked => {
|
||||
this.updateEnforcerField("isEnabled", checked);
|
||||
}} />
|
||||
<Col span={22}>
|
||||
<PolicyTable enforcer={this.state.enforcer} modelCfg={this.state.enforcer?.modelCfg} mode={this.state.mode} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import {Button, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as EnforcerBackend from "./backend/EnforcerBackend";
|
||||
@@ -31,7 +31,6 @@ class EnforcerListPage extends BaseListPage {
|
||||
name: `enforcer_${randomName}`,
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Enforcer - ${randomName}`,
|
||||
isEnabled: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -75,7 +74,7 @@ class EnforcerListPage extends BaseListPage {
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "150px",
|
||||
width: "200px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
@@ -116,19 +115,39 @@ class EnforcerListPage extends BaseListPage {
|
||||
title: i18next.t("general:Display name"),
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
width: "200px",
|
||||
// width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Is enabled"),
|
||||
dataIndex: "isEnabled",
|
||||
key: "isEnabled",
|
||||
width: "120px",
|
||||
title: i18next.t("general:Model"),
|
||||
dataIndex: "model",
|
||||
key: "model",
|
||||
width: "250px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Switch disabled checkedChildren="ON" unCheckedChildren="OFF" checked={text} />
|
||||
<Link to={`/models/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Adapter"),
|
||||
dataIndex: "adapter",
|
||||
key: "adapter",
|
||||
width: "250px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/adapters/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -136,7 +155,7 @@ class EnforcerListPage extends BaseListPage {
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "170px",
|
||||
width: "180px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
|
@@ -103,7 +103,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "120px",
|
||||
width: "150px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
@@ -119,7 +119,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: "owner",
|
||||
key: "owner",
|
||||
width: "120px",
|
||||
width: "140px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("owner"),
|
||||
render: (text, record, index) => {
|
||||
@@ -134,7 +134,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Created time"),
|
||||
dataIndex: "createdTime",
|
||||
key: "createdTime",
|
||||
width: "150px",
|
||||
width: "180px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
@@ -144,7 +144,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Updated time"),
|
||||
dataIndex: "updatedTime",
|
||||
key: "updatedTime",
|
||||
width: "150px",
|
||||
width: "180px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
@@ -154,7 +154,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Display name"),
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
width: "100px",
|
||||
// width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
@@ -162,7 +162,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Type"),
|
||||
dataIndex: "type",
|
||||
key: "type",
|
||||
width: "110px",
|
||||
width: "140px",
|
||||
sorter: true,
|
||||
filterMultiple: false,
|
||||
filters: [
|
||||
@@ -177,7 +177,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("group:Parent group"),
|
||||
dataIndex: "parentId",
|
||||
key: "parentId",
|
||||
width: "110px",
|
||||
width: "220px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("parentId"),
|
||||
render: (text, record, index) => {
|
||||
@@ -199,7 +199,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "170px",
|
||||
width: "180px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
const haveChildren = this.state.groups.find((group) => group.parentId === record.id) !== undefined;
|
||||
|
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select, Switch} from "antd";
|
||||
import {Button, Card, Col, Input, Row, Select} from "antd";
|
||||
import * as ModelBackend from "./backend/ModelBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
@@ -161,16 +161,6 @@ class ModelEditPage extends React.Component {
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Is enabled"), i18next.t("general:Is enabled - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.model.isEnabled} onChange={checked => {
|
||||
this.updateModelField("isEnabled", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
@@ -13,8 +13,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Controlled as CodeMirror} from "react-codemirror2";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import {Button, Popover, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ModelBackend from "./backend/ModelBackend";
|
||||
@@ -47,7 +48,6 @@ class ModelListPage extends BaseListPage {
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Model - ${randomName}`,
|
||||
modelText: rbacModel,
|
||||
isEnabled: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ class ModelListPage extends BaseListPage {
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "150px",
|
||||
width: "180px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
@@ -107,7 +107,7 @@ class ModelListPage extends BaseListPage {
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: "owner",
|
||||
key: "owner",
|
||||
width: "120px",
|
||||
width: "180px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("owner"),
|
||||
render: (text, record, index) => {
|
||||
@@ -122,7 +122,7 @@ class ModelListPage extends BaseListPage {
|
||||
title: i18next.t("general:Created time"),
|
||||
dataIndex: "createdTime",
|
||||
key: "createdTime",
|
||||
width: "160px",
|
||||
width: "180px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
@@ -137,14 +137,26 @@ class ModelListPage extends BaseListPage {
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Is enabled"),
|
||||
dataIndex: "isEnabled",
|
||||
key: "isEnabled",
|
||||
width: "120px",
|
||||
title: i18next.t("model:Model text"),
|
||||
dataIndex: "modelText",
|
||||
key: "modelText",
|
||||
// width: "180px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Switch disabled checkedChildren="ON" unCheckedChildren="OFF" checked={text} />
|
||||
<Popover placement="topRight" content={() => {
|
||||
return (
|
||||
<CodeMirror
|
||||
value={text}
|
||||
options={{mode: "properties", theme: "default"}}
|
||||
onBeforeChange={(editor, data, value) => {}}
|
||||
/>
|
||||
);
|
||||
}} title="" trigger="hover">
|
||||
{
|
||||
Setting.getShortText(text, 100)
|
||||
}
|
||||
</Popover>
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -152,7 +164,7 @@ class ModelListPage extends BaseListPage {
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "170px",
|
||||
width: "180px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
|
@@ -81,7 +81,6 @@ class OrganizationListPage extends BaseListPage {
|
||||
{name: "Properties", visible: false, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Is online", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Is admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Is global admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Is forbidden", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Is deleted", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{Name: "Multi-factor authentication", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
@@ -182,7 +181,7 @@ class OrganizationListPage extends BaseListPage {
|
||||
title: i18next.t("organization:Website URL"),
|
||||
dataIndex: "websiteUrl",
|
||||
key: "websiteUrl",
|
||||
width: "300px",
|
||||
width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("websiteUrl"),
|
||||
render: (text, record, index) => {
|
||||
@@ -243,7 +242,7 @@ class OrganizationListPage extends BaseListPage {
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "320px",
|
||||
width: "350px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
|
@@ -48,7 +48,7 @@ class PaymentResultPage extends React.Component {
|
||||
});
|
||||
// window.console.log("payment=", res.data);
|
||||
if (res.data.state === "Created") {
|
||||
if (res.data.type === "PayPal") {
|
||||
if (["PayPal", "Stripe"].includes(res.data.type)) {
|
||||
this.setState({
|
||||
timeout: setTimeout(() => {
|
||||
PaymentBackend.notifyPayment(this.state.organizationName, this.state.paymentName)
|
||||
@@ -135,6 +135,26 @@ class PaymentResultPage extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (payment.state === "Timeout") {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
Setting.renderHelmet(payment)
|
||||
}
|
||||
<Result
|
||||
status="warning"
|
||||
title={`${i18next.t("payment:The payment has time out")}: ${payment.productDisplayName}, ${i18next.t("payment:the current state is")}: ${payment.state}`}
|
||||
subTitle={i18next.t("payment:Please click the below button to return to the original website")}
|
||||
extra={[
|
||||
<Button type="primary" key="returnUrl" onClick={() => {
|
||||
this.goToPaymentUrl(payment);
|
||||
}}>
|
||||
{i18next.t("payment:Return to Website")}
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
|
@@ -163,6 +163,8 @@ class ProductBuyPage extends React.Component {
|
||||
text = i18next.t("product:WeChat Pay");
|
||||
} else if (provider.type === "PayPal") {
|
||||
text = i18next.t("product:PayPal");
|
||||
} else if (provider.type === "Stripe") {
|
||||
text = i18next.t("product:Stripe");
|
||||
}
|
||||
|
||||
return (
|
||||
|
@@ -13,18 +13,20 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||
import {Button, Card, Checkbox, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import {authConfig} from "./auth/Auth";
|
||||
import * as ProviderEditTestEmail from "./common/TestEmailWidget";
|
||||
import * as ProviderNotification from "./common/TestNotificationWidget";
|
||||
import * as ProviderEditTestSms from "./common/TestSmsWidget";
|
||||
import copy from "copy-to-clipboard";
|
||||
import {CaptchaPreview} from "./common/CaptchaPreview";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import {CountryCodeSelect} from "./common/select/CountryCodeSelect";
|
||||
import * as Web3Auth from "./auth/Web3Auth";
|
||||
|
||||
const {Option} = Select;
|
||||
const {TextArea} = Input;
|
||||
@@ -274,6 +276,11 @@ class ProviderEditPage extends React.Component {
|
||||
text = i18next.t("provider:App ID");
|
||||
tooltip = i18next.t("provider:App ID - Tooltip");
|
||||
}
|
||||
} else if (provider.category === "Notification") {
|
||||
if (provider.type === "Telegram") {
|
||||
text = i18next.t("provider:Api Token");
|
||||
tooltip = i18next.t("provider:Api Token - Tooltip");
|
||||
}
|
||||
}
|
||||
|
||||
if (text === "" && tooltip === "") {
|
||||
@@ -378,6 +385,8 @@ class ProviderEditPage extends React.Component {
|
||||
this.updateProviderField("type", "Default");
|
||||
} else if (value === "Web3") {
|
||||
this.updateProviderField("type", "MetaMask");
|
||||
} else if (value === "Notification") {
|
||||
this.updateProviderField("type", "Telegram");
|
||||
}
|
||||
})}>
|
||||
{
|
||||
@@ -390,6 +399,7 @@ class ProviderEditPage extends React.Component {
|
||||
{id: "SMS", name: "SMS"},
|
||||
{id: "Storage", name: "Storage"},
|
||||
{id: "Web3", name: "Web3"},
|
||||
{id: "Notification", name: "Notification"},
|
||||
]
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.map((providerCategory, index) => <Option key={index} value={providerCategory.id}>{providerCategory.name}</Option>)
|
||||
@@ -554,7 +564,7 @@ class ProviderEditPage extends React.Component {
|
||||
(this.state.provider.category === "Captcha" && this.state.provider.type === "Default") ||
|
||||
(this.state.provider.category === "SMS" && this.state.provider.type === "Custom HTTP SMS") ||
|
||||
(this.state.provider.category === "Web3") ||
|
||||
(this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") ? null : (
|
||||
(this.state.provider.category === "Storage" && this.state.provider.type === "Local File System" || (this.state.provider.category === "Notification")) ? null : (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
@@ -758,7 +768,34 @@ class ProviderEditPage extends React.Component {
|
||||
}
|
||||
{this.getAppIdRow(this.state.provider)}
|
||||
{
|
||||
this.state.provider.category === "Email" ? (
|
||||
this.state.provider.category === "Notification" ? (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Notification content"), i18next.t("provider:Notification content - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<TextArea autoSize={{minRows: 3, maxRows: 100}} value={this.state.provider.content} onChange={e => {
|
||||
this.updateProviderField("content", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Chat Id"), i18next.t("provider:Chat Id - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={4} >
|
||||
<Input value={this.state.provider.receiver} placeholder = {i18next.t("user:Input your chat id")} onChange={e => {
|
||||
this.updateProviderField("receiver", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary"
|
||||
onClick={() => ProviderNotification.sendTestNotification(this.state.provider, this.state.provider.receiver)} >
|
||||
{i18next.t("provider:Send Testing Notification")}
|
||||
</Button>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
) : this.state.provider.category === "Email" ? (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
@@ -1011,6 +1048,30 @@ class ProviderEditPage extends React.Component {
|
||||
</Row>
|
||||
) : null
|
||||
}
|
||||
{
|
||||
this.state.provider.type === "Web3Onboard" ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Wallets"), i18next.t("provider:Wallets - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<Checkbox.Group
|
||||
options={Web3Auth.getWeb3OnboardWalletsOptions()}
|
||||
value={() => {
|
||||
try {
|
||||
return JSON.parse(this.state.provider.metadata);
|
||||
} catch {
|
||||
return ["injected"];
|
||||
}
|
||||
}}
|
||||
onChange={options => {
|
||||
this.updateProviderField("metadata", JSON.stringify(options));
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
) : null
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Provider URL"), i18next.t("provider:Provider URL - Tooltip"))} :
|
||||
|
@@ -46,6 +46,9 @@ export const Countries = [{label: "English", key: "en", country: "US", alt: "Eng
|
||||
{label: "Itariano", key: "it", country: "IT", alt: "Itariano"},
|
||||
{label: "Marley", key: "ms", country: "MY", alt: "Marley"},
|
||||
{label: "Tkiš", key: "tr", country: "TR", alt: "Tkiš"},
|
||||
{label: "لغة عربية", key: "ar", country: "DZ", alt: "لغة عربية"},
|
||||
{label: "עִבְרִית", key: "he", country: "IL", alt: "עִבְרִית"},
|
||||
{label: "Filipino", key: "fi", country: "PH", alt: "Filipino"},
|
||||
];
|
||||
|
||||
export function getThemeData(organization, application) {
|
||||
@@ -217,6 +220,10 @@ export const OtherProviderInfo = {
|
||||
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
|
||||
url: "https://www.paypal.com/",
|
||||
},
|
||||
"Stripe": {
|
||||
logo: `${StaticBaseUrl}/img/social_stripe.png`,
|
||||
url: "https://stripe.com/",
|
||||
},
|
||||
"GC": {
|
||||
logo: `${StaticBaseUrl}/img/payment_gc.png`,
|
||||
url: "https://gc.org",
|
||||
@@ -259,6 +266,16 @@ export const OtherProviderInfo = {
|
||||
logo: `${StaticBaseUrl}/img/social_metamask.svg`,
|
||||
url: "https://metamask.io/",
|
||||
},
|
||||
"Web3Onboard": {
|
||||
logo: `${StaticBaseUrl}/img/social_web3onboard.svg`,
|
||||
url: "https://onboard.blocknative.com/",
|
||||
},
|
||||
},
|
||||
Notification: {
|
||||
"Telegram": {
|
||||
logo: `${StaticBaseUrl}/img/social_telegram.png`,
|
||||
url: "https://telegram.org/",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -609,7 +626,7 @@ export function isAdminUser(account) {
|
||||
if (account === undefined || account === null) {
|
||||
return false;
|
||||
}
|
||||
return account.owner === "built-in" || account.isGlobalAdmin === true;
|
||||
return account.owner === "built-in";
|
||||
}
|
||||
|
||||
export function isLocalAdminUser(account) {
|
||||
@@ -929,6 +946,7 @@ export function getProviderTypeOptions(category) {
|
||||
{id: "Alipay", name: "Alipay"},
|
||||
{id: "WeChat Pay", name: "WeChat Pay"},
|
||||
{id: "PayPal", name: "PayPal"},
|
||||
{id: "Stripe", name: "Stripe"},
|
||||
{id: "GC", name: "GC"},
|
||||
]);
|
||||
} else if (category === "Captcha") {
|
||||
@@ -943,6 +961,11 @@ export function getProviderTypeOptions(category) {
|
||||
} else if (category === "Web3") {
|
||||
return ([
|
||||
{id: "MetaMask", name: "MetaMask"},
|
||||
{id: "Web3Onboard", name: "Web3-Onboard"},
|
||||
]);
|
||||
} else if (category === "Notification") {
|
||||
return ([
|
||||
{id: "Telegram", name: "Telegram"},
|
||||
]);
|
||||
} else {
|
||||
return [];
|
||||
|
@@ -313,16 +313,6 @@ class SyncerEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("syncer:Table primary key"), i18next.t("syncer:Table primary key - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.syncer.tablePrimaryKey} onChange={e => {
|
||||
this.updateSyncerField("tablePrimaryKey", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("syncer:Table columns"), i18next.t("syncer:Table columns - Tooltip"))} :
|
||||
|
@@ -15,9 +15,11 @@
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, InputNumber, List, Result, Row, Select, Space, Spin, Switch, Tag} from "antd";
|
||||
import {withRouter} from "react-router-dom";
|
||||
import {TotpMfaType} from "./auth/MfaSetupPage";
|
||||
import * as GroupBackend from "./backend/GroupBackend";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import EnableMfaModal from "./common/modal/EnableMfaModal";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import CropperDivModal from "./common/modal/CropperDivModal.js";
|
||||
@@ -138,6 +140,10 @@ class UserEditPage extends React.Component {
|
||||
}
|
||||
|
||||
getUserOrganization() {
|
||||
if (this.state.user === null || this.state.organizations.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.state.organizations.filter(organization => organization.name === this.state.user.owner)[0];
|
||||
}
|
||||
|
||||
@@ -206,23 +212,6 @@ class UserEditPage extends React.Component {
|
||||
return this.props.account.countryCode;
|
||||
}
|
||||
|
||||
loadMore = (table, type) => {
|
||||
return <div
|
||||
style={{
|
||||
textAlign: "center",
|
||||
marginTop: 12,
|
||||
height: 32,
|
||||
lineHeight: "32px",
|
||||
}}
|
||||
>
|
||||
<Button onClick={() => {
|
||||
this.setState({
|
||||
multiFactorAuths: Setting.addRow(table, {"type": type}),
|
||||
});
|
||||
}}>{i18next.t("general:Add")}</Button>
|
||||
</div>;
|
||||
};
|
||||
|
||||
deleteMfa = () => {
|
||||
this.setState({
|
||||
RemoveMfaLoading: true,
|
||||
@@ -570,7 +559,7 @@ class UserEditPage extends React.Component {
|
||||
{name: "ID card back", value: "idCardBack"},
|
||||
{name: "ID card with person", value: "idCardWithPerson"},
|
||||
].map((entry) => {
|
||||
return this.renderImage(this.state.user.properties[entry.value] || "", this.getIdCardType(entry.name), this.getIdCardText(entry.name), entry.value, disabled);
|
||||
return this.renderImage(this.state.user.properties === null ? "" : (this.state.user.properties[entry.value] || ""), this.getIdCardType(entry.name), this.getIdCardText(entry.name), entry.value, disabled);
|
||||
})
|
||||
}
|
||||
</Row>
|
||||
@@ -853,19 +842,6 @@ class UserEditPage extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
} else if (accountItem.name === "Is global admin") {
|
||||
return (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("user:Is global admin"), i18next.t("user:Is global admin - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={(Setting.isMobile()) ? 22 : 2} >
|
||||
<Switch disabled={disabled} checked={this.state.user.isGlobalAdmin} onChange={checked => {
|
||||
this.updateUserField("isGlobalAdmin", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
} else if (accountItem.name === "Is forbidden") {
|
||||
return (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
@@ -947,11 +923,18 @@ class UserEditPage extends React.Component {
|
||||
</Button>
|
||||
}
|
||||
</Space>
|
||||
) : <Button type={"default"} onClick={() => {
|
||||
) :
|
||||
<Space>
|
||||
{item.mfaType !== TotpMfaType && Setting.isAdminUser(this.props.account) && window.location.href.indexOf("/users") !== -1 ?
|
||||
<EnableMfaModal user={this.state.user} mfaType={item.mfaType} onSuccess={() => {
|
||||
this.getUser();
|
||||
}} /> : null}
|
||||
<Button type={"default"} onClick={() => {
|
||||
this.props.history.push(`/mfa/setup?mfaType=${item.mfaType}`);
|
||||
}}>
|
||||
{i18next.t("mfa:Setup")}
|
||||
</Button>}
|
||||
</Button>
|
||||
</Space>}
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
@@ -995,11 +978,13 @@ class UserEditPage extends React.Component {
|
||||
<Col span={4} style={{textAlign: "center", margin: "auto"}} key={tag}>
|
||||
{
|
||||
imgUrl ?
|
||||
<div style={{marginBottom: "10px"}}>
|
||||
<a target="_blank" rel="noreferrer" href={imgUrl} style={{marginBottom: "10px"}}>
|
||||
<AccountAvatar src={imgUrl} alt={imgUrl} size={90} style={{marginBottom: "20px"}} />
|
||||
<AccountAvatar src={imgUrl} alt={imgUrl} height={150} />
|
||||
</a>
|
||||
</div>
|
||||
:
|
||||
<Col style={{height: "78%", border: "1px dotted grey", borderRadius: 3, marginBottom: 5}}>
|
||||
<Col style={{height: "78%", border: "1px dotted grey", borderRadius: 3, marginBottom: "10px"}}>
|
||||
<div style={{fontSize: 30, margin: 10}}>+</div>
|
||||
<div style={{verticalAlign: "middle", marginBottom: 10}}>{`Upload ${title}...`}</div>
|
||||
</Col>
|
||||
|
@@ -81,7 +81,6 @@ class UserListPage extends BaseListPage {
|
||||
tag: "staff",
|
||||
region: "",
|
||||
isAdmin: (owner === "built-in"),
|
||||
isGlobalAdmin: (owner === "built-in"),
|
||||
IsForbidden: false,
|
||||
score: this.state.organization.initScore,
|
||||
isDeleted: false,
|
||||
@@ -354,18 +353,6 @@ class UserListPage extends BaseListPage {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("user:Is global admin"),
|
||||
dataIndex: "isGlobalAdmin",
|
||||
key: "isGlobalAdmin",
|
||||
width: "140px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Switch disabled checkedChildren="ON" unCheckedChildren="OFF" checked={text} />
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("user:Is forbidden"),
|
||||
dataIndex: "isForbidden",
|
||||
|
@@ -79,7 +79,6 @@ const userTemplate = {
|
||||
"ranking": 10,
|
||||
"isOnline": false,
|
||||
"isAdmin": true,
|
||||
"isGlobalAdmin": false,
|
||||
"isForbidden": false,
|
||||
"isDeleted": false,
|
||||
"signupApplication": "app-casnode",
|
||||
|
@@ -17,7 +17,7 @@ import {MetaMaskAvatar} from "react-metamask-avatar";
|
||||
|
||||
class AccountAvatar extends React.Component {
|
||||
render() {
|
||||
const {src, size} = this.props;
|
||||
const {src, size, width, height} = this.props;
|
||||
// The avatar for Metamask account is directly generated by an algorithm based on the address
|
||||
// src = "metamask:0xC304b2cC0Be8E9ce10fF3Afd34820Ed306A23600";
|
||||
const matchMetaMask = src.match(/^metamask:(\w+)$/);
|
||||
@@ -27,9 +27,19 @@ class AccountAvatar extends React.Component {
|
||||
<MetaMaskAvatar address={address} size={size} />
|
||||
);
|
||||
}
|
||||
if (size !== undefined) {
|
||||
return (
|
||||
<img width={size} height={size} src={src} />
|
||||
);
|
||||
} else if (width === undefined) {
|
||||
return (
|
||||
<img height={height} src={src} />
|
||||
);
|
||||
} else if (height === undefined) {
|
||||
return (
|
||||
<img width={width} src={src} />
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -46,6 +46,10 @@ export function getEmailAndPhone(organization, username) {
|
||||
}).then((res) => res.json());
|
||||
}
|
||||
|
||||
export function casLoginParamsToQuery(casParams) {
|
||||
return `?type=${casParams?.type}&id=${casParams?.id}&redirectUri=${casParams?.service}`;
|
||||
}
|
||||
|
||||
export function oAuthParamsToQuery(oAuthParams) {
|
||||
// login
|
||||
if (oAuthParams === null || oAuthParams === undefined) {
|
||||
@@ -53,11 +57,12 @@ export function oAuthParamsToQuery(oAuthParams) {
|
||||
}
|
||||
|
||||
// code
|
||||
return `?clientId=${oAuthParams.clientId}&responseType=${oAuthParams.responseType}&redirectUri=${encodeURIComponent(oAuthParams.redirectUri)}&scope=${oAuthParams.scope}&state=${oAuthParams.state}&nonce=${oAuthParams.nonce}&code_challenge_method=${oAuthParams.challengeMethod}&code_challenge=${oAuthParams.codeChallenge}`;
|
||||
return `?clientId=${oAuthParams.clientId}&responseType=${oAuthParams.responseType}&redirectUri=${encodeURIComponent(oAuthParams.redirectUri)}&type=${oAuthParams.type}&scope=${oAuthParams.scope}&state=${oAuthParams.state}&nonce=${oAuthParams.nonce}&code_challenge_method=${oAuthParams.challengeMethod}&code_challenge=${oAuthParams.codeChallenge}`;
|
||||
}
|
||||
|
||||
export function getApplicationLogin(oAuthParams) {
|
||||
return fetch(`${authConfig.serverUrl}/api/get-app-login${oAuthParamsToQuery(oAuthParams)}`, {
|
||||
export function getApplicationLogin(params) {
|
||||
const queryParams = (params?.type === "cas") ? casLoginParamsToQuery(params) : oAuthParamsToQuery(params);
|
||||
return fetch(`${authConfig.serverUrl}/api/get-app-login${queryParams}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
|
@@ -95,7 +95,7 @@ class AuthCallback extends React.Component {
|
||||
if (code === null) {
|
||||
code = params.get("authCode");
|
||||
}
|
||||
// The code for Metamask is the JSON-serialized string of Web3AuthToken
|
||||
// The code for Web3 is the JSON-serialized string of Web3AuthToken
|
||||
// Due to the limited length of URLs, we only pass the web3AuthTokenKey
|
||||
if (code === null) {
|
||||
code = params.get("web3AuthTokenKey");
|
||||
|
@@ -71,9 +71,9 @@ class LoginPage extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
if (this.getApplicationObj() === undefined) {
|
||||
if (this.state.type === "login" || this.state.type === "cas" || this.state.type === "saml") {
|
||||
if (this.state.type === "login" || this.state.type === "saml") {
|
||||
this.getApplication();
|
||||
} else if (this.state.type === "code") {
|
||||
} else if (this.state.type === "code" || this.state.type === "cas") {
|
||||
this.getApplicationLogin();
|
||||
} else {
|
||||
Setting.showMessage("error", `Unknown authentication type: ${this.state.type}`);
|
||||
@@ -143,8 +143,8 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
getApplicationLogin() {
|
||||
const oAuthParams = Util.getOAuthGetParameters();
|
||||
AuthBackend.getApplicationLogin(oAuthParams)
|
||||
const loginParams = (this.state.type === "cas") ? Util.getCasLoginParameters("admin", this.state.applicationName) : Util.getOAuthGetParameters();
|
||||
AuthBackend.getApplicationLogin(loginParams)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
const application = res.data;
|
||||
@@ -167,18 +167,16 @@ class LoginPage extends React.Component {
|
||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||
.then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
this.onUpdateApplication(null);
|
||||
this.setState({
|
||||
msg: res.msg,
|
||||
});
|
||||
return ;
|
||||
}
|
||||
this.onUpdateApplication(res.data);
|
||||
});
|
||||
} else {
|
||||
let redirectUri = "";
|
||||
if (this.state.type === "cas") {
|
||||
const casParams = Util.getCasParameters();
|
||||
redirectUri = casParams.service;
|
||||
}
|
||||
OrganizationBackend.getDefaultApplication("admin", this.state.owner, this.state.type, redirectUri)
|
||||
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
const application = res.data;
|
||||
@@ -188,9 +186,9 @@ class LoginPage extends React.Component {
|
||||
});
|
||||
} else {
|
||||
this.onUpdateApplication(null);
|
||||
this.setState({
|
||||
msg: res.msg,
|
||||
});
|
||||
Setting.showMessage("error", res.msg);
|
||||
|
||||
this.props.history.push("/404");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -321,6 +321,10 @@ const authInfo = {
|
||||
scope: "",
|
||||
endpoint: "",
|
||||
},
|
||||
Web3Onboard: {
|
||||
scope: "",
|
||||
endpoint: "",
|
||||
},
|
||||
};
|
||||
|
||||
export function getProviderUrl(provider) {
|
||||
@@ -465,5 +469,7 @@ export function getAuthUrl(application, provider, method) {
|
||||
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
|
||||
} else if (provider.type === "MetaMask") {
|
||||
return `${redirectUri}?state=${state}`;
|
||||
} else if (provider.type === "Web3Onboard") {
|
||||
return `${redirectUri}?state=${state}`;
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ import i18next from "i18next";
|
||||
import * as Provider from "./Provider";
|
||||
import {getProviderLogoURL} from "../Setting";
|
||||
import {GithubLoginButton, GoogleLoginButton} from "react-social-login-buttons";
|
||||
import {authViaMetaMask} from "./Web3Auth";
|
||||
import {authViaMetaMask, authViaWeb3Onboard} from "./Web3Auth";
|
||||
import QqLoginButton from "./QqLoginButton";
|
||||
import FacebookLoginButton from "./FacebookLoginButton";
|
||||
import WeiboLoginButton from "./WeiboLoginButton";
|
||||
@@ -121,6 +121,8 @@ function goToSamlUrl(provider, location) {
|
||||
export function goToWeb3Url(application, provider, method) {
|
||||
if (provider.type === "MetaMask") {
|
||||
authViaMetaMask(application, provider, method);
|
||||
} else if (provider.type === "Web3Onboard") {
|
||||
authViaWeb3Onboard(application, provider, method);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -96,6 +96,20 @@ function getRawGetParameter(key) {
|
||||
return res;
|
||||
}
|
||||
|
||||
export function getCasLoginParameters(owner, name) {
|
||||
const queries = new URLSearchParams(window.location.search);
|
||||
// CAS service
|
||||
let service = getRawGetParameter("service");
|
||||
if (service === "") {
|
||||
service = getRefinedValue(queries.get("service"));
|
||||
}
|
||||
return {
|
||||
id: `${owner}/${encodeURIComponent(name)}`, // application ID,
|
||||
service: service,
|
||||
type: "cas",
|
||||
};
|
||||
}
|
||||
|
||||
export function getOAuthGetParameters(params) {
|
||||
const queries = (params !== undefined) ? params : new URLSearchParams(window.location.search);
|
||||
const clientId = getRefinedValue(queries.get("client_id"));
|
||||
@@ -144,6 +158,7 @@ export function getOAuthGetParameters(params) {
|
||||
samlRequest: samlRequest,
|
||||
relayState: relayState,
|
||||
noRedirect: noRedirect,
|
||||
type: "code",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -18,7 +18,25 @@ import {v4 as uuidv4} from "uuid";
|
||||
import {SignTypedDataVersion, recoverTypedSignature} from "@metamask/eth-sig-util";
|
||||
import {getAuthUrl} from "./Provider";
|
||||
import {Buffer} from "buffer";
|
||||
// import {toChecksumAddress} from "ethereumjs-util";
|
||||
import Onboard from "@web3-onboard/core";
|
||||
import injectedModule from "@web3-onboard/injected-wallets";
|
||||
import infinityWalletModule from "@web3-onboard/infinity-wallet";
|
||||
import sequenceModule from "@web3-onboard/sequence";
|
||||
import trustModule from "@web3-onboard/trust";
|
||||
import frontierModule from "@web3-onboard/frontier";
|
||||
import tahoModule from "@web3-onboard/taho";
|
||||
import coinbaseModule from "@web3-onboard/coinbase";
|
||||
import gnosisModule from "@web3-onboard/gnosis";
|
||||
// import keystoneModule from "@web3-onboard/keystone";
|
||||
// import keepkeyModule from "@web3-onboard/keepkey";
|
||||
// import dcentModule from "@web3-onboard/dcent";
|
||||
// import ledgerModule from "@web3-onboard/ledger";
|
||||
// import trezorModule from "@web3-onboard/trezor";
|
||||
// import walletConnectModule from "@web3-onboard/walletconnect";
|
||||
// import fortmaticModule from "@web3-onboard/fortmatic";
|
||||
// import portisModule from "@web3-onboard/portis";
|
||||
// import magicModule from "@web3-onboard/magic";
|
||||
|
||||
global.Buffer = Buffer;
|
||||
|
||||
export function generateNonce() {
|
||||
@@ -147,3 +165,174 @@ export async function authViaMetaMask(application, provider, method) {
|
||||
showMessage("error", `${i18next.t("login:Failed to obtain MetaMask authorization")}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const web3Wallets = {
|
||||
// injected wallets
|
||||
injected: {
|
||||
label: "Injected",
|
||||
wallet: injectedModule(),
|
||||
},
|
||||
// sdk wallets
|
||||
coinbase: {
|
||||
label: "Coinbase",
|
||||
wallet: coinbaseModule(),
|
||||
},
|
||||
trust: {
|
||||
label: "Trust",
|
||||
wallet: trustModule(),
|
||||
},
|
||||
gnosis: {
|
||||
label: "Gnosis",
|
||||
wallet: gnosisModule(),
|
||||
},
|
||||
sequence: {
|
||||
label: "Sequence",
|
||||
wallet: sequenceModule(),
|
||||
},
|
||||
taho: {
|
||||
label: "Taho",
|
||||
wallet: tahoModule(),
|
||||
},
|
||||
frontier: {
|
||||
label: "Frontier",
|
||||
wallet: frontierModule(),
|
||||
},
|
||||
infinityWallet: {
|
||||
label: "Infinity Wallet",
|
||||
wallet: infinityWalletModule(),
|
||||
},
|
||||
// hardware wallets
|
||||
// keystone: {
|
||||
// label: "Keystone",
|
||||
// wallet: keystoneModule(),
|
||||
// },
|
||||
// keepkey: {
|
||||
// label: "KeepKey",
|
||||
// wallet: keepkeyModule(),
|
||||
// },
|
||||
// dcent: {
|
||||
// label: "D'CENT",
|
||||
// wallet: dcentModule(),
|
||||
// },
|
||||
|
||||
// some wallet need custome `apiKey` or `projectId` configure item
|
||||
// const magic = magicModule({
|
||||
// apiKey: "magicApiKey",
|
||||
// });
|
||||
// const fortmatic = fortmaticModule({
|
||||
// apiKey: "fortmaticApiKey",
|
||||
// });
|
||||
// const portis = portisModule({
|
||||
// apiKey: "portisApiKey",
|
||||
// });
|
||||
// const ledger = ledgerModule({
|
||||
// projectId: "ledgerProjectId"
|
||||
// });
|
||||
// const walletConnect = walletConnectModule({
|
||||
// projectId: "walletConnectProjectId",
|
||||
// });
|
||||
};
|
||||
|
||||
export function getWeb3OnboardWalletsOptions() {
|
||||
return Object.entries(web3Wallets).map(([key, value]) => ({
|
||||
label: value.label,
|
||||
value: key,
|
||||
}));
|
||||
}
|
||||
|
||||
function getWeb3OnboardWallets(options) {
|
||||
if (options === null || options === undefined || !Array.isArray(options)) {
|
||||
return [];
|
||||
}
|
||||
return options.map(walletType => {
|
||||
if (walletType && web3Wallets[walletType]?.wallet) {
|
||||
return web3Wallets[walletType]?.wallet;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function initWeb3Onboard(application, provider) {
|
||||
// init wallet
|
||||
// options = ["injected","coinbase",...]
|
||||
const options = JSON.parse(provider.metadata);
|
||||
const wallets = getWeb3OnboardWallets(options);
|
||||
|
||||
// init chain
|
||||
// const InfuraKey = "2fa45cbe531e4e65be4fcbf408e651a8";
|
||||
const chains = [
|
||||
// {
|
||||
// id: "0x1",
|
||||
// token: "ETH",
|
||||
// label: "Ethereum Mainnet",
|
||||
// rpcUrl: `https://mainnet.infura.io/v3/${InfuraKey}`,
|
||||
// },
|
||||
// {
|
||||
// id: "0x5",
|
||||
// token: "ETH",
|
||||
// label: "Goerli",
|
||||
// rpcUrl: `https://goerli.infura.io/v3/${InfuraKey}`,
|
||||
// },
|
||||
{
|
||||
id: "0x13881",
|
||||
token: "MATIC",
|
||||
label: "Polygon - Mumbai",
|
||||
rpcUrl: "https://matic-mumbai.chainstacklabs.com",
|
||||
},
|
||||
{
|
||||
id: "0x38",
|
||||
token: "BNB",
|
||||
label: "Binance",
|
||||
rpcUrl: "https://bsc-dataseed.binance.org/",
|
||||
},
|
||||
{
|
||||
id: "0xA",
|
||||
token: "OETH",
|
||||
label: "Optimism",
|
||||
rpcUrl: "https://mainnet.optimism.io",
|
||||
},
|
||||
{
|
||||
id: "0xA4B1",
|
||||
token: "ARB-ETH",
|
||||
label: "Arbitrum",
|
||||
rpcUrl: "https://rpc.ankr.com/arbitrum",
|
||||
},
|
||||
];
|
||||
|
||||
const appMetadata = {
|
||||
name: "Casdoor",
|
||||
description: "Connect a wallet using Casdoor",
|
||||
recommendedInjectedWallets: [
|
||||
{name: "MetaMask", url: "https://metamask.io"},
|
||||
{name: "Coinbase", url: "https://wallet.coinbase.com/"},
|
||||
],
|
||||
};
|
||||
|
||||
const web3Onboard = Onboard({
|
||||
wallets,
|
||||
chains,
|
||||
appMetadata,
|
||||
});
|
||||
return web3Onboard;
|
||||
}
|
||||
|
||||
export async function authViaWeb3Onboard(application, provider, method) {
|
||||
try {
|
||||
const onboard = initWeb3Onboard(application, provider);
|
||||
const connectedWallets = await onboard.connectWallet();
|
||||
if (connectedWallets.length > 0) {
|
||||
const wallet = connectedWallets[0];
|
||||
const account = wallet.accounts[0];
|
||||
const address = account.address;
|
||||
const token = {
|
||||
address: address, // e.g."0xbd5444d31fe4139ee36bea29e43d4ac67ae276de"
|
||||
walletType: wallet.label, // e.g."MetaMask"
|
||||
createAt: Math.floor(new Date().getTime() / 1000),
|
||||
};
|
||||
setWeb3AuthToken(token);
|
||||
const redirectUri = `${getAuthUrl(application, provider, method)}&web3AuthTokenKey=${getWeb3AuthTokenKey(address)}`;
|
||||
goToLink(redirectUri);
|
||||
}
|
||||
} catch (err) {
|
||||
showMessage("error", `${i18next.t("login:Failed to obtain Web3-Onboard authorization")}: ${err}`);
|
||||
}
|
||||
}
|
||||
|
@@ -103,8 +103,8 @@ export function RemovePolicy(owner, name, policy) {
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getPolicies(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-policies?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
export function getPolicies(owner, name, adapterId = "") {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-policies?id=${owner}/${encodeURIComponent(name)}&adapterId=${adapterId}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
|
25
web/src/backend/DashboardBackend.js
Normal file
25
web/src/backend/DashboardBackend.js
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getDashboard(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-dashboard`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
@@ -24,8 +24,8 @@ export function getEnforcers(owner, page = "", pageSize = "", field = "", value
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getEnforcer(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-enforcer?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
export function getEnforcer(owner, name, loadModelCfg = false) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-enforcer?id=${owner}/${encodeURIComponent(name)}&loadModelCfg=${loadModelCfg}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
|
@@ -70,8 +70,8 @@ export function deleteOrganization(organization) {
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getDefaultApplication(owner, name, type = "", redirectUri = "") {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-default-application?id=${owner}/${encodeURIComponent(name)}&type=${type}&redirectUri=${redirectUri}`, {
|
||||
export function getDefaultApplication(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-default-application?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
|
@@ -13,8 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Card, Col, Row} from "antd";
|
||||
import {Card, Col, Row, Spin, Statistic} from "antd";
|
||||
import {ArrowUpOutlined} from "@ant-design/icons";
|
||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||
import * as DashboardBackend from "../backend/DashboardBackend";
|
||||
import * as echarts from "echarts";
|
||||
import * as Setting from "../Setting";
|
||||
import SingleCard from "./SingleCard";
|
||||
import i18next from "i18next";
|
||||
@@ -25,11 +28,13 @@ class HomePage extends React.Component {
|
||||
this.state = {
|
||||
classes: props,
|
||||
applications: null,
|
||||
dashboardData: null,
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getApplicationsByOrganization(this.props.account.owner);
|
||||
this.getDashboard();
|
||||
}
|
||||
|
||||
getApplicationsByOrganization(organizationName) {
|
||||
@@ -41,6 +46,21 @@ class HomePage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getDashboard() {
|
||||
DashboardBackend.getDashboard()
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
dashboardData: res.data,
|
||||
}, () => {
|
||||
this.renderEChart();
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getItems() {
|
||||
let items = [];
|
||||
if (Setting.isAdminUser(this.props.account)) {
|
||||
@@ -75,9 +95,53 @@ class HomePage extends React.Component {
|
||||
return items;
|
||||
}
|
||||
|
||||
renderEChart() {
|
||||
const data = this.state.dashboardData;
|
||||
|
||||
const chartDom = document.getElementById("echarts-chart");
|
||||
const myChart = echarts.init(chartDom);
|
||||
const currentDate = new Date();
|
||||
const dateArray = [];
|
||||
for (let i = 30; i >= 0; i--) {
|
||||
const date = new Date(currentDate);
|
||||
date.setDate(date.getDate() - i);
|
||||
const month = parseInt(date.getMonth()) + 1;
|
||||
const day = parseInt(date.getDate());
|
||||
const formattedDate = `${month}-${day}`;
|
||||
dateArray.push(formattedDate);
|
||||
}
|
||||
const option = {
|
||||
title: {text: i18next.t("home:Past 30 Days")},
|
||||
tooltip: {trigger: "axis"},
|
||||
legend: {data: [
|
||||
i18next.t("general:Users"),
|
||||
i18next.t("general:Providers"),
|
||||
i18next.t("general:Applications"),
|
||||
i18next.t("general:Organizations"),
|
||||
i18next.t("general:Subscriptions"),
|
||||
]},
|
||||
grid: {left: "3%", right: "4%", bottom: "3%", containLabel: true},
|
||||
xAxis: {type: "category", boundaryGap: false, data: dateArray},
|
||||
yAxis: {type: "value"},
|
||||
series: [
|
||||
{name: i18next.t("general:Organizations"), type: "line", data: data?.organizationCounts},
|
||||
{name: i18next.t("general:Users"), type: "line", data: data?.userCounts},
|
||||
{name: i18next.t("general:Providers"), type: "line", data: data?.providerCounts},
|
||||
{name: i18next.t("general:Applications"), type: "line", data: data?.applicationCounts},
|
||||
{name: i18next.t("general:Subscriptions"), type: "line", data: data?.subscriptionCounts},
|
||||
],
|
||||
};
|
||||
myChart.setOption(option);
|
||||
}
|
||||
|
||||
renderCards() {
|
||||
if (this.state.applications === null) {
|
||||
return null;
|
||||
const data = this.state.dashboardData;
|
||||
if (data === null) {
|
||||
return (
|
||||
<div style={{display: "flex", justifyContent: "center", alignItems: "center", marginTop: "10%"}}>
|
||||
<Spin size="large" tip={i18next.t("login:Loading")} style={{paddingTop: "10%"}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const items = this.getItems();
|
||||
@@ -96,24 +160,35 @@ class HomePage extends React.Component {
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div style={{marginRight: "15px", marginLeft: "15px"}}>
|
||||
<Row style={{marginLeft: "-20px", marginRight: "-20px", marginTop: "20px"}} gutter={24}>
|
||||
{
|
||||
items.map(item => {
|
||||
return (
|
||||
<SingleCard logo={item.logo} link={item.link} title={item.name} desc={item.organizer} time={item.createdTime} isSingle={items.length === 1} key={item.name} />
|
||||
);
|
||||
})
|
||||
}
|
||||
<Row gutter={80}>
|
||||
<Col span={50}>
|
||||
<Card bordered={false} bodyStyle={{width: "100%", height: "150px", display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Statistic title={i18next.t("home:Total users")} fontSize="100px" value={data?.userCounts[30]} valueStyle={{fontSize: "30px"}} style={{width: "200px", paddingLeft: "10px"}} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={50}>
|
||||
<Card bordered={false} bodyStyle={{width: "100%", height: "150px", display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Statistic title={i18next.t("home:New users today")} fontSize="100px" value={data?.userCounts[30] - data?.userCounts[30 - 1]} valueStyle={{fontSize: "30px"}} prefix={<ArrowUpOutlined />} style={{width: "200px", paddingLeft: "10px"}} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={50}>
|
||||
<Card bordered={false} bodyStyle={{width: "100%", height: "150px", display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Statistic title={i18next.t("home:New users past 7 days")} value={data?.userCounts[30] - data?.userCounts[30 - 7]} valueStyle={{fontSize: "30px"}} prefix={<ArrowUpOutlined />} style={{width: "200px", paddingLeft: "10px"}} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={50}>
|
||||
<Card bordered={false} bodyStyle={{width: "100%", height: "150px", display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Statistic title={i18next.t("home:New users past 30 days")} value={data?.userCounts[30] - data?.userCounts[30 - 30]} valueStyle={{fontSize: "30px"}} prefix={<ArrowUpOutlined />} style={{width: "200px", paddingLeft: "10px"}} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div style={{display: "flex", justifyContent: "center", flexDirection: "column", alignItems: "center"}}>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={24} style={{display: "flex", justifyContent: "center"}} >
|
||||
{
|
||||
@@ -121,6 +196,8 @@ class HomePage extends React.Component {
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
<div id="echarts-chart"
|
||||
style={{width: "80%", height: "400px", textAlign: "center", marginTop: "20px"}}></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -97,7 +97,7 @@ class OAuthWidget extends React.Component {
|
||||
// should add the unlink user's info, cause the user may not be logged in, but a admin want to unlink the user.
|
||||
user: this.props.user,
|
||||
};
|
||||
if (providerType === "MetaMask") {
|
||||
if (providerType === "MetaMask" || providerType === "Web3Onboard") {
|
||||
delWeb3AuthToken(linkedValue);
|
||||
}
|
||||
AuthBackend.unlink(body)
|
||||
@@ -158,7 +158,12 @@ class OAuthWidget extends React.Component {
|
||||
</Col>
|
||||
<Col span={24 - this.props.labelSpan} >
|
||||
<AccountAvatar style={{marginRight: "10px"}} size={30} src={avatarUrl} alt={name} referrerPolicy="no-referrer" />
|
||||
<span style={{width: this.props.labelSpan === 3 ? "300px" : "200px", display: (Setting.isMobile()) ? "inline" : "inline-block"}}>
|
||||
<span style={{
|
||||
width: this.props.labelSpan === 3 ? "300px" : "200px",
|
||||
display: (Setting.isMobile()) ? "inline" : "inline-block",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
}} title={name}>
|
||||
{
|
||||
linkedValue === "" ? (
|
||||
`(${i18next.t("general:empty")})`
|
||||
@@ -183,7 +188,7 @@ class OAuthWidget extends React.Component {
|
||||
</a>
|
||||
)
|
||||
) : (
|
||||
<Button disabled={!providerItem.canUnlink && !account.isGlobalAdmin} style={{marginLeft: "20px", width: linkButtonWidth}} onClick={() => this.unlinkUser(provider.type, linkedValue)}>{i18next.t("user:Unlink")}</Button>
|
||||
<Button disabled={!providerItem.canUnlink && !Setting.isAdminUser(account)} style={{marginLeft: "20px", width: linkButtonWidth}} onClick={() => this.unlinkUser(provider.type, linkedValue)}>{i18next.t("user:Unlink")}</Button>
|
||||
)
|
||||
}
|
||||
</Col>
|
||||
|
@@ -19,7 +19,7 @@ export function sendTestEmail(provider, email) {
|
||||
testEmailProvider(provider, email)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", `${i18next.t("provider:Email sent successfully")}`);
|
||||
Setting.showMessage("success", i18next.t("general:Successfully sent"));
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
|
42
web/src/common/TestNotificationWidget.js
Normal file
42
web/src/common/TestNotificationWidget.js
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function sendTestNotification(provider, notification) {
|
||||
testNotificationProvider(provider, notification)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully sent"));
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
function testNotificationProvider(provider, email = "") {
|
||||
const notificationForm = {
|
||||
content: provider.content,
|
||||
};
|
||||
|
||||
return fetch(`${Setting.ServerUrl}/api/send-notification?provider=` + provider.name, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(notificationForm),
|
||||
}).then(res => res.json());
|
||||
}
|
@@ -19,7 +19,7 @@ export function sendTestSms(provider, phone) {
|
||||
testSmsProvider(provider, phone)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", `${i18next.t("provider:SMS sent successfully")}`);
|
||||
Setting.showMessage("success", i18next.t("general:Successfully sent"));
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
|
113
web/src/common/modal/EnableMfaModal.js
Normal file
113
web/src/common/modal/EnableMfaModal.js
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import {Button, Modal} from "antd";
|
||||
import i18next from "i18next";
|
||||
import React from "react";
|
||||
import {useEffect, useState} from "react";
|
||||
import {EmailMfaType} from "../../auth/MfaSetupPage";
|
||||
import * as MfaBackend from "../../backend/MfaBackend";
|
||||
import * as Setting from "../../Setting";
|
||||
|
||||
const EnableMfaModal = ({user, mfaType, onSuccess}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || !user) {
|
||||
return;
|
||||
}
|
||||
MfaBackend.MfaSetupInitiate({
|
||||
mfaType,
|
||||
...user,
|
||||
}).then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", i18next.t("mfa:Failed to initiate MFA"));
|
||||
}
|
||||
});
|
||||
}, [open]);
|
||||
|
||||
const handleOk = () => {
|
||||
setLoading(true);
|
||||
MfaBackend.MfaSetupEnable({
|
||||
mfaType,
|
||||
...user,
|
||||
}).then(res => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Enabled successfully"));
|
||||
setOpen(false);
|
||||
onSuccess();
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to enable")}: ${res.msg}`);
|
||||
}
|
||||
}
|
||||
).finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const showModal = () => {
|
||||
if (!isValid()) {
|
||||
if (mfaType === EmailMfaType) {
|
||||
Setting.showMessage("error", i18next.t("signup:Please input your Email!"));
|
||||
} else {
|
||||
Setting.showMessage("error", i18next.t("signup:Please input your phone number!"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const renderText = () => {
|
||||
return (
|
||||
<p>{i18next.t("mfa:Please confirm the information below")}<br />
|
||||
<b>{i18next.t("general:User")}</b>: {`${user.owner}/${user.name}`}<br />
|
||||
{mfaType === EmailMfaType ?
|
||||
<><b>{i18next.t("general:Email")}</b> : {user.email}</> :
|
||||
<><b>{i18next.t("general:Phone")}</b> : {user.phone}</>}
|
||||
</p>
|
||||
);
|
||||
};
|
||||
|
||||
const isValid = () => {
|
||||
if (mfaType === EmailMfaType) {
|
||||
return user.email !== "";
|
||||
} else {
|
||||
return user.phone !== "";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button type="primary" onClick={showModal}>
|
||||
{i18next.t("general:Enable")}
|
||||
</Button>
|
||||
<Modal
|
||||
title={i18next.t("mfa:Enable multi-factor authentication")}
|
||||
open={open}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
confirmLoading={loading}
|
||||
>
|
||||
{renderText()}
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default EnableMfaModal;
|
@@ -27,6 +27,9 @@ import pt from "./locales/pt/data.json";
|
||||
import it from "./locales/it/data.json";
|
||||
import ms from "./locales/ms/data.json";
|
||||
import tr from "./locales/tr/data.json";
|
||||
import ar from "./locales/ar/data.json";
|
||||
import he from "./locales/he/data.json";
|
||||
import fi from "./locales/fi/data.json";
|
||||
import * as Conf from "./Conf";
|
||||
import {initReactI18next} from "react-i18next";
|
||||
|
||||
@@ -45,6 +48,9 @@ const resources = {
|
||||
it: it,
|
||||
ms: ms,
|
||||
tr: tr,
|
||||
ar: ar,
|
||||
he: he,
|
||||
fi: fi,
|
||||
};
|
||||
|
||||
function initLanguage() {
|
||||
@@ -103,6 +109,15 @@ function initLanguage() {
|
||||
case "tr":
|
||||
language = "tr";
|
||||
break;
|
||||
case "ar":
|
||||
language = "ar";
|
||||
break;
|
||||
case "he":
|
||||
language = "he";
|
||||
break;
|
||||
case "fi":
|
||||
language = "fi";
|
||||
break;
|
||||
default:
|
||||
language = Conf.DefaultLanguage;
|
||||
}
|
||||
|
1008
web/src/locales/ar/data.json
Normal file
1008
web/src/locales/ar/data.json
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user