mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-05 20:38:47 +08:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
56d0de64dc | ||
![]() |
1813e8e8c7 | ||
![]() |
e27c764a55 | ||
![]() |
e5a2057382 | ||
![]() |
8457ff7433 | ||
![]() |
888a6f2feb | ||
![]() |
b57b64fc36 | ||
![]() |
0d239ba1cf |
@@ -28,6 +28,7 @@ ldapServerPort = 389
|
|||||||
ldapsCertId = ""
|
ldapsCertId = ""
|
||||||
ldapsServerPort = 636
|
ldapsServerPort = 636
|
||||||
radiusServerPort = 1812
|
radiusServerPort = 1812
|
||||||
|
radiusDefaultOrganization = "built-in"
|
||||||
radiusSecret = "secret"
|
radiusSecret = "secret"
|
||||||
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||||
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
||||||
|
@@ -22,6 +22,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -617,6 +618,17 @@ func (c *ApiController) Login() {
|
|||||||
c.ResponseError(fmt.Sprintf(c.T("auth:Failed to login in: %s"), err.Error()))
|
c.ResponseError(fmt.Sprintf(c.T("auth:Failed to login in: %s"), err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if provider.EmailRegex != "" {
|
||||||
|
reg, err := regexp.Compile(provider.EmailRegex)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("auth:Failed to login in: %s"), err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reg.MatchString(userInfo.Email) {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("check:Email is invalid")))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if authForm.Method == "signup" {
|
if authForm.Method == "signup" {
|
||||||
|
@@ -195,6 +195,12 @@ type GitHubUserEmailInfo struct {
|
|||||||
Visibility string `json:"visibility"`
|
Visibility string `json:"visibility"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GitHubErrorInfo struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
DocumentationUrl string `json:"documentation_url"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
func (idp *GithubIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
func (idp *GithubIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
req, err := http.NewRequest("GET", "https://api.github.com/user", nil)
|
req, err := http.NewRequest("GET", "https://api.github.com/user", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -236,13 +242,23 @@ func (idp *GithubIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var userEmails []GitHubUserEmailInfo
|
if respEmail.StatusCode != 200 {
|
||||||
err = json.Unmarshal(emailBody, &userEmails)
|
var errMessage GitHubErrorInfo
|
||||||
if err != nil {
|
err = json.Unmarshal(emailBody, &errMessage)
|
||||||
return nil, err
|
if err != nil {
|
||||||
}
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
githubUserInfo.Email = idp.getEmailFromEmailsResult(userEmails)
|
fmt.Printf("GithubIdProvider:GetUserInfo() error, status code = %d, error message = %v\n", respEmail.StatusCode, errMessage)
|
||||||
|
} else {
|
||||||
|
var userEmails []GitHubUserEmailInfo
|
||||||
|
err = json.Unmarshal(emailBody, &userEmails)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
githubUserInfo.Email = idp.getEmailFromEmailsResult(userEmails)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo := UserInfo{
|
userInfo := UserInfo{
|
||||||
|
5
main.go
5
main.go
@@ -83,6 +83,11 @@ func main() {
|
|||||||
// logs.SetLevel(logs.LevelInformational)
|
// logs.SetLevel(logs.LevelInformational)
|
||||||
logs.SetLogFuncCall(false)
|
logs.SetLogFuncCall(false)
|
||||||
|
|
||||||
|
err = util.StopOldInstance(port)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
go ldap.StartLdapServer()
|
go ldap.StartLdapServer()
|
||||||
go radius.StartRadiusServer()
|
go radius.StartRadiusServer()
|
||||||
go object.ClearThroughputPerSecond()
|
go object.ClearThroughputPerSecond()
|
||||||
|
@@ -41,11 +41,11 @@ func GetDashboard(owner string) (*map[string][]int64, error) {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var err error
|
var err error
|
||||||
wg.Add(len(tableNames))
|
wg.Add(len(tableNames))
|
||||||
|
ch := make(chan error, len(tableNames))
|
||||||
for _, tableName := range tableNames {
|
for _, tableName := range tableNames {
|
||||||
dashboard[tableName+"Counts"] = make([]int64, 31)
|
dashboard[tableName+"Counts"] = make([]int64, 31)
|
||||||
tableName := tableName
|
tableName := tableName
|
||||||
go func() {
|
go func(ch chan error) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
dashboardDateItems := []DashboardDateItem{}
|
dashboardDateItems := []DashboardDateItem{}
|
||||||
var countResult int64
|
var countResult int64
|
||||||
@@ -59,20 +59,29 @@ func GetDashboard(owner string) (*map[string][]int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if countResult, err = dbQueryBefore.And("created_time < ?", time30day).Table(tableName).Count(); err != nil {
|
if countResult, err = dbQueryBefore.And("created_time < ?", time30day).Table(tableName).Count(); err != nil {
|
||||||
panic(err)
|
ch <- err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if err = dbQueryAfter.And("created_time >= ?", time30day).Table(tableName).Find(&dashboardDateItems); err != nil {
|
if err = dbQueryAfter.And("created_time >= ?", time30day).Table(tableName).Find(&dashboardDateItems); err != nil {
|
||||||
panic(err)
|
ch <- err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dashboardMap.Store(tableName, DashboardMapItem{
|
dashboardMap.Store(tableName, DashboardMapItem{
|
||||||
dashboardDateItems: dashboardDateItems,
|
dashboardDateItems: dashboardDateItems,
|
||||||
itemCount: countResult,
|
itemCount: countResult,
|
||||||
})
|
})
|
||||||
}()
|
}(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
close(ch)
|
||||||
|
|
||||||
|
for err = range ch {
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nowTime := time.Now()
|
nowTime := time.Now()
|
||||||
for i := 30; i >= 0; i-- {
|
for i := 30; i >= 0; i-- {
|
||||||
|
@@ -16,6 +16,7 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/beego/beego/context"
|
"github.com/beego/beego/context"
|
||||||
@@ -70,6 +71,7 @@ type Provider struct {
|
|||||||
IdP string `xorm:"mediumtext" json:"idP"`
|
IdP string `xorm:"mediumtext" json:"idP"`
|
||||||
IssuerUrl string `xorm:"varchar(100)" json:"issuerUrl"`
|
IssuerUrl string `xorm:"varchar(100)" json:"issuerUrl"`
|
||||||
EnableSignAuthnRequest bool `json:"enableSignAuthnRequest"`
|
EnableSignAuthnRequest bool `json:"enableSignAuthnRequest"`
|
||||||
|
EmailRegex string `xorm:"varchar(200)" json:"emailRegex"`
|
||||||
|
|
||||||
ProviderUrl string `xorm:"varchar(200)" json:"providerUrl"`
|
ProviderUrl string `xorm:"varchar(200)" json:"providerUrl"`
|
||||||
}
|
}
|
||||||
@@ -200,6 +202,13 @@ func UpdateProvider(id string, provider *Provider) (bool, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if provider.EmailRegex != "" {
|
||||||
|
_, err := regexp.Compile(provider.EmailRegex)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if name != provider.Name {
|
if name != provider.Name {
|
||||||
err := providerChangeTrigger(name, provider.Name)
|
err := providerChangeTrigger(name, provider.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -234,6 +243,13 @@ func AddProvider(provider *Provider) (bool, error) {
|
|||||||
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
|
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if provider.EmailRegex != "" {
|
||||||
|
_, err := regexp.Compile(provider.EmailRegex)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.Insert(provider)
|
affected, err := ormer.Engine.Insert(provider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@@ -309,22 +309,29 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var oldTokenScope string
|
||||||
if application.TokenFormat == "JWT-Standard" {
|
if application.TokenFormat == "JWT-Standard" {
|
||||||
_, err = ParseStandardJwtToken(refreshToken, cert)
|
oldToken, err := ParseStandardJwtToken(refreshToken, cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: InvalidGrant,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: fmt.Sprintf("parse refresh token error: %s", err.Error()),
|
ErrorDescription: fmt.Sprintf("parse refresh token error: %s", err.Error()),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
oldTokenScope = oldToken.Scope
|
||||||
} else {
|
} else {
|
||||||
_, err = ParseJwtToken(refreshToken, cert)
|
oldToken, err := ParseJwtToken(refreshToken, cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
Error: InvalidGrant,
|
Error: InvalidGrant,
|
||||||
ErrorDescription: fmt.Sprintf("parse refresh token error: %s", err.Error()),
|
ErrorDescription: fmt.Sprintf("parse refresh token error: %s", err.Error()),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
oldTokenScope = oldToken.Scope
|
||||||
|
}
|
||||||
|
|
||||||
|
if scope == "" {
|
||||||
|
scope = oldTokenScope
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a new token
|
// generate a new token
|
||||||
|
@@ -237,6 +237,7 @@ type MfaAccount struct {
|
|||||||
AccountName string `xorm:"varchar(100)" json:"accountName"`
|
AccountName string `xorm:"varchar(100)" json:"accountName"`
|
||||||
Issuer string `xorm:"varchar(100)" json:"issuer"`
|
Issuer string `xorm:"varchar(100)" json:"issuer"`
|
||||||
SecretKey string `xorm:"varchar(100)" json:"secretKey"`
|
SecretKey string `xorm:"varchar(100)" json:"secretKey"`
|
||||||
|
Origin string `xorm:"varchar(100)" json:"origin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FaceId struct {
|
type FaceId struct {
|
||||||
|
@@ -68,8 +68,10 @@ func handleAccessRequest(w radius.ResponseWriter, r *radius.Request) {
|
|||||||
log.Printf("handleAccessRequest() username=%v, org=%v, password=%v", username, organization, password)
|
log.Printf("handleAccessRequest() username=%v, org=%v, password=%v", username, organization, password)
|
||||||
|
|
||||||
if organization == "" {
|
if organization == "" {
|
||||||
w.Write(r.Response(radius.CodeAccessReject))
|
organization = conf.GetConfigString("radiusDefaultOrganization")
|
||||||
return
|
if organization == "" {
|
||||||
|
organization = "built-in"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var user *object.User
|
var user *object.User
|
||||||
|
97
util/process.go
Normal file
97
util/process.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2025 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 util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getPidByPort(port int) (int, error) {
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "windows":
|
||||||
|
cmd = exec.Command("cmd", "/c", "netstat -ano | findstr :"+strconv.Itoa(port))
|
||||||
|
case "darwin", "linux":
|
||||||
|
cmd = exec.Command("lsof", "-i", ":"+strconv.Itoa(port))
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("unsupported OS: %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
|
if exitErr.ExitCode() == 1 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(output), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
if len(fields) > 0 {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
if fields[1] == "0.0.0.0:"+strconv.Itoa(port) {
|
||||||
|
pid, err := strconv.Atoi(fields[len(fields)-1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pid, err := strconv.Atoi(fields[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopOldInstance(port int) error {
|
||||||
|
pid, err := getPidByPort(port)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if pid == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
process, err := os.FindProcess(pid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = process.Kill()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
fmt.Printf("The old instance with pid: %d has been stopped\n", pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@@ -633,6 +633,20 @@ class ProviderEditPage extends React.Component {
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
this.state.provider.category === "OAuth" ? (
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("provider:Email regex"), i18next.t("provider:Email regex - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22}>
|
||||||
|
<TextArea rows={4} value={this.state.provider.emailRegex} onChange={e => {
|
||||||
|
this.updateProviderField("emailRegex", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
{
|
{
|
||||||
this.state.provider.type === "Custom" ? (
|
this.state.provider.type === "Custom" ? (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
@@ -105,6 +105,18 @@ class MfaAccountTable extends React.Component {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("mfaAccount:Origin"),
|
||||||
|
dataIndex: "origin",
|
||||||
|
key: "origin",
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Input value={text} onChange={e => {
|
||||||
|
this.updateField(table, index, "origin", e.target.value);
|
||||||
|
}} />
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("mfaAccount:Secret Key"),
|
title: i18next.t("mfaAccount:Secret Key"),
|
||||||
dataIndex: "secretKey",
|
dataIndex: "secretKey",
|
||||||
|
Reference in New Issue
Block a user