mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-20 23:03:49 +08:00
Compare commits
64 Commits
Author | SHA1 | Date | |
---|---|---|---|
8e9ed1205b | |||
a341c65bb1 | |||
91fa024f0b | |||
aedef1eea1 | |||
70f2988f09 | |||
2dcdfbe6d3 | |||
c92d34e27c | |||
dfbf7753c3 | |||
ba732b3075 | |||
ca13247572 | |||
108fdc174f | |||
a741c5179a | |||
6676cc8ff3 | |||
13de019d08 | |||
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 |
25
.github/workflows/build.yml
vendored
25
.github/workflows/build.yml
vendored
@ -35,6 +35,10 @@ jobs:
|
|||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '14.17.0'
|
node-version: '14.17.0'
|
||||||
|
# cache
|
||||||
|
- uses: c-hive/gha-yarn-cache@v2
|
||||||
|
with:
|
||||||
|
directory: ./web
|
||||||
- run: yarn install && CI=false yarn run build
|
- run: yarn install && CI=false yarn run build
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
|
|
||||||
@ -53,11 +57,30 @@ jobs:
|
|||||||
go build -race -ldflags "-extldflags '-static'"
|
go build -race -ldflags "-extldflags '-static'"
|
||||||
working-directory: ./
|
working-directory: ./
|
||||||
|
|
||||||
|
linter:
|
||||||
|
name: Go-Linter
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ go-tests ]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '^1.16.5'
|
||||||
|
|
||||||
|
# gen a dummy config file
|
||||||
|
- run: touch dummy.yml
|
||||||
|
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: --disable-all -c dummy.yml -E=gofumpt --max-same-issues=0 --timeout 5m --modules-download-mode=mod
|
||||||
|
|
||||||
release-and-push:
|
release-and-push:
|
||||||
name: Release And Push
|
name: Release And Push
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
||||||
needs: [ frontend, backend ]
|
needs: [ frontend, backend, linter ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
@ -31,7 +31,7 @@ run:
|
|||||||
- api
|
- api
|
||||||
# skip-files:
|
# skip-files:
|
||||||
# - ".*_test\\.go$"
|
# - ".*_test\\.go$"
|
||||||
modules-download-mode: vendor
|
modules-download-mode: mod
|
||||||
# all available settings of specific linters
|
# all available settings of specific linters
|
||||||
linters-settings:
|
linters-settings:
|
||||||
lll:
|
lll:
|
||||||
|
@ -83,7 +83,7 @@ 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, *, *
|
||||||
@ -92,7 +92,6 @@ 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/notify-payment, *, *
|
||||||
p, *, *, POST, /api/unlink, *, *
|
p, *, *, POST, /api/unlink, *, *
|
||||||
p, *, *, POST, /api/set-password, *, *
|
p, *, *, POST, /api/set-password, *, *
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -16,3 +16,4 @@ verificationCodeTimeout = 10
|
|||||||
initScore = 2000
|
initScore = 2000
|
||||||
logPostOnly = true
|
logPostOnly = true
|
||||||
origin =
|
origin =
|
||||||
|
staticBaseUrl = "https://cdn.casbin.org"
|
@ -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)
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package conf
|
package conf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -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)
|
||||||
@ -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,7 +44,6 @@ 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 ...
|
||||||
@ -94,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 {
|
||||||
@ -120,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
|
||||||
|
@ -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,25 @@ func (c *ApiController) GetPermissions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPermissionsBySubmitter
|
||||||
|
// @Title GetPermissionsBySubmitter
|
||||||
|
// @Tag Permission API
|
||||||
|
// @Description get permissions by submitter
|
||||||
|
// @Success 200 {array} object.Permission The Response object
|
||||||
|
// @router /get-permissions-by-submitter [get]
|
||||||
|
func (c *ApiController) GetPermissionsBySubmitter() {
|
||||||
|
userId, ok := c.RequireSignedIn()
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
owner, username := util.GetOwnerAndNameFromId(userId)
|
||||||
|
permissions := object.GetPermissionsBySubmitter(owner, username)
|
||||||
|
c.ResponseOk(permissions, len(permissions))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPermission
|
||||||
// @Title GetPermission
|
// @Title GetPermission
|
||||||
// @Tag Permission API
|
// @Tag Permission API
|
||||||
// @Description get permission
|
// @Description get permission
|
||||||
@ -61,6 +80,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 +101,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 +119,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
|
||||||
|
@ -255,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) {
|
||||||
@ -273,6 +273,7 @@ func (c *ApiController) TokenLogout() {
|
|||||||
// representing the meta information surrounding the
|
// representing the meta information surrounding the
|
||||||
// token, including whether this token is currently active.
|
// token, including whether this token is currently active.
|
||||||
// This endpoint only support Basic Authorization.
|
// This endpoint only support Basic Authorization.
|
||||||
|
//
|
||||||
// @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
|
||||||
@ -288,7 +289,7 @@ func (c *ApiController) IntrospectToken() {
|
|||||||
if clientId == "" || clientSecret == "" {
|
if clientId == "" || clientSecret == "" {
|
||||||
c.ResponseError("empty clientId or clientSecret")
|
c.ResponseError("empty clientId or clientSecret")
|
||||||
c.Data["json"] = &object.TokenError{
|
c.Data["json"] = &object.TokenError{
|
||||||
Error: object.INVALID_REQUEST,
|
Error: object.InvalidRequest,
|
||||||
}
|
}
|
||||||
c.SetTokenErrorHttpStatus()
|
c.SetTokenErrorHttpStatus()
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
@ -299,7 +300,7 @@ func (c *ApiController) IntrospectToken() {
|
|||||||
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{
|
c.Data["json"] = &object.TokenError{
|
||||||
Error: object.INVALID_CLIENT,
|
Error: object.InvalidClient,
|
||||||
}
|
}
|
||||||
c.SetTokenErrorHttpStatus()
|
c.SetTokenErrorHttpStatus()
|
||||||
return
|
return
|
||||||
|
@ -81,11 +81,15 @@ 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")
|
||||||
email := c.Input().Get("email")
|
email := c.Input().Get("email")
|
||||||
|
phone := c.Input().Get("phone")
|
||||||
userId := c.Input().Get("userId")
|
userId := c.Input().Get("userId")
|
||||||
|
|
||||||
owner := c.Input().Get("owner")
|
owner := c.Input().Get("owner")
|
||||||
@ -96,7 +100,7 @@ func (c *ApiController) GetUser() {
|
|||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", owner))
|
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
|
||||||
@ -104,14 +108,24 @@ func (c *ApiController) GetUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var user *object.User
|
var user *object.User
|
||||||
if email != "" {
|
switch {
|
||||||
|
case email != "":
|
||||||
user = object.GetUserByEmail(owner, email)
|
user = object.GetUserByEmail(owner, email)
|
||||||
} else if userId != "" {
|
case phone != "":
|
||||||
|
user = object.GetUserByPhone(owner, phone)
|
||||||
|
case userId != "":
|
||||||
user = object.GetUserByUserId(owner, userId)
|
user = object.GetUserByUserId(owner, userId)
|
||||||
} else {
|
default:
|
||||||
user = object.GetUser(id)
|
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)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
@ -252,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
|
||||||
@ -284,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
|
||||||
|
@ -55,7 +55,7 @@ func (c *ApiController) ResponseError(error string, data ...interface{}) {
|
|||||||
func (c *ApiController) SetTokenErrorHttpStatus() {
|
func (c *ApiController) SetTokenErrorHttpStatus() {
|
||||||
_, ok := c.Data["json"].(*object.TokenError)
|
_, ok := c.Data["json"].(*object.TokenError)
|
||||||
if ok {
|
if ok {
|
||||||
if c.Data["json"].(*object.TokenError).Error == object.INVALID_CLIENT {
|
if c.Data["json"].(*object.TokenError).Error == object.InvalidClient {
|
||||||
c.Ctx.Output.SetStatus(401)
|
c.Ctx.Output.SetStatus(401)
|
||||||
c.Ctx.Output.Header("WWW-Authenticate", "Basic realm=\"OAuth2\"")
|
c.Ctx.Output.Header("WWW-Authenticate", "Basic realm=\"OAuth2\"")
|
||||||
} else {
|
} else {
|
||||||
|
@ -49,8 +49,24 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
||||||
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
||||||
|
|
||||||
if destType == "" || dest == "" || applicationId == "" || !strings.Contains(applicationId, "/") || checkType == "" {
|
if destType == "" {
|
||||||
c.ResponseError("Missing parameter.")
|
c.ResponseError("Missing parameter: type.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if dest == "" {
|
||||||
|
c.ResponseError("Missing parameter: dest.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if applicationId == "" {
|
||||||
|
c.ResponseError("Missing parameter: applicationId.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !strings.Contains(applicationId, "/") {
|
||||||
|
c.ResponseError("Wrong parameter: applicationId.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if checkType == "" {
|
||||||
|
c.ResponseError("Missing parameter: checkType.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +98,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
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 := application.Organization
|
name := application.Organization
|
||||||
@ -152,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)
|
||||||
|
@ -16,7 +16,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
"io"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/duo-labs/webauthn/webauthn"
|
"github.com/duo-labs/webauthn/webauthn"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WebAuthnSignupBegin
|
||||||
// @Title WebAuthnSignupBegin
|
// @Title WebAuthnSignupBegin
|
||||||
// @Tag User API
|
// @Tag User API
|
||||||
// @Description WebAuthn Registration Flow 1st stage
|
// @Description WebAuthn Registration Flow 1st stage
|
||||||
@ -53,6 +54,7 @@ func (c *ApiController) WebAuthnSignupBegin() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebAuthnSignupFinish
|
||||||
// @Title WebAuthnSignupFinish
|
// @Title WebAuthnSignupFinish
|
||||||
// @Tag User API
|
// @Tag User API
|
||||||
// @Description WebAuthn Registration Flow 2nd stage
|
// @Description WebAuthn Registration Flow 2nd stage
|
||||||
@ -72,7 +74,7 @@ func (c *ApiController) WebAuthnSignupFinish() {
|
|||||||
c.ResponseError("Please call WebAuthnSignupBegin first")
|
c.ResponseError("Please call WebAuthnSignupBegin first")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||||
|
|
||||||
credential, err := webauthnObj.FinishRegistration(user, sessionData, c.Ctx.Request)
|
credential, err := webauthnObj.FinishRegistration(user, sessionData, c.Ctx.Request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -84,6 +86,7 @@ func (c *ApiController) WebAuthnSignupFinish() {
|
|||||||
c.ResponseOk()
|
c.ResponseOk()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebAuthnSigninBegin
|
||||||
// @Title WebAuthnSigninBegin
|
// @Title WebAuthnSigninBegin
|
||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
// @Description WebAuthn Login Flow 1st stage
|
// @Description WebAuthn Login Flow 1st stage
|
||||||
@ -110,6 +113,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebAuthnSigninFinish
|
||||||
// @Title WebAuthnSigninBegin
|
// @Title WebAuthnSigninBegin
|
||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
// @Description WebAuthn Login Flow 2nd stage
|
// @Description WebAuthn Login Flow 2nd stage
|
||||||
@ -124,7 +128,7 @@ func (c *ApiController) WebAuthnSigninFinish() {
|
|||||||
c.ResponseError("Please call WebAuthnSigninBegin first")
|
c.ResponseError("Please call WebAuthnSigninBegin first")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||||
userId := string(sessionData.UserID)
|
userId := string(sessionData.UserID)
|
||||||
user := object.GetUser(userId)
|
user := object.GetUser(userId)
|
||||||
_, err := webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
|
_, err := webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
|
||||||
|
@ -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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
4
go.mod
4
go.mod
@ -10,10 +10,11 @@ require (
|
|||||||
github.com/beevik/etree v1.1.0
|
github.com/beevik/etree v1.1.0
|
||||||
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.3.0
|
||||||
github.com/casdoor/goth v1.69.0-FIX2
|
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/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
|
||||||
@ -23,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
|
||||||
|
6
go.sum
6
go.sum
@ -98,8 +98,8 @@ github.com/casbin/casbin/v2 v2.30.1 h1:P5HWadDL7olwUXNdcuKUBk+x75Y2eitFxYTcLNKeK
|
|||||||
github.com/casbin/casbin/v2 v2.30.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
github.com/casbin/casbin/v2 v2.30.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||||
github.com/casbin/xorm-adapter/v2 v2.5.1 h1:BkpIxRHKa0s3bSMx173PpuU7oTs+Zw7XmD0BIta0HGM=
|
github.com/casbin/xorm-adapter/v2 v2.5.1 h1:BkpIxRHKa0s3bSMx173PpuU7oTs+Zw7XmD0BIta0HGM=
|
||||||
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.3.0 h1:c4bWVcKZhO2L3Xu1oy7aeVkCK6HRJkW/b5K1xU9mV60=
|
||||||
github.com/casdoor/go-sms-sender v0.2.0/go.mod h1:fsZsNnALvFIo+HFcE1U/oCQv4ZT42FdglXKMsEm3WSk=
|
github.com/casdoor/go-sms-sender v0.3.0/go.mod h1:fsZsNnALvFIo+HFcE1U/oCQv4ZT42FdglXKMsEm3WSk=
|
||||||
github.com/casdoor/goth v1.69.0-FIX2 h1:RgfIMkL9kekylgxHHK2ZY8ASAwOGns2HVlaBwLu7Bcs=
|
github.com/casdoor/goth v1.69.0-FIX2 h1:RgfIMkL9kekylgxHHK2ZY8ASAwOGns2HVlaBwLu7Bcs=
|
||||||
github.com/casdoor/goth v1.69.0-FIX2/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=
|
||||||
@ -125,6 +125,7 @@ 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 h1:L63RATZFZuFMXy6ixnKmv3eNAXwYQF6HW1vd4IYsQqQ=
|
||||||
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b/go.mod h1:EYSpSkwoEcryMmQGfhol2IiB3IMN9IIIaNd/wcAQMGQ=
|
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b/go.mod h1:EYSpSkwoEcryMmQGfhol2IiB3IMN9IIIaNd/wcAQMGQ=
|
||||||
@ -173,6 +174,7 @@ github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptG
|
|||||||
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
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=
|
||||||
|
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
|
||||||
}
|
}
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
)
|
)
|
||||||
|
@ -317,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
|
||||||
|
@ -18,6 +18,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/cred"
|
"github.com/casdoor/casdoor/cred"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@ -29,6 +31,11 @@ var (
|
|||||||
reFieldWhiteList *regexp.Regexp
|
reFieldWhiteList *regexp.Regexp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SigninWrongTimesLimit = 5
|
||||||
|
LastSignWrongTimeDuration = time.Minute * 15
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
reWhiteSpace, _ = regexp.Compile(`\s`)
|
reWhiteSpace, _ = regexp.Compile(`\s`)
|
||||||
reFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
reFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
||||||
@ -42,11 +49,25 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
|||||||
if application.IsSignupItemVisible("Username") {
|
if application.IsSignupItemVisible("Username") {
|
||||||
if len(username) <= 1 {
|
if len(username) <= 1 {
|
||||||
return "username must have at least 2 characters"
|
return "username must have at least 2 characters"
|
||||||
} else if reWhiteSpace.MatchString(username) {
|
}
|
||||||
|
if unicode.IsDigit(rune(username[0])) {
|
||||||
|
return "username cannot start with a digit"
|
||||||
|
}
|
||||||
|
if util.IsEmailValid(username) {
|
||||||
|
return "username cannot be an email address"
|
||||||
|
}
|
||||||
|
if reWhiteSpace.MatchString(username) {
|
||||||
return "username cannot contain white spaces"
|
return "username cannot contain white spaces"
|
||||||
} else if HasUserByField(organization.Name, "name", username) {
|
}
|
||||||
|
if HasUserByField(organization.Name, "name", username) {
|
||||||
return "username already exists"
|
return "username already exists"
|
||||||
}
|
}
|
||||||
|
if HasUserByField(organization.Name, "email", username) {
|
||||||
|
return "email already exists"
|
||||||
|
}
|
||||||
|
if HasUserByField(organization.Name, "phone", username) {
|
||||||
|
return "phone already exists"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(password) <= 5 {
|
if len(password) <= 5 {
|
||||||
@ -112,7 +133,32 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkSigninErrorTimes(user *User) string {
|
||||||
|
if user.SigninWrongTimes >= SigninWrongTimesLimit {
|
||||||
|
lastSignWrongTime, _ := time.Parse(time.RFC3339, user.LastSigninWrongTime)
|
||||||
|
passedTime := time.Now().UTC().Sub(lastSignWrongTime)
|
||||||
|
seconds := int(LastSignWrongTimeDuration.Seconds() - passedTime.Seconds())
|
||||||
|
|
||||||
|
// deny the login if the error times is greater than the limit and the last login time is less than the duration
|
||||||
|
if seconds > 0 {
|
||||||
|
return fmt.Sprintf("You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again", seconds/60, seconds%60)
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset the error times
|
||||||
|
user.SigninWrongTimes = 0
|
||||||
|
|
||||||
|
UpdateUser(user.GetId(), user, []string{"signin_wrong_times"}, user.IsGlobalAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func CheckPassword(user *User, password string) string {
|
func CheckPassword(user *User, password string) string {
|
||||||
|
// check the login error times
|
||||||
|
if msg := checkSigninErrorTimes(user); msg != "" {
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
organization := GetOrganizationByUser(user)
|
organization := GetOrganizationByUser(user)
|
||||||
if organization == nil {
|
if organization == nil {
|
||||||
return "organization does not exist"
|
return "organization does not exist"
|
||||||
@ -122,14 +168,17 @@ func CheckPassword(user *User, password string) string {
|
|||||||
if credManager != nil {
|
if credManager != nil {
|
||||||
if organization.MasterPassword != "" {
|
if organization.MasterPassword != "" {
|
||||||
if credManager.IsPasswordCorrect(password, organization.MasterPassword, "", organization.PasswordSalt) {
|
if credManager.IsPasswordCorrect(password, organization.MasterPassword, "", organization.PasswordSalt) {
|
||||||
|
resetUserSigninErrorTimes(user)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if credManager.IsPasswordCorrect(password, user.Password, user.PasswordSalt, organization.PasswordSalt) {
|
if credManager.IsPasswordCorrect(password, user.Password, user.PasswordSalt, organization.PasswordSalt) {
|
||||||
|
resetUserSigninErrorTimes(user)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return "password incorrect"
|
|
||||||
|
return recordSigninErrorInfo(user)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("unsupported password type: %s", organization.PasswordType)
|
return fmt.Sprintf("unsupported password type: %s", organization.PasswordType)
|
||||||
}
|
}
|
||||||
@ -197,16 +246,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 +272,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 {
|
||||||
|
@ -14,7 +14,11 @@
|
|||||||
|
|
||||||
package object
|
package object
|
||||||
|
|
||||||
import "regexp"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
var reRealName *regexp.Regexp
|
var reRealName *regexp.Regexp
|
||||||
|
|
||||||
@ -29,3 +33,32 @@ func init() {
|
|||||||
func isValidRealName(s string) bool {
|
func isValidRealName(s string) bool {
|
||||||
return reRealName.MatchString(s)
|
return reRealName.MatchString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resetUserSigninErrorTimes(user *User) {
|
||||||
|
// if the password is correct and wrong times is not zero, reset the error times
|
||||||
|
if user.SigninWrongTimes == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user.SigninWrongTimes = 0
|
||||||
|
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
|
func recordSigninErrorInfo(user *User) string {
|
||||||
|
// increase failed login count
|
||||||
|
user.SigninWrongTimes++
|
||||||
|
|
||||||
|
if user.SigninWrongTimes >= SigninWrongTimesLimit {
|
||||||
|
// record the latest failed login time
|
||||||
|
user.LastSigninWrongTime = time.Now().UTC().Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
|
||||||
|
// update user
|
||||||
|
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||||
|
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
||||||
|
if leftChances > 0 {
|
||||||
|
return fmt.Sprintf("password is incorrect, you have %d remaining chances", leftChances)
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't show the chance error message if the user has no chance left
|
||||||
|
return fmt.Sprintf("You have entered the wrong password too many times, please wait for %d minutes and try again", int(LastSignWrongTimeDuration.Minutes()))
|
||||||
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -16,8 +16,10 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"io/ioutil"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/duo-labs/webauthn/webauthn"
|
"github.com/duo-labs/webauthn/webauthn"
|
||||||
)
|
)
|
||||||
@ -36,6 +38,8 @@ func InitDb() {
|
|||||||
initWebAuthn()
|
initWebAuthn()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var staticBaseUrl = beego.AppConfig.String("staticBaseUrl")
|
||||||
|
|
||||||
func initBuiltInOrganization() bool {
|
func initBuiltInOrganization() bool {
|
||||||
organization := getOrganization("admin", "built-in")
|
organization := getOrganization("admin", "built-in")
|
||||||
if organization != nil {
|
if organization != nil {
|
||||||
@ -48,10 +52,10 @@ func initBuiltInOrganization() bool {
|
|||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
DisplayName: "Built-in Organization",
|
DisplayName: "Built-in Organization",
|
||||||
WebsiteUrl: "https://example.com",
|
WebsiteUrl: "https://example.com",
|
||||||
Favicon: "https://cdn.casbin.com/static/favicon.ico",
|
Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", staticBaseUrl),
|
||||||
PasswordType: "plain",
|
PasswordType: "plain",
|
||||||
PhonePrefix: "86",
|
PhonePrefix: "86",
|
||||||
DefaultAvatar: "https://casbin.org/img/casbin.svg",
|
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", staticBaseUrl),
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
AccountItems: []*AccountItem{
|
AccountItems: []*AccountItem{
|
||||||
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
@ -71,6 +75,8 @@ 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"},
|
||||||
@ -98,7 +104,7 @@ func initBuiltInUser() {
|
|||||||
Type: "normal-user",
|
Type: "normal-user",
|
||||||
Password: "123",
|
Password: "123",
|
||||||
DisplayName: "Admin",
|
DisplayName: "Admin",
|
||||||
Avatar: "https://casbin.org/img/casbin.svg",
|
Avatar: fmt.Sprintf("%s/img/casbin.svg", staticBaseUrl),
|
||||||
Email: "admin@example.com",
|
Email: "admin@example.com",
|
||||||
Phone: "12345678910",
|
Phone: "12345678910",
|
||||||
Address: []string{},
|
Address: []string{},
|
||||||
@ -128,7 +134,7 @@ func initBuiltInApplication() {
|
|||||||
Name: "app-built-in",
|
Name: "app-built-in",
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
DisplayName: "Casdoor",
|
DisplayName: "Casdoor",
|
||||||
Logo: "https://cdn.casbin.com/logo/logo_1024x256.png",
|
Logo: fmt.Sprintf("%s/img/casdoor-logo_1185x256.png", staticBaseUrl),
|
||||||
HomepageUrl: "https://casdoor.org",
|
HomepageUrl: "https://casdoor.org",
|
||||||
Organization: "built-in",
|
Organization: "built-in",
|
||||||
Cert: "cert-built-in",
|
Cert: "cert-built-in",
|
||||||
@ -156,11 +162,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 "", ""
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,8 @@ func initDefinedOrganization(organization *Organization) {
|
|||||||
{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"},
|
||||||
|
@ -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{}
|
||||||
|
@ -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, ""
|
||||||
|
}
|
||||||
|
@ -16,12 +16,7 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/casbin/casbin/v2"
|
|
||||||
"github.com/casbin/casbin/v2/model"
|
|
||||||
xormadapter "github.com/casbin/xorm-adapter/v2"
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"xorm.io/core"
|
"xorm.io/core"
|
||||||
)
|
)
|
||||||
@ -34,24 +29,31 @@ type Permission struct {
|
|||||||
|
|
||||||
Users []string `xorm:"mediumtext" json:"users"`
|
Users []string `xorm:"mediumtext" json:"users"`
|
||||||
Roles []string `xorm:"mediumtext" json:"roles"`
|
Roles []string `xorm:"mediumtext" json:"roles"`
|
||||||
|
Domains []string `xorm:"mediumtext" json:"domains"`
|
||||||
|
|
||||||
Model string `xorm:"varchar(100)" json:"model"`
|
Model string `xorm:"varchar(100)" json:"model"`
|
||||||
|
Adapter string `xorm:"varchar(100)" json:"adapter"`
|
||||||
ResourceType string `xorm:"varchar(100)" json:"resourceType"`
|
ResourceType string `xorm:"varchar(100)" json:"resourceType"`
|
||||||
Resources []string `xorm:"mediumtext" json:"resources"`
|
Resources []string `xorm:"mediumtext" json:"resources"`
|
||||||
Actions []string `xorm:"mediumtext" json:"actions"`
|
Actions []string `xorm:"mediumtext" json:"actions"`
|
||||||
Effect string `xorm:"varchar(100)" json:"effect"`
|
Effect string `xorm:"varchar(100)" json:"effect"`
|
||||||
|
|
||||||
IsEnabled bool `json:"isEnabled"`
|
IsEnabled bool `json:"isEnabled"`
|
||||||
|
|
||||||
|
Submitter string `xorm:"varchar(100)" json:"submitter"`
|
||||||
|
Approver string `xorm:"varchar(100)" json:"approver"`
|
||||||
|
ApproveTime string `xorm:"varchar(100)" json:"approveTime"`
|
||||||
|
State string `xorm:"varchar(100)" json:"state"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PermissionRule struct {
|
type PermissionRule struct {
|
||||||
PType string `xorm:"varchar(100) index not null default ''"`
|
Ptype string `xorm:"varchar(100) index not null default ''" json:"ptype"`
|
||||||
V0 string `xorm:"varchar(100) index not null default ''"`
|
V0 string `xorm:"varchar(100) index not null default ''" json:"v0"`
|
||||||
V1 string `xorm:"varchar(100) index not null default ''"`
|
V1 string `xorm:"varchar(100) index not null default ''" json:"v1"`
|
||||||
V2 string `xorm:"varchar(100) index not null default ''"`
|
V2 string `xorm:"varchar(100) index not null default ''" json:"v2"`
|
||||||
V3 string `xorm:"varchar(100) index not null default ''"`
|
V3 string `xorm:"varchar(100) index not null default ''" json:"v3"`
|
||||||
V4 string `xorm:"varchar(100) index not null default ''"`
|
V4 string `xorm:"varchar(100) index not null default ''" json:"v4"`
|
||||||
V5 string `xorm:"varchar(100) index not null default ''"`
|
V5 string `xorm:"varchar(100) index not null default ''" json:"v5"`
|
||||||
|
Id string `xorm:"varchar(100) index not null default ''" json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPermissionCount(owner, field, value string) int {
|
func GetPermissionCount(owner, field, value string) int {
|
||||||
@ -121,7 +123,18 @@ func UpdatePermission(id string, permission *Permission) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if affected != 0 {
|
if affected != 0 {
|
||||||
|
if oldPermission.Adapter != "" {
|
||||||
removePolicies(oldPermission)
|
removePolicies(oldPermission)
|
||||||
|
if oldPermission.Adapter != permission.Adapter {
|
||||||
|
isEmpty, _ := adapter.Engine.IsTableEmpty(oldPermission.Adapter)
|
||||||
|
if isEmpty {
|
||||||
|
err = adapter.Engine.DropTables(oldPermission.Adapter)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
addPolicies(permission)
|
addPolicies(permission)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,10 +147,6 @@ func AddPermission(permission *Permission) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if affected != 0 {
|
|
||||||
addPolicies(permission)
|
|
||||||
}
|
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,8 +156,17 @@ func DeletePermission(permission *Permission) bool {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if affected != 0 {
|
if affected != 0 && permission.Adapter != "" {
|
||||||
removePolicies(permission)
|
removePolicies(permission)
|
||||||
|
if permission.Adapter != "permission_rule" {
|
||||||
|
isEmpty, _ := adapter.Engine.IsTableEmpty(permission.Adapter)
|
||||||
|
if isEmpty {
|
||||||
|
err = adapter.Engine.DropTables(permission.Adapter)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
@ -158,74 +176,32 @@ func (permission *Permission) GetId() string {
|
|||||||
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
|
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEnforcer(permission *Permission) *casbin.Enforcer {
|
func GetPermissionsByUser(userId string) []*Permission {
|
||||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
permissions := []*Permission{}
|
||||||
adapter, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName()+conf.GetConfigString("dbName"), "permission_rule", tableNamePrefix, true)
|
err := adapter.Engine.Where("users like ?", "%"+userId+"%").Find(&permissions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
modelText := `
|
return permissions
|
||||||
[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)
|
|
||||||
|
func GetPermissionsByRole(roleId string) []*Permission {
|
||||||
|
permissions := []*Permission{}
|
||||||
|
err := adapter.Engine.Where("roles like ?", "%"+roleId+"%").Find(&permissions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
enforcer, err := casbin.NewEnforcer(m, adapter)
|
return permissions
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPermissionsBySubmitter(owner string, submitter string) []*Permission {
|
||||||
|
permissions := []*Permission{}
|
||||||
|
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}})
|
return permissions
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return enforcer
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPolicies(permission *Permission) [][]string {
|
|
||||||
var policies [][]string
|
|
||||||
for _, user := range permission.Users {
|
|
||||||
for _, resource := range permission.Resources {
|
|
||||||
for _, action := range permission.Actions {
|
|
||||||
policies = append(policies, []string{permission.GetId(), user, resource, strings.ToLower(action)})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return policies
|
|
||||||
}
|
|
||||||
|
|
||||||
func addPolicies(permission *Permission) {
|
|
||||||
enforcer := getEnforcer(permission)
|
|
||||||
policies := getPolicies(permission)
|
|
||||||
|
|
||||||
_, err := enforcer.AddPolicies(policies)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func removePolicies(permission *Permission) {
|
|
||||||
enforcer := getEnforcer(permission)
|
|
||||||
|
|
||||||
_, err := enforcer.RemoveFilteredPolicy(0, permission.GetId())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
212
object/permission_enforcer.go
Normal file
212
object/permission_enforcer.go
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
// 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 {
|
||||||
|
tableName := "permission_rule"
|
||||||
|
if len(permission.Adapter) != 0 {
|
||||||
|
tableName = permission.Adapter
|
||||||
|
}
|
||||||
|
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||||
|
adapter, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName()+conf.GetConfigString("dbName"), tableName, tableNamePrefix, true)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
modelText := `
|
||||||
|
[request_definition]
|
||||||
|
r = sub, obj, act
|
||||||
|
|
||||||
|
[policy_definition]
|
||||||
|
p = sub, obj, act
|
||||||
|
|
||||||
|
[role_definition]
|
||||||
|
g = _, _
|
||||||
|
|
||||||
|
[policy_effect]
|
||||||
|
e = some(where (p.eft == allow))
|
||||||
|
|
||||||
|
[matchers]
|
||||||
|
m = g(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)
|
||||||
|
}
|
||||||
|
|
||||||
|
return enforcer
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPolicies(permission *Permission) ([][]string, [][]string) {
|
||||||
|
var policies [][]string
|
||||||
|
var groupingPolicies [][]string
|
||||||
|
domainExist := len(permission.Domains) > 0
|
||||||
|
for _, user := range permission.Users {
|
||||||
|
for _, resource := range permission.Resources {
|
||||||
|
for _, action := range permission.Actions {
|
||||||
|
if domainExist {
|
||||||
|
for _, domain := range permission.Domains {
|
||||||
|
policies = append(policies, []string{user, domain, resource, strings.ToLower(action)})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
policies = append(policies, []string{user, resource, strings.ToLower(action)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, role := range permission.Roles {
|
||||||
|
roleObj := GetRole(role)
|
||||||
|
for _, subUser := range roleObj.Users {
|
||||||
|
if domainExist {
|
||||||
|
for _, domain := range permission.Domains {
|
||||||
|
groupingPolicies = append(groupingPolicies, []string{subUser, domain, role})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
groupingPolicies = append(groupingPolicies, []string{subUser, role})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, subRole := range roleObj.Roles {
|
||||||
|
if domainExist {
|
||||||
|
for _, domain := range permission.Domains {
|
||||||
|
groupingPolicies = append(groupingPolicies, []string{subRole, domain, role})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
groupingPolicies = append(groupingPolicies, []string{subRole, role})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, resource := range permission.Resources {
|
||||||
|
for _, action := range permission.Actions {
|
||||||
|
if domainExist {
|
||||||
|
for _, domain := range permission.Domains {
|
||||||
|
policies = append(policies, []string{role, domain, resource, strings.ToLower(action)})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
policies = append(policies, []string{role, resource, strings.ToLower(action)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return policies, groupingPolicies
|
||||||
|
}
|
||||||
|
|
||||||
|
func addPolicies(permission *Permission) {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
policies, groupingPolicies := getPolicies(permission)
|
||||||
|
|
||||||
|
if len(groupingPolicies) > 0 {
|
||||||
|
_, err := enforcer.AddGroupingPolicies(groupingPolicies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := enforcer.AddPolicies(policies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func removePolicies(permission *Permission) {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
policies, groupingPolicies := getPolicies(permission)
|
||||||
|
|
||||||
|
if len(groupingPolicies) > 0 {
|
||||||
|
_, err := enforcer.RemoveGroupingPolicies(groupingPolicies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := enforcer.RemovePolicies(policies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Enforce(userId string, permissionRule *PermissionRule) bool {
|
||||||
|
permission := GetPermission(permissionRule.Id)
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
allow, err := enforcer.Enforce(userId, permissionRule.V1, permissionRule.V2)
|
||||||
|
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.V1, permissionRule.V2})
|
||||||
|
}
|
||||||
|
permission := GetPermission(permissionRules[0].Id)
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
allow, err := enforcer.BatchEnforce(requests)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return allow
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllValues(userId string, fn func(enforcer *casbin.Enforcer) []string) []string {
|
||||||
|
permissions := GetPermissionsByUser(userId)
|
||||||
|
for _, role := range GetAllRoles(userId) {
|
||||||
|
permissions = append(permissions, GetPermissionsByRole(role)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
var values []string
|
||||||
|
for _, permission := range permissions {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
values = append(values, fn(enforcer)...)
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllObjects(userId string) []string {
|
||||||
|
return getAllValues(userId, func(enforcer *casbin.Enforcer) []string {
|
||||||
|
return enforcer.GetAllObjects()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllActions(userId string) []string {
|
||||||
|
return getAllValues(userId, func(enforcer *casbin.Enforcer) []string {
|
||||||
|
return enforcer.GetAllActions()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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"`
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -29,6 +29,7 @@ type Role struct {
|
|||||||
|
|
||||||
Users []string `xorm:"mediumtext" json:"users"`
|
Users []string `xorm:"mediumtext" json:"users"`
|
||||||
Roles []string `xorm:"mediumtext" json:"roles"`
|
Roles []string `xorm:"mediumtext" json:"roles"`
|
||||||
|
Domains []string `xorm:"mediumtext" json:"domains"`
|
||||||
IsEnabled bool `json:"isEnabled"`
|
IsEnabled bool `json:"isEnabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,8 @@ func GetRole(id string) *Role {
|
|||||||
|
|
||||||
func UpdateRole(id string, role *Role) bool {
|
func UpdateRole(id string, role *Role) bool {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
if getRole(owner, name) == nil {
|
oldRole := getRole(owner, name)
|
||||||
|
if oldRole == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,3 +123,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,6 +35,7 @@ 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, certificate 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{
|
||||||
@ -100,7 +101,6 @@ func NewSamlResponse(user *User, host string, certificate string, destination st
|
|||||||
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"`
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
110
object/token.go
110
object/token.go
@ -28,13 +28,13 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
hourSeconds = 3600
|
hourSeconds = 3600
|
||||||
INVALID_REQUEST = "invalid_request"
|
InvalidRequest = "invalid_request"
|
||||||
INVALID_CLIENT = "invalid_client"
|
InvalidClient = "invalid_client"
|
||||||
INVALID_GRANT = "invalid_grant"
|
InvalidGrant = "invalid_grant"
|
||||||
UNAUTHORIZED_CLIENT = "unauthorized_client"
|
UnauthorizedClient = "unauthorized_client"
|
||||||
UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type"
|
UnsupportedGrantType = "unsupported_grant_type"
|
||||||
INVALID_SCOPE = "invalid_scope"
|
InvalidScope = "invalid_scope"
|
||||||
ENDPOINT_ERROR = "endpoint_error"
|
EndpointError = "endpoint_error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Code struct {
|
type Code struct {
|
||||||
@ -200,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 {
|
||||||
@ -287,7 +287,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken, refreshToken, err := generateJwtToken(application, user, nonce, scope, host)
|
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, nonce, scope, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -298,7 +298,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
|||||||
|
|
||||||
token := &Token{
|
token := &Token{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
Name: util.GenerateId(),
|
Name: tokenName,
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
Application: application.Name,
|
Application: application.Name,
|
||||||
Organization: user.Owner,
|
Organization: user.Owner,
|
||||||
@ -325,7 +325,7 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
|
|||||||
application := GetApplicationByClientId(clientId)
|
application := GetApplicationByClientId(clientId)
|
||||||
if application == nil {
|
if application == nil {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: INVALID_CLIENT,
|
Error: InvalidClient,
|
||||||
ErrorDescription: "client_id is invalid",
|
ErrorDescription: "client_id is invalid",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -334,7 +334,7 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
|
|||||||
|
|
||||||
if !IsGrantTypeValid(grantType, application.GrantTypes) && tag == "" {
|
if !IsGrantTypeValid(grantType, application.GrantTypes) && tag == "" {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: UNSUPPORTED_GRANT_TYPE,
|
Error: UnsupportedGrantType,
|
||||||
ErrorDescription: fmt.Sprintf("grant_type: %s is not supported in this application", grantType),
|
ErrorDescription: fmt.Sprintf("grant_type: %s is not supported in this application", grantType),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,20 +377,20 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
|
|||||||
// check parameters
|
// check parameters
|
||||||
if grantType != "refresh_token" {
|
if grantType != "refresh_token" {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: UNSUPPORTED_GRANT_TYPE,
|
Error: UnsupportedGrantType,
|
||||||
ErrorDescription: "grant_type should be refresh_token",
|
ErrorDescription: "grant_type should be refresh_token",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
application := GetApplicationByClientId(clientId)
|
application := GetApplicationByClientId(clientId)
|
||||||
if application == nil {
|
if application == nil {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: INVALID_CLIENT,
|
Error: InvalidClient,
|
||||||
ErrorDescription: "client_id is invalid",
|
ErrorDescription: "client_id is invalid",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if clientSecret != "" && application.ClientSecret != clientSecret {
|
if clientSecret != "" && application.ClientSecret != clientSecret {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: INVALID_CLIENT,
|
Error: InvalidClient,
|
||||||
ErrorDescription: "client_secret is invalid",
|
ErrorDescription: "client_secret is invalid",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,7 +399,7 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
|
|||||||
existed, err := adapter.Engine.Get(&token)
|
existed, err := adapter.Engine.Get(&token)
|
||||||
if err != nil || !existed {
|
if err != nil || !existed {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "refresh token is invalid, expired or revoked",
|
ErrorDescription: "refresh token is invalid, expired or revoked",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -408,7 +408,7 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
|
|||||||
_, err = ParseJwtToken(refreshToken, cert)
|
_, err = ParseJwtToken(refreshToken, cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: fmt.Sprintf("parse refresh token error: %s", err.Error()),
|
ErrorDescription: fmt.Sprintf("parse refresh token error: %s", err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,21 +416,22 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
|
|||||||
user := getUser(application.Organization, token.User)
|
user := getUser(application.Organization, token.User)
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
|
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newAccessToken, newRefreshToken, err := generateJwtToken(application, user, "", scope, host)
|
|
||||||
|
newAccessToken, newRefreshToken, tokenName, err := generateJwtToken(application, user, "", scope, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: ENDPOINT_ERROR,
|
Error: EndpointError,
|
||||||
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newToken := &Token{
|
newToken := &Token{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
Name: util.GenerateId(),
|
Name: tokenName,
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
Application: application.Name,
|
Application: application.Name,
|
||||||
Organization: user.Owner,
|
Organization: user.Owner,
|
||||||
@ -464,6 +465,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 {
|
||||||
@ -478,11 +480,12 @@ 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, *TokenError) {
|
func GetAuthorizationCodeToken(application *Application, clientSecret string, code string, verifier string) (*Token, *TokenError) {
|
||||||
if code == "" {
|
if code == "" {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_REQUEST,
|
Error: InvalidRequest,
|
||||||
ErrorDescription: "authorization code should not be empty",
|
ErrorDescription: "authorization code should not be empty",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -490,21 +493,21 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
|
|||||||
token := getTokenByCode(code)
|
token := getTokenByCode(code)
|
||||||
if token == nil {
|
if token == nil {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "authorization code is invalid",
|
ErrorDescription: "authorization code is invalid",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if token.CodeIsUsed {
|
if token.CodeIsUsed {
|
||||||
// anti replay attacks
|
// anti replay attacks
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "authorization code has been used",
|
ErrorDescription: "authorization code has been used",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if token.CodeChallenge != "" && pkceChallenge(verifier) != token.CodeChallenge {
|
if token.CodeChallenge != "" && pkceChallenge(verifier) != token.CodeChallenge {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "verifier is invalid",
|
ErrorDescription: "verifier is invalid",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -514,13 +517,13 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
|
|||||||
// 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, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_CLIENT,
|
Error: InvalidClient,
|
||||||
ErrorDescription: "client_secret is invalid",
|
ErrorDescription: "client_secret is invalid",
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if clientSecret != "" {
|
if clientSecret != "" {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_CLIENT,
|
Error: InvalidClient,
|
||||||
ErrorDescription: "client_secret is invalid",
|
ErrorDescription: "client_secret is invalid",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -529,7 +532,7 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
|
|||||||
|
|
||||||
if application.Name != token.Application {
|
if application.Name != token.Application {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "the token is for wrong application (client_id)",
|
ErrorDescription: "the token is for wrong application (client_id)",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -537,45 +540,47 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
|
|||||||
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, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "authorization code has expired",
|
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, *TokenError) {
|
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, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "the user does not exist",
|
ErrorDescription: "the user does not exist",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg := CheckPassword(user, password)
|
msg := CheckPassword(user, password)
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "invalid username or password",
|
ErrorDescription: "invalid username or password",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
|
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accessToken, refreshToken, err := generateJwtToken(application, user, "", scope, host)
|
|
||||||
|
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, "", scope, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: ENDPOINT_ERROR,
|
Error: EndpointError,
|
||||||
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token := &Token{
|
token := &Token{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
Name: util.GenerateId(),
|
Name: tokenName,
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
Application: application.Name,
|
Application: application.Name,
|
||||||
Organization: user.Owner,
|
Organization: user.Owner,
|
||||||
@ -592,11 +597,12 @@ 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, *TokenError) {
|
func GetClientCredentialsToken(application *Application, clientSecret string, scope string, host string) (*Token, *TokenError) {
|
||||||
if application.ClientSecret != clientSecret {
|
if application.ClientSecret != clientSecret {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_CLIENT,
|
Error: InvalidClient,
|
||||||
ErrorDescription: "client_secret is invalid",
|
ErrorDescription: "client_secret is invalid",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -605,16 +611,17 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
|
|||||||
Id: application.GetId(),
|
Id: application.GetId(),
|
||||||
Name: fmt.Sprintf("app/%s", application.Name),
|
Name: fmt.Sprintf("app/%s", application.Name),
|
||||||
}
|
}
|
||||||
accessToken, _, err := generateJwtToken(application, nullUser, "", scope, host)
|
|
||||||
|
accessToken, _, tokenName, err := generateJwtToken(application, nullUser, "", scope, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: ENDPOINT_ERROR,
|
Error: EndpointError,
|
||||||
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token := &Token{
|
token := &Token{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
Name: util.GenerateId(),
|
Name: tokenName,
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
Application: application.Name,
|
Application: application.Name,
|
||||||
Organization: application.Organization,
|
Organization: application.Organization,
|
||||||
@ -630,15 +637,16 @@ 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, tokenName, err := generateJwtToken(application, user, "", scope, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
token := &Token{
|
token := &Token{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
Name: util.GenerateId(),
|
Name: tokenName,
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
Application: application.Name,
|
Application: application.Name,
|
||||||
Organization: user.Owner,
|
Organization: user.Owner,
|
||||||
@ -655,12 +663,13 @@ 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, *TokenError) {
|
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, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_CLIENT,
|
Error: InvalidClient,
|
||||||
ErrorDescription: "the application does not support wechat mini program",
|
ErrorDescription: "the application does not support wechat mini program",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,14 +678,14 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
|
|||||||
session, err := mpIdp.GetSessionByCode(code)
|
session, err := mpIdp.GetSessionByCode(code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: fmt.Sprintf("get wechat mini program session error: %s", err.Error()),
|
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, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_REQUEST,
|
Error: InvalidRequest,
|
||||||
ErrorDescription: "the wechat mini program session is invalid",
|
ErrorDescription: "the wechat mini program session is invalid",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,7 +693,7 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
|
|||||||
if user == nil {
|
if user == nil {
|
||||||
if !application.EnableSignUp {
|
if !application.EnableSignUp {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: INVALID_GRANT,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: "the application does not allow to sign up new account",
|
ErrorDescription: "the application does not allow to sign up new account",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -703,28 +712,31 @@ 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, tokenName, err := generateJwtToken(application, user, "", "", host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &TokenError{
|
return nil, &TokenError{
|
||||||
Error: ENDPOINT_ERROR,
|
Error: EndpointError,
|
||||||
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token := &Token{
|
token := &Token{
|
||||||
Owner: application.Owner,
|
Owner: application.Owner,
|
||||||
Name: util.GenerateId(),
|
Name: tokenName,
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
Application: application.Name,
|
Application: application.Name,
|
||||||
Organization: user.Owner,
|
Organization: user.Owner,
|
||||||
|
@ -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
|
||||||
@ -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
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ func getShortClaims(claims Claims) ClaimsShort {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateJwtToken(application *Application, user *User, nonce string, scope string, host string) (string, string, error) {
|
func generateJwtToken(application *Application, user *User, nonce string, scope string, host string) (string, string, string, error) {
|
||||||
nowTime := time.Now()
|
nowTime := time.Now()
|
||||||
expireTime := nowTime.Add(time.Duration(application.ExpireInHours) * time.Hour)
|
expireTime := nowTime.Add(time.Duration(application.ExpireInHours) * time.Hour)
|
||||||
refreshExpireTime := nowTime.Add(time.Duration(application.RefreshExpireInHours) * time.Hour)
|
refreshExpireTime := nowTime.Add(time.Duration(application.RefreshExpireInHours) * time.Hour)
|
||||||
@ -72,6 +73,9 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
|||||||
originBackend = origin
|
originBackend = origin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := util.GenerateId()
|
||||||
|
jti := fmt.Sprintf("%s/%s", application.Owner, name)
|
||||||
|
|
||||||
claims := Claims{
|
claims := Claims{
|
||||||
User: user,
|
User: user,
|
||||||
Nonce: nonce,
|
Nonce: nonce,
|
||||||
@ -85,7 +89,7 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
|||||||
ExpiresAt: jwt.NewNumericDate(expireTime),
|
ExpiresAt: jwt.NewNumericDate(expireTime),
|
||||||
NotBefore: jwt.NewNumericDate(nowTime),
|
NotBefore: jwt.NewNumericDate(nowTime),
|
||||||
IssuedAt: jwt.NewNumericDate(nowTime),
|
IssuedAt: jwt.NewNumericDate(nowTime),
|
||||||
ID: "",
|
ID: jti,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,17 +114,17 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
|||||||
// RSA private key
|
// RSA private key
|
||||||
key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(cert.PrivateKey))
|
key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(cert.PrivateKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
token.Header["kid"] = cert.Name
|
token.Header["kid"] = cert.Name
|
||||||
tokenString, err := token.SignedString(key)
|
tokenString, err := token.SignedString(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
refreshTokenString, err := refreshToken.SignedString(key)
|
refreshTokenString, err := refreshToken.SignedString(key)
|
||||||
|
|
||||||
return tokenString, refreshTokenString, err
|
return tokenString, refreshTokenString, name, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseJwtToken(token string, cert *Cert) (*Claims, error) {
|
func ParseJwtToken(token string, cert *Cert) (*Claims, error) {
|
||||||
|
@ -24,6 +24,11 @@ import (
|
|||||||
"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"`
|
||||||
@ -73,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"`
|
||||||
@ -104,6 +108,12 @@ type User struct {
|
|||||||
|
|
||||||
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"`
|
||||||
|
|
||||||
|
LastSigninWrongTime string `xorm:"varchar(100)" json:"lastSigninWrongTime"`
|
||||||
|
SigninWrongTimes int `json:"signinWrongTimes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Userinfo struct {
|
type Userinfo struct {
|
||||||
@ -240,7 +250,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)
|
||||||
}
|
}
|
||||||
@ -270,6 +280,24 @@ 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 {
|
func GetUserByUserId(owner string, userId string) *User {
|
||||||
if owner == "" || userId == "" {
|
if owner == "" || userId == "" {
|
||||||
return nil
|
return nil
|
||||||
@ -351,6 +379,7 @@ func UpdateUser(id string, user *User, columns []string, isGlobalAdmin bool) boo
|
|||||||
"owner", "display_name", "avatar",
|
"owner", "display_name", "avatar",
|
||||||
"location", "address", "region", "language", "affiliation", "title", "homepage", "bio", "score", "tag", "signup_application",
|
"location", "address", "region", "language", "affiliation", "title", "homepage", "bio", "score", "tag", "signup_application",
|
||||||
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials",
|
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials",
|
||||||
|
"signin_wrong_times", "last_signin_wrong_time",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isGlobalAdmin {
|
if isGlobalAdmin {
|
||||||
@ -396,6 +425,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()
|
||||||
|
@ -37,11 +37,11 @@ func TestSyncAvatarsFromGitHub(t *testing.T) {
|
|||||||
|
|
||||||
users := GetGlobalUsers()
|
users := GetGlobalUsers()
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
if user.Github == "" {
|
if user.GitHub == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Avatar = fmt.Sprintf("https://avatars.githubusercontent.com/%s", user.Github)
|
user.Avatar = fmt.Sprintf("https://avatars.githubusercontent.com/%s", user.GitHub)
|
||||||
updateUserColumn("avatar", user)
|
updateUserColumn("avatar", user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,10 @@ func setUserProperty(user *User, field string, value string) {
|
|||||||
if value == "" {
|
if value == "" {
|
||||||
delete(user.Properties, field)
|
delete(user.Properties, field)
|
||||||
} else {
|
} else {
|
||||||
|
if user.Properties == nil {
|
||||||
|
user.Properties = make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
user.Properties[field] = value
|
user.Properties[field] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,30 +50,31 @@ func GetWebAuthnObject(host string) *webauthn.WebAuthn {
|
|||||||
return webAuthn
|
return webAuthn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebAuthnID
|
||||||
// implementation of webauthn.User interface
|
// implementation of webauthn.User interface
|
||||||
func (u *User) WebAuthnID() []byte {
|
func (user *User) WebAuthnID() []byte {
|
||||||
return []byte(u.GetId())
|
return []byte(user.GetId())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) WebAuthnName() string {
|
func (user *User) WebAuthnName() string {
|
||||||
return u.Name
|
return user.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) WebAuthnDisplayName() string {
|
func (user *User) WebAuthnDisplayName() string {
|
||||||
return u.DisplayName
|
return user.DisplayName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) WebAuthnCredentials() []webauthn.Credential {
|
func (user *User) WebAuthnCredentials() []webauthn.Credential {
|
||||||
return u.WebauthnCredentials
|
return user.WebauthnCredentials
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) WebAuthnIcon() string {
|
func (user *User) WebAuthnIcon() string {
|
||||||
return u.Avatar
|
return user.Avatar
|
||||||
}
|
}
|
||||||
|
|
||||||
// CredentialExcludeList returns a CredentialDescriptor array filled with all the user's credentials
|
// CredentialExcludeList returns a CredentialDescriptor array filled with all the user's credentials
|
||||||
func (u *User) CredentialExcludeList() []protocol.CredentialDescriptor {
|
func (user *User) CredentialExcludeList() []protocol.CredentialDescriptor {
|
||||||
credentials := u.WebAuthnCredentials()
|
credentials := user.WebAuthnCredentials()
|
||||||
credentialExcludeList := []protocol.CredentialDescriptor{}
|
credentialExcludeList := []protocol.CredentialDescriptor{}
|
||||||
for _, cred := range credentials {
|
for _, cred := range credentials {
|
||||||
descriptor := protocol.CredentialDescriptor{
|
descriptor := protocol.CredentialDescriptor{
|
||||||
@ -86,16 +87,16 @@ func (u *User) CredentialExcludeList() []protocol.CredentialDescriptor {
|
|||||||
return credentialExcludeList
|
return credentialExcludeList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) AddCredentials(credential webauthn.Credential, isGlobalAdmin bool) bool {
|
func (user *User) AddCredentials(credential webauthn.Credential, isGlobalAdmin bool) bool {
|
||||||
u.WebauthnCredentials = append(u.WebauthnCredentials, credential)
|
user.WebauthnCredentials = append(user.WebauthnCredentials, credential)
|
||||||
return UpdateUser(u.GetId(), u, []string{"webauthnCredentials"}, isGlobalAdmin)
|
return UpdateUser(user.GetId(), user, []string{"webauthnCredentials"}, isGlobalAdmin)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) DeleteCredentials(credentialIdBase64 string) bool {
|
func (user *User) DeleteCredentials(credentialIdBase64 string) bool {
|
||||||
for i, credential := range u.WebauthnCredentials {
|
for i, credential := range user.WebauthnCredentials {
|
||||||
if base64.StdEncoding.EncodeToString(credential.ID) == credentialIdBase64 {
|
if base64.StdEncoding.EncodeToString(credential.ID) == credentialIdBase64 {
|
||||||
u.WebauthnCredentials = append(u.WebauthnCredentials[0:i], u.WebauthnCredentials[i+1:]...)
|
user.WebauthnCredentials = append(user.WebauthnCredentials[0:i], user.WebauthnCredentials[i+1:]...)
|
||||||
return UpdateUserForAllFields(u.GetId(), u)
|
return UpdateUserForAllFields(user.GetId(), user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -42,7 +42,7 @@ type VerificationRecord struct {
|
|||||||
|
|
||||||
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
return fmt.Errorf("Please set an Email provider first")
|
return fmt.Errorf("please set an Email provider first")
|
||||||
}
|
}
|
||||||
|
|
||||||
sender := organization.DisplayName
|
sender := organization.DisplayName
|
||||||
@ -60,7 +60,7 @@ func SendVerificationCodeToEmail(organization *Organization, user *User, provide
|
|||||||
|
|
||||||
func SendVerificationCodeToPhone(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
func SendVerificationCodeToPhone(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
return errors.New("Please set a SMS provider first")
|
return errors.New("please set a SMS provider first")
|
||||||
}
|
}
|
||||||
|
|
||||||
code := getRandomCode(5)
|
code := getRandomCode(5)
|
||||||
@ -85,7 +85,7 @@ func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordT
|
|||||||
|
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
if has && now-record.Time < 60 {
|
if has && now-record.Time < 60 {
|
||||||
return errors.New("You can only send one code in 60s.")
|
return errors.New("you can only send one code in 60s")
|
||||||
}
|
}
|
||||||
|
|
||||||
record.Owner = provider.Owner
|
record.Owner = provider.Owner
|
||||||
|
3
pp/gc.go
3
pp/gc.go
@ -20,7 +20,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@ -147,7 +146,7 @@ func (pp *GcPaymentProvider) doPost(postBytes []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}(resp.Body)
|
}(resp.Body)
|
||||||
|
|
||||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
respBytes, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,10 @@ import (
|
|||||||
"golang.org/x/net/proxy"
|
"golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DefaultHttpClient *http.Client
|
var (
|
||||||
var ProxyHttpClient *http.Client
|
DefaultHttpClient *http.Client
|
||||||
|
ProxyHttpClient *http.Client
|
||||||
|
)
|
||||||
|
|
||||||
func InitHttpClient() {
|
func InitHttpClient() {
|
||||||
// not use proxy
|
// not use proxy
|
||||||
|
@ -71,5 +71,4 @@ func AutoSigninFilter(ctx *context.Context) {
|
|||||||
setSessionUser(ctx, userId)
|
setSessionUser(ctx, userId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initAPI() {
|
func initAPI() {
|
||||||
ns :=
|
ns := beego.NewNamespace("/",
|
||||||
beego.NewNamespace("/",
|
|
||||||
beego.NSNamespace("/api",
|
beego.NSNamespace("/api",
|
||||||
beego.NSInclude(
|
beego.NSInclude(
|
||||||
&controllers.ApiController{},
|
&controllers.ApiController{},
|
||||||
@ -79,11 +78,18 @@ func initAPI() {
|
|||||||
beego.Router("/api/delete-role", &controllers.ApiController{}, "POST:DeleteRole")
|
beego.Router("/api/delete-role", &controllers.ApiController{}, "POST:DeleteRole")
|
||||||
|
|
||||||
beego.Router("/api/get-permissions", &controllers.ApiController{}, "GET:GetPermissions")
|
beego.Router("/api/get-permissions", &controllers.ApiController{}, "GET:GetPermissions")
|
||||||
|
beego.Router("/api/get-permissions-by-submitter", &controllers.ApiController{}, "GET:GetPermissionsBySubmitter")
|
||||||
beego.Router("/api/get-permission", &controllers.ApiController{}, "GET:GetPermission")
|
beego.Router("/api/get-permission", &controllers.ApiController{}, "GET:GetPermission")
|
||||||
beego.Router("/api/update-permission", &controllers.ApiController{}, "POST:UpdatePermission")
|
beego.Router("/api/update-permission", &controllers.ApiController{}, "POST:UpdatePermission")
|
||||||
beego.Router("/api/add-permission", &controllers.ApiController{}, "POST:AddPermission")
|
beego.Router("/api/add-permission", &controllers.ApiController{}, "POST:AddPermission")
|
||||||
beego.Router("/api/delete-permission", &controllers.ApiController{}, "POST:DeletePermission")
|
beego.Router("/api/delete-permission", &controllers.ApiController{}, "POST:DeletePermission")
|
||||||
|
|
||||||
|
beego.Router("/api/enforce", &controllers.ApiController{}, "POST:Enforce")
|
||||||
|
beego.Router("/api/batch-enforce", &controllers.ApiController{}, "POST:BatchEnforce")
|
||||||
|
beego.Router("/api/get-all-objects", &controllers.ApiController{}, "GET:GetAllObjects")
|
||||||
|
beego.Router("/api/get-all-actions", &controllers.ApiController{}, "GET:GetAllActions")
|
||||||
|
beego.Router("/api/get-all-roles", &controllers.ApiController{}, "GET:GetAllRoles")
|
||||||
|
|
||||||
beego.Router("/api/get-models", &controllers.ApiController{}, "GET:GetModels")
|
beego.Router("/api/get-models", &controllers.ApiController{}, "GET:GetModels")
|
||||||
beego.Router("/api/get-model", &controllers.ApiController{}, "GET:GetModel")
|
beego.Router("/api/get-model", &controllers.ApiController{}, "GET:GetModel")
|
||||||
beego.Router("/api/update-model", &controllers.ApiController{}, "POST:UpdateModel")
|
beego.Router("/api/update-model", &controllers.ApiController{}, "POST:UpdateModel")
|
||||||
@ -116,6 +122,7 @@ func initAPI() {
|
|||||||
beego.Router("/api/get-applications", &controllers.ApiController{}, "GET:GetApplications")
|
beego.Router("/api/get-applications", &controllers.ApiController{}, "GET:GetApplications")
|
||||||
beego.Router("/api/get-application", &controllers.ApiController{}, "GET:GetApplication")
|
beego.Router("/api/get-application", &controllers.ApiController{}, "GET:GetApplication")
|
||||||
beego.Router("/api/get-user-application", &controllers.ApiController{}, "GET:GetUserApplication")
|
beego.Router("/api/get-user-application", &controllers.ApiController{}, "GET:GetUserApplication")
|
||||||
|
beego.Router("/api/get-organization-applications", &controllers.ApiController{}, "GET:GetOrganizationApplications")
|
||||||
beego.Router("/api/update-application", &controllers.ApiController{}, "POST:UpdateApplication")
|
beego.Router("/api/update-application", &controllers.ApiController{}, "POST:UpdateApplication")
|
||||||
beego.Router("/api/add-application", &controllers.ApiController{}, "POST:AddApplication")
|
beego.Router("/api/add-application", &controllers.ApiController{}, "POST:AddApplication")
|
||||||
beego.Router("/api/delete-application", &controllers.ApiController{}, "POST:DeleteApplication")
|
beego.Router("/api/delete-application", &controllers.ApiController{}, "POST:DeleteApplication")
|
||||||
@ -195,5 +202,4 @@ func initAPI() {
|
|||||||
beego.Router("/api/webauthn/signup/finish", &controllers.ApiController{}, "Post:WebAuthnSignupFinish")
|
beego.Router("/api/webauthn/signup/finish", &controllers.ApiController{}, "Post:WebAuthnSignupFinish")
|
||||||
beego.Router("/api/webauthn/signin/begin", &controllers.ApiController{}, "Get:WebAuthnSigninBegin")
|
beego.Router("/api/webauthn/signin/begin", &controllers.ApiController{}, "Get:WebAuthnSigninBegin")
|
||||||
beego.Router("/api/webauthn/signin/finish", &controllers.ApiController{}, "Post:WebAuthnSigninFinish")
|
beego.Router("/api/webauthn/signin/finish", &controllers.ApiController{}, "Post:WebAuthnSigninFinish")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1291,6 +1291,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/get-organization-applications": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Application API"
|
||||||
|
],
|
||||||
|
"description": "get the detail of the organization's application",
|
||||||
|
"operationId": "ApiController.GetOrganizationApplications",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "organization",
|
||||||
|
"description": "The organization name",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/object.Application"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/get-organizations": {
|
"/api/get-organizations": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -1853,6 +1882,24 @@
|
|||||||
"description": "The id of the user",
|
"description": "The id of the user",
|
||||||
"required": true,
|
"required": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "owner",
|
||||||
|
"description": "The owner of the user",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "email",
|
||||||
|
"description": "The email of the user",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "phone",
|
||||||
|
"description": "The phone of the user",
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -3220,11 +3267,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"2127.0xc000427560.false": {
|
"2200.0xc0003f8480.false": {
|
||||||
"title": "false",
|
"title": "false",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"2161.0xc000427590.false": {
|
"2235.0xc0003f84b0.false": {
|
||||||
"title": "false",
|
"title": "false",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
@ -3342,10 +3389,10 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"data": {
|
"data": {
|
||||||
"$ref": "#/definitions/2127.0xc000427560.false"
|
"$ref": "#/definitions/2200.0xc0003f8480.false"
|
||||||
},
|
},
|
||||||
"data2": {
|
"data2": {
|
||||||
"$ref": "#/definitions/2161.0xc000427590.false"
|
"$ref": "#/definitions/2235.0xc0003f84b0.false"
|
||||||
},
|
},
|
||||||
"msg": {
|
"msg": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -3549,6 +3596,9 @@
|
|||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64"
|
"format": "int64"
|
||||||
},
|
},
|
||||||
|
"certificate": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"createdTime": {
|
"createdTime": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -3571,9 +3621,6 @@
|
|||||||
"privateKey": {
|
"privateKey": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"certificate": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"scope": {
|
"scope": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -4585,6 +4632,12 @@
|
|||||||
"permanentAvatar": {
|
"permanentAvatar": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissions": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/object.Permission"
|
||||||
|
}
|
||||||
|
},
|
||||||
"phone": {
|
"phone": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -4606,6 +4659,12 @@
|
|||||||
"region": {
|
"region": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/object.Role"
|
||||||
|
}
|
||||||
|
},
|
||||||
"score": {
|
"score": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64"
|
"format": "int64"
|
||||||
|
@ -837,6 +837,25 @@ paths:
|
|||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.Organization'
|
$ref: '#/definitions/object.Organization'
|
||||||
|
/api/get-organization-applications:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Application API
|
||||||
|
description: get the detail of the organization's application
|
||||||
|
operationId: ApiController.GetOrganizationApplications
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: organization
|
||||||
|
description: The organization name
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.Application'
|
||||||
/api/get-organizations:
|
/api/get-organizations:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@ -1209,6 +1228,18 @@ paths:
|
|||||||
description: The id of the user
|
description: The id of the user
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: owner
|
||||||
|
description: The owner of the user
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: email
|
||||||
|
description: The email of the user
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: phone
|
||||||
|
description: The phone of the user
|
||||||
|
type: string
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: The Response object
|
description: The Response object
|
||||||
@ -2108,10 +2139,10 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Response'
|
$ref: '#/definitions/Response'
|
||||||
definitions:
|
definitions:
|
||||||
2127.0xc000427560.false:
|
2200.0xc0003f8480.false:
|
||||||
title: "false"
|
title: "false"
|
||||||
type: object
|
type: object
|
||||||
2161.0xc000427590.false:
|
2235.0xc0003f84b0.false:
|
||||||
title: "false"
|
title: "false"
|
||||||
type: object
|
type: object
|
||||||
Response:
|
Response:
|
||||||
@ -2192,9 +2223,9 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
$ref: '#/definitions/2127.0xc000427560.false'
|
$ref: '#/definitions/2200.0xc0003f8480.false'
|
||||||
data2:
|
data2:
|
||||||
$ref: '#/definitions/2161.0xc000427590.false'
|
$ref: '#/definitions/2235.0xc0003f84b0.false'
|
||||||
msg:
|
msg:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
@ -2331,6 +2362,8 @@ definitions:
|
|||||||
bitSize:
|
bitSize:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
certificate:
|
||||||
|
type: string
|
||||||
createdTime:
|
createdTime:
|
||||||
type: string
|
type: string
|
||||||
cryptoAlgorithm:
|
cryptoAlgorithm:
|
||||||
@ -2346,8 +2379,6 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
privateKey:
|
privateKey:
|
||||||
type: string
|
type: string
|
||||||
certificate:
|
|
||||||
type: string
|
|
||||||
scope:
|
scope:
|
||||||
type: string
|
type: string
|
||||||
type:
|
type:
|
||||||
@ -3027,6 +3058,10 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
permanentAvatar:
|
permanentAvatar:
|
||||||
type: string
|
type: string
|
||||||
|
permissions:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.Permission'
|
||||||
phone:
|
phone:
|
||||||
type: string
|
type: string
|
||||||
preHash:
|
preHash:
|
||||||
@ -3041,6 +3076,10 @@ definitions:
|
|||||||
format: int64
|
format: int64
|
||||||
region:
|
region:
|
||||||
type: string
|
type: string
|
||||||
|
roles:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.Role'
|
||||||
score:
|
score:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
@ -17,7 +17,9 @@ package util
|
|||||||
import (
|
import (
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetHmacSha1(keyStr, value string) string {
|
func GetHmacSha1(keyStr, value string) string {
|
||||||
@ -28,3 +30,10 @@ func GetHmacSha1(keyStr, value string) string {
|
|||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetHmacSha256(key string, data string) string {
|
||||||
|
mac := hmac.New(sha256.New, []byte(key))
|
||||||
|
mac.Write([]byte(data))
|
||||||
|
|
||||||
|
return hex.EncodeToString(mac.Sum(nil))
|
||||||
|
}
|
||||||
|
@ -19,8 +19,10 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rePhoneCn *regexp.Regexp
|
var (
|
||||||
var rePhone *regexp.Regexp
|
rePhoneCn *regexp.Regexp
|
||||||
|
rePhone *regexp.Regexp
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// https://learnku.com/articles/31543
|
// https://learnku.com/articles/31543
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user