mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-25 08:20:30 +08:00
Compare commits
87 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
53ad454962 | ||
![]() |
fb203a6f30 | ||
![]() |
f716a0985f | ||
![]() |
340fbe135d | ||
![]() |
79119760f2 | ||
![]() |
4dd67a8dcb | ||
![]() |
deed857788 | ||
![]() |
802995ed16 | ||
![]() |
b14554a5ba | ||
![]() |
4665ffa759 | ||
![]() |
f914e8e929 | ||
![]() |
dc33b41107 | ||
![]() |
ee8dd23a56 | ||
![]() |
08d0269e30 | ||
![]() |
8e5cd18c91 | ||
![]() |
32b4d98c2a | ||
![]() |
2ea58cd639 | ||
![]() |
45d2745b67 | ||
![]() |
cba338eef2 | ||
![]() |
c428de6e42 | ||
![]() |
9bca6bb72e | ||
![]() |
cd966116d4 | ||
![]() |
9abf1b9d73 | ||
![]() |
6aaba6debd | ||
![]() |
77565712e0 | ||
![]() |
d025259db7 | ||
![]() |
aafdc546fa | ||
![]() |
539ca2d731 | ||
![]() |
ea326b3513 | ||
![]() |
98ef766fb4 | ||
![]() |
e94ada9ea2 | ||
![]() |
4ea482223d | ||
![]() |
d55ae7d1d2 | ||
![]() |
d72e00605f | ||
![]() |
be74cb621f | ||
![]() |
13404d6035 | ||
![]() |
afa9c530ad | ||
![]() |
1600615aca | ||
![]() |
2bb8491499 | ||
![]() |
293283ed25 | ||
![]() |
9cb519d1e9 | ||
![]() |
fb9b8f1662 | ||
![]() |
2fec3f72ae | ||
![]() |
11695220a8 | ||
![]() |
155660b0d7 | ||
![]() |
1c72f5300c | ||
![]() |
3dd56195d9 | ||
![]() |
8865244262 | ||
![]() |
3400fa1e9c | ||
![]() |
bdc5c92ef0 | ||
![]() |
4e3eedf246 | ||
![]() |
8e98fc5a9f | ||
![]() |
6f6159be07 | ||
![]() |
3e4dbc2dcb | ||
![]() |
48b5b27982 | ||
![]() |
1839252c30 | ||
![]() |
1fff1db6a7 | ||
![]() |
a0b0e186b7 | ||
![]() |
8c7f235ee1 | ||
![]() |
a0a762aa6f | ||
![]() |
2eec53a6d0 | ||
![]() |
117dec4542 | ||
![]() |
895cdd024d | ||
![]() |
f0b0891ac9 | ||
![]() |
10449e89ab | ||
![]() |
6e70f0fc58 | ||
![]() |
2bca424370 | ||
![]() |
de49a45e19 | ||
![]() |
f7243f879b | ||
![]() |
7f3b2500b3 | ||
![]() |
208dc11d25 | ||
![]() |
503d244166 | ||
![]() |
475b6da35a | ||
![]() |
b9404f14dc | ||
![]() |
0baae87390 | ||
![]() |
06759041a8 | ||
![]() |
cf4e76f9dc | ||
![]() |
81f2d01dc1 | ||
![]() |
61773d3173 | ||
![]() |
ec29621547 | ||
![]() |
b8e324cadf | ||
![]() |
f37fd6ba87 | ||
![]() |
b4bf734fe8 | ||
![]() |
f0431701c9 | ||
![]() |
aa5078de15 | ||
![]() |
9a324b2cca | ||
![]() |
919eaf1df4 |
14
Dockerfile
14
Dockerfile
@@ -14,13 +14,16 @@ RUN ./build.sh
|
|||||||
FROM alpine:latest AS STANDARD
|
FROM alpine:latest AS STANDARD
|
||||||
LABEL MAINTAINER="https://casdoor.org/"
|
LABEL MAINTAINER="https://casdoor.org/"
|
||||||
|
|
||||||
WORKDIR /app
|
RUN sed -i 's/https/http/' /etc/apk/repositories
|
||||||
|
RUN apk add curl
|
||||||
|
RUN apk add ca-certificates && update-ca-certificates
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
COPY --from=BACK /go/src/casdoor/server ./server
|
COPY --from=BACK /go/src/casdoor/server ./server
|
||||||
COPY --from=BACK /go/src/casdoor/swagger ./swagger
|
COPY --from=BACK /go/src/casdoor/swagger ./swagger
|
||||||
COPY --from=BACK /go/src/casdoor/conf/app.conf ./conf/app.conf
|
COPY --from=BACK /go/src/casdoor/conf/app.conf ./conf/app.conf
|
||||||
COPY --from=FRONT /web/build ./web/build
|
COPY --from=FRONT /web/build ./web/build
|
||||||
VOLUME /app/files /app/logs
|
ENTRYPOINT ["/server"]
|
||||||
ENTRYPOINT ["/app/server"]
|
|
||||||
|
|
||||||
|
|
||||||
FROM debian:latest AS db
|
FROM debian:latest AS db
|
||||||
@@ -34,9 +37,10 @@ RUN apt update \
|
|||||||
FROM db AS ALLINONE
|
FROM db AS ALLINONE
|
||||||
LABEL MAINTAINER="https://casdoor.org/"
|
LABEL MAINTAINER="https://casdoor.org/"
|
||||||
|
|
||||||
ENV MYSQL_ROOT_PASSWORD=123456
|
RUN apt update
|
||||||
|
RUN apt install -y ca-certificates && update-ca-certificates
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /
|
||||||
COPY --from=BACK /go/src/casdoor/server ./server
|
COPY --from=BACK /go/src/casdoor/server ./server
|
||||||
COPY --from=BACK /go/src/casdoor/swagger ./swagger
|
COPY --from=BACK /go/src/casdoor/swagger ./swagger
|
||||||
COPY --from=BACK /go/src/casdoor/docker-entrypoint.sh /docker-entrypoint.sh
|
COPY --from=BACK /go/src/casdoor/docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
@@ -98,7 +98,7 @@ For casdoor, if you have any questions, you can give Issues, or you can also dir
|
|||||||
|
|
||||||
### I18n translation
|
### I18n translation
|
||||||
|
|
||||||
If you are contributing to casdoor, please note that we use [Crowdin](https://crowdin.com/project/casdoor-web) as translating platform and i18next as translating tool. When you add some words using i18next in the ```web/``` directory, please remember to add what you have added to the ```web/src/locales/en/data.json``` file.
|
If you are contributing to casdoor, please note that we use [Crowdin](https://crowdin.com/project/casdoor-site) as translating platform and i18next as translating tool. When you add some words using i18next in the ```web/``` directory, please remember to add what you have added to the ```web/src/locales/en/data.json``` file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -78,11 +78,12 @@ p, *, *, POST, /api/get-email-and-phone, *, *
|
|||||||
p, *, *, POST, /api/login, *, *
|
p, *, *, POST, /api/login, *, *
|
||||||
p, *, *, GET, /api/get-app-login, *, *
|
p, *, *, GET, /api/get-app-login, *, *
|
||||||
p, *, *, POST, /api/logout, *, *
|
p, *, *, POST, /api/logout, *, *
|
||||||
|
p, *, *, GET, /api/logout, *, *
|
||||||
p, *, *, GET, /api/get-account, *, *
|
p, *, *, GET, /api/get-account, *, *
|
||||||
p, *, *, GET, /api/userinfo, *, *
|
p, *, *, GET, /api/userinfo, *, *
|
||||||
p, *, *, *, /api/login/oauth, *, *
|
p, *, *, *, /api/login/oauth, *, *
|
||||||
p, *, *, GET, /api/get-application, *, *
|
p, *, *, GET, /api/get-application, *, *
|
||||||
p, *, *, GET, /api/get-applications, *, *
|
p, *, *, GET, /api/get-organization-applications, *, *
|
||||||
p, *, *, GET, /api/get-user, *, *
|
p, *, *, GET, /api/get-user, *, *
|
||||||
p, *, *, GET, /api/get-user-application, *, *
|
p, *, *, GET, /api/get-user-application, *, *
|
||||||
p, *, *, GET, /api/get-resources, *, *
|
p, *, *, GET, /api/get-resources, *, *
|
||||||
@@ -91,7 +92,7 @@ p, *, *, POST, /api/buy-product, *, *
|
|||||||
p, *, *, GET, /api/get-payment, *, *
|
p, *, *, GET, /api/get-payment, *, *
|
||||||
p, *, *, POST, /api/update-payment, *, *
|
p, *, *, POST, /api/update-payment, *, *
|
||||||
p, *, *, POST, /api/invoice-payment, *, *
|
p, *, *, POST, /api/invoice-payment, *, *
|
||||||
p, *, *, GET, /api/get-providers, *, *
|
p, *, *, POST, /api/notify-payment, *, *
|
||||||
p, *, *, POST, /api/unlink, *, *
|
p, *, *, POST, /api/unlink, *, *
|
||||||
p, *, *, POST, /api/set-password, *, *
|
p, *, *, POST, /api/set-password, *, *
|
||||||
p, *, *, POST, /api/send-verification-code, *, *
|
p, *, *, POST, /api/send-verification-code, *, *
|
||||||
@@ -105,6 +106,7 @@ p, *, *, GET, /api/get-saml-login, *, *
|
|||||||
p, *, *, POST, /api/acs, *, *
|
p, *, *, POST, /api/acs, *, *
|
||||||
p, *, *, GET, /api/saml/metadata, *, *
|
p, *, *, GET, /api/saml/metadata, *, *
|
||||||
p, *, *, *, /cas, *, *
|
p, *, *, *, /cas, *, *
|
||||||
|
p, *, *, *, /api/webauthn, *, *
|
||||||
`
|
`
|
||||||
|
|
||||||
sa := stringadapter.NewAdapter(ruleText)
|
sa := stringadapter.NewAdapter(ruleText)
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -31,8 +31,7 @@ import (
|
|||||||
|
|
||||||
const AliyunCaptchaVerifyUrl = "http://afs.aliyuncs.com"
|
const AliyunCaptchaVerifyUrl = "http://afs.aliyuncs.com"
|
||||||
|
|
||||||
type AliyunCaptchaProvider struct {
|
type AliyunCaptchaProvider struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func NewAliyunCaptchaProvider() *AliyunCaptchaProvider {
|
func NewAliyunCaptchaProvider() *AliyunCaptchaProvider {
|
||||||
captcha := &AliyunCaptchaProvider{}
|
captcha := &AliyunCaptchaProvider{}
|
||||||
@@ -81,7 +80,7 @@ func (captcha *AliyunCaptchaProvider) VerifyCaptcha(token, clientSecret string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@@ -16,8 +16,7 @@ package captcha
|
|||||||
|
|
||||||
import "github.com/casdoor/casdoor/object"
|
import "github.com/casdoor/casdoor/object"
|
||||||
|
|
||||||
type DefaultCaptchaProvider struct {
|
type DefaultCaptchaProvider struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func NewDefaultCaptchaProvider() *DefaultCaptchaProvider {
|
func NewDefaultCaptchaProvider() *DefaultCaptchaProvider {
|
||||||
captcha := &DefaultCaptchaProvider{}
|
captcha := &DefaultCaptchaProvider{}
|
||||||
|
81
captcha/geetest.go
Normal file
81
captcha/geetest.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// Copyright 2022 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 captcha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
const GEETESTCaptchaVerifyUrl = "http://gcaptcha4.geetest.com/validate"
|
||||||
|
|
||||||
|
type GEETESTCaptchaProvider struct{}
|
||||||
|
|
||||||
|
func NewGEETESTCaptchaProvider() *GEETESTCaptchaProvider {
|
||||||
|
captcha := &GEETESTCaptchaProvider{}
|
||||||
|
return captcha
|
||||||
|
}
|
||||||
|
|
||||||
|
func (captcha *GEETESTCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
||||||
|
pathData, err := url.ParseQuery(token)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
signToken := util.GetHmacSha256(clientSecret, pathData["lot_number"][0])
|
||||||
|
|
||||||
|
formData := make(url.Values)
|
||||||
|
formData["lot_number"] = []string{pathData["lot_number"][0]}
|
||||||
|
formData["captcha_output"] = []string{pathData["captcha_output"][0]}
|
||||||
|
formData["pass_token"] = []string{pathData["pass_token"][0]}
|
||||||
|
formData["gen_time"] = []string{pathData["gen_time"][0]}
|
||||||
|
formData["sign_token"] = []string{signToken}
|
||||||
|
captchaId := pathData["captcha_id"][0]
|
||||||
|
|
||||||
|
cli := http.Client{Timeout: time.Second * 5}
|
||||||
|
resp, err := cli.PostForm(fmt.Sprintf("%s?captcha_id=%s", GEETESTCaptchaVerifyUrl, captchaId), formData)
|
||||||
|
if err != nil || resp.StatusCode != 200 {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type captchaResponse struct {
|
||||||
|
Result string `json:"result"`
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
captchaResp := &captchaResponse{}
|
||||||
|
err = json.Unmarshal(body, captchaResp)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if captchaResp.Result == "success" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, errors.New(captchaResp.Reason)
|
||||||
|
}
|
@@ -17,7 +17,7 @@ package captcha
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -25,8 +25,7 @@ import (
|
|||||||
|
|
||||||
const HCaptchaVerifyUrl = "https://hcaptcha.com/siteverify"
|
const HCaptchaVerifyUrl = "https://hcaptcha.com/siteverify"
|
||||||
|
|
||||||
type HCaptchaProvider struct {
|
type HCaptchaProvider struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func NewHCaptchaProvider() *HCaptchaProvider {
|
func NewHCaptchaProvider() *HCaptchaProvider {
|
||||||
captcha := &HCaptchaProvider{}
|
captcha := &HCaptchaProvider{}
|
||||||
@@ -44,7 +43,7 @@ func (captcha *HCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,8 @@ func GetCaptchaProvider(captchaType string) CaptchaProvider {
|
|||||||
return NewHCaptchaProvider()
|
return NewHCaptchaProvider()
|
||||||
} else if captchaType == "Aliyun Captcha" {
|
} else if captchaType == "Aliyun Captcha" {
|
||||||
return NewAliyunCaptchaProvider()
|
return NewAliyunCaptchaProvider()
|
||||||
|
} else if captchaType == "GEETEST" {
|
||||||
|
return NewGEETESTCaptchaProvider()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ package captcha
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -25,8 +25,7 @@ import (
|
|||||||
|
|
||||||
const ReCaptchaVerifyUrl = "https://recaptcha.net/recaptcha/api/siteverify"
|
const ReCaptchaVerifyUrl = "https://recaptcha.net/recaptcha/api/siteverify"
|
||||||
|
|
||||||
type ReCaptchaProvider struct {
|
type ReCaptchaProvider struct{}
|
||||||
}
|
|
||||||
|
|
||||||
func NewReCaptchaProvider() *ReCaptchaProvider {
|
func NewReCaptchaProvider() *ReCaptchaProvider {
|
||||||
captcha := &ReCaptchaProvider{}
|
captcha := &ReCaptchaProvider{}
|
||||||
@@ -44,7 +43,7 @@ func (captcha *ReCaptchaProvider) VerifyCaptcha(token, clientSecret string) (boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
appname = casdoor
|
appname = casdoor
|
||||||
httpport = 8000
|
httpport = 8000
|
||||||
runmode = dev
|
runmode = dev
|
||||||
SessionOn = true
|
|
||||||
copyrequestbody = true
|
copyrequestbody = true
|
||||||
driverName = mysql
|
driverName = mysql
|
||||||
dataSourceName = root:123456@tcp(localhost:3306)/
|
dataSourceName = root:123456@tcp(localhost:3306)/
|
||||||
@@ -12,7 +11,7 @@ redisEndpoint =
|
|||||||
defaultStorageProvider =
|
defaultStorageProvider =
|
||||||
isCloudIntranet = false
|
isCloudIntranet = false
|
||||||
authState = "casdoor"
|
authState = "casdoor"
|
||||||
sock5Proxy = "127.0.0.1:10808"
|
socks5Proxy = "127.0.0.1:10808"
|
||||||
verificationCodeTimeout = 10
|
verificationCodeTimeout = 10
|
||||||
initScore = 2000
|
initScore = 2000
|
||||||
logPostOnly = true
|
logPostOnly = true
|
||||||
|
@@ -49,7 +49,7 @@ func GetConfigInt64(key string) (int64, error) {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// this array contains the beego configuration items that may be modified via env
|
// this array contains the beego configuration items that may be modified via env
|
||||||
var presetConfigItems = []string{"httpport", "appname"}
|
presetConfigItems := []string{"httpport", "appname"}
|
||||||
for _, key := range presetConfigItems {
|
for _, key := range presetConfigItems {
|
||||||
if value, ok := os.LookupEnv(key); ok {
|
if value, ok := os.LookupEnv(key); ok {
|
||||||
beego.AppConfig.Set(key, value)
|
beego.AppConfig.Set(key, value)
|
||||||
|
@@ -79,13 +79,9 @@ func TestGetConfBool(t *testing.T) {
|
|||||||
input string
|
input string
|
||||||
expected interface{}
|
expected interface{}
|
||||||
}{
|
}{
|
||||||
{"Should be return false", "SessionOn", false},
|
|
||||||
{"Should be return false", "copyrequestbody", true},
|
{"Should be return false", "copyrequestbody", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
//do some set up job
|
|
||||||
os.Setenv("SessionOn", "false")
|
|
||||||
|
|
||||||
err := beego.LoadAppConfig("ini", "app.conf")
|
err := beego.LoadAppConfig("ini", "app.conf")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
for _, scenery := range scenarios {
|
for _, scenery := range scenarios {
|
||||||
|
@@ -217,7 +217,7 @@ func (c *ApiController) Signup() {
|
|||||||
record.User = user.Name
|
record.User = user.Name
|
||||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||||
|
|
||||||
userId := fmt.Sprintf("%s/%s", user.Owner, user.Name)
|
userId := user.GetId()
|
||||||
util.LogInfo(c.Ctx, "API: [%s] is signed up as new user", userId)
|
util.LogInfo(c.Ctx, "API: [%s] is signed up as new user", userId)
|
||||||
|
|
||||||
c.ResponseOk(userId)
|
c.ResponseOk(userId)
|
||||||
@@ -228,7 +228,7 @@ func (c *ApiController) Signup() {
|
|||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
// @Description logout the current user
|
// @Description logout the current user
|
||||||
// @Success 200 {object} controllers.Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /logout [post]
|
// @router /logout [get,post]
|
||||||
func (c *ApiController) Logout() {
|
func (c *ApiController) Logout() {
|
||||||
user := c.GetSessionUsername()
|
user := c.GetSessionUsername()
|
||||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||||
@@ -274,6 +274,7 @@ func (c *ApiController) GetAccount() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserinfo
|
||||||
// UserInfo
|
// UserInfo
|
||||||
// @Title UserInfo
|
// @Title UserInfo
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
|
@@ -94,6 +94,29 @@ func (c *ApiController) GetUserApplication() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOrganizationApplications
|
||||||
|
// @Title GetOrganizationApplications
|
||||||
|
// @Tag Application API
|
||||||
|
// @Description get the detail of the organization's application
|
||||||
|
// @Param organization query string true "The organization name"
|
||||||
|
// @Success 200 {array} object.Application The Response object
|
||||||
|
// @router /get-organization-applications [get]
|
||||||
|
func (c *ApiController) GetOrganizationApplications() {
|
||||||
|
userId := c.GetSessionUsername()
|
||||||
|
owner := c.Input().Get("owner")
|
||||||
|
organization := c.Input().Get("organization")
|
||||||
|
|
||||||
|
if organization == "" {
|
||||||
|
c.ResponseError("Parameter organization is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var applications []*object.Application
|
||||||
|
applications = object.GetApplicationsByOrganizationName(owner, organization)
|
||||||
|
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateApplication
|
// UpdateApplication
|
||||||
// @Title UpdateApplication
|
// @Title UpdateApplication
|
||||||
// @Tag Application API
|
// @Tag Application API
|
||||||
|
@@ -44,12 +44,22 @@ func tokenToResponse(token *object.Token) *Response {
|
|||||||
return &Response{Status: "error", Msg: "fail to get accessToken", Data: token.AccessToken}
|
return &Response{Status: "error", Msg: "fail to get accessToken", Data: token.AccessToken}
|
||||||
}
|
}
|
||||||
return &Response{Status: "ok", Msg: "", Data: token.AccessToken}
|
return &Response{Status: "ok", Msg: "", Data: token.AccessToken}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleLoggedIn ...
|
// HandleLoggedIn ...
|
||||||
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *RequestForm) (resp *Response) {
|
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *RequestForm) (resp *Response) {
|
||||||
userId := user.GetId()
|
userId := user.GetId()
|
||||||
|
|
||||||
|
allowed, err := object.CheckAccessPermission(userId, application)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error(), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !allowed {
|
||||||
|
c.ResponseError("Unauthorized operation")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if form.Type == ResponseTypeLogin {
|
if form.Type == ResponseTypeLogin {
|
||||||
c.SetSessionUsername(userId)
|
c.SetSessionUsername(userId)
|
||||||
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
||||||
@@ -83,7 +93,6 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
token, _ := object.GetTokenByUser(application, user, scope, c.Ctx.Request.Host)
|
token, _ := object.GetTokenByUser(application, user, scope, c.Ctx.Request.Host)
|
||||||
resp = tokenToResponse(token)
|
resp = tokenToResponse(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if form.Type == ResponseTypeSaml { // saml flow
|
} else if form.Type == ResponseTypeSaml { // saml flow
|
||||||
res, redirectUrl, err := object.GetSamlResponse(application, user, form.SamlRequest, c.Ctx.Request.Host)
|
res, redirectUrl, err := object.GetSamlResponse(application, user, form.SamlRequest, c.Ctx.Request.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,7 +118,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resp = wrapErrorResponse(fmt.Errorf("Unknown response type: %s", form.Type))
|
resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
// if user did not check auto signin
|
// if user did not check auto signin
|
||||||
|
@@ -23,11 +23,13 @@ import (
|
|||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ApiController
|
||||||
// controller for handlers under /api uri
|
// controller for handlers under /api uri
|
||||||
type ApiController struct {
|
type ApiController struct {
|
||||||
beego.Controller
|
beego.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RootController
|
||||||
// controller for handlers directly under / (root)
|
// controller for handlers directly under / (root)
|
||||||
type RootController struct {
|
type RootController struct {
|
||||||
ApiController
|
ApiController
|
||||||
@@ -136,9 +138,9 @@ func (c *ApiController) SetSessionData(s *SessionData) {
|
|||||||
|
|
||||||
func wrapActionResponse(affected bool) *Response {
|
func wrapActionResponse(affected bool) *Response {
|
||||||
if affected {
|
if affected {
|
||||||
return &Response{Status: "ok", Msg: "", Data: "Affected"}
|
return &Response{Status: "ok", Msg: ""}
|
||||||
} else {
|
} else {
|
||||||
return &Response{Status: "ok", Msg: "", Data: "Unaffected"}
|
return &Response{Status: "error", Msg: "this operation has no effect"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,7 +31,7 @@ const (
|
|||||||
InvalidProxyCallback string = "INVALID_PROXY_CALLBACK"
|
InvalidProxyCallback string = "INVALID_PROXY_CALLBACK"
|
||||||
InvalidTicket string = "INVALID_TICKET"
|
InvalidTicket string = "INVALID_TICKET"
|
||||||
InvalidService string = "INVALID_SERVICE"
|
InvalidService string = "INVALID_SERVICE"
|
||||||
InteralError string = "INTERNAL_ERROR"
|
InternalError string = "INTERNAL_ERROR"
|
||||||
UnauthorizedService string = "UNAUTHORIZED_SERVICE"
|
UnauthorizedService string = "UNAUTHORIZED_SERVICE"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -49,7 +49,6 @@ func (c *RootController) CasValidate() {
|
|||||||
c.Ctx.Output.Body([]byte(fmt.Sprintf("yes\n%s\n", response.User)))
|
c.Ctx.Output.Body([]byte(fmt.Sprintf("yes\n%s\n", response.User)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// token not found
|
// token not found
|
||||||
c.Ctx.Output.Body([]byte("no\n"))
|
c.Ctx.Output.Body([]byte("no\n"))
|
||||||
@@ -117,7 +116,7 @@ func (c *RootController) CasP3ServiceAndProxyValidate() {
|
|||||||
}
|
}
|
||||||
// make a request to pgturl passing pgt and pgtiou
|
// make a request to pgturl passing pgt and pgtiou
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.sendCasAuthenticationResponseErr(InteralError, err.Error(), format)
|
c.sendCasAuthenticationResponseErr(InternalError, err.Error(), format)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
param := pgtUrlObj.Query()
|
param := pgtUrlObj.Query()
|
||||||
@@ -127,7 +126,7 @@ func (c *RootController) CasP3ServiceAndProxyValidate() {
|
|||||||
|
|
||||||
request, err := http.NewRequest("GET", pgtUrlObj.String(), nil)
|
request, err := http.NewRequest("GET", pgtUrlObj.String(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.sendCasAuthenticationResponseErr(InteralError, err.Error(), format)
|
c.sendCasAuthenticationResponseErr(InternalError, err.Error(), format)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +183,6 @@ func (c *RootController) CasProxy() {
|
|||||||
c.Data["xml"] = serviceResponse
|
c.Data["xml"] = serviceResponse
|
||||||
c.ServeXML()
|
c.ServeXML()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RootController) SamlValidate() {
|
func (c *RootController) SamlValidate() {
|
||||||
@@ -216,7 +214,7 @@ func (c *RootController) SamlValidate() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
envelopReponse := struct {
|
envelopResponse := struct {
|
||||||
XMLName xml.Name `xml:"SOAP-ENV:Envelope"`
|
XMLName xml.Name `xml:"SOAP-ENV:Envelope"`
|
||||||
Xmlns string `xml:"xmlns:SOAP-ENV"`
|
Xmlns string `xml:"xmlns:SOAP-ENV"`
|
||||||
Body struct {
|
Body struct {
|
||||||
@@ -224,15 +222,15 @@ func (c *RootController) SamlValidate() {
|
|||||||
Content string `xml:",innerxml"`
|
Content string `xml:",innerxml"`
|
||||||
}
|
}
|
||||||
}{}
|
}{}
|
||||||
envelopReponse.Xmlns = "http://schemas.xmlsoap.org/soap/envelope/"
|
envelopResponse.Xmlns = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||||
envelopReponse.Body.Content = response
|
envelopResponse.Body.Content = response
|
||||||
|
|
||||||
data, err := xml.Marshal(envelopReponse)
|
data, err := xml.Marshal(envelopResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Ctx.Output.Body([]byte(data))
|
c.Ctx.Output.Body(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RootController) sendCasProxyResponseErr(code, msg, format string) {
|
func (c *RootController) sendCasProxyResponseErr(code, msg, format string) {
|
||||||
|
@@ -48,6 +48,7 @@ func (c *ApiController) GetCerts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCert
|
||||||
// @Title GetCert
|
// @Title GetCert
|
||||||
// @Tag Cert API
|
// @Tag Cert API
|
||||||
// @Description get cert
|
// @Description get cert
|
||||||
@@ -61,6 +62,7 @@ func (c *ApiController) GetCert() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateCert
|
||||||
// @Title UpdateCert
|
// @Title UpdateCert
|
||||||
// @Tag Cert API
|
// @Tag Cert API
|
||||||
// @Description update cert
|
// @Description update cert
|
||||||
@@ -81,6 +83,7 @@ func (c *ApiController) UpdateCert() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddCert
|
||||||
// @Title AddCert
|
// @Title AddCert
|
||||||
// @Tag Cert API
|
// @Tag Cert API
|
||||||
// @Description add cert
|
// @Description add cert
|
||||||
@@ -98,6 +101,7 @@ func (c *ApiController) AddCert() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteCert
|
||||||
// @Title DeleteCert
|
// @Title DeleteCert
|
||||||
// @Tag Cert API
|
// @Tag Cert API
|
||||||
// @Description delete cert
|
// @Description delete cert
|
||||||
|
88
controllers/enforcer.go
Normal file
88
controllers/enforcer.go
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// Copyright 2022 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 (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/object"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *ApiController) Enforce() {
|
||||||
|
userId := c.GetSessionUsername()
|
||||||
|
if userId == "" {
|
||||||
|
c.ResponseError("Please sign in first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var permissionRule object.PermissionRule
|
||||||
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRule)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = object.Enforce(userId, &permissionRule)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) BatchEnforce() {
|
||||||
|
userId := c.GetSessionUsername()
|
||||||
|
if userId == "" {
|
||||||
|
c.ResponseError("Please sign in first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var permissionRules []object.PermissionRule
|
||||||
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRules)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = object.BatchEnforce(userId, permissionRules)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) GetAllObjects() {
|
||||||
|
userId := c.GetSessionUsername()
|
||||||
|
if userId == "" {
|
||||||
|
c.ResponseError("Please sign in first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = object.GetAllObjects(userId)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) GetAllActions() {
|
||||||
|
userId := c.GetSessionUsername()
|
||||||
|
if userId == "" {
|
||||||
|
c.ResponseError("Please sign in first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = object.GetAllActions(userId)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ApiController) GetAllRoles() {
|
||||||
|
userId := c.GetSessionUsername()
|
||||||
|
if userId == "" {
|
||||||
|
c.ResponseError("Please sign in first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = object.GetAllRoles(userId)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
@@ -44,6 +44,7 @@ type LdapSyncResp struct {
|
|||||||
Failed []object.LdapRespUser `json:"failed"`
|
Failed []object.LdapRespUser `json:"failed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLdapUser
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title GetLdapser
|
// @Title GetLdapser
|
||||||
// @router /get-ldap-user [post]
|
// @router /get-ldap-user [post]
|
||||||
@@ -100,6 +101,7 @@ func (c *ApiController) GetLdapUser() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLdaps
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title GetLdaps
|
// @Title GetLdaps
|
||||||
// @router /get-ldaps [post]
|
// @router /get-ldaps [post]
|
||||||
@@ -110,6 +112,7 @@ func (c *ApiController) GetLdaps() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLdap
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title GetLdap
|
// @Title GetLdap
|
||||||
// @router /get-ldap [post]
|
// @router /get-ldap [post]
|
||||||
@@ -125,6 +128,7 @@ func (c *ApiController) GetLdap() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddLdap
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title AddLdap
|
// @Title AddLdap
|
||||||
// @router /add-ldap [post]
|
// @router /add-ldap [post]
|
||||||
@@ -159,6 +163,7 @@ func (c *ApiController) AddLdap() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateLdap
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title UpdateLdap
|
// @Title UpdateLdap
|
||||||
// @router /update-ldap [post]
|
// @router /update-ldap [post]
|
||||||
@@ -186,6 +191,7 @@ func (c *ApiController) UpdateLdap() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteLdap
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title DeleteLdap
|
// @Title DeleteLdap
|
||||||
// @router /delete-ldap [post]
|
// @router /delete-ldap [post]
|
||||||
@@ -201,6 +207,7 @@ func (c *ApiController) DeleteLdap() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SyncLdapUsers
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title SyncLdapUsers
|
// @Title SyncLdapUsers
|
||||||
// @router /sync-ldap-users [post]
|
// @router /sync-ldap-users [post]
|
||||||
@@ -223,6 +230,7 @@ func (c *ApiController) SyncLdapUsers() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckLdapUsersExist
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title CheckLdapUserExist
|
// @Title CheckLdapUserExist
|
||||||
// @router /check-ldap-users-exist [post]
|
// @router /check-ldap-users-exist [post]
|
||||||
|
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
type LinkForm struct {
|
type LinkForm struct {
|
||||||
ProviderType string `json:"providerType"`
|
ProviderType string `json:"providerType"`
|
||||||
|
User object.User `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlink ...
|
// Unlink ...
|
||||||
@@ -40,16 +41,55 @@ func (c *ApiController) Unlink() {
|
|||||||
}
|
}
|
||||||
providerType := form.ProviderType
|
providerType := form.ProviderType
|
||||||
|
|
||||||
|
// the user will be unlinked from the provider
|
||||||
|
unlinkedUser := form.User
|
||||||
user := object.GetUser(userId)
|
user := object.GetUser(userId)
|
||||||
value := object.GetUserField(user, providerType)
|
|
||||||
|
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("You are not the global admin, you can't unlink other users")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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 := object.GetApplicationByUser(user)
|
||||||
|
if application == nil {
|
||||||
|
c.ResponseError("You can't unlink yourself, you are not a member of any application")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(application.Providers) == 0 {
|
||||||
|
c.ResponseError("This application has no providers")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
provider := application.GetProviderItemByType(providerType)
|
||||||
|
if provider == nil {
|
||||||
|
c.ResponseError("This application has no providers of type " + providerType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !provider.CanUnlink {
|
||||||
|
c.ResponseError("This provider can't be unlinked")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// only two situations can happen here
|
||||||
|
// 1. the user is the global admin
|
||||||
|
// 2. the user is unlinking themselves and provider can be unlinked
|
||||||
|
|
||||||
|
value := object.GetUserField(&unlinkedUser, providerType)
|
||||||
|
|
||||||
if value == "" {
|
if value == "" {
|
||||||
c.ResponseError("Please link first", value)
|
c.ResponseError("Please link first", value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
object.ClearUserOAuthProperties(user, providerType)
|
object.ClearUserOAuthProperties(&unlinkedUser, providerType)
|
||||||
|
|
||||||
object.LinkUserAccount(user, providerType, "")
|
object.LinkUserAccount(&unlinkedUser, providerType, "")
|
||||||
c.ResponseOk()
|
c.ResponseOk()
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,7 @@ package controllers
|
|||||||
|
|
||||||
import "github.com/casdoor/casdoor/object"
|
import "github.com/casdoor/casdoor/object"
|
||||||
|
|
||||||
|
// GetOidcDiscovery
|
||||||
// @Title GetOidcDiscovery
|
// @Title GetOidcDiscovery
|
||||||
// @Tag OIDC API
|
// @Tag OIDC API
|
||||||
// @Description Get Oidc Discovery
|
// @Description Get Oidc Discovery
|
||||||
@@ -27,6 +28,7 @@ func (c *RootController) GetOidcDiscovery() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetJwks
|
||||||
// @Title GetJwks
|
// @Title GetJwks
|
||||||
// @Tag OIDC API
|
// @Tag OIDC API
|
||||||
// @Success 200 {object} jose.JSONWebKey
|
// @Success 200 {object} jose.JSONWebKey
|
||||||
|
@@ -67,6 +67,7 @@ func (c *ApiController) GetUserPayments() {
|
|||||||
c.ResponseOk(payments)
|
c.ResponseOk(payments)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPayment
|
||||||
// @Title GetPayment
|
// @Title GetPayment
|
||||||
// @Tag Payment API
|
// @Tag Payment API
|
||||||
// @Description get payment
|
// @Description get payment
|
||||||
@@ -80,6 +81,7 @@ func (c *ApiController) GetPayment() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdatePayment
|
||||||
// @Title UpdatePayment
|
// @Title UpdatePayment
|
||||||
// @Tag Payment API
|
// @Tag Payment API
|
||||||
// @Description update payment
|
// @Description update payment
|
||||||
@@ -100,6 +102,7 @@ func (c *ApiController) UpdatePayment() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddPayment
|
||||||
// @Title AddPayment
|
// @Title AddPayment
|
||||||
// @Tag Payment API
|
// @Tag Payment API
|
||||||
// @Description add payment
|
// @Description add payment
|
||||||
@@ -117,6 +120,7 @@ func (c *ApiController) AddPayment() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletePayment
|
||||||
// @Title DeletePayment
|
// @Title DeletePayment
|
||||||
// @Tag Payment API
|
// @Tag Payment API
|
||||||
// @Description delete payment
|
// @Description delete payment
|
||||||
@@ -134,6 +138,7 @@ func (c *ApiController) DeletePayment() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotifyPayment
|
||||||
// @Title NotifyPayment
|
// @Title NotifyPayment
|
||||||
// @Tag Payment API
|
// @Tag Payment API
|
||||||
// @Description notify payment
|
// @Description notify payment
|
||||||
@@ -159,6 +164,7 @@ func (c *ApiController) NotifyPayment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InvoicePayment
|
||||||
// @Title InvoicePayment
|
// @Title InvoicePayment
|
||||||
// @Tag Payment API
|
// @Tag Payment API
|
||||||
// @Description invoice payment
|
// @Description invoice payment
|
||||||
|
@@ -48,6 +48,7 @@ func (c *ApiController) GetPermissions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPermission
|
||||||
// @Title GetPermission
|
// @Title GetPermission
|
||||||
// @Tag Permission API
|
// @Tag Permission API
|
||||||
// @Description get permission
|
// @Description get permission
|
||||||
@@ -61,6 +62,7 @@ func (c *ApiController) GetPermission() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdatePermission
|
||||||
// @Title UpdatePermission
|
// @Title UpdatePermission
|
||||||
// @Tag Permission API
|
// @Tag Permission API
|
||||||
// @Description update permission
|
// @Description update permission
|
||||||
@@ -81,6 +83,7 @@ func (c *ApiController) UpdatePermission() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddPermission
|
||||||
// @Title AddPermission
|
// @Title AddPermission
|
||||||
// @Tag Permission API
|
// @Tag Permission API
|
||||||
// @Description add permission
|
// @Description add permission
|
||||||
@@ -98,6 +101,7 @@ func (c *ApiController) AddPermission() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletePermission
|
||||||
// @Title DeletePermission
|
// @Title DeletePermission
|
||||||
// @Tag Permission API
|
// @Tag Permission API
|
||||||
// @Description delete permission
|
// @Description delete permission
|
||||||
|
@@ -49,6 +49,7 @@ func (c *ApiController) GetProducts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProduct
|
||||||
// @Title GetProduct
|
// @Title GetProduct
|
||||||
// @Tag Product API
|
// @Tag Product API
|
||||||
// @Description get product
|
// @Description get product
|
||||||
@@ -58,10 +59,14 @@ func (c *ApiController) GetProducts() {
|
|||||||
func (c *ApiController) GetProduct() {
|
func (c *ApiController) GetProduct() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
c.Data["json"] = object.GetProduct(id)
|
product := object.GetProduct(id)
|
||||||
|
object.ExtendProductWithProviders(product)
|
||||||
|
|
||||||
|
c.Data["json"] = product
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateProduct
|
||||||
// @Title UpdateProduct
|
// @Title UpdateProduct
|
||||||
// @Tag Product API
|
// @Tag Product API
|
||||||
// @Description update product
|
// @Description update product
|
||||||
@@ -82,6 +87,7 @@ func (c *ApiController) UpdateProduct() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddProduct
|
||||||
// @Title AddProduct
|
// @Title AddProduct
|
||||||
// @Tag Product API
|
// @Tag Product API
|
||||||
// @Description add product
|
// @Description add product
|
||||||
@@ -99,6 +105,7 @@ func (c *ApiController) AddProduct() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteProduct
|
||||||
// @Title DeleteProduct
|
// @Title DeleteProduct
|
||||||
// @Tag Product API
|
// @Tag Product API
|
||||||
// @Description delete product
|
// @Description delete product
|
||||||
@@ -116,6 +123,7 @@ func (c *ApiController) DeleteProduct() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BuyProduct
|
||||||
// @Title BuyProduct
|
// @Title BuyProduct
|
||||||
// @Tag Product API
|
// @Tag Product API
|
||||||
// @Description buy product
|
// @Description buy product
|
||||||
|
@@ -16,6 +16,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/astaxie/beego/utils/pagination"
|
"github.com/astaxie/beego/utils/pagination"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@@ -47,6 +48,7 @@ func (c *ApiController) GetProviders() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProvider
|
||||||
// @Title GetProvider
|
// @Title GetProvider
|
||||||
// @Tag Provider API
|
// @Tag Provider API
|
||||||
// @Description get provider
|
// @Description get provider
|
||||||
@@ -60,6 +62,7 @@ func (c *ApiController) GetProvider() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateProvider
|
||||||
// @Title UpdateProvider
|
// @Title UpdateProvider
|
||||||
// @Tag Provider API
|
// @Tag Provider API
|
||||||
// @Description update provider
|
// @Description update provider
|
||||||
@@ -80,6 +83,7 @@ func (c *ApiController) UpdateProvider() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddProvider
|
||||||
// @Title AddProvider
|
// @Title AddProvider
|
||||||
// @Tag Provider API
|
// @Tag Provider API
|
||||||
// @Description add provider
|
// @Description add provider
|
||||||
@@ -97,6 +101,7 @@ func (c *ApiController) AddProvider() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteProvider
|
||||||
// @Title DeleteProvider
|
// @Title DeleteProvider
|
||||||
// @Tag Provider API
|
// @Tag Provider API
|
||||||
// @Description delete provider
|
// @Description delete provider
|
||||||
|
@@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetResources
|
||||||
// @router /get-resources [get]
|
// @router /get-resources [get]
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title GetResources
|
// @Title GetResources
|
||||||
@@ -50,6 +51,7 @@ func (c *ApiController) GetResources() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title GetResource
|
// @Title GetResource
|
||||||
// @router /get-resource [get]
|
// @router /get-resource [get]
|
||||||
@@ -60,6 +62,7 @@ func (c *ApiController) GetResource() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title UpdateResource
|
// @Title UpdateResource
|
||||||
// @router /update-resource [post]
|
// @router /update-resource [post]
|
||||||
@@ -76,6 +79,7 @@ func (c *ApiController) UpdateResource() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title AddResource
|
// @Title AddResource
|
||||||
// @router /add-resource [post]
|
// @router /add-resource [post]
|
||||||
@@ -90,6 +94,7 @@ func (c *ApiController) AddResource() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title DeleteResource
|
// @Title DeleteResource
|
||||||
// @router /delete-resource [post]
|
// @router /delete-resource [post]
|
||||||
@@ -115,6 +120,7 @@ func (c *ApiController) DeleteResource() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UploadResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title UploadResource
|
// @Title UploadResource
|
||||||
// @router /upload-resource [post]
|
// @router /upload-resource [post]
|
||||||
|
@@ -48,6 +48,7 @@ func (c *ApiController) GetRoles() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRole
|
||||||
// @Title GetRole
|
// @Title GetRole
|
||||||
// @Tag Role API
|
// @Tag Role API
|
||||||
// @Description get role
|
// @Description get role
|
||||||
@@ -61,6 +62,7 @@ func (c *ApiController) GetRole() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateRole
|
||||||
// @Title UpdateRole
|
// @Title UpdateRole
|
||||||
// @Tag Role API
|
// @Tag Role API
|
||||||
// @Description update role
|
// @Description update role
|
||||||
@@ -81,6 +83,7 @@ func (c *ApiController) UpdateRole() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRole
|
||||||
// @Title AddRole
|
// @Title AddRole
|
||||||
// @Tag Role API
|
// @Tag Role API
|
||||||
// @Description add role
|
// @Description add role
|
||||||
@@ -98,6 +101,7 @@ func (c *ApiController) AddRole() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteRole
|
||||||
// @Title DeleteRole
|
// @Title DeleteRole
|
||||||
// @Tag Role API
|
// @Tag Role API
|
||||||
// @Description delete role
|
// @Description delete role
|
||||||
|
@@ -16,6 +16,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/astaxie/beego/utils/pagination"
|
"github.com/astaxie/beego/utils/pagination"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@@ -47,6 +48,7 @@ func (c *ApiController) GetSyncers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSyncer
|
||||||
// @Title GetSyncer
|
// @Title GetSyncer
|
||||||
// @Tag Syncer API
|
// @Tag Syncer API
|
||||||
// @Description get syncer
|
// @Description get syncer
|
||||||
@@ -60,6 +62,7 @@ func (c *ApiController) GetSyncer() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateSyncer
|
||||||
// @Title UpdateSyncer
|
// @Title UpdateSyncer
|
||||||
// @Tag Syncer API
|
// @Tag Syncer API
|
||||||
// @Description update syncer
|
// @Description update syncer
|
||||||
@@ -80,6 +83,7 @@ func (c *ApiController) UpdateSyncer() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddSyncer
|
||||||
// @Title AddSyncer
|
// @Title AddSyncer
|
||||||
// @Tag Syncer API
|
// @Tag Syncer API
|
||||||
// @Description add syncer
|
// @Description add syncer
|
||||||
@@ -97,6 +101,7 @@ func (c *ApiController) AddSyncer() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteSyncer
|
||||||
// @Title DeleteSyncer
|
// @Title DeleteSyncer
|
||||||
// @Tag Syncer API
|
// @Tag Syncer API
|
||||||
// @Description delete syncer
|
// @Description delete syncer
|
||||||
@@ -114,6 +119,7 @@ func (c *ApiController) DeleteSyncer() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RunSyncer
|
||||||
// @Title RunSyncer
|
// @Title RunSyncer
|
||||||
// @Tag Syncer API
|
// @Tag Syncer API
|
||||||
// @Description run syncer
|
// @Description run syncer
|
||||||
|
@@ -165,6 +165,8 @@ func (c *ApiController) GetOAuthCode() {
|
|||||||
// @Param client_secret query string true "OAuth client secret"
|
// @Param client_secret query string true "OAuth client secret"
|
||||||
// @Param code query string true "OAuth code"
|
// @Param code query string true "OAuth code"
|
||||||
// @Success 200 {object} object.TokenWrapper The Response object
|
// @Success 200 {object} object.TokenWrapper The Response object
|
||||||
|
// @Success 400 {object} object.TokenError The Response object
|
||||||
|
// @Success 401 {object} object.TokenError The Response object
|
||||||
// @router /login/oauth/access_token [post]
|
// @router /login/oauth/access_token [post]
|
||||||
func (c *ApiController) GetOAuthToken() {
|
func (c *ApiController) GetOAuthToken() {
|
||||||
grantType := c.Input().Get("grant_type")
|
grantType := c.Input().Get("grant_type")
|
||||||
@@ -200,6 +202,7 @@ func (c *ApiController) GetOAuthToken() {
|
|||||||
host := c.Ctx.Request.Host
|
host := c.Ctx.Request.Host
|
||||||
|
|
||||||
c.Data["json"] = object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, tag, avatar)
|
c.Data["json"] = object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, tag, avatar)
|
||||||
|
c.SetTokenErrorHttpStatus()
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +216,8 @@ func (c *ApiController) GetOAuthToken() {
|
|||||||
// @Param client_id query string true "OAuth client id"
|
// @Param client_id query string true "OAuth client id"
|
||||||
// @Param client_secret query string false "OAuth client secret"
|
// @Param client_secret query string false "OAuth client secret"
|
||||||
// @Success 200 {object} object.TokenWrapper The Response object
|
// @Success 200 {object} object.TokenWrapper The Response object
|
||||||
|
// @Success 400 {object} object.TokenError The Response object
|
||||||
|
// @Success 401 {object} object.TokenError The Response object
|
||||||
// @router /login/oauth/refresh_token [post]
|
// @router /login/oauth/refresh_token [post]
|
||||||
func (c *ApiController) RefreshToken() {
|
func (c *ApiController) RefreshToken() {
|
||||||
grantType := c.Input().Get("grant_type")
|
grantType := c.Input().Get("grant_type")
|
||||||
@@ -235,6 +240,7 @@ func (c *ApiController) RefreshToken() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
|
c.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
|
||||||
|
c.SetTokenErrorHttpStatus()
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +255,7 @@ func (c *ApiController) RefreshToken() {
|
|||||||
// @router /login/oauth/logout [get]
|
// @router /login/oauth/logout [get]
|
||||||
func (c *ApiController) TokenLogout() {
|
func (c *ApiController) TokenLogout() {
|
||||||
token := c.Input().Get("id_token_hint")
|
token := c.Input().Get("id_token_hint")
|
||||||
flag, application := object.DeleteTokenByAceessToken(token)
|
flag, application := object.DeleteTokenByAccessToken(token)
|
||||||
redirectUri := c.Input().Get("post_logout_redirect_uri")
|
redirectUri := c.Input().Get("post_logout_redirect_uri")
|
||||||
state := c.Input().Get("state")
|
state := c.Input().Get("state")
|
||||||
if application != nil && object.CheckRedirectUriValid(application, redirectUri) {
|
if application != nil && object.CheckRedirectUriValid(application, redirectUri) {
|
||||||
@@ -270,6 +276,8 @@ func (c *ApiController) TokenLogout() {
|
|||||||
// @Param token formData string true "access_token's value or refresh_token's value"
|
// @Param token formData string true "access_token's value or refresh_token's value"
|
||||||
// @Param token_type_hint formData string true "the token type access_token or refresh_token"
|
// @Param token_type_hint formData string true "the token type access_token or refresh_token"
|
||||||
// @Success 200 {object} object.IntrospectionResponse The Response object
|
// @Success 200 {object} object.IntrospectionResponse The Response object
|
||||||
|
// @Success 400 {object} object.TokenError The Response object
|
||||||
|
// @Success 401 {object} object.TokenError The Response object
|
||||||
// @router /login/oauth/introspect [post]
|
// @router /login/oauth/introspect [post]
|
||||||
func (c *ApiController) IntrospectToken() {
|
func (c *ApiController) IntrospectToken() {
|
||||||
tokenValue := c.Input().Get("token")
|
tokenValue := c.Input().Get("token")
|
||||||
@@ -279,12 +287,21 @@ func (c *ApiController) IntrospectToken() {
|
|||||||
clientSecret = c.Input().Get("client_secret")
|
clientSecret = c.Input().Get("client_secret")
|
||||||
if clientId == "" || clientSecret == "" {
|
if clientId == "" || clientSecret == "" {
|
||||||
c.ResponseError("empty clientId or clientSecret")
|
c.ResponseError("empty clientId or clientSecret")
|
||||||
|
c.Data["json"] = &object.TokenError{
|
||||||
|
Error: object.InvalidRequest,
|
||||||
|
}
|
||||||
|
c.SetTokenErrorHttpStatus()
|
||||||
|
c.ServeJSON()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
application := object.GetApplicationByClientId(clientId)
|
application := object.GetApplicationByClientId(clientId)
|
||||||
if application == nil || application.ClientSecret != clientSecret {
|
if application == nil || application.ClientSecret != clientSecret {
|
||||||
c.ResponseError("invalid application or wrong clientSecret")
|
c.ResponseError("invalid application or wrong clientSecret")
|
||||||
|
c.Data["json"] = &object.TokenError{
|
||||||
|
Error: object.InvalidClient,
|
||||||
|
}
|
||||||
|
c.SetTokenErrorHttpStatus()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
token := object.GetTokenByTokenAndApplication(tokenValue, application.Name)
|
token := object.GetTokenByTokenAndApplication(tokenValue, application.Name)
|
||||||
|
@@ -81,18 +81,26 @@ func (c *ApiController) GetUsers() {
|
|||||||
// @Tag User API
|
// @Tag User API
|
||||||
// @Description get user
|
// @Description get user
|
||||||
// @Param id query string true "The id of the user"
|
// @Param id query string true "The id of the user"
|
||||||
|
// @Param owner query string false "The owner of the user"
|
||||||
|
// @Param email query string false "The email of the user"
|
||||||
|
// @Param phone query string false "The phone of the user"
|
||||||
// @Success 200 {object} object.User The Response object
|
// @Success 200 {object} object.User The Response object
|
||||||
// @router /get-user [get]
|
// @router /get-user [get]
|
||||||
func (c *ApiController) GetUser() {
|
func (c *ApiController) GetUser() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
owner := c.Input().Get("owner")
|
|
||||||
email := c.Input().Get("email")
|
email := c.Input().Get("email")
|
||||||
userOwner, _ := util.GetOwnerAndNameFromId(id)
|
phone := c.Input().Get("phone")
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", userOwner))
|
userId := c.Input().Get("userId")
|
||||||
|
|
||||||
|
owner := c.Input().Get("owner")
|
||||||
|
if owner == "" {
|
||||||
|
owner, _ = util.GetOwnerAndNameFromId(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", owner))
|
||||||
if !organization.IsProfilePublic {
|
if !organization.IsProfilePublic {
|
||||||
requestUserId := c.GetSessionUsername()
|
requestUserId := c.GetSessionUsername()
|
||||||
hasPermission, err := object.CheckUserPermission(requestUserId, id, false)
|
hasPermission, err := object.CheckUserPermission(requestUserId, id, owner, false)
|
||||||
if !hasPermission {
|
if !hasPermission {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@@ -100,10 +108,22 @@ func (c *ApiController) GetUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var user *object.User
|
var user *object.User
|
||||||
if email == "" {
|
switch {
|
||||||
user = object.GetUser(id)
|
case email != "":
|
||||||
} else {
|
|
||||||
user = object.GetUserByEmail(owner, email)
|
user = object.GetUserByEmail(owner, email)
|
||||||
|
case phone != "":
|
||||||
|
user = object.GetUserByPhone(owner, phone)
|
||||||
|
case userId != "":
|
||||||
|
user = object.GetUserByUserId(owner, userId)
|
||||||
|
default:
|
||||||
|
user = object.GetUser(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user != nil {
|
||||||
|
roles := object.GetRolesByUser(user.GetId())
|
||||||
|
user.Roles = roles
|
||||||
|
permissions := object.GetPermissionsByUser(user.GetId())
|
||||||
|
user.Permissions = permissions
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedUser(user)
|
c.Data["json"] = object.GetMaskedUser(user)
|
||||||
@@ -246,7 +266,7 @@ func (c *ApiController) SetPassword() {
|
|||||||
requestUserId := c.GetSessionUsername()
|
requestUserId := c.GetSessionUsername()
|
||||||
userId := fmt.Sprintf("%s/%s", userOwner, userName)
|
userId := fmt.Sprintf("%s/%s", userOwner, userName)
|
||||||
|
|
||||||
hasPermission, err := object.CheckUserPermission(requestUserId, userId, true)
|
hasPermission, err := object.CheckUserPermission(requestUserId, userId, userOwner, true)
|
||||||
if !hasPermission {
|
if !hasPermission {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@@ -278,6 +298,7 @@ func (c *ApiController) SetPassword() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckUserPassword
|
||||||
// @Title CheckUserPassword
|
// @Title CheckUserPassword
|
||||||
// @router /check-user-password [post]
|
// @router /check-user-password [post]
|
||||||
// @Tag User API
|
// @Tag User API
|
||||||
|
@@ -51,6 +51,23 @@ func (c *ApiController) ResponseError(error string, data ...interface{}) {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTokenErrorHttpStatus ...
|
||||||
|
func (c *ApiController) SetTokenErrorHttpStatus() {
|
||||||
|
_, ok := c.Data["json"].(*object.TokenError)
|
||||||
|
if ok {
|
||||||
|
if c.Data["json"].(*object.TokenError).Error == object.InvalidClient {
|
||||||
|
c.Ctx.Output.SetStatus(401)
|
||||||
|
c.Ctx.Output.Header("WWW-Authenticate", "Basic realm=\"OAuth2\"")
|
||||||
|
} else {
|
||||||
|
c.Ctx.Output.SetStatus(400)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, ok = c.Data["json"].(*object.TokenWrapper)
|
||||||
|
if ok {
|
||||||
|
c.Ctx.Output.SetStatus(200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RequireSignedIn ...
|
// RequireSignedIn ...
|
||||||
func (c *ApiController) RequireSignedIn() (string, bool) {
|
func (c *ApiController) RequireSignedIn() (string, bool) {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
|
@@ -42,15 +42,31 @@ func (c *ApiController) getCurrentUser() *object.User {
|
|||||||
func (c *ApiController) SendVerificationCode() {
|
func (c *ApiController) SendVerificationCode() {
|
||||||
destType := c.Ctx.Request.Form.Get("type")
|
destType := c.Ctx.Request.Form.Get("type")
|
||||||
dest := c.Ctx.Request.Form.Get("dest")
|
dest := c.Ctx.Request.Form.Get("dest")
|
||||||
orgId := c.Ctx.Request.Form.Get("organizationId")
|
|
||||||
checkType := c.Ctx.Request.Form.Get("checkType")
|
checkType := c.Ctx.Request.Form.Get("checkType")
|
||||||
checkId := c.Ctx.Request.Form.Get("checkId")
|
checkId := c.Ctx.Request.Form.Get("checkId")
|
||||||
checkKey := c.Ctx.Request.Form.Get("checkKey")
|
checkKey := c.Ctx.Request.Form.Get("checkKey")
|
||||||
checkUser := c.Ctx.Request.Form.Get("checkUser")
|
checkUser := c.Ctx.Request.Form.Get("checkUser")
|
||||||
|
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
||||||
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
||||||
|
|
||||||
if len(destType) == 0 || len(dest) == 0 || len(orgId) == 0 || !strings.Contains(orgId, "/") || len(checkType) == 0 {
|
if destType == "" {
|
||||||
c.ResponseError("Missing parameter.")
|
c.ResponseError("Missing parameter: type.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if dest == "" {
|
||||||
|
c.ResponseError("Missing parameter: dest.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if applicationId == "" {
|
||||||
|
c.ResponseError("Missing parameter: applicationId.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !strings.Contains(applicationId, "/") {
|
||||||
|
c.ResponseError("Wrong parameter: applicationId.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if checkType == "" {
|
||||||
|
c.ResponseError("Missing parameter: checkType.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,18 +90,18 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user := c.getCurrentUser()
|
user := c.getCurrentUser()
|
||||||
organization := object.GetOrganization(orgId)
|
application := object.GetApplication(applicationId)
|
||||||
application := object.GetApplicationByOrganizationName(organization.Name)
|
organization := object.GetOrganization(fmt.Sprintf("%s/%s", application.Owner, application.Organization))
|
||||||
|
|
||||||
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
||||||
c.ResponseError("Please login first")
|
c.ResponseError("Please login first")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResp := errors.New("Invalid dest type")
|
sendResp := errors.New("invalid dest type")
|
||||||
|
|
||||||
if user == nil && checkUser != "" && checkUser != "true" {
|
if user == nil && checkUser != "" && checkUser != "true" {
|
||||||
_, name := util.GetOwnerAndNameFromId(orgId)
|
name := application.Organization
|
||||||
user = object.GetUser(fmt.Sprintf("%s/%s", name, checkUser))
|
user = object.GetUser(fmt.Sprintf("%s/%s", name, checkUser))
|
||||||
}
|
}
|
||||||
switch destType {
|
switch destType {
|
||||||
@@ -108,13 +124,12 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
c.ResponseError("Invalid phone number")
|
c.ResponseError("Invalid phone number")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
org := object.GetOrganization(orgId)
|
if organization == nil {
|
||||||
if org == nil {
|
c.ResponseError("The organization doesn't exist.")
|
||||||
c.ResponseError("Missing parameter.")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = fmt.Sprintf("+%s%s", org.PhonePrefix, dest)
|
dest = fmt.Sprintf("+%s%s", organization.PhonePrefix, dest)
|
||||||
provider := application.GetSmsProvider()
|
provider := application.GetSmsProvider()
|
||||||
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, remoteAddr, dest)
|
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, remoteAddr, dest)
|
||||||
}
|
}
|
||||||
@@ -153,13 +168,35 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkDest := dest
|
checkDest := dest
|
||||||
if destType == "phone" {
|
|
||||||
org := object.GetOrganizationByUser(user)
|
org := object.GetOrganizationByUser(user)
|
||||||
|
if destType == "phone" {
|
||||||
|
phoneItem := object.GetAccountItemByName("Phone", org)
|
||||||
|
if phoneItem == nil {
|
||||||
|
c.ResponseError("Unable to get the phone modify rule.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if pass, errMsg := object.CheckAccountItemModifyRule(phoneItem, user); !pass {
|
||||||
|
c.ResponseError(errMsg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
phonePrefix := "86"
|
phonePrefix := "86"
|
||||||
if org != nil && org.PhonePrefix != "" {
|
if org != nil && org.PhonePrefix != "" {
|
||||||
phonePrefix = org.PhonePrefix
|
phonePrefix = org.PhonePrefix
|
||||||
}
|
}
|
||||||
checkDest = fmt.Sprintf("+%s%s", phonePrefix, dest)
|
checkDest = fmt.Sprintf("+%s%s", phonePrefix, dest)
|
||||||
|
} else if destType == "email" {
|
||||||
|
emailItem := object.GetAccountItemByName("Email", org)
|
||||||
|
if emailItem == nil {
|
||||||
|
c.ResponseError("Unable to get the email modify rule.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if pass, errMsg := object.CheckAccountItemModifyRule(emailItem, user); !pass {
|
||||||
|
c.ResponseError(errMsg)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ret := object.CheckVerificationCode(checkDest, code); len(ret) != 0 {
|
if ret := object.CheckVerificationCode(checkDest, code); len(ret) != 0 {
|
||||||
c.ResponseError(ret)
|
c.ResponseError(ret)
|
||||||
|
142
controllers/webauthn.go
Normal file
142
controllers/webauthn.go
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
// Copyright 2022 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 (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/object"
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"github.com/duo-labs/webauthn/protocol"
|
||||||
|
"github.com/duo-labs/webauthn/webauthn"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WebAuthnSignupBegin
|
||||||
|
// @Title WebAuthnSignupBegin
|
||||||
|
// @Tag User API
|
||||||
|
// @Description WebAuthn Registration Flow 1st stage
|
||||||
|
// @Success 200 {object} protocol.CredentialCreation The CredentialCreationOptions object
|
||||||
|
// @router /webauthn/signup/begin [get]
|
||||||
|
func (c *ApiController) WebAuthnSignupBegin() {
|
||||||
|
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
|
user := c.getCurrentUser()
|
||||||
|
if user == nil {
|
||||||
|
c.ResponseError("Please login first.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOptions := func(credCreationOpts *protocol.PublicKeyCredentialCreationOptions) {
|
||||||
|
credCreationOpts.CredentialExcludeList = user.CredentialExcludeList()
|
||||||
|
}
|
||||||
|
options, sessionData, err := webauthnObj.BeginRegistration(
|
||||||
|
user,
|
||||||
|
registerOptions,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.SetSession("registration", *sessionData)
|
||||||
|
c.Data["json"] = options
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebAuthnSignupFinish
|
||||||
|
// @Title WebAuthnSignupFinish
|
||||||
|
// @Tag User API
|
||||||
|
// @Description WebAuthn Registration Flow 2nd stage
|
||||||
|
// @Param body body protocol.CredentialCreationResponse true "authenticator attestation Response"
|
||||||
|
// @Success 200 {object} Response "The Response object"
|
||||||
|
// @router /webauthn/signup/finish [post]
|
||||||
|
func (c *ApiController) WebAuthnSignupFinish() {
|
||||||
|
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
|
user := c.getCurrentUser()
|
||||||
|
if user == nil {
|
||||||
|
c.ResponseError("Please login first.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sessionObj := c.GetSession("registration")
|
||||||
|
sessionData, ok := sessionObj.(webauthn.SessionData)
|
||||||
|
if !ok {
|
||||||
|
c.ResponseError("Please call WebAuthnSignupBegin first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||||
|
|
||||||
|
credential, err := webauthnObj.FinishRegistration(user, sessionData, c.Ctx.Request)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isGlobalAdmin := c.IsGlobalAdmin()
|
||||||
|
user.AddCredentials(*credential, isGlobalAdmin)
|
||||||
|
c.ResponseOk()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebAuthnSigninBegin
|
||||||
|
// @Title WebAuthnSigninBegin
|
||||||
|
// @Tag Login API
|
||||||
|
// @Description WebAuthn Login Flow 1st stage
|
||||||
|
// @Param owner query string true "owner"
|
||||||
|
// @Param name query string true "name"
|
||||||
|
// @Success 200 {object} protocol.CredentialAssertion The CredentialAssertion object
|
||||||
|
// @router /webauthn/signin/begin [get]
|
||||||
|
func (c *ApiController) WebAuthnSigninBegin() {
|
||||||
|
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
|
userOwner := c.Input().Get("owner")
|
||||||
|
userName := c.Input().Get("name")
|
||||||
|
user := object.GetUserByFields(userOwner, userName)
|
||||||
|
if user == nil {
|
||||||
|
c.ResponseError("Please Giveout Owner and Username.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
options, sessionData, err := webauthnObj.BeginLogin(user)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.SetSession("authentication", *sessionData)
|
||||||
|
c.Data["json"] = options
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebAuthnSigninFinish
|
||||||
|
// @Title WebAuthnSigninBegin
|
||||||
|
// @Tag Login API
|
||||||
|
// @Description WebAuthn Login Flow 2nd stage
|
||||||
|
// @Param body body protocol.CredentialAssertionResponse true "authenticator assertion Response"
|
||||||
|
// @Success 200 {object} Response "The Response object"
|
||||||
|
// @router /webauthn/signin/finish [post]
|
||||||
|
func (c *ApiController) WebAuthnSigninFinish() {
|
||||||
|
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
|
sessionObj := c.GetSession("authentication")
|
||||||
|
sessionData, ok := sessionObj.(webauthn.SessionData)
|
||||||
|
if !ok {
|
||||||
|
c.ResponseError("Please call WebAuthnSigninBegin first")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||||
|
userId := string(sessionData.UserID)
|
||||||
|
user := object.GetUser(userId)
|
||||||
|
_, err := webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.SetSessionUsername(userId)
|
||||||
|
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
||||||
|
c.ResponseOk(userId)
|
||||||
|
}
|
@@ -48,6 +48,7 @@ func (c *ApiController) GetWebhooks() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetWebhook
|
||||||
// @Title GetWebhook
|
// @Title GetWebhook
|
||||||
// @Tag Webhook API
|
// @Tag Webhook API
|
||||||
// @Description get webhook
|
// @Description get webhook
|
||||||
@@ -61,6 +62,7 @@ func (c *ApiController) GetWebhook() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateWebhook
|
||||||
// @Title UpdateWebhook
|
// @Title UpdateWebhook
|
||||||
// @Tag Webhook API
|
// @Tag Webhook API
|
||||||
// @Description update webhook
|
// @Description update webhook
|
||||||
@@ -81,6 +83,7 @@ func (c *ApiController) UpdateWebhook() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddWebhook
|
||||||
// @Title AddWebhook
|
// @Title AddWebhook
|
||||||
// @Tag Webhook API
|
// @Tag Webhook API
|
||||||
// @Description add webhook
|
// @Description add webhook
|
||||||
@@ -98,6 +101,7 @@ func (c *ApiController) AddWebhook() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteWebhook
|
||||||
// @Title DeleteWebhook
|
// @Title DeleteWebhook
|
||||||
// @Tag Webhook API
|
// @Tag Webhook API
|
||||||
// @Description delete webhook
|
// @Description delete webhook
|
||||||
|
@@ -24,7 +24,6 @@ func NewArgon2idCredManager() *Argon2idCredManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cm *Argon2idCredManager) GetHashedPassword(password string, userSalt string, organizationSalt string) string {
|
func (cm *Argon2idCredManager) GetHashedPassword(password string, userSalt string, organizationSalt string) string {
|
||||||
|
|
||||||
hash, err := argon2id.CreateHash(password, argon2id.DefaultParams)
|
hash, err := argon2id.CreateHash(password, argon2id.DefaultParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
|
@@ -17,6 +17,7 @@ package cred
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
if [ "${MYSQL_ROOT_PASSWORD}" = "" ] ;then MYSQL_ROOT_PASSWORD=123456 ;fi
|
||||||
|
|
||||||
service mariadb start
|
service mariadb start
|
||||||
|
|
||||||
mysqladmin -u root password ${MYSQL_ROOT_PASSWORD}
|
mysqladmin -u root password ${MYSQL_ROOT_PASSWORD}
|
||||||
|
|
||||||
exec /app/server --createDatabase=true
|
exec /server --createDatabase=true
|
||||||
|
5
go.mod
5
go.mod
@@ -11,9 +11,11 @@ require (
|
|||||||
github.com/casbin/casbin/v2 v2.30.1
|
github.com/casbin/casbin/v2 v2.30.1
|
||||||
github.com/casbin/xorm-adapter/v2 v2.5.1
|
github.com/casbin/xorm-adapter/v2 v2.5.1
|
||||||
github.com/casdoor/go-sms-sender v0.2.0
|
github.com/casdoor/go-sms-sender v0.2.0
|
||||||
github.com/casdoor/goth v1.69.0-FIX1
|
github.com/casdoor/goth v1.69.0-FIX2
|
||||||
github.com/casdoor/oss v1.2.0
|
github.com/casdoor/oss v1.2.0
|
||||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||||
|
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
|
||||||
|
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b
|
||||||
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df
|
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df
|
||||||
github.com/go-ldap/ldap/v3 v3.3.0
|
github.com/go-ldap/ldap/v3 v3.3.0
|
||||||
github.com/go-pay/gopay v1.5.72
|
github.com/go-pay/gopay v1.5.72
|
||||||
@@ -22,6 +24,7 @@ require (
|
|||||||
github.com/google/uuid v1.2.0
|
github.com/google/uuid v1.2.0
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||||
github.com/lestrrat-go/jwx v0.9.0
|
github.com/lestrrat-go/jwx v0.9.0
|
||||||
|
github.com/lib/pq v1.8.0
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
|
20
go.sum
20
go.sum
@@ -100,8 +100,8 @@ github.com/casbin/xorm-adapter/v2 v2.5.1 h1:BkpIxRHKa0s3bSMx173PpuU7oTs+Zw7XmD0B
|
|||||||
github.com/casbin/xorm-adapter/v2 v2.5.1/go.mod h1:AeH4dBKHC9/zYxzdPVHhPDzF8LYLqjDdb767CWJoV54=
|
github.com/casbin/xorm-adapter/v2 v2.5.1/go.mod h1:AeH4dBKHC9/zYxzdPVHhPDzF8LYLqjDdb767CWJoV54=
|
||||||
github.com/casdoor/go-sms-sender v0.2.0 h1:52bin4EBOPzOee64s9UK7jxd22FODvT9/+Y/Z+PSHpg=
|
github.com/casdoor/go-sms-sender v0.2.0 h1:52bin4EBOPzOee64s9UK7jxd22FODvT9/+Y/Z+PSHpg=
|
||||||
github.com/casdoor/go-sms-sender v0.2.0/go.mod h1:fsZsNnALvFIo+HFcE1U/oCQv4ZT42FdglXKMsEm3WSk=
|
github.com/casdoor/go-sms-sender v0.2.0/go.mod h1:fsZsNnALvFIo+HFcE1U/oCQv4ZT42FdglXKMsEm3WSk=
|
||||||
github.com/casdoor/goth v1.69.0-FIX1 h1:24Y3tfaJxWGJbxickGe3F9y2c8X1PgsQynhxGXV1f9Q=
|
github.com/casdoor/goth v1.69.0-FIX2 h1:RgfIMkL9kekylgxHHK2ZY8ASAwOGns2HVlaBwLu7Bcs=
|
||||||
github.com/casdoor/goth v1.69.0-FIX1/go.mod h1:Om55nRo8CkeDkPSNBbzXW4G5uI28ZUkSk5S69dPek3s=
|
github.com/casdoor/goth v1.69.0-FIX2/go.mod h1:Om55nRo8CkeDkPSNBbzXW4G5uI28ZUkSk5S69dPek3s=
|
||||||
github.com/casdoor/oss v1.2.0 h1:ozLAE+nnNdFQBWbzH8U9spzaO8h8NrB57lBcdyMUUQ8=
|
github.com/casdoor/oss v1.2.0 h1:ozLAE+nnNdFQBWbzH8U9spzaO8h8NrB57lBcdyMUUQ8=
|
||||||
github.com/casdoor/oss v1.2.0/go.mod h1:qii35VBuxnR/uEuYSKpS0aJ8htQFOcCVsZ4FHgHLuss=
|
github.com/casdoor/oss v1.2.0/go.mod h1:qii35VBuxnR/uEuYSKpS0aJ8htQFOcCVsZ4FHgHLuss=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
@@ -111,6 +111,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
|
|||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 h1:Puu1hUwfps3+1CUzYdAZXijuvLuRMirgiXdf3zsM2Ig=
|
||||||
|
github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
|
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
|
||||||
@@ -123,7 +125,10 @@ 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/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 h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M=
|
||||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
|
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
|
||||||
|
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||||
|
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b h1:L63RATZFZuFMXy6ixnKmv3eNAXwYQF6HW1vd4IYsQqQ=
|
||||||
|
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b/go.mod h1:EYSpSkwoEcryMmQGfhol2IiB3IMN9IIIaNd/wcAQMGQ=
|
||||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
|
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
||||||
@@ -135,6 +140,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
|
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/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ=
|
||||||
|
github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||||
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
@@ -164,8 +171,10 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
|||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
|
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
|
||||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
|
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-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
@@ -201,6 +210,8 @@ github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNu
|
|||||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=
|
||||||
|
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
@@ -298,6 +309,8 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJK
|
|||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
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 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@@ -397,6 +410,8 @@ github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnD
|
|||||||
github.com/volcengine/volc-sdk-golang v1.0.19 h1:jJp+aJgK0e//rZ9I0K2Y7ufJwvuZRo/AQsYDynXMNgA=
|
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/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF0Ui9vIInTojMM0IfSS4=
|
||||||
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||||
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@@ -413,6 +428,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/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=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
@@ -39,6 +39,7 @@ func readI18nFile(language string) *I18nData {
|
|||||||
func writeI18nFile(language string, data *I18nData) {
|
func writeI18nFile(language string, data *I18nData) {
|
||||||
s := util.StructToJsonFormatted(data)
|
s := util.StructToJsonFormatted(data)
|
||||||
s = strings.ReplaceAll(s, "\\u0026", "&")
|
s = strings.ReplaceAll(s, "\\u0026", "&")
|
||||||
|
s += "\n"
|
||||||
println(s)
|
println(s)
|
||||||
|
|
||||||
util.WriteStringToPath(s, getI18nFilePath(language))
|
util.WriteStringToPath(s, getI18nFilePath(language))
|
||||||
|
18
idp/adfs.go
18
idp/adfs.go
@@ -19,7 +19,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
@@ -59,12 +59,12 @@ func (idp *AdfsIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *AdfsIdProvider) getConfig(hostUrl string) *oauth2.Config {
|
func (idp *AdfsIdProvider) getConfig(hostUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
AuthURL: fmt.Sprintf("%s/adfs/oauth2/authorize", hostUrl),
|
AuthURL: fmt.Sprintf("%s/adfs/oauth2/authorize", hostUrl),
|
||||||
TokenURL: fmt.Sprintf("%s/adfs/oauth2/token", hostUrl),
|
TokenURL: fmt.Sprintf("%s/adfs/oauth2/token", hostUrl),
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +77,7 @@ type AdfsToken struct {
|
|||||||
ErrMsg string `json:"error_description"`
|
ErrMsg string `json:"error_description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetToken
|
||||||
// get more detail via: https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#request-an-access-token
|
// get more detail via: https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#request-an-access-token
|
||||||
func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||||
payload := url.Values{}
|
payload := url.Values{}
|
||||||
@@ -88,7 +89,7 @@ func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -109,6 +110,7 @@ func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserInfo
|
||||||
// Since the userinfo endpoint of ADFS only returns sub,
|
// Since the userinfo endpoint of ADFS only returns sub,
|
||||||
// the id_token is used to resolve the userinfo
|
// the id_token is used to resolve the userinfo
|
||||||
func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
@@ -122,10 +124,10 @@ func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
}
|
}
|
||||||
tokenSrc := []byte(token.AccessToken)
|
tokenSrc := []byte(token.AccessToken)
|
||||||
publicKey, _ := keyset.Keys[0].Materialize()
|
publicKey, _ := keyset.Keys[0].Materialize()
|
||||||
id_token, _ := jwt.Parse(bytes.NewReader(tokenSrc), jwt.WithVerify(jwa.RS256, publicKey))
|
idToken, _ := jwt.Parse(bytes.NewReader(tokenSrc), jwt.WithVerify(jwa.RS256, publicKey))
|
||||||
sid, _ := id_token.Get("sid")
|
sid, _ := idToken.Get("sid")
|
||||||
upn, _ := id_token.Get("upn")
|
upn, _ := idToken.Get("upn")
|
||||||
name, _ := id_token.Get("unique_name")
|
name, _ := idToken.Get("unique_name")
|
||||||
userinfo := &UserInfo{
|
userinfo := &UserInfo{
|
||||||
Id: sid.(string),
|
Id: sid.(string),
|
||||||
Username: name.(string),
|
Username: name.(string),
|
||||||
|
@@ -24,7 +24,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -56,12 +55,12 @@ func (idp *AlipayIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *AlipayIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *AlipayIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
AuthURL: "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm",
|
AuthURL: "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm",
|
||||||
TokenURL: "https://openapi.alipay.com/gateway.do",
|
TokenURL: "https://openapi.alipay.com/gateway.do",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"", ""},
|
Scopes: []string{"", ""},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -205,8 +204,7 @@ func (idp *AlipayIdProvider) postWithBody(body interface{}, targetUrl string) ([
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
@@ -46,12 +46,12 @@ func (idp *BaiduIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *BaiduIdProvider) getConfig() *oauth2.Config {
|
func (idp *BaiduIdProvider) getConfig() *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
AuthURL: "https://openapi.baidu.com/oauth/2.0/authorize",
|
AuthURL: "https://openapi.baidu.com/oauth/2.0/authorize",
|
||||||
TokenURL: "https://openapi.baidu.com/oauth/2.0/token",
|
TokenURL: "https://openapi.baidu.com/oauth/2.0/token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"email"},
|
Scopes: []string{"email"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ func (idp *BaiduIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -47,12 +46,12 @@ func (idp *BilibiliIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *BilibiliIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *BilibiliIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://api.bilibili.com/x/account-oauth2/v1/token",
|
TokenURL: "https://api.bilibili.com/x/account-oauth2/v1/token",
|
||||||
AuthURL: "http://member.bilibili.com/arcopen/fn/user/account/info",
|
AuthURL: "http://member.bilibili.com/arcopen/fn/user/account/info",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"", ""},
|
Scopes: []string{"", ""},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -76,6 +75,7 @@ type BilibiliIdProviderTokenResponse struct {
|
|||||||
Data BilibiliProviderToken `json:"data"`
|
Data BilibiliProviderToken `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetToken
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
"code": 0,
|
"code": 0,
|
||||||
@@ -104,7 +104,6 @@ func (idp *BilibiliIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data, err := idp.postWithBody(pTokenParams, idp.Config.Endpoint.TokenURL)
|
data, err := idp.postWithBody(pTokenParams, idp.Config.Endpoint.TokenURL)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -144,7 +143,7 @@ func (idp *BilibiliIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
type BilibiliUserInfo struct {
|
type BilibiliUserInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Face string `json:"face"`
|
Face string `json:"face"`
|
||||||
OpenId string `json:"openid`
|
OpenId string `json:"openid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BilibiliUserInfoResponse struct {
|
type BilibiliUserInfoResponse struct {
|
||||||
@@ -167,12 +166,11 @@ func (idp *BilibiliIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
|||||||
userInfoUrl := fmt.Sprintf("%s?%s", idp.Config.Endpoint.AuthURL, params.Encode())
|
userInfoUrl := fmt.Sprintf("%s?%s", idp.Config.Endpoint.AuthURL, params.Encode())
|
||||||
|
|
||||||
resp, err := idp.Client.Get(userInfoUrl)
|
resp, err := idp.Client.Get(userInfoUrl)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -206,7 +204,7 @@ func (idp *BilibiliIdProvider) postWithBody(body interface{}, url string) ([]byt
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ package idp
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
@@ -71,8 +71,7 @@ func (idp *CasdoorIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -91,7 +90,6 @@ func (idp *CasdoorIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
Expiry: time.Unix(time.Now().Unix()+int64(pToken.ExpiresIn), 0),
|
Expiry: time.Unix(time.Now().Unix()+int64(pToken.ExpiresIn), 0),
|
||||||
}
|
}
|
||||||
return token, nil
|
return token, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -133,7 +131,7 @@ func (idp *CasdoorIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -155,5 +153,4 @@ func (idp *CasdoorIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error
|
|||||||
AvatarUrl: cdUserinfo.AvatarUrl,
|
AvatarUrl: cdUserinfo.AvatarUrl,
|
||||||
}
|
}
|
||||||
return userInfo, nil
|
return userInfo, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/url"
|
_ "net/url"
|
||||||
_ "time"
|
_ "time"
|
||||||
@@ -36,7 +36,7 @@ func NewCustomIdProvider(clientId string, clientSecret string, redirectUrl strin
|
|||||||
idp := &CustomIdProvider{}
|
idp := &CustomIdProvider{}
|
||||||
idp.UserInfoUrl = userInfoUrl
|
idp.UserInfoUrl = userInfoUrl
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
RedirectURL: redirectUrl,
|
RedirectURL: redirectUrl,
|
||||||
@@ -84,7 +84,7 @@ func (idp *CustomIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -48,12 +47,12 @@ func (idp *DingTalkIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *DingTalkIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *DingTalkIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
AuthURL: "https://api.dingtalk.com/v1.0/contact/users/me",
|
AuthURL: "https://api.dingtalk.com/v1.0/contact/users/me",
|
||||||
TokenURL: "https://api.dingtalk.com/v1.0/oauth2/userAccessToken",
|
TokenURL: "https://api.dingtalk.com/v1.0/oauth2/userAccessToken",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
// DingTalk not allow to set scopes,here it is just a placeholder,
|
// DingTalk not allow to set scopes,here it is just a placeholder,
|
||||||
// convenient to use later
|
// convenient to use later
|
||||||
Scopes: []string{"", ""},
|
Scopes: []string{"", ""},
|
||||||
@@ -101,7 +100,7 @@ func (idp *DingTalkIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
|
|
||||||
token := &oauth2.Token{
|
token := &oauth2.Token{
|
||||||
AccessToken: pToken.AccessToken,
|
AccessToken: pToken.AccessToken,
|
||||||
Expiry: time.Unix(time.Now().Unix()+int64(pToken.ExpiresIn), 0),
|
Expiry: time.Unix(time.Now().Unix()+pToken.ExpiresIn, 0),
|
||||||
}
|
}
|
||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
@@ -145,7 +144,7 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -180,7 +179,7 @@ func (idp *DingTalkIdProvider) postWithBody(body interface{}, url string) ([]byt
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
@@ -42,12 +42,12 @@ func (idp *DouyinIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *DouyinIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *DouyinIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://open.douyin.com/oauth/access_token",
|
TokenURL: "https://open.douyin.com/oauth/access_token",
|
||||||
AuthURL: "https://open.douyin.com/platform/oauth/connect",
|
AuthURL: "https://open.douyin.com/platform/oauth/connect",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"user_info"},
|
Scopes: []string{"user_info"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -98,7 +98,7 @@ func (idp *DouyinIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ func (idp *DouyinIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
respBody, err := ioutil.ReadAll(resp.Body)
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -46,11 +46,11 @@ func (idp *FacebookIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *FacebookIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *FacebookIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://graph.facebook.com/oauth/access_token",
|
TokenURL: "https://graph.facebook.com/oauth/access_token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"email,public_profile"},
|
Scopes: []string{"email,public_profile"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -71,6 +71,7 @@ type FacebookCheckToken struct {
|
|||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FacebookCheckTokenData
|
||||||
// Get more detail via: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken
|
// Get more detail via: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken
|
||||||
type FacebookCheckTokenData struct {
|
type FacebookCheckTokenData struct {
|
||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
|
@@ -19,7 +19,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -49,11 +48,11 @@ func (idp *GiteeIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *GiteeIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *GiteeIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://gitee.com/oauth/token",
|
TokenURL: "https://gitee.com/oauth/token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"user_info emails"},
|
Scopes: []string{"user_info emails"},
|
||||||
|
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
@@ -93,7 +92,7 @@ func (idp *GiteeIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rbs, err := ioutil.ReadAll(resp.Body)
|
rbs, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -49,12 +48,12 @@ func (idp *GithubIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *GithubIdProvider) getConfig() *oauth2.Config {
|
func (idp *GithubIdProvider) getConfig() *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
AuthURL: "https://github.com/login/oauth/authorize",
|
AuthURL: "https://github.com/login/oauth/authorize",
|
||||||
TokenURL: "https://github.com/login/oauth/access_token",
|
TokenURL: "https://github.com/login/oauth/access_token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"user:email", "read:user"},
|
Scopes: []string{"user:email", "read:user"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
}
|
}
|
||||||
@@ -93,7 +92,6 @@ func (idp *GithubIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return token, nil
|
return token, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//{
|
//{
|
||||||
@@ -203,7 +201,7 @@ func (idp *GithubIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -237,7 +235,7 @@ func (idp *GithubIdProvider) postWithBody(body interface{}, url string) ([]byte,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ package idp
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -46,11 +46,11 @@ func (idp *GitlabIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *GitlabIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *GitlabIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://gitlab.com/oauth/token",
|
TokenURL: "https://gitlab.com/oauth/token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"read_user+profile"},
|
Scopes: []string{"read_user+profile"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -85,7 +85,7 @@ func (idp *GitlabIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ func (idp *GitlabIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
@@ -47,12 +47,12 @@ func (idp *GoogleIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *GoogleIdProvider) getConfig() *oauth2.Config {
|
func (idp *GoogleIdProvider) getConfig() *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
AuthURL: "https://accounts.google.com/o/oauth2/auth",
|
AuthURL: "https://accounts.google.com/o/oauth2/auth",
|
||||||
TokenURL: "https://accounts.google.com/o/oauth2/token",
|
TokenURL: "https://accounts.google.com/o/oauth2/token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"profile", "email"},
|
Scopes: []string{"profile", "email"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ func (idp *GoogleIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -207,6 +207,7 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
|||||||
return &idp
|
return &idp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHttpClient
|
||||||
// Goth's idp all implement the Client method, but since the goth.Provider interface does not provide to modify idp's client method, reflection is required
|
// Goth's idp all implement the Client method, but since the goth.Provider interface does not provide to modify idp's client method, reflection is required
|
||||||
func (idp *GothIdProvider) SetHttpClient(client *http.Client) {
|
func (idp *GothIdProvider) SetHttpClient(client *http.Client) {
|
||||||
idpClient := reflect.ValueOf(idp.Provider).Elem().FieldByName("HTTPClient")
|
idpClient := reflect.ValueOf(idp.Provider).Elem().FieldByName("HTTPClient")
|
||||||
|
@@ -17,7 +17,7 @@ package idp
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
@@ -43,7 +43,7 @@ func (idp *InfoflowInternalIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *InfoflowInternalIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *InfoflowInternalIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
RedirectURL: redirectUrl,
|
RedirectURL: redirectUrl,
|
||||||
@@ -58,6 +58,7 @@ type InfoflowInterToken struct {
|
|||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetToken
|
||||||
// get more detail via: https://qy.baidu.com/doc/index.html#/inner_quickstart/flow?id=%E8%8E%B7%E5%8F%96accesstoken
|
// get more detail via: https://qy.baidu.com/doc/index.html#/inner_quickstart/flow?id=%E8%8E%B7%E5%8F%96accesstoken
|
||||||
func (idp *InfoflowInternalIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
func (idp *InfoflowInternalIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||||
pTokenParams := &struct {
|
pTokenParams := &struct {
|
||||||
@@ -69,7 +70,7 @@ func (idp *InfoflowInternalIdProvider) GetToken(code string) (*oauth2.Token, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -137,6 +138,7 @@ type InfoflowInternalUserInfo struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserInfo
|
||||||
// get more detail via: https://qy.baidu.com/doc/index.html#/inner_serverapi/contacts?id=%e8%8e%b7%e5%8f%96%e6%88%90%e5%91%98
|
// get more detail via: https://qy.baidu.com/doc/index.html#/inner_serverapi/contacts?id=%e8%8e%b7%e5%8f%96%e6%88%90%e5%91%98
|
||||||
func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
// Get userid first
|
// Get userid first
|
||||||
@@ -147,7 +149,7 @@ func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserIn
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -165,7 +167,7 @@ func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserIn
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err = ioutil.ReadAll(resp.Body)
|
data, err = io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -47,7 +46,7 @@ func (idp *InfoflowIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *InfoflowIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *InfoflowIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
RedirectURL: redirectUrl,
|
RedirectURL: redirectUrl,
|
||||||
@@ -63,6 +62,7 @@ type InfoflowToken struct {
|
|||||||
ExpiresIn int `json:"expires_in"`
|
ExpiresIn int `json:"expires_in"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetToken
|
||||||
// get more detail via: https://qy.baidu.com/doc/index.html#/third_serverapi/authority
|
// get more detail via: https://qy.baidu.com/doc/index.html#/third_serverapi/authority
|
||||||
func (idp *InfoflowIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
func (idp *InfoflowIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||||
pTokenParams := &struct {
|
pTokenParams := &struct {
|
||||||
@@ -134,6 +134,7 @@ type InfoflowUserInfo struct {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserInfo
|
||||||
// get more detail via: https://qy.baidu.com/doc/index.html#/third_serverapi/contacts?id=%e8%8e%b7%e5%8f%96%e6%88%90%e5%91%98
|
// get more detail via: https://qy.baidu.com/doc/index.html#/third_serverapi/contacts?id=%e8%8e%b7%e5%8f%96%e6%88%90%e5%91%98
|
||||||
func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
// Get userid first
|
// Get userid first
|
||||||
@@ -144,7 +145,7 @@ func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -162,7 +163,7 @@ func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err = ioutil.ReadAll(resp.Body)
|
data, err = io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -197,7 +198,7 @@ func (idp *InfoflowIdProvider) postWithBody(body interface{}, url string) ([]byt
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,6 @@ package idp
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -45,11 +44,11 @@ func (idp *LarkIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *LarkIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *LarkIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
|
TokenURL: "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{},
|
Scopes: []string{},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -173,7 +172,7 @@ func (idp *LarkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
data, err = ioutil.ReadAll(resp.Body)
|
data, err = io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -204,7 +203,7 @@ func (idp *LarkIdProvider) postWithBody(body interface{}, url string) ([]byte, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -47,11 +46,11 @@ func (idp *LinkedInIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *LinkedInIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *LinkedInIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://www.linkedIn.com/oauth/v2/accessToken",
|
TokenURL: "https://www.linkedIn.com/oauth/v2/accessToken",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"email,public_profile"},
|
Scopes: []string{"email,public_profile"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -85,7 +84,7 @@ func (idp *LinkedInIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rbs, err := ioutil.ReadAll(resp.Body)
|
rbs, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -323,7 +322,7 @@ func (idp *LinkedInIdProvider) GetUrlRespWithAuthorization(url, token string) ([
|
|||||||
}
|
}
|
||||||
}(resp.Body)
|
}(resp.Body)
|
||||||
|
|
||||||
bs, err := ioutil.ReadAll(resp.Body)
|
bs, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
10
idp/okta.go
10
idp/okta.go
@@ -17,7 +17,7 @@ package idp
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
@@ -48,12 +48,12 @@ func (idp *OktaIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *OktaIdProvider) getConfig(hostUrl string, clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *OktaIdProvider) getConfig(hostUrl string, clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: fmt.Sprintf("%s/v1/token", hostUrl),
|
TokenURL: fmt.Sprintf("%s/v1/token", hostUrl),
|
||||||
AuthURL: fmt.Sprintf("%s/v1/authorize", hostUrl),
|
AuthURL: fmt.Sprintf("%s/v1/authorize", hostUrl),
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
// openid is required for authentication requests
|
// openid is required for authentication requests
|
||||||
// get more details via: https://developer.okta.com/docs/reference/api/oidc/#reserved-scopes
|
// get more details via: https://developer.okta.com/docs/reference/api/oidc/#reserved-scopes
|
||||||
Scopes: []string{"openid", "profile", "email"},
|
Scopes: []string{"openid", "profile", "email"},
|
||||||
@@ -114,7 +114,7 @@ func (idp *OktaIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ func (idp *OktaIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
12
idp/qq.go
12
idp/qq.go
@@ -18,7 +18,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -48,11 +48,11 @@ func (idp *QqIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *QqIdProvider) getConfig() *oauth2.Config {
|
func (idp *QqIdProvider) getConfig() *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"get_user_info"},
|
Scopes: []string{"get_user_info"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ func (idp *QqIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
tokenContent, err := ioutil.ReadAll(resp.Body)
|
tokenContent, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ func (idp *QqIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
openIdBody, err := ioutil.ReadAll(resp.Body)
|
openIdBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ func (idp *QqIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
userInfoBody, err := ioutil.ReadAll(resp.Body)
|
userInfoBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -47,11 +47,11 @@ func (idp *WeChatIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *WeChatIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *WeChatIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"snsapi_login"},
|
Scopes: []string{"snsapi_login"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -144,7 +144,7 @@ type WechatUserInfo struct {
|
|||||||
City string `json:"city"` // City filled in by general user's personal data
|
City string `json:"city"` // City filled in by general user's personal data
|
||||||
Province string `json:"province"` // Province filled in by ordinary user's personal information
|
Province string `json:"province"` // Province filled in by ordinary user's personal information
|
||||||
Country string `json:"country"` // Country, such as China is CN
|
Country string `json:"country"` // Country, such as China is CN
|
||||||
Headimgurl string `json:"headimgurl"` // User avatar, the last value represents the size of the square avatar (there are optional values of 0, 46, 64, 96, 132, 0 represents a 640*640 square avatar), this item is empty when the user does not have a avatar
|
Headimgurl string `json:"headimgurl"` // User avatar, the last value represents the size of the square avatar (there are optional values of 0, 46, 64, 96, 132, 0 represents a 640*640 square avatar), this item is empty when the user does not have an avatar
|
||||||
Privilege []string `json:"privilege"` // User Privilege information, json array, such as Wechat Woka user (chinaunicom)
|
Privilege []string `json:"privilege"` // User Privilege information, json array, such as Wechat Woka user (chinaunicom)
|
||||||
Unionid string `json:"unionid"` // Unified user identification. For an application under a WeChat open platform account, the unionid of the same user is unique.
|
Unionid string `json:"unionid"` // Unified user identification. For an application under a WeChat open platform account, the unionid of the same user is unique.
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ package idp
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
@@ -42,7 +42,7 @@ func (idp *WeChatMiniProgramIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *WeChatMiniProgramIdProvider) getConfig(clientId string, clientSecret string) *oauth2.Config {
|
func (idp *WeChatMiniProgramIdProvider) getConfig(clientId string, clientSecret string) *oauth2.Config {
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ func (idp *WeChatMiniProgramIdProvider) GetSessionByCode(code string) (*WeChatMi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer sessionResponse.Body.Close()
|
defer sessionResponse.Body.Close()
|
||||||
data, err := ioutil.ReadAll(sessionResponse.Body)
|
data, err := io.ReadAll(sessionResponse.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -78,5 +78,4 @@ func (idp *WeChatMiniProgramIdProvider) GetSessionByCode(code string) (*WeChatMi
|
|||||||
return nil, fmt.Errorf("err: %s", session.Errmsg)
|
return nil, fmt.Errorf("err: %s", session.Errmsg)
|
||||||
}
|
}
|
||||||
return &session, nil
|
return &session, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -17,13 +17,14 @@ package idp
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WeComInternalIdProvider
|
||||||
// This idp is using wecom internal application api as idp
|
// This idp is using wecom internal application api as idp
|
||||||
type WeComInternalIdProvider struct {
|
type WeComInternalIdProvider struct {
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
@@ -44,7 +45,7 @@ func (idp *WeComInternalIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (idp *WeComInternalIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *WeComInternalIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
RedirectURL: redirectUrl,
|
RedirectURL: redirectUrl,
|
||||||
@@ -72,7 +73,7 @@ func (idp *WeComInternalIdProvider) GetToken(code string) (*oauth2.Token, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -123,7 +124,7 @@ func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -144,7 +145,7 @@ func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err = ioutil.ReadAll(resp.Body)
|
data, err = io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -46,11 +45,11 @@ func (idp *WeComIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *WeComIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *WeComIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{"snsapi_login"},
|
Scopes: []string{"snsapi_login"},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -195,7 +194,7 @@ func (idp *WeComIdProvider) postWithBody(body interface{}, url string) ([]byte,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -48,11 +47,11 @@ func (idp *WeiBoIdProvider) SetHttpClient(client *http.Client) {
|
|||||||
|
|
||||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
func (idp *WeiBoIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
func (idp *WeiBoIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
var endpoint = oauth2.Endpoint{
|
endpoint := oauth2.Endpoint{
|
||||||
TokenURL: "https://api.weibo.com/oauth2/access_token",
|
TokenURL: "https://api.weibo.com/oauth2/access_token",
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = &oauth2.Config{
|
config := &oauth2.Config{
|
||||||
Scopes: []string{""},
|
Scopes: []string{""},
|
||||||
Endpoint: endpoint,
|
Endpoint: endpoint,
|
||||||
ClientID: clientId,
|
ClientID: clientId,
|
||||||
@@ -92,7 +91,7 @@ func (idp *WeiBoIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}(resp.Body)
|
}(resp.Body)
|
||||||
bs, err := ioutil.ReadAll(resp.Body)
|
bs, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
160
init_data.json.template
Normal file
160
init_data.json.template
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
{
|
||||||
|
"organizations": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"displayName": "",
|
||||||
|
"websiteUrl": "",
|
||||||
|
"favicon": "",
|
||||||
|
"passwordType": "",
|
||||||
|
"phonePrefix": "",
|
||||||
|
"defaultAvatar": "",
|
||||||
|
"tags": [""]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"applications": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"displayName": "",
|
||||||
|
"logo": "",
|
||||||
|
"homepageUrl": "",
|
||||||
|
"organization": "",
|
||||||
|
"cert": "",
|
||||||
|
"enablePassword": true,
|
||||||
|
"enableSignUp": true,
|
||||||
|
"clientId": "",
|
||||||
|
"clientSecret": "",
|
||||||
|
"providers": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"canSignUp": true,
|
||||||
|
"canSignIn": true,
|
||||||
|
"canUnlink": false,
|
||||||
|
"prompted": false,
|
||||||
|
"alertType": "None"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"signupItems": [
|
||||||
|
{
|
||||||
|
"name": "ID",
|
||||||
|
"visible": false,
|
||||||
|
"required": true,
|
||||||
|
"prompted": false,
|
||||||
|
"rule": "Random"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Username",
|
||||||
|
"visible": true,
|
||||||
|
"required": true,
|
||||||
|
"prompted": false,
|
||||||
|
"rule": "None"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Display name",
|
||||||
|
"visible": true,
|
||||||
|
"required": true,
|
||||||
|
"prompted": false,
|
||||||
|
"rule": "None"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Password",
|
||||||
|
"visible": true,
|
||||||
|
"required": true,
|
||||||
|
"prompted": false,
|
||||||
|
"rule": "None"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Confirm password",
|
||||||
|
"visible": true,
|
||||||
|
"required": true,
|
||||||
|
"prompted": false,
|
||||||
|
"rule": "None"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Email",
|
||||||
|
"visible": true,
|
||||||
|
"required": true,
|
||||||
|
"prompted": false,
|
||||||
|
"rule": "None"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Phone",
|
||||||
|
"visible": true,
|
||||||
|
"required": true,
|
||||||
|
"prompted": false,
|
||||||
|
"rule": "None"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Agreement",
|
||||||
|
"visible": true,
|
||||||
|
"required": true,
|
||||||
|
"prompted": false,
|
||||||
|
"rule": "None"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"redirectUris": [""],
|
||||||
|
"expireInHours": 168
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"type": "normal-user",
|
||||||
|
"password": "",
|
||||||
|
"displayName": "",
|
||||||
|
"avatar": "",
|
||||||
|
"email": "",
|
||||||
|
"phone": "",
|
||||||
|
"address": [],
|
||||||
|
"affiliation": "",
|
||||||
|
"tag": "",
|
||||||
|
"score": 2000,
|
||||||
|
"ranking": 1,
|
||||||
|
"isAdmin": true,
|
||||||
|
"isGlobalAdmin": true,
|
||||||
|
"isForbidden": false,
|
||||||
|
"isDeleted": false,
|
||||||
|
"signupApplication": "",
|
||||||
|
"createdIp": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"providers": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"displayName": "",
|
||||||
|
"category": "",
|
||||||
|
"type": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"certs": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"displayName": "",
|
||||||
|
"scope": "JWT",
|
||||||
|
"type": "x509",
|
||||||
|
"cryptoAlgorithm": "RS256",
|
||||||
|
"bitSize": 4096,
|
||||||
|
"expireInYears": 20,
|
||||||
|
"certificate": "",
|
||||||
|
"privateKey": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ldaps": [
|
||||||
|
{
|
||||||
|
"id": "",
|
||||||
|
"owner": "",
|
||||||
|
"serverName": "",
|
||||||
|
"host": "",
|
||||||
|
"port": 389,
|
||||||
|
"admin": "",
|
||||||
|
"passwd": "",
|
||||||
|
"baseDn": "",
|
||||||
|
"autoSync": 0,
|
||||||
|
"lastSync": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
2
main.go
2
main.go
@@ -36,6 +36,7 @@ func main() {
|
|||||||
|
|
||||||
object.InitAdapter(*createDatabase)
|
object.InitAdapter(*createDatabase)
|
||||||
object.InitDb()
|
object.InitDb()
|
||||||
|
object.InitFromFile()
|
||||||
object.InitDefaultStorageProvider()
|
object.InitDefaultStorageProvider()
|
||||||
object.InitLdapAutoSynchronizer()
|
object.InitLdapAutoSynchronizer()
|
||||||
proxy.InitHttpClient()
|
proxy.InitHttpClient()
|
||||||
@@ -55,6 +56,7 @@ func main() {
|
|||||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
||||||
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
||||||
|
|
||||||
|
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||||
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
||||||
if conf.GetConfigString("redisEndpoint") == "" {
|
if conf.GetConfigString("redisEndpoint") == "" {
|
||||||
beego.BConfig.WebConfig.Session.SessionProvider = "file"
|
beego.BConfig.WebConfig.Session.SessionProvider = "file"
|
||||||
|
@@ -16,7 +16,7 @@ data:
|
|||||||
defaultStorageProvider =
|
defaultStorageProvider =
|
||||||
isCloudIntranet = false
|
isCloudIntranet = false
|
||||||
authState = "casdoor"
|
authState = "casdoor"
|
||||||
sock5Proxy = "127.0.0.1:10808"
|
socks5Proxy = "127.0.0.1:10808"
|
||||||
verificationCodeTimeout = 10
|
verificationCodeTimeout = 10
|
||||||
initScore = 2000
|
initScore = 2000
|
||||||
logPostOnly = true
|
logPostOnly = true
|
||||||
|
@@ -21,9 +21,10 @@ import (
|
|||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
//_ "github.com/denisenkom/go-mssqldb" // db = mssql
|
_ "github.com/denisenkom/go-mssqldb" // db = mssql
|
||||||
_ "github.com/go-sql-driver/mysql" // db = mysql
|
_ "github.com/go-sql-driver/mysql" // db = mysql
|
||||||
//_ "github.com/lib/pq" // db = postgres
|
_ "github.com/lib/pq" // db = postgres
|
||||||
|
//_ "github.com/mattn/go-sqlite3" // db = sqlite3
|
||||||
"xorm.io/core"
|
"xorm.io/core"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
@@ -36,11 +37,12 @@ func InitConfig() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||||
|
|
||||||
InitAdapter(true)
|
InitAdapter(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitAdapter(createDatabase bool) {
|
func InitAdapter(createDatabase bool) {
|
||||||
|
|
||||||
adapter = NewAdapter(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName(), conf.GetConfigString("dbName"))
|
adapter = NewAdapter(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName(), conf.GetConfigString("dbName"))
|
||||||
if createDatabase {
|
if createDatabase {
|
||||||
adapter.CreateDatabase()
|
adapter.CreateDatabase()
|
||||||
@@ -202,6 +204,11 @@ func (a *Adapter) createTable() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = a.Engine.Sync2(new(PermissionRule))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||||
|
@@ -47,6 +47,7 @@ type Application struct {
|
|||||||
EnableSigninSession bool `json:"enableSigninSession"`
|
EnableSigninSession bool `json:"enableSigninSession"`
|
||||||
EnableCodeSignin bool `json:"enableCodeSignin"`
|
EnableCodeSignin bool `json:"enableCodeSignin"`
|
||||||
EnableSamlCompress bool `json:"enableSamlCompress"`
|
EnableSamlCompress bool `json:"enableSamlCompress"`
|
||||||
|
EnableWebAuthn bool `json:"enableWebAuthn"`
|
||||||
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
||||||
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
||||||
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
||||||
@@ -280,8 +281,12 @@ func UpdateApplication(id string, application *Application) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddApplication(application *Application) bool {
|
func AddApplication(application *Application) bool {
|
||||||
|
if application.ClientId == "" {
|
||||||
application.ClientId = util.GenerateClientId()
|
application.ClientId = util.GenerateClientId()
|
||||||
|
}
|
||||||
|
if application.ClientSecret == "" {
|
||||||
application.ClientSecret = util.GenerateClientSecret()
|
application.ClientSecret = util.GenerateClientSecret()
|
||||||
|
}
|
||||||
for _, providerItem := range application.Providers {
|
for _, providerItem := range application.Providers {
|
||||||
providerItem.Provider = nil
|
providerItem.Provider = nil
|
||||||
}
|
}
|
||||||
@@ -312,7 +317,7 @@ func (application *Application) GetId() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CheckRedirectUriValid(application *Application, redirectUri string) bool {
|
func CheckRedirectUriValid(application *Application, redirectUri string) bool {
|
||||||
var validUri = false
|
validUri := false
|
||||||
for _, tmpUri := range application.RedirectUris {
|
for _, tmpUri := range application.RedirectUris {
|
||||||
if strings.Contains(redirectUri, tmpUri) {
|
if strings.Contains(redirectUri, tmpUri) {
|
||||||
validUri = true
|
validUri = true
|
||||||
|
@@ -51,6 +51,10 @@ func downloadFile(url string) (*bytes.Buffer, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getPermanentAvatarUrl(organization string, username string, url string) string {
|
func getPermanentAvatarUrl(organization string, username string, url string) string {
|
||||||
|
if url == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
if defaultStorageProvider == nil {
|
if defaultStorageProvider == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ type Cert struct {
|
|||||||
BitSize int `json:"bitSize"`
|
BitSize int `json:"bitSize"`
|
||||||
ExpireInYears int `json:"expireInYears"`
|
ExpireInYears int `json:"expireInYears"`
|
||||||
|
|
||||||
PublicKey string `xorm:"mediumtext" json:"publicKey"`
|
Certificate string `xorm:"mediumtext" json:"certificate"`
|
||||||
PrivateKey string `xorm:"mediumtext" json:"privateKey"`
|
PrivateKey string `xorm:"mediumtext" json:"privateKey"`
|
||||||
AuthorityPublicKey string `xorm:"mediumtext" json:"authorityPublicKey"`
|
AuthorityPublicKey string `xorm:"mediumtext" json:"authorityPublicKey"`
|
||||||
AuthorityRootPublicKey string `xorm:"mediumtext" json:"authorityRootPublicKey"`
|
AuthorityRootPublicKey string `xorm:"mediumtext" json:"authorityRootPublicKey"`
|
||||||
@@ -123,9 +123,9 @@ func UpdateCert(id string, cert *Cert) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddCert(cert *Cert) bool {
|
func AddCert(cert *Cert) bool {
|
||||||
if cert.PublicKey == "" || cert.PrivateKey == "" {
|
if cert.Certificate == "" || cert.PrivateKey == "" {
|
||||||
publicKey, privateKey := generateRsaKeys(cert.BitSize, cert.ExpireInYears, cert.Name, cert.Owner)
|
certificate, privateKey := generateRsaKeys(cert.BitSize, cert.ExpireInYears, cert.Name, cert.Owner)
|
||||||
cert.PublicKey = publicKey
|
cert.Certificate = certificate
|
||||||
cert.PrivateKey = privateKey
|
cert.PrivateKey = privateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -197,16 +197,20 @@ func filterField(field string) bool {
|
|||||||
return reFieldWhiteList.MatchString(field)
|
return reFieldWhiteList.MatchString(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckUserPermission(requestUserId, userId string, strict bool) (bool, error) {
|
func CheckUserPermission(requestUserId, userId, userOwner string, strict bool) (bool, error) {
|
||||||
if requestUserId == "" {
|
if requestUserId == "" {
|
||||||
return false, fmt.Errorf("please login first")
|
return false, fmt.Errorf("please login first")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if userId != "" {
|
||||||
targetUser := GetUser(userId)
|
targetUser := GetUser(userId)
|
||||||
if targetUser == nil {
|
if targetUser == nil {
|
||||||
return false, fmt.Errorf("the user: %s doesn't exist", userId)
|
return false, fmt.Errorf("the user: %s doesn't exist", userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userOwner = targetUser.Owner
|
||||||
|
}
|
||||||
|
|
||||||
hasPermission := false
|
hasPermission := false
|
||||||
if strings.HasPrefix(requestUserId, "app/") {
|
if strings.HasPrefix(requestUserId, "app/") {
|
||||||
hasPermission = true
|
hasPermission = true
|
||||||
@@ -219,7 +223,7 @@ func CheckUserPermission(requestUserId, userId string, strict bool) (bool, error
|
|||||||
hasPermission = true
|
hasPermission = true
|
||||||
} else if requestUserId == userId {
|
} else if requestUserId == userId {
|
||||||
hasPermission = true
|
hasPermission = true
|
||||||
} else if targetUser.Owner == requestUser.Owner {
|
} else if userOwner == requestUser.Owner {
|
||||||
if strict {
|
if strict {
|
||||||
hasPermission = requestUser.IsAdmin
|
hasPermission = requestUser.IsAdmin
|
||||||
} else {
|
} else {
|
||||||
@@ -230,3 +234,29 @@ func CheckUserPermission(requestUserId, userId string, strict bool) (bool, error
|
|||||||
|
|
||||||
return hasPermission, fmt.Errorf("you don't have the permission to do this")
|
return hasPermission, fmt.Errorf("you don't have the permission to do this")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
||||||
|
permissions := GetPermissions(application.Organization)
|
||||||
|
allowed := true
|
||||||
|
var err error
|
||||||
|
for _, permission := range permissions {
|
||||||
|
if !permission.IsEnabled || len(permission.Users) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
isHit := false
|
||||||
|
for _, resource := range permission.Resources {
|
||||||
|
if application.Name == resource {
|
||||||
|
isHit = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isHit {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
allowed, err = enforcer.Enforce(userId, application.Name, "read")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allowed, err
|
||||||
|
}
|
||||||
|
@@ -33,6 +33,7 @@ func SendEmail(provider *Provider, title string, content string, dest string, se
|
|||||||
// DailSmtpServer Dail Smtp server
|
// DailSmtpServer Dail Smtp server
|
||||||
func DailSmtpServer(provider *Provider) error {
|
func DailSmtpServer(provider *Provider) error {
|
||||||
dialer := gomail.NewDialer(provider.Host, provider.Port, provider.ClientId, provider.ClientSecret)
|
dialer := gomail.NewDialer(provider.Host, provider.Port, provider.ClientId, provider.ClientSecret)
|
||||||
|
dialer.SSL = !provider.DisableSsl
|
||||||
|
|
||||||
sender, err := dialer.Dial()
|
sender, err := dialer.Dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -15,20 +15,25 @@
|
|||||||
package object
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"encoding/gob"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"github.com/duo-labs/webauthn/webauthn"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitDb() {
|
func InitDb() {
|
||||||
existed := initBuiltInOrganization()
|
existed := initBuiltInOrganization()
|
||||||
if !existed {
|
if !existed {
|
||||||
|
initBuiltInPermission()
|
||||||
initBuiltInProvider()
|
initBuiltInProvider()
|
||||||
initBuiltInUser()
|
initBuiltInUser()
|
||||||
initBuiltInApplication()
|
initBuiltInApplication()
|
||||||
initBuiltInCert()
|
initBuiltInCert()
|
||||||
initBuiltInLdap()
|
initBuiltInLdap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initWebAuthn()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initBuiltInOrganization() bool {
|
func initBuiltInOrganization() bool {
|
||||||
@@ -66,12 +71,15 @@ func initBuiltInOrganization() bool {
|
|||||||
{Name: "Bio", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
{Name: "Bio", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
{Name: "Tag", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
{Name: "Tag", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
|
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
{Name: "Is global 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 forbidden", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
|
{Name: "WebAuthn credentials", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
AddOrganization(organization)
|
AddOrganization(organization)
|
||||||
@@ -150,11 +158,11 @@ func initBuiltInApplication() {
|
|||||||
func readTokenFromFile() (string, string) {
|
func readTokenFromFile() (string, string) {
|
||||||
pemPath := "./object/token_jwt_key.pem"
|
pemPath := "./object/token_jwt_key.pem"
|
||||||
keyPath := "./object/token_jwt_key.key"
|
keyPath := "./object/token_jwt_key.key"
|
||||||
pem, err := ioutil.ReadFile(pemPath)
|
pem, err := os.ReadFile(pemPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
key, err := ioutil.ReadFile(keyPath)
|
key, err := os.ReadFile(keyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
@@ -162,7 +170,7 @@ func readTokenFromFile() (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initBuiltInCert() {
|
func initBuiltInCert() {
|
||||||
tokenJwtPublicKey, tokenJwtPrivateKey := readTokenFromFile()
|
tokenJwtCertificate, tokenJwtPrivateKey := readTokenFromFile()
|
||||||
cert := getCert("admin", "cert-built-in")
|
cert := getCert("admin", "cert-built-in")
|
||||||
if cert != nil {
|
if cert != nil {
|
||||||
return
|
return
|
||||||
@@ -178,7 +186,7 @@ func initBuiltInCert() {
|
|||||||
CryptoAlgorithm: "RS256",
|
CryptoAlgorithm: "RS256",
|
||||||
BitSize: 4096,
|
BitSize: 4096,
|
||||||
ExpireInYears: 20,
|
ExpireInYears: 20,
|
||||||
PublicKey: tokenJwtPublicKey,
|
Certificate: tokenJwtCertificate,
|
||||||
PrivateKey: tokenJwtPrivateKey,
|
PrivateKey: tokenJwtPrivateKey,
|
||||||
}
|
}
|
||||||
AddCert(cert)
|
AddCert(cert)
|
||||||
@@ -221,3 +229,29 @@ func initBuiltInProvider() {
|
|||||||
}
|
}
|
||||||
AddProvider(provider)
|
AddProvider(provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initWebAuthn() {
|
||||||
|
gob.Register(webauthn.SessionData{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func initBuiltInPermission() {
|
||||||
|
permission := GetPermission("built-in/permission-built-in")
|
||||||
|
if permission != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
permission = &Permission{
|
||||||
|
Owner: "built-in",
|
||||||
|
Name: "permission-built-in",
|
||||||
|
CreatedTime: util.GetCurrentTime(),
|
||||||
|
DisplayName: "Built-in Permission",
|
||||||
|
Users: []string{"built-in/admin"},
|
||||||
|
Roles: []string{},
|
||||||
|
ResourceType: "Application",
|
||||||
|
Resources: []string{"app-built-in"},
|
||||||
|
Actions: []string{"Read", "Write", "Admin"},
|
||||||
|
Effect: "Allow",
|
||||||
|
IsEnabled: true,
|
||||||
|
}
|
||||||
|
AddPermission(permission)
|
||||||
|
}
|
||||||
|
148
object/init_data.go
Normal file
148
object/init_data.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
// Copyright 2022 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 "github.com/casdoor/casdoor/util"
|
||||||
|
|
||||||
|
type InitData struct {
|
||||||
|
Organizations []*Organization `json:"organizations"`
|
||||||
|
Applications []*Application `json:"applications"`
|
||||||
|
Users []*User `json:"users"`
|
||||||
|
Certs []*Cert `json:"certs"`
|
||||||
|
Providers []*Provider `json:"providers"`
|
||||||
|
Ldaps []*Ldap `json:"ldaps"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitFromFile() {
|
||||||
|
initData := readInitDataFromFile("./init_data.json")
|
||||||
|
if initData != nil {
|
||||||
|
for _, organization := range initData.Organizations {
|
||||||
|
initDefinedOrganization(organization)
|
||||||
|
}
|
||||||
|
for _, provider := range initData.Providers {
|
||||||
|
initDefinedProvider(provider)
|
||||||
|
}
|
||||||
|
for _, user := range initData.Users {
|
||||||
|
initDefinedUser(user)
|
||||||
|
}
|
||||||
|
for _, application := range initData.Applications {
|
||||||
|
initDefinedApplication(application)
|
||||||
|
}
|
||||||
|
for _, cert := range initData.Certs {
|
||||||
|
initDefinedCert(cert)
|
||||||
|
}
|
||||||
|
for _, ldap := range initData.Ldaps {
|
||||||
|
initDefinedLdap(ldap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readInitDataFromFile(filePath string) *InitData {
|
||||||
|
if !util.FileExist(filePath) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s := util.ReadStringFromPath(filePath)
|
||||||
|
|
||||||
|
data := &InitData{}
|
||||||
|
err := util.JsonToStruct(s, data)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedOrganization(organization *Organization) {
|
||||||
|
existed := getOrganization(organization.Owner, organization.Name)
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
organization.CreatedTime = util.GetCurrentTime()
|
||||||
|
organization.AccountItems = []*AccountItem{
|
||||||
|
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
|
{Name: "Name", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Display name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Avatar", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "User type", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Password", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
|
{Name: "Email", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Phone", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Country/Region", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Location", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Affiliation", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Title", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Homepage", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Bio", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Tag", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
|
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
|
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
|
{Name: "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"},
|
||||||
|
}
|
||||||
|
|
||||||
|
AddOrganization(organization)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedApplication(application *Application) {
|
||||||
|
existed := getApplication(application.Owner, application.Name)
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
application.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddApplication(application)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedUser(user *User) {
|
||||||
|
existed := getUser(user.Owner, user.Name)
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user.CreatedTime = util.GetCurrentTime()
|
||||||
|
user.Id = util.GenerateId()
|
||||||
|
user.Properties = make(map[string]string)
|
||||||
|
AddUser(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedCert(cert *Cert) {
|
||||||
|
existed := getCert(cert.Owner, cert.Name)
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cert.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddCert(cert)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedLdap(ldap *Ldap) {
|
||||||
|
existed := GetLdap(ldap.Id)
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
AddLdap(ldap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedProvider(provider *Provider) {
|
||||||
|
existed := GetProvider(provider.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
AddProvider(provider)
|
||||||
|
}
|
@@ -208,11 +208,15 @@ func GetLdapConn(host string, port int, adminUser string, adminPasswd string) (*
|
|||||||
|
|
||||||
func (l *ldapConn) GetLdapUsers(baseDn string) ([]ldapUser, error) {
|
func (l *ldapConn) GetLdapUsers(baseDn string) ([]ldapUser, error) {
|
||||||
SearchFilter := "(objectClass=posixAccount)"
|
SearchFilter := "(objectClass=posixAccount)"
|
||||||
SearchAttributes := []string{"uidNumber", "uid", "cn", "gidNumber", "entryUUID", "mail", "email",
|
SearchAttributes := []string{
|
||||||
"emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress"}
|
"uidNumber", "uid", "cn", "gidNumber", "entryUUID", "mail", "email",
|
||||||
|
"emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
|
||||||
|
}
|
||||||
SearchFilterMsAD := "(objectClass=user)"
|
SearchFilterMsAD := "(objectClass=user)"
|
||||||
SearchAttributesMsAD := []string{"uidNumber", "sAMAccountName", "cn", "gidNumber", "entryUUID", "mail", "email",
|
SearchAttributesMsAD := []string{
|
||||||
"emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress"}
|
"uidNumber", "sAMAccountName", "cn", "gidNumber", "entryUUID", "mail", "email",
|
||||||
|
"emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
|
||||||
|
}
|
||||||
var searchReq *goldap.SearchRequest
|
var searchReq *goldap.SearchRequest
|
||||||
if l.IsAD {
|
if l.IsAD {
|
||||||
searchReq = goldap.NewSearchRequest(baseDn,
|
searchReq = goldap.NewSearchRequest(baseDn,
|
||||||
@@ -459,7 +463,7 @@ func CheckLdapUuidExist(owner string, uuids []string) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for uuid, _ := range existUuidSet {
|
for uuid := range existUuidSet {
|
||||||
existUuids = append(existUuids, uuid)
|
existUuids = append(existUuids, uuid)
|
||||||
}
|
}
|
||||||
return existUuids
|
return existUuids
|
||||||
|
@@ -31,6 +31,7 @@ func GetLdapAutoSynchronizer() *LdapAutoSynchronizer {
|
|||||||
return globalLdapAutoSynchronizer
|
return globalLdapAutoSynchronizer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartAutoSync
|
||||||
// start autosync for specified ldap, old existing autosync goroutine will be ceased
|
// start autosync for specified ldap, old existing autosync goroutine will be ceased
|
||||||
func (l *LdapAutoSynchronizer) StartAutoSync(ldapId string) error {
|
func (l *LdapAutoSynchronizer) StartAutoSync(ldapId string) error {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
@@ -93,9 +94,9 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) {
|
|||||||
logs.Info(fmt.Sprintf("ldap autosync success, %d new users, %d existing users", len(users)-len(*existed), len(*existed)))
|
logs.Info(fmt.Sprintf("ldap autosync success, %d new users, %d existing users", len(users)-len(*existed), len(*existed)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LdapAutoSynchronizerStartUpAll
|
||||||
// start all autosync goroutine for existing ldap servers in each organizations
|
// start all autosync goroutine for existing ldap servers in each organizations
|
||||||
func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() {
|
func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() {
|
||||||
organizations := []*Organization{}
|
organizations := []*Organization{}
|
||||||
|
@@ -97,7 +97,7 @@ func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
|
|||||||
// link here: https://self-issued.info/docs/draft-ietf-jose-json-web-key.html
|
// link here: https://self-issued.info/docs/draft-ietf-jose-json-web-key.html
|
||||||
// or https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key
|
// or https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key
|
||||||
for _, cert := range certs {
|
for _, cert := range certs {
|
||||||
certPemBlock := []byte(cert.PublicKey)
|
certPemBlock := []byte(cert.Certificate)
|
||||||
certDerBlock, _ := pem.Decode(certPemBlock)
|
certDerBlock, _ := pem.Decode(certPemBlock)
|
||||||
x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes)
|
x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes)
|
||||||
|
|
||||||
|
@@ -15,6 +15,8 @@
|
|||||||
package object
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/cred"
|
"github.com/casdoor/casdoor/cred"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"xorm.io/core"
|
"xorm.io/core"
|
||||||
@@ -186,3 +188,31 @@ func DeleteOrganization(organization *Organization) bool {
|
|||||||
func GetOrganizationByUser(user *User) *Organization {
|
func GetOrganizationByUser(user *User) *Organization {
|
||||||
return getOrganization("admin", user.Owner)
|
return getOrganization("admin", user.Owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAccountItemByName(name string, organization *Organization) *AccountItem {
|
||||||
|
if organization == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, accountItem := range organization.AccountItems {
|
||||||
|
if accountItem.Name == name {
|
||||||
|
return accountItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckAccountItemModifyRule(accountItem *AccountItem, user *User) (bool, string) {
|
||||||
|
switch accountItem.ModifyRule {
|
||||||
|
case "Admin":
|
||||||
|
if !(user.IsAdmin || user.IsGlobalAdmin) {
|
||||||
|
return false, fmt.Sprintf("Only admin can modify the %s.", accountItem.Name)
|
||||||
|
}
|
||||||
|
case "Immutable":
|
||||||
|
return false, fmt.Sprintf("The %s is immutable.", accountItem.Name)
|
||||||
|
case "Self":
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return false, fmt.Sprintf("Unknown modify rule %s.", accountItem.ModifyRule)
|
||||||
|
}
|
||||||
|
return true, ""
|
||||||
|
}
|
||||||
|
@@ -39,6 +39,16 @@ type Permission struct {
|
|||||||
IsEnabled bool `json:"isEnabled"`
|
IsEnabled bool `json:"isEnabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PermissionRule struct {
|
||||||
|
Ptype string `xorm:"varchar(100) index not null default ''" json:"ptype"`
|
||||||
|
V0 string `xorm:"varchar(100) index not null default ''" json:"v0"`
|
||||||
|
V1 string `xorm:"varchar(100) index not null default ''" json:"v1"`
|
||||||
|
V2 string `xorm:"varchar(100) index not null default ''" json:"v2"`
|
||||||
|
V3 string `xorm:"varchar(100) index not null default ''" json:"v3"`
|
||||||
|
V4 string `xorm:"varchar(100) index not null default ''" json:"v4"`
|
||||||
|
V5 string `xorm:"varchar(100) index not null default ''" json:"v5"`
|
||||||
|
}
|
||||||
|
|
||||||
func GetPermissionCount(owner, field, value string) int {
|
func GetPermissionCount(owner, field, value string) int {
|
||||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||||
count, err := session.Count(&Permission{})
|
count, err := session.Count(&Permission{})
|
||||||
@@ -95,7 +105,8 @@ func GetPermission(id string) *Permission {
|
|||||||
|
|
||||||
func UpdatePermission(id string, permission *Permission) bool {
|
func UpdatePermission(id string, permission *Permission) bool {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
if getPermission(owner, name) == nil {
|
oldPermission := getPermission(owner, name)
|
||||||
|
if oldPermission == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +115,11 @@ func UpdatePermission(id string, permission *Permission) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
removePolicies(oldPermission)
|
||||||
|
addPolicies(permission)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +129,10 @@ func AddPermission(permission *Permission) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
addPolicies(permission)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,9 +142,23 @@ func DeletePermission(permission *Permission) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affected != 0 {
|
||||||
|
removePolicies(permission)
|
||||||
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (permission *Permission) GetId() string {
|
func (permission *Permission) GetId() string {
|
||||||
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
|
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetPermissionsByUser(userId string) []*Permission {
|
||||||
|
permissions := []*Permission{}
|
||||||
|
err := adapter.Engine.Where("users like ?", "%"+userId+"%").Find(&permissions)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions
|
||||||
|
}
|
||||||
|
162
object/permission_enforcer.go
Normal file
162
object/permission_enforcer.go
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
// 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 (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casbin/casbin/v2"
|
||||||
|
"github.com/casbin/casbin/v2/model"
|
||||||
|
xormadapter "github.com/casbin/xorm-adapter/v2"
|
||||||
|
"github.com/casdoor/casdoor/conf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getEnforcer(permission *Permission) *casbin.Enforcer {
|
||||||
|
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||||
|
adapter, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName()+conf.GetConfigString("dbName"), "permission_rule", tableNamePrefix, true)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
modelText := `
|
||||||
|
[request_definition]
|
||||||
|
r = sub, obj, act
|
||||||
|
|
||||||
|
[policy_definition]
|
||||||
|
p = permission, sub, obj, act
|
||||||
|
|
||||||
|
[policy_effect]
|
||||||
|
e = some(where (p.eft == allow))
|
||||||
|
|
||||||
|
[matchers]
|
||||||
|
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`
|
||||||
|
permissionModel := getModel(permission.Owner, permission.Model)
|
||||||
|
if permissionModel != nil {
|
||||||
|
modelText = permissionModel.ModelText
|
||||||
|
}
|
||||||
|
m, err := model.NewModelFromString(modelText)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
enforcer, err := casbin.NewEnforcer(m, adapter)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return enforcer
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPolicies(permission *Permission) [][]string {
|
||||||
|
var policies [][]string
|
||||||
|
for _, user := range permission.Users {
|
||||||
|
for _, resource := range permission.Resources {
|
||||||
|
for _, action := range permission.Actions {
|
||||||
|
policies = append(policies, []string{permission.GetId(), user, resource, strings.ToLower(action)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, role := range permission.Roles {
|
||||||
|
for _, resource := range permission.Resources {
|
||||||
|
for _, action := range permission.Actions {
|
||||||
|
policies = append(policies, []string{permission.GetId(), role, resource, strings.ToLower(action)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return policies
|
||||||
|
}
|
||||||
|
|
||||||
|
func addPolicies(permission *Permission) {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
policies := getPolicies(permission)
|
||||||
|
|
||||||
|
_, err := enforcer.AddPolicies(policies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func removePolicies(permission *Permission) {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
|
||||||
|
_, err := enforcer.RemoveFilteredPolicy(0, permission.GetId())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Enforce(userId string, permissionRule *PermissionRule) bool {
|
||||||
|
permission := GetPermission(permissionRule.V0)
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
allow, err := enforcer.Enforce(userId, permissionRule.V2, permissionRule.V3)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return allow
|
||||||
|
}
|
||||||
|
|
||||||
|
func BatchEnforce(userId string, permissionRules []PermissionRule) []bool {
|
||||||
|
var requests [][]interface{}
|
||||||
|
for _, permissionRule := range permissionRules {
|
||||||
|
requests = append(requests, []interface{}{userId, permissionRule.V2, permissionRule.V3})
|
||||||
|
}
|
||||||
|
permission := GetPermission(permissionRules[0].V0)
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
allow, err := enforcer.BatchEnforce(requests)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return allow
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllValues(userId string, sec string, fieldIndex int) []string {
|
||||||
|
permissions := GetPermissionsByUser(userId)
|
||||||
|
var values []string
|
||||||
|
for _, permission := range permissions {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
enforcer.ClearPolicy()
|
||||||
|
err := enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}, V1: []string{userId}})
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, value := range enforcer.GetModel().GetValuesForFieldInPolicyAllTypes(sec, fieldIndex) {
|
||||||
|
values = append(values, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllObjects(userId string) []string {
|
||||||
|
return getAllValues(userId, "p", 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllActions(userId string) []string {
|
||||||
|
return getAllValues(userId, "p", 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllRoles(userId string) []string {
|
||||||
|
roles := GetRolesByUser(userId)
|
||||||
|
var res []string
|
||||||
|
for _, role := range roles {
|
||||||
|
res = append(res, role.Name)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
@@ -38,6 +38,8 @@ type Product struct {
|
|||||||
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
|
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
|
||||||
|
|
||||||
State string `xorm:"varchar(100)" json:"state"`
|
State string `xorm:"varchar(100)" json:"state"`
|
||||||
|
|
||||||
|
ProviderObjs []*Provider `xorm:"-" json:"providerObjs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetProductCount(owner, field, value string) int {
|
func GetProductCount(owner, field, value string) int {
|
||||||
@@ -209,3 +211,14 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
|
|||||||
|
|
||||||
return payUrl, err
|
return payUrl, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExtendProductWithProviders(product *Product) {
|
||||||
|
product.ProviderObjs = []*Provider{}
|
||||||
|
|
||||||
|
m := getProviderMap(product.Owner)
|
||||||
|
for _, providerItem := range product.Providers {
|
||||||
|
if provider, ok := m[providerItem]; ok {
|
||||||
|
product.ProviderObjs = append(product.ProviderObjs, provider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -30,7 +30,7 @@ func TestProduct(t *testing.T) {
|
|||||||
product := GetProduct("admin/product_123")
|
product := GetProduct("admin/product_123")
|
||||||
provider := getProvider(product.Owner, "provider_pay_alipay")
|
provider := getProvider(product.Owner, "provider_pay_alipay")
|
||||||
cert := getCert(product.Owner, "cert-pay-alipay")
|
cert := getCert(product.Owner, "cert-pay-alipay")
|
||||||
pProvider := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.PublicKey, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
pProvider := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.Certificate, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
||||||
|
|
||||||
paymentName := util.GenerateTimeId()
|
paymentName := util.GenerateTimeId()
|
||||||
returnUrl := ""
|
returnUrl := ""
|
||||||
|
@@ -45,6 +45,7 @@ type Provider struct {
|
|||||||
|
|
||||||
Host string `xorm:"varchar(100)" json:"host"`
|
Host string `xorm:"varchar(100)" json:"host"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
|
DisableSsl bool `json:"disableSsl"`
|
||||||
Title string `xorm:"varchar(100)" json:"title"`
|
Title string `xorm:"varchar(100)" json:"title"`
|
||||||
Content string `xorm:"varchar(1000)" json:"content"`
|
Content string `xorm:"varchar(1000)" json:"content"`
|
||||||
|
|
||||||
@@ -214,7 +215,7 @@ func (p *Provider) getPaymentProvider() (pp.PaymentProvider, *Cert, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pProvider := pp.GetPaymentProvider(p.Type, p.ClientId, p.ClientSecret, p.Host, cert.PublicKey, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
pProvider := pp.GetPaymentProvider(p.Type, p.ClientId, p.ClientSecret, p.Host, cert.Certificate, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey)
|
||||||
if pProvider == nil {
|
if pProvider == nil {
|
||||||
return nil, cert, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
return nil, cert, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
||||||
}
|
}
|
||||||
|
@@ -33,6 +33,15 @@ func (application *Application) GetProviderItem(providerName string) *ProviderIt
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (application *Application) GetProviderItemByType(providerType string) *ProviderItem {
|
||||||
|
for _, item := range application.Providers {
|
||||||
|
if item.Provider.Type == providerType {
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (pi *ProviderItem) IsProviderVisible() bool {
|
func (pi *ProviderItem) IsProviderVisible() bool {
|
||||||
if pi.Provider == nil {
|
if pi.Provider == nil {
|
||||||
return false
|
return false
|
||||||
|
@@ -121,3 +121,13 @@ func DeleteRole(role *Role) bool {
|
|||||||
func (role *Role) GetId() string {
|
func (role *Role) GetId() string {
|
||||||
return fmt.Sprintf("%s/%s", role.Owner, role.Name)
|
return fmt.Sprintf("%s/%s", role.Owner, role.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetRolesByUser(userId string) []*Role {
|
||||||
|
roles := []*Role{}
|
||||||
|
err := adapter.Engine.Where("users like ?", "%"+userId+"%").Find(&roles)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles
|
||||||
|
}
|
||||||
|
@@ -35,8 +35,9 @@ import (
|
|||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewSamlResponse
|
||||||
// returns a saml2 response
|
// returns a saml2 response
|
||||||
func NewSamlResponse(user *User, host string, publicKey string, destination string, iss string, requestId string, redirectUri []string) (*etree.Element, error) {
|
func NewSamlResponse(user *User, host string, certificate string, destination string, iss string, requestId string, redirectUri []string) (*etree.Element, error) {
|
||||||
samlResponse := &etree.Element{
|
samlResponse := &etree.Element{
|
||||||
Space: "samlp",
|
Space: "samlp",
|
||||||
Tag: "Response",
|
Tag: "Response",
|
||||||
@@ -100,7 +101,6 @@ func NewSamlResponse(user *User, host string, publicKey string, destination stri
|
|||||||
displayName.CreateElement("saml:AttributeValue").CreateAttr("xsi:type", "xs:string").Element().SetText(user.DisplayName)
|
displayName.CreateElement("saml:AttributeValue").CreateAttr("xsi:type", "xs:string").Element().SetText(user.DisplayName)
|
||||||
|
|
||||||
return samlResponse, nil
|
return samlResponse, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type X509Key struct {
|
type X509Key struct {
|
||||||
@@ -114,6 +114,7 @@ func (x X509Key) GetKeyPair() (privateKey *rsa.PrivateKey, cert []byte, err erro
|
|||||||
return privateKey, cert, err
|
return privateKey, cert, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IdpEntityDescriptor
|
||||||
// SAML METADATA
|
// SAML METADATA
|
||||||
type IdpEntityDescriptor struct {
|
type IdpEntityDescriptor struct {
|
||||||
XMLName xml.Name `xml:"EntityDescriptor"`
|
XMLName xml.Name `xml:"EntityDescriptor"`
|
||||||
@@ -177,8 +178,8 @@ type Attribute struct {
|
|||||||
func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, error) {
|
func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, error) {
|
||||||
//_, originBackend := getOriginFromHost(host)
|
//_, originBackend := getOriginFromHost(host)
|
||||||
cert := getCertByApplication(application)
|
cert := getCertByApplication(application)
|
||||||
block, _ := pem.Decode([]byte(cert.PublicKey))
|
block, _ := pem.Decode([]byte(cert.Certificate))
|
||||||
publicKey := base64.StdEncoding.EncodeToString(block.Bytes)
|
certificate := base64.StdEncoding.EncodeToString(block.Bytes)
|
||||||
|
|
||||||
origin := beego.AppConfig.String("origin")
|
origin := beego.AppConfig.String("origin")
|
||||||
originFrontend, originBackend := getOriginFromHost(host)
|
originFrontend, originBackend := getOriginFromHost(host)
|
||||||
@@ -199,7 +200,7 @@ func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, e
|
|||||||
KeyInfo: KeyInfo{
|
KeyInfo: KeyInfo{
|
||||||
X509Data: X509Data{
|
X509Data: X509Data{
|
||||||
X509Certificate: X509Certificate{
|
X509Certificate: X509Certificate{
|
||||||
Cert: publicKey,
|
Cert: certificate,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -248,18 +249,18 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
return "", "", fmt.Errorf("err: invalid issuer url")
|
return "", "", fmt.Errorf("err: invalid issuer url")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get public key string
|
// get certificate string
|
||||||
cert := getCertByApplication(application)
|
cert := getCertByApplication(application)
|
||||||
block, _ := pem.Decode([]byte(cert.PublicKey))
|
block, _ := pem.Decode([]byte(cert.Certificate))
|
||||||
publicKey := base64.StdEncoding.EncodeToString(block.Bytes)
|
certificate := base64.StdEncoding.EncodeToString(block.Bytes)
|
||||||
|
|
||||||
_, originBackend := getOriginFromHost(host)
|
_, originBackend := getOriginFromHost(host)
|
||||||
|
|
||||||
// build signedResponse
|
// build signedResponse
|
||||||
samlResponse, _ := NewSamlResponse(user, originBackend, publicKey, authnRequest.AssertionConsumerServiceURL, authnRequest.Issuer.Url, authnRequest.ID, application.RedirectUris)
|
samlResponse, _ := NewSamlResponse(user, originBackend, certificate, authnRequest.AssertionConsumerServiceURL, authnRequest.Issuer.Url, authnRequest.ID, application.RedirectUris)
|
||||||
randomKeyStore := &X509Key{
|
randomKeyStore := &X509Key{
|
||||||
PrivateKey: cert.PrivateKey,
|
PrivateKey: cert.PrivateKey,
|
||||||
X509Certificate: publicKey,
|
X509Certificate: certificate,
|
||||||
}
|
}
|
||||||
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
|
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
|
||||||
ctx.Hash = crypto.SHA1
|
ctx.Hash = crypto.SHA1
|
||||||
|
@@ -44,7 +44,7 @@ func ParseSamlResponse(samlResponse string, providerType string) (string, error)
|
|||||||
func GenerateSamlLoginUrl(id, relayState string) (string, string, error) {
|
func GenerateSamlLoginUrl(id, relayState string) (string, string, error) {
|
||||||
provider := GetProvider(id)
|
provider := GetProvider(id)
|
||||||
if provider.Category != "SAML" {
|
if provider.Category != "SAML" {
|
||||||
return "", "", fmt.Errorf("Provider %s's category is not SAML", provider.Name)
|
return "", "", fmt.Errorf("provider %s's category is not SAML", provider.Name)
|
||||||
}
|
}
|
||||||
sp, err := buildSp(provider, "")
|
sp, err := buildSp(provider, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -17,6 +17,7 @@ package object
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
@@ -42,8 +43,19 @@ func getProviderEndpoint(provider *Provider) string {
|
|||||||
return endpoint
|
return endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func escapePath(path string) string {
|
||||||
|
tokens := strings.Split(path, "/")
|
||||||
|
if len(tokens) > 0 {
|
||||||
|
tokens[len(tokens)-1] = url.QueryEscape(tokens[len(tokens)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
res := strings.Join(tokens, "/")
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool) (string, string) {
|
func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool) (string, string) {
|
||||||
objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), fullFilePath)
|
escapedPath := escapePath(fullFilePath)
|
||||||
|
objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), escapedPath)
|
||||||
|
|
||||||
host := ""
|
host := ""
|
||||||
if provider.Type != "Local File System" {
|
if provider.Type != "Local File System" {
|
||||||
@@ -60,9 +72,9 @@ func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool
|
|||||||
host = fmt.Sprintf("%s/%s", host, provider.Bucket)
|
host = fmt.Sprintf("%s/%s", host, provider.Bucket)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileUrl := util.UrlJoin(host, objectKey)
|
fileUrl := util.UrlJoin(host, escapePath(objectKey))
|
||||||
if hasTimestamp {
|
if hasTimestamp {
|
||||||
fileUrl = fmt.Sprintf("%s?t=%s", util.UrlJoin(host, objectKey), util.GetCurrentUnixTime())
|
fileUrl = fmt.Sprintf("%s?t=%s", fileUrl, util.GetCurrentUnixTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileUrl, objectKey
|
return fileUrl, objectKey
|
||||||
|
@@ -22,7 +22,7 @@ import (
|
|||||||
func (syncer *Syncer) syncUsers() {
|
func (syncer *Syncer) syncUsers() {
|
||||||
fmt.Printf("Running syncUsers()..\n")
|
fmt.Printf("Running syncUsers()..\n")
|
||||||
|
|
||||||
users, userMap := syncer.getUserMap()
|
users, userMap, userNameMap := syncer.getUserMap()
|
||||||
oUsers, oUserMap, err := syncer.getOriginalUserMap()
|
oUsers, oUserMap, err := syncer.getOriginalUserMap()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf(err.Error())
|
fmt.Printf(err.Error())
|
||||||
@@ -44,9 +44,11 @@ func (syncer *Syncer) syncUsers() {
|
|||||||
for _, oUser := range oUsers {
|
for _, oUser := range oUsers {
|
||||||
id := oUser.Id
|
id := oUser.Id
|
||||||
if _, ok := userMap[id]; !ok {
|
if _, ok := userMap[id]; !ok {
|
||||||
|
if _, ok := userNameMap[oUser.Name]; !ok {
|
||||||
newUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
|
newUser := syncer.createUserFromOriginalUser(oUser, affiliationMap)
|
||||||
fmt.Printf("New user: %v\n", newUser)
|
fmt.Printf("New user: %v\n", newUser)
|
||||||
newUsers = append(newUsers, newUser)
|
newUsers = append(newUsers, newUser)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
user := userMap[id]
|
user := userMap[id]
|
||||||
oHash := syncer.calculateHash(oUser)
|
oHash := syncer.calculateHash(oUser)
|
||||||
|
@@ -151,6 +151,8 @@ func (syncer *Syncer) initAdapter() {
|
|||||||
var dataSourceName string
|
var dataSourceName string
|
||||||
if syncer.DatabaseType == "mssql" {
|
if syncer.DatabaseType == "mssql" {
|
||||||
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", syncer.User, syncer.Password, syncer.Host, syncer.Port, syncer.Database)
|
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", syncer.User, syncer.Password, syncer.Host, syncer.Port, syncer.Database)
|
||||||
|
} else if syncer.DatabaseType == "postgres" {
|
||||||
|
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s", syncer.User, syncer.Password, syncer.Host, syncer.Port, syncer.Database)
|
||||||
} else {
|
} else {
|
||||||
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/", syncer.User, syncer.Password, syncer.Host, syncer.Port)
|
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/", syncer.User, syncer.Password, syncer.Host, syncer.Port)
|
||||||
}
|
}
|
||||||
|
@@ -173,16 +173,21 @@ func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*Or
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tableColumn := range syncer.TableColumns {
|
for _, tableColumn := range syncer.TableColumns {
|
||||||
|
tableColumnName := tableColumn.Name
|
||||||
|
if syncer.Type == "Keycloak" && syncer.DatabaseType == "postgres" {
|
||||||
|
tableColumnName = strings.ToLower(tableColumnName)
|
||||||
|
}
|
||||||
|
|
||||||
value := ""
|
value := ""
|
||||||
if strings.Contains(tableColumn.Name, "+") {
|
if strings.Contains(tableColumnName, "+") {
|
||||||
names := strings.Split(tableColumn.Name, "+")
|
names := strings.Split(tableColumnName, "+")
|
||||||
var values []string
|
var values []string
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
values = append(values, result[strings.Trim(name, " ")])
|
values = append(values, result[strings.Trim(name, " ")])
|
||||||
}
|
}
|
||||||
value = strings.Join(values, " ")
|
value = strings.Join(values, " ")
|
||||||
} else {
|
} else {
|
||||||
value = result[tableColumn.Name]
|
value = result[tableColumnName]
|
||||||
}
|
}
|
||||||
syncer.setUserByKeyValue(originalUser, tableColumn.CasdoorName, value)
|
syncer.setUserByKeyValue(originalUser, tableColumn.CasdoorName, value)
|
||||||
}
|
}
|
||||||
@@ -209,7 +214,12 @@ func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*Or
|
|||||||
tm := time.Unix(i/int64(1000), 0)
|
tm := time.Unix(i/int64(1000), 0)
|
||||||
originalUser.CreatedTime = tm.Format("2006-01-02T15:04:05+08:00")
|
originalUser.CreatedTime = tm.Format("2006-01-02T15:04:05+08:00")
|
||||||
// enable
|
// enable
|
||||||
originalUser.IsForbidden = !(result["ENABLED"] == "\x01")
|
value, ok := result["ENABLED"]
|
||||||
|
if ok {
|
||||||
|
originalUser.IsForbidden = !util.ParseBool(value)
|
||||||
|
} else {
|
||||||
|
originalUser.IsForbidden = !util.ParseBool(result["enabled"])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
users = append(users, originalUser)
|
users = append(users, originalUser)
|
||||||
|
@@ -19,12 +19,15 @@ func (syncer *Syncer) getUsers() []*User {
|
|||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
|
||||||
func (syncer *Syncer) getUserMap() ([]*User, map[string]*User) {
|
func (syncer *Syncer) getUserMap() ([]*User, map[string]*User, map[string]*User) {
|
||||||
users := syncer.getUsers()
|
users := syncer.getUsers()
|
||||||
|
|
||||||
m := map[string]*User{}
|
m1 := map[string]*User{}
|
||||||
|
m2 := map[string]*User{}
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
m[user.Id] = user
|
m1[user.Id] = user
|
||||||
|
m2[user.Name] = user
|
||||||
}
|
}
|
||||||
return users, m
|
|
||||||
|
return users, m1, m2
|
||||||
}
|
}
|
||||||
|
243
object/token.go
243
object/token.go
@@ -17,7 +17,6 @@ package object
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -29,6 +28,13 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
hourSeconds = 3600
|
hourSeconds = 3600
|
||||||
|
InvalidRequest = "invalid_request"
|
||||||
|
InvalidClient = "invalid_client"
|
||||||
|
InvalidGrant = "invalid_grant"
|
||||||
|
UnauthorizedClient = "unauthorized_client"
|
||||||
|
UnsupportedGrantType = "unsupported_grant_type"
|
||||||
|
InvalidScope = "invalid_scope"
|
||||||
|
EndpointError = "endpoint_error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Code struct {
|
type Code struct {
|
||||||
@@ -63,7 +69,11 @@ type TokenWrapper struct {
|
|||||||
TokenType string `json:"token_type"`
|
TokenType string `json:"token_type"`
|
||||||
ExpiresIn int `json:"expires_in"`
|
ExpiresIn int `json:"expires_in"`
|
||||||
Scope string `json:"scope"`
|
Scope string `json:"scope"`
|
||||||
Error string `json:"error,omitempty"`
|
}
|
||||||
|
|
||||||
|
type TokenError struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
ErrorDescription string `json:"error_description,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type IntrospectionResponse struct {
|
type IntrospectionResponse struct {
|
||||||
@@ -190,7 +200,7 @@ func DeleteToken(token *Token) bool {
|
|||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteTokenByAceessToken(accessToken string) (bool, *Application) {
|
func DeleteTokenByAccessToken(accessToken string) (bool, *Application) {
|
||||||
token := Token{AccessToken: accessToken}
|
token := Token{AccessToken: accessToken}
|
||||||
existed, err := adapter.Engine.Get(&token)
|
existed, err := adapter.Engine.Get(&token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -311,59 +321,42 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetOAuthToken(grantType string, clientId string, clientSecret string, code string, verifier string, scope string, username string, password string, host string, tag string, avatar string) interface{} {
|
||||||
func GetOAuthToken(grantType string, clientId string, clientSecret string, code string, verifier string, scope string, username string, password string, host string, tag string, avatar string) *TokenWrapper {
|
|
||||||
var errString string
|
|
||||||
application := GetApplicationByClientId(clientId)
|
application := GetApplicationByClientId(clientId)
|
||||||
if application == nil {
|
if application == nil {
|
||||||
errString = "error: invalid client_id"
|
return &TokenError{
|
||||||
return &TokenWrapper{
|
Error: InvalidClient,
|
||||||
AccessToken: errString,
|
ErrorDescription: "client_id is invalid",
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if grantType is allowed in the current application
|
// Check if grantType is allowed in the current application
|
||||||
|
|
||||||
if !IsGrantTypeValid(grantType, application.GrantTypes) && tag == "" {
|
if !IsGrantTypeValid(grantType, application.GrantTypes) && tag == "" {
|
||||||
errString = fmt.Sprintf("error: grant_type: %s is not supported in this application", grantType)
|
return &TokenError{
|
||||||
return &TokenWrapper{
|
Error: UnsupportedGrantType,
|
||||||
AccessToken: errString,
|
ErrorDescription: fmt.Sprintf("grant_type: %s is not supported in this application", grantType),
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var token *Token
|
var token *Token
|
||||||
var err error
|
var tokenError *TokenError
|
||||||
switch grantType {
|
switch grantType {
|
||||||
case "authorization_code": // Authorization Code Grant
|
case "authorization_code": // Authorization Code Grant
|
||||||
token, err = GetAuthorizationCodeToken(application, clientSecret, code, verifier)
|
token, tokenError = GetAuthorizationCodeToken(application, clientSecret, code, verifier)
|
||||||
case "password": // Resource Owner Password Credentials Grant
|
case "password": // Resource Owner Password Credentials Grant
|
||||||
token, err = GetPasswordToken(application, username, password, scope, host)
|
token, tokenError = GetPasswordToken(application, username, password, scope, host)
|
||||||
case "client_credentials": // Client Credentials Grant
|
case "client_credentials": // Client Credentials Grant
|
||||||
token, err = GetClientCredentialsToken(application, clientSecret, scope, host)
|
token, tokenError = GetClientCredentialsToken(application, clientSecret, scope, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tag == "wechat_miniprogram" {
|
if tag == "wechat_miniprogram" {
|
||||||
// Wechat Mini Program
|
// Wechat Mini Program
|
||||||
token, err = GetWechatMiniProgramToken(application, code, host, username, avatar)
|
token, tokenError = GetWechatMiniProgramToken(application, code, host, username, avatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if tokenError != nil {
|
||||||
errString = err.Error()
|
return tokenError
|
||||||
return &TokenWrapper{
|
|
||||||
AccessToken: errString,
|
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
token.CodeIsUsed = true
|
token.CodeIsUsed = true
|
||||||
@@ -380,81 +373,59 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
|
|||||||
return tokenWrapper
|
return tokenWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func RefreshToken(grantType string, refreshToken string, scope string, clientId string, clientSecret string, host string) *TokenWrapper {
|
func RefreshToken(grantType string, refreshToken string, scope string, clientId string, clientSecret string, host string) interface{} {
|
||||||
var errString string
|
|
||||||
// check parameters
|
// check parameters
|
||||||
if grantType != "refresh_token" {
|
if grantType != "refresh_token" {
|
||||||
errString = "error: grant_type should be \"refresh_token\""
|
return &TokenError{
|
||||||
return &TokenWrapper{
|
Error: UnsupportedGrantType,
|
||||||
AccessToken: errString,
|
ErrorDescription: "grant_type should be refresh_token",
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
application := GetApplicationByClientId(clientId)
|
application := GetApplicationByClientId(clientId)
|
||||||
if application == nil {
|
if application == nil {
|
||||||
errString = "error: invalid client_id"
|
return &TokenError{
|
||||||
return &TokenWrapper{
|
Error: InvalidClient,
|
||||||
AccessToken: errString,
|
ErrorDescription: "client_id is invalid",
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if clientSecret != "" && application.ClientSecret != clientSecret {
|
if clientSecret != "" && application.ClientSecret != clientSecret {
|
||||||
errString = "error: invalid client_secret"
|
return &TokenError{
|
||||||
return &TokenWrapper{
|
Error: InvalidClient,
|
||||||
AccessToken: errString,
|
ErrorDescription: "client_secret is invalid",
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check whether the refresh token is valid, and has not expired.
|
// check whether the refresh token is valid, and has not expired.
|
||||||
token := Token{RefreshToken: refreshToken}
|
token := Token{RefreshToken: refreshToken}
|
||||||
existed, err := adapter.Engine.Get(&token)
|
existed, err := adapter.Engine.Get(&token)
|
||||||
if err != nil || !existed {
|
if err != nil || !existed {
|
||||||
errString = "error: invalid refresh_token"
|
return &TokenError{
|
||||||
return &TokenWrapper{
|
Error: InvalidGrant,
|
||||||
AccessToken: errString,
|
ErrorDescription: "refresh token is invalid, expired or revoked",
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cert := getCertByApplication(application)
|
cert := getCertByApplication(application)
|
||||||
_, err = ParseJwtToken(refreshToken, cert)
|
_, err = ParseJwtToken(refreshToken, cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errString := fmt.Sprintf("error: %s", err.Error())
|
return &TokenError{
|
||||||
return &TokenWrapper{
|
Error: InvalidGrant,
|
||||||
AccessToken: errString,
|
ErrorDescription: fmt.Sprintf("parse refresh token error: %s", err.Error()),
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// generate a new token
|
// generate a new token
|
||||||
user := getUser(application.Organization, token.User)
|
user := getUser(application.Organization, token.User)
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
errString = "error: the user is forbidden to sign in, please contact the administrator"
|
return &TokenError{
|
||||||
return &TokenWrapper{
|
Error: InvalidGrant,
|
||||||
AccessToken: errString,
|
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
|
||||||
TokenType: "",
|
|
||||||
ExpiresIn: 0,
|
|
||||||
Scope: "",
|
|
||||||
Error: errString,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newAccessToken, newRefreshToken, err := generateJwtToken(application, user, "", scope, host)
|
newAccessToken, newRefreshToken, err := generateJwtToken(application, user, "", scope, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return &TokenError{
|
||||||
|
Error: EndpointError,
|
||||||
|
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newToken := &Token{
|
newToken := &Token{
|
||||||
@@ -493,6 +464,7 @@ func pkceChallenge(verifier string) string {
|
|||||||
return challenge
|
return challenge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsGrantTypeValid
|
||||||
// Check if grantType is allowed in the current application
|
// Check if grantType is allowed in the current application
|
||||||
// authorization_code is allowed by default
|
// authorization_code is allowed by default
|
||||||
func IsGrantTypeValid(method string, grantTypes []string) bool {
|
func IsGrantTypeValid(method string, grantTypes []string) bool {
|
||||||
@@ -507,64 +479,102 @@ func IsGrantTypeValid(method string, grantTypes []string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAuthorizationCodeToken
|
||||||
// Authorization code flow
|
// Authorization code flow
|
||||||
func GetAuthorizationCodeToken(application *Application, clientSecret string, code string, verifier string) (*Token, error) {
|
func GetAuthorizationCodeToken(application *Application, clientSecret string, code string, verifier string) (*Token, *TokenError) {
|
||||||
if code == "" {
|
if code == "" {
|
||||||
return nil, errors.New("error: authorization code should not be empty")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidRequest,
|
||||||
|
ErrorDescription: "authorization code should not be empty",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token := getTokenByCode(code)
|
token := getTokenByCode(code)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
return nil, errors.New("error: invalid authorization code")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "authorization code is invalid",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if token.CodeIsUsed {
|
if token.CodeIsUsed {
|
||||||
// anti replay attacks
|
// anti replay attacks
|
||||||
return nil, errors.New("error: authorization code has been used")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "authorization code has been used",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if token.CodeChallenge != "" && pkceChallenge(verifier) != token.CodeChallenge {
|
if token.CodeChallenge != "" && pkceChallenge(verifier) != token.CodeChallenge {
|
||||||
return nil, errors.New("error: incorrect code_verifier")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "verifier is invalid",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.ClientSecret != clientSecret {
|
if application.ClientSecret != clientSecret {
|
||||||
// when using PKCE, the Client Secret can be empty,
|
// when using PKCE, the Client Secret can be empty,
|
||||||
// but if it is provided, it must be accurate.
|
// but if it is provided, it must be accurate.
|
||||||
if token.CodeChallenge == "" {
|
if token.CodeChallenge == "" {
|
||||||
return nil, errors.New("error: invalid client_secret")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidClient,
|
||||||
|
ErrorDescription: "client_secret is invalid",
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if clientSecret != "" {
|
if clientSecret != "" {
|
||||||
return nil, errors.New("error: invalid client_secret")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidClient,
|
||||||
|
ErrorDescription: "client_secret is invalid",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.Name != token.Application {
|
if application.Name != token.Application {
|
||||||
return nil, errors.New("error: the token is for wrong application (client_id)")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "the token is for wrong application (client_id)",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if time.Now().Unix() > token.CodeExpireIn {
|
if time.Now().Unix() > token.CodeExpireIn {
|
||||||
// code must be used within 5 minutes
|
// code must be used within 5 minutes
|
||||||
return nil, errors.New("error: authorization code has expired")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "authorization code has expired",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPasswordToken
|
||||||
// Resource Owner Password Credentials flow
|
// Resource Owner Password Credentials flow
|
||||||
func GetPasswordToken(application *Application, username string, password string, scope string, host string) (*Token, error) {
|
func GetPasswordToken(application *Application, username string, password string, scope string, host string) (*Token, *TokenError) {
|
||||||
user := getUser(application.Organization, username)
|
user := getUser(application.Organization, username)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return nil, errors.New("error: the user does not exist")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "the user does not exist",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
msg := CheckPassword(user, password)
|
msg := CheckPassword(user, password)
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
return nil, errors.New("error: invalid username or password")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "invalid username or password",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
return nil, errors.New("error: the user is forbidden to sign in, please contact the administrator")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
accessToken, refreshToken, err := generateJwtToken(application, user, "", scope, host)
|
accessToken, refreshToken, err := generateJwtToken(application, user, "", scope, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, &TokenError{
|
||||||
|
Error: EndpointError,
|
||||||
|
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
token := &Token{
|
token := &Token{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
@@ -585,10 +595,14 @@ func GetPasswordToken(application *Application, username string, password string
|
|||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetClientCredentialsToken
|
||||||
// Client Credentials flow
|
// Client Credentials flow
|
||||||
func GetClientCredentialsToken(application *Application, clientSecret string, scope string, host string) (*Token, error) {
|
func GetClientCredentialsToken(application *Application, clientSecret string, scope string, host string) (*Token, *TokenError) {
|
||||||
if application.ClientSecret != clientSecret {
|
if application.ClientSecret != clientSecret {
|
||||||
return nil, errors.New("error: invalid client_secret")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidClient,
|
||||||
|
ErrorDescription: "client_secret is invalid",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
nullUser := &User{
|
nullUser := &User{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
@@ -597,7 +611,10 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
|
|||||||
}
|
}
|
||||||
accessToken, _, err := generateJwtToken(application, nullUser, "", scope, host)
|
accessToken, _, err := generateJwtToken(application, nullUser, "", scope, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, &TokenError{
|
||||||
|
Error: EndpointError,
|
||||||
|
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
token := &Token{
|
token := &Token{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
@@ -617,6 +634,7 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
|
|||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTokenByUser
|
||||||
// Implicit flow
|
// Implicit flow
|
||||||
func GetTokenByUser(application *Application, user *User, scope string, host string) (*Token, error) {
|
func GetTokenByUser(application *Application, user *User, scope string, host string) (*Token, error) {
|
||||||
accessToken, refreshToken, err := generateJwtToken(application, user, "", scope, host)
|
accessToken, refreshToken, err := generateJwtToken(application, user, "", scope, host)
|
||||||
@@ -642,26 +660,39 @@ func GetTokenByUser(application *Application, user *User, scope string, host str
|
|||||||
return token, nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetWechatMiniProgramToken
|
||||||
// Wechat Mini Program flow
|
// Wechat Mini Program flow
|
||||||
func GetWechatMiniProgramToken(application *Application, code string, host string, username string, avatar string) (*Token, error) {
|
func GetWechatMiniProgramToken(application *Application, code string, host string, username string, avatar string) (*Token, *TokenError) {
|
||||||
mpProvider := GetWechatMiniProgramProvider(application)
|
mpProvider := GetWechatMiniProgramProvider(application)
|
||||||
if mpProvider == nil {
|
if mpProvider == nil {
|
||||||
return nil, errors.New("error: the application does not support wechat mini program")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidClient,
|
||||||
|
ErrorDescription: "the application does not support wechat mini program",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
provider := GetProvider(util.GetId(mpProvider.Name))
|
provider := GetProvider(util.GetId(mpProvider.Name))
|
||||||
mpIdp := idp.NewWeChatMiniProgramIdProvider(provider.ClientId, provider.ClientSecret)
|
mpIdp := idp.NewWeChatMiniProgramIdProvider(provider.ClientId, provider.ClientSecret)
|
||||||
session, err := mpIdp.GetSessionByCode(code)
|
session, err := mpIdp.GetSessionByCode(code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: fmt.Sprintf("get wechat mini program session error: %s", err.Error()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
openId, unionId := session.Openid, session.Unionid
|
openId, unionId := session.Openid, session.Unionid
|
||||||
if openId == "" && unionId == "" {
|
if openId == "" && unionId == "" {
|
||||||
return nil, errors.New("err: WeChat's openid and unionid are empty")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidRequest,
|
||||||
|
ErrorDescription: "the wechat mini program session is invalid",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
user := getUserByWechatId(openId, unionId)
|
user := getUserByWechatId(openId, unionId)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
if !application.EnableSignUp {
|
if !application.EnableSignUp {
|
||||||
return nil, errors.New("err: the application does not allow to sign up new account")
|
return nil, &TokenError{
|
||||||
|
Error: InvalidGrant,
|
||||||
|
ErrorDescription: "the application does not allow to sign up new account",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Add new user
|
// Add new user
|
||||||
var name string
|
var name string
|
||||||
@@ -678,20 +709,26 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
|
|||||||
Avatar: avatar,
|
Avatar: avatar,
|
||||||
SignupApplication: application.Name,
|
SignupApplication: application.Name,
|
||||||
WeChat: openId,
|
WeChat: openId,
|
||||||
WeChatUnionId: unionId,
|
|
||||||
Type: "normal-user",
|
Type: "normal-user",
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
IsAdmin: false,
|
IsAdmin: false,
|
||||||
IsGlobalAdmin: false,
|
IsGlobalAdmin: false,
|
||||||
IsForbidden: false,
|
IsForbidden: false,
|
||||||
IsDeleted: false,
|
IsDeleted: false,
|
||||||
|
Properties: map[string]string{
|
||||||
|
UserPropertiesWechatOpenId: openId,
|
||||||
|
UserPropertiesWechatUnionId: unionId,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
AddUser(user)
|
AddUser(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken, refreshToken, err := generateJwtToken(application, user, "", "", host)
|
accessToken, refreshToken, err := generateJwtToken(application, user, "", "", host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, &TokenError{
|
||||||
|
Error: EndpointError,
|
||||||
|
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token := &Token{
|
token := &Token{
|
||||||
|
@@ -136,6 +136,7 @@ func GenerateId() {
|
|||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCasTokenByPgt
|
||||||
/**
|
/**
|
||||||
@ret1: whether a token is found
|
@ret1: whether a token is found
|
||||||
@ret2: token, nil if not found
|
@ret2: token, nil if not found
|
||||||
@@ -150,6 +151,7 @@ func GetCasTokenByPgt(pgt string) (bool, *CasAuthenticationSuccess, string, stri
|
|||||||
return false, nil, "", ""
|
return false, nil, "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCasTokenByTicket
|
||||||
/**
|
/**
|
||||||
@ret1: whether a token is found
|
@ret1: whether a token is found
|
||||||
@ret2: token, nil if not found
|
@ret2: token, nil if not found
|
||||||
@@ -207,6 +209,7 @@ func GenerateCasToken(userId string, service string) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetValidationBySaml
|
||||||
/**
|
/**
|
||||||
@ret1: saml response
|
@ret1: saml response
|
||||||
@ret2: the service URL who requested to issue this token
|
@ret2: the service URL who requested to issue this token
|
||||||
@@ -241,11 +244,11 @@ func GetValidationBySaml(samlRequest string, host string) (string, string, error
|
|||||||
samlResponse := NewSamlResponse11(user, request.RequestID, host)
|
samlResponse := NewSamlResponse11(user, request.RequestID, host)
|
||||||
|
|
||||||
cert := getCertByApplication(application)
|
cert := getCertByApplication(application)
|
||||||
block, _ := pem.Decode([]byte(cert.PublicKey))
|
block, _ := pem.Decode([]byte(cert.Certificate))
|
||||||
publicKey := base64.StdEncoding.EncodeToString(block.Bytes)
|
certificate := base64.StdEncoding.EncodeToString(block.Bytes)
|
||||||
randomKeyStore := &X509Key{
|
randomKeyStore := &X509Key{
|
||||||
PrivateKey: cert.PrivateKey,
|
PrivateKey: cert.PrivateKey,
|
||||||
X509Certificate: publicKey,
|
X509Certificate: certificate,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
|
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
|
||||||
@@ -262,7 +265,6 @@ func GetValidationBySaml(samlRequest string, host string) (string, string, error
|
|||||||
return "", "", fmt.Errorf("err: %s", err.Error())
|
return "", "", fmt.Errorf("err: %s", err.Error())
|
||||||
}
|
}
|
||||||
return xmlStr, service, nil
|
return xmlStr, service, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CasAuthenticationSuccess) DeepCopy() CasAuthenticationSuccess {
|
func (c *CasAuthenticationSuccess) DeepCopy() CasAuthenticationSuccess {
|
||||||
@@ -307,7 +309,6 @@ func (c *CasAttributes) DeepCopy() CasAttributes {
|
|||||||
res.ExtraAttributes[i] = &tmp
|
res.ExtraAttributes[i] = &tmp
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CasUserAttributes) DeepCopy() CasUserAttributes {
|
func (c *CasUserAttributes) DeepCopy() CasUserAttributes {
|
||||||
@@ -316,11 +317,11 @@ func (c *CasUserAttributes) DeepCopy() CasUserAttributes {
|
|||||||
Attributes: make([]*CasNamedAttribute, len(c.Attributes)),
|
Attributes: make([]*CasNamedAttribute, len(c.Attributes)),
|
||||||
}
|
}
|
||||||
for i, a := range c.AnyAttributes {
|
for i, a := range c.AnyAttributes {
|
||||||
var tmp = *a
|
tmp := *a
|
||||||
res.AnyAttributes[i] = &tmp
|
res.AnyAttributes[i] = &tmp
|
||||||
}
|
}
|
||||||
for i, a := range c.Attributes {
|
for i, a := range c.Attributes {
|
||||||
var tmp = *a
|
tmp := *a
|
||||||
res.Attributes[i] = &tmp
|
res.Attributes[i] = &tmp
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
|
@@ -129,13 +129,13 @@ func ParseJwtToken(token string, cert *Cert) (*Claims, error) {
|
|||||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSA public key
|
// RSA certificate
|
||||||
publicKey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(cert.PublicKey))
|
certificate, err := jwt.ParseRSAPublicKeyFromPEM([]byte(cert.Certificate))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return publicKey, nil
|
return certificate, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if t != nil {
|
if t != nil {
|
||||||
|
@@ -23,10 +23,10 @@ import (
|
|||||||
|
|
||||||
func TestGenerateRsaKeys(t *testing.T) {
|
func TestGenerateRsaKeys(t *testing.T) {
|
||||||
fileId := "token_jwt_key"
|
fileId := "token_jwt_key"
|
||||||
publicKey, privateKey := generateRsaKeys(4096, 20, "Casdoor Cert", "Casdoor Organization")
|
certificate, privateKey := generateRsaKeys(4096, 20, "Casdoor Cert", "Casdoor Organization")
|
||||||
|
|
||||||
// Write certificate (aka public key) to file.
|
// Write certificate (aka certificate) to file.
|
||||||
util.WriteStringToPath(publicKey, fmt.Sprintf("%s.pem", fileId))
|
util.WriteStringToPath(certificate, fmt.Sprintf("%s.pem", fileId))
|
||||||
|
|
||||||
// Write private key to file.
|
// Write private key to file.
|
||||||
util.WriteStringToPath(privateKey, fmt.Sprintf("%s.key", fileId))
|
util.WriteStringToPath(privateKey, fmt.Sprintf("%s.key", fileId))
|
||||||
|
@@ -20,9 +20,15 @@ import (
|
|||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"github.com/duo-labs/webauthn/webauthn"
|
||||||
"xorm.io/core"
|
"xorm.io/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserPropertiesWechatUnionId = "wechatUnionId"
|
||||||
|
UserPropertiesWechatOpenId = "wechatOpenId"
|
||||||
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
@@ -72,11 +78,10 @@ type User struct {
|
|||||||
LastSigninTime string `xorm:"varchar(100)" json:"lastSigninTime"`
|
LastSigninTime string `xorm:"varchar(100)" json:"lastSigninTime"`
|
||||||
LastSigninIp string `xorm:"varchar(100)" json:"lastSigninIp"`
|
LastSigninIp string `xorm:"varchar(100)" json:"lastSigninIp"`
|
||||||
|
|
||||||
Github string `xorm:"varchar(100)" json:"github"`
|
GitHub string `xorm:"github varchar(100)" json:"github"`
|
||||||
Google string `xorm:"varchar(100)" json:"google"`
|
Google string `xorm:"varchar(100)" json:"google"`
|
||||||
QQ string `xorm:"qq varchar(100)" json:"qq"`
|
QQ string `xorm:"qq varchar(100)" json:"qq"`
|
||||||
WeChat string `xorm:"wechat varchar(100)" json:"wechat"`
|
WeChat string `xorm:"wechat varchar(100)" json:"wechat"`
|
||||||
WeChatUnionId string `xorm:"varchar(100)" json:"unionId"`
|
|
||||||
Facebook string `xorm:"facebook varchar(100)" json:"facebook"`
|
Facebook string `xorm:"facebook varchar(100)" json:"facebook"`
|
||||||
DingTalk string `xorm:"dingtalk varchar(100)" json:"dingtalk"`
|
DingTalk string `xorm:"dingtalk varchar(100)" json:"dingtalk"`
|
||||||
Weibo string `xorm:"weibo varchar(100)" json:"weibo"`
|
Weibo string `xorm:"weibo varchar(100)" json:"weibo"`
|
||||||
@@ -96,11 +101,16 @@ type User struct {
|
|||||||
Steam string `xorm:"steam varchar(100)" json:"steam"`
|
Steam string `xorm:"steam varchar(100)" json:"steam"`
|
||||||
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
|
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
|
||||||
Okta string `xorm:"okta varchar(100)" json:"okta"`
|
Okta string `xorm:"okta varchar(100)" json:"okta"`
|
||||||
Douyin string `xorm:"douyin vachar(100)" json:"douyin"`
|
Douyin string `xorm:"douyin varchar(100)" json:"douyin"`
|
||||||
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
||||||
|
|
||||||
|
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
||||||
|
|
||||||
Ldap string `xorm:"ldap varchar(100)" json:"ldap"`
|
Ldap string `xorm:"ldap varchar(100)" json:"ldap"`
|
||||||
Properties map[string]string `json:"properties"`
|
Properties map[string]string `json:"properties"`
|
||||||
|
|
||||||
|
Roles []*Role `json:"roles"`
|
||||||
|
Permissions []*Permission `json:"permissions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Userinfo struct {
|
type Userinfo struct {
|
||||||
@@ -237,7 +247,7 @@ func getUserByWechatId(wechatOpenId string, wechatUnionId string) *User {
|
|||||||
wechatUnionId = wechatOpenId
|
wechatUnionId = wechatOpenId
|
||||||
}
|
}
|
||||||
user := &User{}
|
user := &User{}
|
||||||
existed, err := adapter.Engine.Where("wechat = ? OR wechat = ? OR unionid = ?", wechatOpenId, wechatUnionId, wechatUnionId).Get(user)
|
existed, err := adapter.Engine.Where("wechat = ? OR wechat = ?", wechatOpenId, wechatUnionId).Get(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -267,6 +277,42 @@ func GetUserByEmail(owner string, email string) *User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetUserByPhone(owner string, phone string) *User {
|
||||||
|
if owner == "" || phone == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{Owner: owner, Phone: phone}
|
||||||
|
existed, err := adapter.Engine.Get(&user)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if existed {
|
||||||
|
return &user
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserByUserId(owner string, userId string) *User {
|
||||||
|
if owner == "" || userId == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{Owner: owner, Id: userId}
|
||||||
|
existed, err := adapter.Engine.Get(&user)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if existed {
|
||||||
|
return &user
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GetUser(id string) *User {
|
func GetUser(id string) *User {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
return getUser(owner, name)
|
return getUser(owner, name)
|
||||||
@@ -326,9 +372,11 @@ func UpdateUser(id string, user *User, columns []string, isGlobalAdmin bool) boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(columns) == 0 {
|
if len(columns) == 0 {
|
||||||
columns = []string{"owner", "display_name", "avatar",
|
columns = []string{
|
||||||
|
"owner", "display_name", "avatar",
|
||||||
"location", "address", "region", "language", "affiliation", "title", "homepage", "bio", "score", "tag", "signup_application",
|
"location", "address", "region", "language", "affiliation", "title", "homepage", "bio", "score", "tag", "signup_application",
|
||||||
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties"}
|
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if isGlobalAdmin {
|
if isGlobalAdmin {
|
||||||
columns = append(columns, "name", "email", "phone")
|
columns = append(columns, "name", "email", "phone")
|
||||||
@@ -373,6 +421,10 @@ func AddUser(user *User) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
organization := GetOrganizationByUser(user)
|
organization := GetOrganizationByUser(user)
|
||||||
|
if organization == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
user.UpdateUserPassword(organization)
|
user.UpdateUserPassword(organization)
|
||||||
|
|
||||||
user.UpdateUserHash()
|
user.UpdateUserHash()
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user