forked from casdoor/casdoor
Compare commits
2 Commits
custom
...
copilot/ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb35137dd7 | ||
|
|
f3fc41e03e |
2
go.mod
2
go.mod
@@ -87,6 +87,7 @@ require (
|
||||
golang.org/x/text v0.33.0
|
||||
golang.org/x/time v0.8.0
|
||||
google.golang.org/api v0.215.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
layeh.com/radius v0.0.0-20231213012653-1006025d24f8
|
||||
maunium.net/go/mautrix v0.22.1
|
||||
modernc.org/sqlite v1.18.2
|
||||
@@ -300,7 +301,6 @@ require (
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/grpc v1.79.3 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
|
||||
27
log/provider.go
Normal file
27
log/provider.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// 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 log
|
||||
|
||||
type LogProvider interface {
|
||||
WriteLog(context string) error
|
||||
}
|
||||
|
||||
func GetLogProvider(typ string, host string, port int, title string, method string) (LogProvider, error) {
|
||||
if typ == "Linux Syslog" {
|
||||
return NewSyslogProvider(host, port, title, method)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
51
log/syslog.go
Normal file
51
log/syslog.go
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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.
|
||||
|
||||
//go:build !windows
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
golog "log/syslog"
|
||||
)
|
||||
|
||||
type SyslogProvider struct {
|
||||
writer *golog.Writer
|
||||
}
|
||||
|
||||
func NewSyslogProvider(host string, port int, tag string, network string) (*SyslogProvider, error) {
|
||||
var writer *golog.Writer
|
||||
var err error
|
||||
|
||||
if host == "" {
|
||||
writer, err = golog.New(golog.LOG_INFO|golog.LOG_USER, tag)
|
||||
} else {
|
||||
if port <= 0 {
|
||||
port = 514
|
||||
}
|
||||
addr := fmt.Sprintf("%s:%d", host, port)
|
||||
writer, err = golog.Dial(network, addr, golog.LOG_INFO|golog.LOG_USER, tag)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SyslogProvider{writer: writer}, nil
|
||||
}
|
||||
|
||||
func (s *SyslogProvider) WriteLog(context string) error {
|
||||
return s.writer.Info(context)
|
||||
}
|
||||
29
log/syslog_windows.go
Normal file
29
log/syslog_windows.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
|
||||
//go:build windows
|
||||
|
||||
package log
|
||||
|
||||
import "fmt"
|
||||
|
||||
func NewSyslogProvider(host string, port int, tag string, network string) (*SyslogProvider, error) {
|
||||
return nil, fmt.Errorf("syslog is not supported on Windows")
|
||||
}
|
||||
|
||||
type SyslogProvider struct{}
|
||||
|
||||
func (s *SyslogProvider) WriteLog(context string) error {
|
||||
return fmt.Errorf("syslog is not supported on Windows")
|
||||
}
|
||||
51
object/log_provider.go
Normal file
51
object/log_provider.go
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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 object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/log"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
func SendLog(provider *Provider, record *Record) error {
|
||||
logProvider, err := log.GetLogProvider(provider.Type, provider.Host, provider.Port, provider.Title, provider.Method)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if logProvider == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return logProvider.WriteLog(util.StructToJson(record))
|
||||
}
|
||||
|
||||
func AddRecordToLogProviders(record *Record) error {
|
||||
providers, err := GetProvidersByCategory(record.Organization, "Log")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, provider := range providers {
|
||||
err = SendLog(provider, record)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -160,6 +160,11 @@ func AddRecord(record *Record) bool {
|
||||
fmt.Println(errWebhook)
|
||||
}
|
||||
|
||||
errLog := AddRecordToLogProviders(record)
|
||||
if errLog != nil {
|
||||
fmt.Println(errLog)
|
||||
}
|
||||
|
||||
affected, err := addRecord(record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -32,6 +32,7 @@ import {renderWeb3ProviderFields} from "./provider/Web3ProviderFields";
|
||||
import {renderStorageProviderFields} from "./provider/StorageProviderFields";
|
||||
import {renderFaceIdProviderFields} from "./provider/FaceIDProviderFields";
|
||||
import {renderIDVerificationProviderFields} from "./provider/IDVerificationProviderFields";
|
||||
import {renderLogProviderFields} from "./provider/LogProviderFields";
|
||||
|
||||
const {Option} = Select;
|
||||
const {TextArea} = Input;
|
||||
@@ -715,6 +716,8 @@ class ProviderEditPage extends React.Component {
|
||||
} else if (value === "ID Verification") {
|
||||
this.updateProviderField("type", "Jumio");
|
||||
this.updateProviderField("endpoint", "");
|
||||
} else if (value === "Log") {
|
||||
this.updateProviderField("type", "Linux Syslog");
|
||||
}
|
||||
})}>
|
||||
{
|
||||
@@ -722,6 +725,7 @@ class ProviderEditPage extends React.Component {
|
||||
{id: "Captcha", name: "Captcha"},
|
||||
{id: "Email", name: "Email"},
|
||||
{id: "ID Verification", name: "ID Verification"},
|
||||
{id: "Log", name: "Log"},
|
||||
{id: "MFA", name: "MFA"},
|
||||
{id: "Notification", name: "Notification"},
|
||||
{id: "OAuth", name: "OAuth"},
|
||||
@@ -851,6 +855,7 @@ class ProviderEditPage extends React.Component {
|
||||
(this.state.provider.category === "Captcha" && this.state.provider.type === "Default") ||
|
||||
(this.state.provider.category === "Web3") ||
|
||||
(this.state.provider.category === "MFA") ||
|
||||
(this.state.provider.category === "Log") ||
|
||||
(this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") ||
|
||||
(this.state.provider.category === "SMS" && this.state.provider.type === "Custom HTTP SMS") ||
|
||||
(this.state.provider.category === "Email" && this.state.provider.type === "Custom HTTP Email") ||
|
||||
@@ -975,6 +980,10 @@ class ProviderEditPage extends React.Component {
|
||||
this.state.provider,
|
||||
this.updateProviderField.bind(this)
|
||||
) : null}
|
||||
{this.state.provider.category === "Log" ? renderLogProviderFields(
|
||||
this.state.provider,
|
||||
this.updateProviderField.bind(this)
|
||||
) : null}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Provider URL"), i18next.t("provider:Provider URL - Tooltip"))} :
|
||||
|
||||
@@ -1419,6 +1419,10 @@ export function getProviderTypeOptions(category) {
|
||||
{id: "Jumio", name: "Jumio"},
|
||||
{id: "Alibaba Cloud", name: "Alibaba Cloud"},
|
||||
]);
|
||||
} else if (category === "Log") {
|
||||
return ([
|
||||
{id: "Linux Syslog", name: "Linux Syslog"},
|
||||
]);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Brieftaschen",
|
||||
"Wallets - Tooltip": "Unterstützte digitale Brieftaschen",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "admin (Gemeinsam)"
|
||||
"admin (Shared)": "admin (Gemeinsam)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Wurde ausgelöst",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Supported digital wallets",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "admin (Shared)"
|
||||
"admin (Shared)": "admin (Shared)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Is triggered",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Billeteras",
|
||||
"Wallets - Tooltip": "Billeteras - Información adicional",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "administrador (compartido)"
|
||||
"admin (Shared)": "administrador (compartido)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Fue activado",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Portefeuilles",
|
||||
"Wallets - Tooltip": "Portefeuilles - Infobulle",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "admin (Partagé)"
|
||||
"admin (Shared)": "admin (Partagé)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Est déclenché",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "ウォレット",
|
||||
"Wallets - Tooltip": "ウォレット - ツールチップ",
|
||||
"Web": "ウェブ",
|
||||
"admin (Shared)": "管理者(共有)"
|
||||
"admin (Shared)": "管理者(共有)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "トリガーされました",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Portfele",
|
||||
"Wallets - Tooltip": "Portfele - Podpowiedź",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "admin (Wspólny)"
|
||||
"admin (Shared)": "admin (Wspólny)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Zostało wyzwolone",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Carteiras",
|
||||
"Wallets - Tooltip": "Dica: carteiras",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "admin (Compartilhado)"
|
||||
"admin (Shared)": "admin (Compartilhado)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Foi acionado",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Cüzdanlar",
|
||||
"Wallets - Tooltip": "Cüzdanlar - Araç ipucu",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "yönetici (Paylaşılan)"
|
||||
"admin (Shared)": "yönetici (Paylaşılan)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Tetiklendi mi",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Гаманці",
|
||||
"Wallets - Tooltip": "Гаманці – підказка",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "адміністратор (спільно)"
|
||||
"admin (Shared)": "адміністратор (спільно)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Спрацьовує",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "Ví",
|
||||
"Wallets - Tooltip": "Gợi ý ví",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "quản trị viên (Chung)"
|
||||
"admin (Shared)": "quản trị viên (Chung)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "Đã kích hoạt",
|
||||
|
||||
@@ -1165,7 +1165,10 @@
|
||||
"Wallets": "钱包",
|
||||
"Wallets - Tooltip": "支持的数字钱包",
|
||||
"Web": "Web",
|
||||
"admin (Shared)": "admin(共享)"
|
||||
"admin (Shared)": "admin(共享)",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "The syslog tag (program name) to identify log messages",
|
||||
"Leave empty to use local syslog": "Leave empty to use local syslog"
|
||||
},
|
||||
"record": {
|
||||
"Is triggered": "是否触发",
|
||||
|
||||
78
web/src/provider/LogProviderFields.js
Normal file
78
web/src/provider/LogProviderFields.js
Normal file
@@ -0,0 +1,78 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Col, Input, InputNumber, Row, Select} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
export function renderLogProviderFields(provider, updateProviderField) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{provider.type === "Linux Syslog" ? (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Host"), i18next.t("provider:Host - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.host} placeholder={i18next.t("provider:Leave empty to use local syslog")} onChange={e => {
|
||||
updateProviderField("host", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Port"), i18next.t("provider:Port - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<InputNumber value={provider.port} min={0} max={65535} style={{width: "100%"}} onChange={value => {
|
||||
updateProviderField("port", value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Tag"), i18next.t("provider:Tag - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.title} onChange={e => {
|
||||
updateProviderField("title", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={provider.method || "udp"} onChange={value => {
|
||||
updateProviderField("method", value);
|
||||
}}>
|
||||
{
|
||||
[
|
||||
{id: "udp", name: "UDP"},
|
||||
{id: "tcp", name: "TCP"},
|
||||
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user