mirror of
https://github.com/Direct-Dev-Ru/go-lcg.git
synced 2025-11-16 17:49:55 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d213de7a95 | |||
| deb80f2b37 | |||
| 81b01d74ae | |||
| 3c95eb85db | |||
| 1fbdd237a3 | |||
| 5b78e775c1 | |||
| 2d82b91090 | |||
| 9044b02d27 | |||
| 5d3829d1fe | |||
| e7c11879a1 | |||
| edadedcf80 | |||
| 6444c35bbb | |||
| 5ff6d4e072 | |||
| 6ec41355d3 | |||
| ffc2d6ba0a | |||
| 7a0d0746d4 |
@@ -1 +1 @@
|
||||
v2.0.3
|
||||
v2.0.5
|
||||
|
||||
@@ -68,6 +68,15 @@ type ValidationConfig struct {
|
||||
MaxExplanationLength int
|
||||
}
|
||||
|
||||
func GetEnvBool(key string, defaultValue bool) bool {
|
||||
if value, exists := os.LookupEnv(key); exists {
|
||||
if boolValue, err := strconv.ParseBool(value); err == nil {
|
||||
return boolValue
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value, exists := os.LookupEnv(key); exists {
|
||||
return value
|
||||
|
||||
@@ -16,7 +16,7 @@ data:
|
||||
LCG_CONFIG_FOLDER: "/app/data/config"
|
||||
LCG_NO_HISTORY: "false"
|
||||
LCG_ALLOW_EXECUTION: "false"
|
||||
LCG_DEBUG: "false"
|
||||
LCG_DEBUG: "true"
|
||||
|
||||
# Настройки аутентификации
|
||||
LCG_SERVER_REQUIRE_AUTH: "true"
|
||||
|
||||
@@ -14,8 +14,7 @@ spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: lcg
|
||||
version: ${VERSION}
|
||||
app: lcg
|
||||
spec:
|
||||
containers:
|
||||
- name: lcg
|
||||
@@ -58,21 +57,18 @@ spec:
|
||||
readOnly: true
|
||||
# Health checks
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /login
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /login
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /login
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 60
|
||||
|
||||
@@ -127,15 +127,24 @@ fi
|
||||
if [ "$current_branch" != "main" ]; then
|
||||
git checkout main
|
||||
git merge --no-ff -m "Merged branch '$current_branch' into main while building $VERSION" "$current_branch"
|
||||
git push origin main
|
||||
elif [ "$current_branch" = "main" ]; then
|
||||
log "🔄 Вы находитесь на ветке main. Слияние с release..."
|
||||
git add .
|
||||
git commit -m "Исправления в ветке $current_branch"
|
||||
git push origin main
|
||||
fi
|
||||
|
||||
# переключиться на ветку release и слить с веткой main
|
||||
git checkout release
|
||||
git merge --no-ff -m "Merged main into release while building $VERSION" main
|
||||
if git show-ref --quiet refs/heads/release; then
|
||||
log "ℹ️ Branch 'release' exists. Proceeding with merge."
|
||||
git checkout release
|
||||
git merge --no-ff -m "Merged main into release while building $VERSION" main
|
||||
else
|
||||
log "❌ Branch 'release' does not exist. Please create the branch before proceeding."
|
||||
git checkout -b release
|
||||
git merge --no-ff -m "Merged main into release while building $VERSION" main
|
||||
fi
|
||||
|
||||
# если тег $VERSION существует, удалить его и принудительно запушить
|
||||
tag_exists=$(git tag -l "$VERSION")
|
||||
|
||||
@@ -1 +1 @@
|
||||
v2.0.3
|
||||
v2.0.5
|
||||
|
||||
@@ -4,8 +4,7 @@ metadata:
|
||||
name: lcg-route
|
||||
namespace: lcg
|
||||
labels:
|
||||
app: lcg
|
||||
version: ${VERSION}
|
||||
app: lcg
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
|
||||
@@ -13,13 +13,13 @@ resources:
|
||||
- ingress-route.yaml
|
||||
|
||||
# Common labels
|
||||
commonLabels:
|
||||
app: lcg
|
||||
version: ${VERSION}
|
||||
managed-by: kustomize
|
||||
# commonLabels:
|
||||
# app: lcg
|
||||
# version: ${VERSION}
|
||||
# managed-by: kustomize
|
||||
|
||||
# Images
|
||||
images:
|
||||
- name: lcg
|
||||
newName: ${REPOSITORY}
|
||||
newTag: ${VERSION}
|
||||
# images:
|
||||
# - name: lcg
|
||||
# newName: ${REPOSITORY}
|
||||
# newTag: ${VERSION}
|
||||
|
||||
@@ -4,8 +4,7 @@ metadata:
|
||||
name: lcg
|
||||
namespace: lcg
|
||||
labels:
|
||||
app: lcg
|
||||
version: ${VERSION}
|
||||
app: lcg
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
@@ -14,5 +13,4 @@ spec:
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: lcg
|
||||
version: ${VERSION}
|
||||
app: lcg
|
||||
|
||||
@@ -124,6 +124,11 @@ func (p *ProxyAPIProvider) Chat(messages []Chat) (string, error) {
|
||||
req.Header.Set("Authorization", "Bearer "+p.JWTToken)
|
||||
}
|
||||
|
||||
if config.AppConfig.MainFlags.Debug {
|
||||
fmt.Println("Chat URL: ", p.BaseURL+config.AppConfig.Server.ProxyUrl)
|
||||
fmt.Println("ProxyChatRequest: ", req)
|
||||
}
|
||||
|
||||
resp, err := p.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("ошибка выполнения запроса: %w", err)
|
||||
|
||||
@@ -5,7 +5,7 @@ metadata:
|
||||
namespace: lcg
|
||||
data:
|
||||
# Основные настройки
|
||||
LCG_VERSION: "v2.0.3"
|
||||
LCG_VERSION: "v2.0.5"
|
||||
LCG_BASE_PATH: "/lcg"
|
||||
LCG_SERVER_HOST: "0.0.0.0"
|
||||
LCG_SERVER_PORT: "8080"
|
||||
@@ -16,7 +16,7 @@ data:
|
||||
LCG_CONFIG_FOLDER: "/app/data/config"
|
||||
LCG_NO_HISTORY: "false"
|
||||
LCG_ALLOW_EXECUTION: "false"
|
||||
LCG_DEBUG: "false"
|
||||
LCG_DEBUG: "true"
|
||||
|
||||
# Настройки аутентификации
|
||||
LCG_SERVER_REQUIRE_AUTH: "true"
|
||||
|
||||
@@ -5,7 +5,7 @@ metadata:
|
||||
namespace: lcg
|
||||
labels:
|
||||
app: lcg
|
||||
version: v2.0.3
|
||||
version: v2.0.5
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
@@ -14,12 +14,11 @@ spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: lcg
|
||||
version: v2.0.3
|
||||
app: lcg
|
||||
spec:
|
||||
containers:
|
||||
- name: lcg
|
||||
image: kuznetcovay/lcg:v2.0.3
|
||||
image: kuznetcovay/lcg:v2.0.5
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
@@ -58,21 +57,18 @@ spec:
|
||||
readOnly: true
|
||||
# Health checks
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /login
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
failureThreshold: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /login
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /login
|
||||
tcpSocket:
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 60
|
||||
|
||||
@@ -4,8 +4,7 @@ metadata:
|
||||
name: lcg-route
|
||||
namespace: lcg
|
||||
labels:
|
||||
app: lcg
|
||||
version: v2.0.3
|
||||
app: lcg
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
|
||||
@@ -13,13 +13,13 @@ resources:
|
||||
- ingress-route.yaml
|
||||
|
||||
# Common labels
|
||||
commonLabels:
|
||||
app: lcg
|
||||
version: v2.0.3
|
||||
managed-by: kustomize
|
||||
# commonLabels:
|
||||
# app: lcg
|
||||
# version: v2.0.5
|
||||
# managed-by: kustomize
|
||||
|
||||
# Images
|
||||
images:
|
||||
- name: lcg
|
||||
newName: kuznetcovay/lcg
|
||||
newTag: v2.0.3
|
||||
# images:
|
||||
# - name: lcg
|
||||
# newName: kuznetcovay/lcg
|
||||
# newTag: v2.0.5
|
||||
|
||||
@@ -4,8 +4,7 @@ metadata:
|
||||
name: lcg
|
||||
namespace: lcg
|
||||
labels:
|
||||
app: lcg
|
||||
version: v2.0.3
|
||||
app: lcg
|
||||
spec:
|
||||
type: ClusterIP
|
||||
ports:
|
||||
@@ -14,5 +13,4 @@ spec:
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: lcg
|
||||
version: v2.0.3
|
||||
app: lcg
|
||||
|
||||
3
main.go
3
main.go
@@ -156,6 +156,9 @@ lcg [опции] <описание команды>
|
||||
Debug: c.Bool("debug"),
|
||||
}
|
||||
disableHistory = config.AppConfig.MainFlags.NoHistory || config.AppConfig.IsNoHistoryEnabled()
|
||||
|
||||
config.AppConfig.MainFlags.Debug = config.AppConfig.MainFlags.Debug || config.GetEnvBool("LCG_DEBUG", false)
|
||||
|
||||
args := c.Args().Slice()
|
||||
|
||||
if len(args) == 0 {
|
||||
|
||||
@@ -94,7 +94,7 @@ func validateJWTToken(tokenString string) (*JWTClaims, error) {
|
||||
}
|
||||
|
||||
// Парсим токен
|
||||
token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (any, error) {
|
||||
// Проверяем метод подписи
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
func handleLoginPage(w http.ResponseWriter, r *http.Request) {
|
||||
// Если пользователь уже авторизован, перенаправляем на главную
|
||||
if isAuthenticated(r) {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
http.Redirect(w, r, makePath("/"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ func handleLoginPage(w http.ResponseWriter, r *http.Request) {
|
||||
Message: "",
|
||||
Error: "",
|
||||
CSRFToken: csrfToken,
|
||||
BasePath: getBasePath(),
|
||||
}
|
||||
|
||||
if err := RenderLoginPage(w, data); err != nil {
|
||||
@@ -73,6 +74,7 @@ type LoginPageData struct {
|
||||
Message string
|
||||
Error string
|
||||
CSRFToken string
|
||||
BasePath string
|
||||
}
|
||||
|
||||
// RenderLoginPage рендерит страницу входа
|
||||
|
||||
@@ -2,6 +2,7 @@ package serve
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/direct-dev-ru/linux-command-gpt/config"
|
||||
)
|
||||
@@ -15,8 +16,8 @@ func AuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// Исключаем страницу входа и API логина из проверки
|
||||
if r.URL.Path == "/login" || r.URL.Path == "/api/login" || r.URL.Path == "/api/validate-token" {
|
||||
// Исключаем страницу входа и API логина из проверки (с учетом BasePath)
|
||||
if r.URL.Path == makePath("/login") || r.URL.Path == makePath("/api/login") || r.URL.Path == makePath("/api/validate-token") {
|
||||
next(w, r)
|
||||
return
|
||||
}
|
||||
@@ -31,8 +32,8 @@ func AuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// Для веб-запросов перенаправляем на страницу входа
|
||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
||||
// Для веб-запросов перенаправляем на страницу входа (с учетом BasePath)
|
||||
http.Redirect(w, r, makePath("/login"), http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -50,8 +51,8 @@ func CSRFMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// Исключаем некоторые API endpoints
|
||||
if r.URL.Path == "/api/login" || r.URL.Path == "/api/logout" {
|
||||
// Исключаем некоторые API endpoints (с учетом BasePath)
|
||||
if r.URL.Path == makePath("/api/login") || r.URL.Path == makePath("/api/logout") {
|
||||
next(w, r)
|
||||
return
|
||||
}
|
||||
@@ -103,7 +104,8 @@ func CSRFMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
// isAPIRequest проверяет, является ли запрос API запросом
|
||||
func isAPIRequest(r *http.Request) bool {
|
||||
path := r.URL.Path
|
||||
return len(path) >= 4 && path[:4] == "/api"
|
||||
apiPrefix := makePath("/api")
|
||||
return strings.HasPrefix(path, apiPrefix)
|
||||
}
|
||||
|
||||
// RequireAuth обертка для requireAuth из auth.go
|
||||
|
||||
@@ -285,7 +285,7 @@ const LoginPageTemplate = `
|
||||
|
||||
try {
|
||||
const csrfToken = document.getElementById('csrf_token').value;
|
||||
const response = await fetch('/api/login', {
|
||||
const response = await fetch('{{.BasePath}}/api/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -302,7 +302,7 @@ const LoginPageTemplate = `
|
||||
|
||||
if (data.success) {
|
||||
// Успешная авторизация, перенаправляем на главную страницу
|
||||
window.location.href = '/';
|
||||
window.location.href = '{{.BasePath}}/';
|
||||
} else {
|
||||
// Ошибка авторизации
|
||||
showMessage(data.error || 'Ошибка авторизации', 'error');
|
||||
|
||||
18
ssl/ssl.go
18
ssl/ssl.go
@@ -1,6 +1,7 @@
|
||||
package ssl
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
@@ -139,25 +140,22 @@ func LoadOrGenerateCert(host string) (*tls.Certificate, error) {
|
||||
// IsSecureHost проверяет, является ли хост безопасным для HTTP
|
||||
func IsSecureHost(host string) bool {
|
||||
secureHosts := []string{"localhost", "127.0.0.1", "::1"}
|
||||
for _, secureHost := range secureHosts {
|
||||
if host == secureHost {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(secureHosts, host)
|
||||
}
|
||||
|
||||
// ShouldUseHTTPS определяет, нужно ли использовать HTTPS
|
||||
func ShouldUseHTTPS(host string) bool {
|
||||
|
||||
// Если явно разрешен HTTP, используем HTTP
|
||||
if config.AppConfig.Server.AllowHTTP {
|
||||
return false
|
||||
}
|
||||
|
||||
// Если хост не localhost/127.0.0.1, принуждаем к HTTPS
|
||||
if !IsSecureHost(host) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Если явно разрешен HTTP, используем HTTP
|
||||
if config.AppConfig.Server.AllowHTTP {
|
||||
return false
|
||||
}
|
||||
|
||||
// По умолчанию для localhost используем HTTP
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user