优化结构

This commit is contained in:
Yvan
2026-08-28 00:29:40 +08:00
parent 04ff85116c
commit 03a4131f6e
118 changed files with 758 additions and 834 deletions
+3 -9
View File
@@ -8,23 +8,17 @@ import (
"kra/internal/config"
websocket "kra/internal/integration/websocket"
"kra/internal/server/handler"
"kra/internal/server/httpx"
"kra/internal/server/middleware"
"kra/internal/server/router"
"kra/internal/server/staticfiles"
"kra/internal/service"
"kra/pkg/httpx"
systemservice "kra/internal/service/system"
platformmodule "kra/pkg/module"
"github.com/gin-gonic/gin"
kratoshttp "github.com/go-kratos/kratos/v3/transport/http"
)
func NewGinEngine(runtime *config.Store, access *service.AccessControlService, handlers *handler.Set, auth *service.AuthService, security *service.SecurityService, audit *service.AuditRecorder, logger *slog.Logger, version string) *gin.Engine {
return NewGinEngineWithRuntime(runtime, access, auth, security, audit, logger, version, router.NewRoutes(handlers), nil)
}
func NewGinEngineWithRuntime(runtime *config.Store, access *service.AccessControlService, auth middleware.TokenAuthenticator, security *service.SecurityService, audit *service.AuditRecorder, logger *slog.Logger, version string, routes platformmodule.RouteRegistrar, ws *websocket.Server) *gin.Engine {
func NewGinEngineWithRuntime(runtime *config.Store, access *systemservice.AccessControlService, auth middleware.TokenAuthenticator, security *systemservice.SecurityService, audit *systemservice.AuditRecorder, logger *slog.Logger, version string, routes platformmodule.RouteRegistrar, ws *websocket.Server) *gin.Engine {
if runtime == nil {
runtime = config.NewStore(nil)
}
+6
View File
@@ -14,10 +14,16 @@ import (
"kra/internal/config"
"kra/internal/routecatalog"
"kra/internal/server/handler"
"kra/internal/server/router"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
func NewGinEngine(runtime *config.Store, access *systemservice.AccessControlService, handlers *handler.Set, auth *systemservice.AuthService, security *systemservice.SecurityService, audit *systemservice.AuditRecorder, logger *slog.Logger, version string) *gin.Engine {
return NewGinEngineWithRuntime(runtime, access, auth, security, audit, logger, version, router.NewRoutes(handlers), nil)
}
func emptyHandlers() *handler.Set {
return &handler.Set{
Authority: &handler.Authority{}, Menu: &handler.Menu{}, API: &handler.API{},
+5 -3
View File
@@ -1,16 +1,18 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"time"
"github.com/gin-gonic/gin"
)
type Announcement struct{ service *service.AnnouncementService }
type Announcement struct {
service *systemservice.AnnouncementService
}
func NewAnnouncement(service *service.AnnouncementService) *Announcement {
func NewAnnouncement(service *systemservice.AnnouncementService) *Announcement {
return &Announcement{service: service}
}
+3 -3
View File
@@ -1,15 +1,15 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type API struct{ service *service.APIService }
type API struct{ service *systemservice.APIService }
func NewAPI(service *service.APIService) *API { return &API{service: service} }
func NewAPI(service *systemservice.APIService) *API { return &API{service: service} }
func (h *API) List(c *gin.Context) {
var req dto.APIListRequest
+3 -3
View File
@@ -1,17 +1,17 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type APIToken struct {
service *service.TokenService
service *systemservice.TokenService
}
func NewAPIToken(service *service.TokenService) *APIToken {
func NewAPIToken(service *systemservice.TokenService) *APIToken {
return &APIToken{service: service}
}
+6 -6
View File
@@ -7,20 +7,20 @@ import (
"strconv"
"time"
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Audit struct {
service *service.AuditService
recorder *service.AuditRecorder
logs *service.LogViewerService
service *systemservice.AuditService
recorder *systemservice.AuditRecorder
logs *systemservice.LogViewerService
logger *slog.Logger
}
func NewAudit(service *service.AuditService, recorder *service.AuditRecorder, logs *service.LogViewerService, logger *slog.Logger) *Audit {
func NewAudit(service *systemservice.AuditService, recorder *systemservice.AuditRecorder, logs *systemservice.LogViewerService, logger *slog.Logger) *Audit {
return &Audit{service: service, recorder: recorder, logs: logs, logger: logger}
}
@@ -85,7 +85,7 @@ func (h *Audit) Logins(c *gin.Context) {
Fail(c, err.Error())
return
}
items, total, err := h.service.LoginsFilter(c.Request.Context(), req.Page, req.PageSize, req.Username, req.Status)
items, total, err := h.service.LoginsFilter(c.Request.Context(), req)
if err != nil {
Fail(c, "获取失败")
return
+7 -3
View File
@@ -1,15 +1,19 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Authority struct{ service *service.AuthorityService }
type Authority struct {
service *systemservice.AuthorityService
}
func NewAuthority(service *service.AuthorityService) *Authority { return &Authority{service: service} }
func NewAuthority(service *systemservice.AuthorityService) *Authority {
return &Authority{service: service}
}
func (h *Authority) List(c *gin.Context) {
items, err := h.service.Authorities(c.Request.Context())
+5 -3
View File
@@ -1,16 +1,18 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"strconv"
"github.com/gin-gonic/gin"
)
type Dictionary struct{ service *service.DictionaryService }
type Dictionary struct {
service *systemservice.DictionaryService
}
func NewDictionary(service *service.DictionaryService) *Dictionary {
func NewDictionary(service *systemservice.DictionaryService) *Dictionary {
return &Dictionary{service: service}
}
+3 -3
View File
@@ -1,15 +1,15 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Email struct{ service *service.EmailService }
type Email struct{ service *systemservice.EmailService }
func NewEmail(service *service.EmailService) *Email { return &Email{service: service} }
func NewEmail(service *systemservice.EmailService) *Email { return &Email{service: service} }
func (h *Email) Test(c *gin.Context) {
if err := h.service.Test(c.Request.Context()); err != nil {
+5 -5
View File
@@ -2,8 +2,8 @@ package handler
import (
"errors"
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"net/http"
"net/url"
"strings"
@@ -13,10 +13,10 @@ import (
)
type Export struct {
service *service.ExportService
service *systemservice.ExportService
}
func NewExport(service *service.ExportService) *Export {
func NewExport(service *systemservice.ExportService) *Export {
return &Export{service: service}
}
@@ -214,9 +214,9 @@ func (h *Export) Download(expectBlank bool) gin.HandlerFunc {
value, err := h.service.ConsumeToken(c.Request.Context(), token, expectBlank)
if err != nil {
switch {
case errors.Is(err, service.ErrExportTokenMalformed):
case errors.Is(err, systemservice.ErrExportTokenMalformed):
Fail(c, "解析导出参数失败")
case errors.Is(err, service.ErrExportTokenType):
case errors.Is(err, systemservice.ErrExportTokenType):
Fail(c, "token类型错误")
default:
Fail(c, "导出token无效或已过期")
+1 -1
View File
@@ -5,8 +5,8 @@ package handler
import (
"kra/internal/biz/system"
"kra/internal/server/httpx"
"kra/internal/server/middleware"
"kra/pkg/httpx"
"github.com/gin-gonic/gin"
)
@@ -1,17 +1,17 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
integrationservice "kra/internal/service/integration"
"github.com/gin-gonic/gin"
)
type IntegrationConfig struct {
service *service.IntegrationConfigService
service *integrationservice.IntegrationConfigService
}
func NewIntegrationConfig(service *service.IntegrationConfigService) *IntegrationConfig {
func NewIntegrationConfig(service *integrationservice.IntegrationConfigService) *IntegrationConfig {
return &IntegrationConfig{service: service}
}
+3 -3
View File
@@ -2,17 +2,17 @@ package handler
import (
"errors"
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
type Media struct{ service *service.MediaService }
type Media struct{ service *systemservice.MediaService }
func NewMedia(service *service.MediaService) *Media { return &Media{service: service} }
func NewMedia(service *systemservice.MediaService) *Media { return &Media{service: service} }
func (h *Media) limitMultipartBody(c *gin.Context) int64 {
limit := h.service.MediaConfig().EffectiveMaxFileSize()
+3 -3
View File
@@ -2,15 +2,15 @@ package handler
import (
"errors"
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Menu struct{ service *service.MenuService }
type Menu struct{ service *systemservice.MenuService }
func NewMenu(service *service.MenuService) *Menu { return &Menu{service: service} }
func NewMenu(service *systemservice.MenuService) *Menu { return &Menu{service: service} }
func validateMenuRequest(req *dto.MenuRequest) error {
if req == nil {
+5 -3
View File
@@ -1,14 +1,16 @@
package handler
import (
"kra/internal/service"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Navigation struct{ service *service.UserService }
type Navigation struct{ service *systemservice.UserService }
func NewNavigation(service *service.UserService) *Navigation { return &Navigation{service: service} }
func NewNavigation(service *systemservice.UserService) *Navigation {
return &Navigation{service: service}
}
func (h *Navigation) Menu(c *gin.Context) {
claims := Claims(c)
if claims == nil {
+4 -4
View File
@@ -1,18 +1,18 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Organization struct {
departments *service.DepartmentService
positions *service.PositionService
departments *systemservice.DepartmentService
positions *systemservice.PositionService
}
func NewOrganization(departments *service.DepartmentService, positions *service.PositionService) *Organization {
func NewOrganization(departments *systemservice.DepartmentService, positions *systemservice.PositionService) *Organization {
return &Organization{departments: departments, positions: positions}
}
+3 -3
View File
@@ -1,17 +1,17 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Parameter struct {
service *service.ParameterService
service *systemservice.ParameterService
}
func NewParameter(service *service.ParameterService) *Parameter {
func NewParameter(service *systemservice.ParameterService) *Parameter {
return &Parameter{service: service}
}
+7 -4
View File
@@ -2,16 +2,18 @@ package handler
import (
"io"
"kra/internal/service"
"kra/internal/service/dto"
paymentservice "kra/internal/service/payment"
"net/http"
"github.com/gin-gonic/gin"
)
type Payment struct{ service *service.PaymentService }
type Payment struct {
service *paymentservice.PaymentService
}
func NewPayment(service *service.PaymentService) *Payment { return &Payment{service: service} }
func NewPayment(service *paymentservice.PaymentService) *Payment { return &Payment{service: service} }
func (h *Payment) Order(c *gin.Context) {
var req dto.PaymentQueryRequest
if err := c.ShouldBindJSON(&req); err != nil {
@@ -148,7 +150,8 @@ func (h *Payment) Callback(c *gin.Context) {
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 8<<20)
raw, err := io.ReadAll(c.Request.Body)
if err != nil {
writePaymentCallbackAck(c, service.DefaultPaymentCallbackAck(c.Param("provider"), false))
_ = c.Error(err)
writePaymentCallbackAck(c, paymentservice.DefaultPaymentCallbackAck(c.Param("provider"), false))
return
}
headers := map[string]string{}
+5 -3
View File
@@ -1,15 +1,17 @@
package handler
import (
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Permission struct{ service *service.PermissionService }
type Permission struct {
service *systemservice.PermissionService
}
func NewPermission(service *service.PermissionService) *Permission {
func NewPermission(service *systemservice.PermissionService) *Permission {
return &Permission{service: service}
}
+6 -6
View File
@@ -9,21 +9,21 @@ import (
"strings"
"time"
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
"github.com/mojocn/base64Captcha"
)
type Public struct {
auth *service.AuthService
system *service.SystemConfigService
settings *service.SecurityService
auth *systemservice.AuthService
system *systemservice.SystemConfigService
settings *systemservice.SecurityService
store *captchaStore
}
func NewPublic(auth *service.AuthService, system *service.SystemConfigService, settings *service.SecurityService) *Public {
func NewPublic(auth *systemservice.AuthService, system *systemservice.SystemConfigService, settings *systemservice.SecurityService) *Public {
return &Public{auth: auth, system: system, settings: settings, store: &captchaStore{service: settings}}
}
@@ -155,7 +155,7 @@ func (h *Public) InitializeDatabase(engine *gin.Engine) gin.HandlerFunc {
}
type captchaStore struct {
service *service.SecurityService
service *systemservice.SecurityService
}
func (s *captchaStore) Set(id, value string) error {
+3 -3
View File
@@ -2,14 +2,14 @@ package handler
import (
"kra/internal/server/middleware"
"kra/internal/service"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Session struct{ tokens *service.TokenService }
type Session struct{ tokens *systemservice.TokenService }
func NewSession(tokens *service.TokenService) *Session { return &Session{tokens: tokens} }
func NewSession(tokens *systemservice.TokenService) *Session { return &Session{tokens: tokens} }
func (h *Session) Logout(c *gin.Context) {
token := middleware.RequestToken(c, false)
if token == "" {
+4 -4
View File
@@ -3,19 +3,19 @@ package handler
import (
"errors"
"kra/internal/biz/system"
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"log/slog"
"github.com/gin-gonic/gin"
)
type SystemConfig struct {
system *service.SystemConfigService
settings *service.SecurityService
system *systemservice.SystemConfigService
settings *systemservice.SecurityService
}
func NewSystemConfig(system *service.SystemConfigService, settings *service.SecurityService) *SystemConfig {
func NewSystemConfig(system *systemservice.SystemConfigService, settings *systemservice.SecurityService) *SystemConfig {
return &SystemConfig{system: system, settings: settings}
}
+3 -3
View File
@@ -2,8 +2,8 @@ package handler
import (
"fmt"
"kra/internal/service"
"kra/internal/service/dto"
taskservice "kra/internal/service/task"
"net/http"
"time"
@@ -11,10 +11,10 @@ import (
)
type Task struct {
service *service.TaskService
service *taskservice.TaskService
}
func NewTask(service *service.TaskService) *Task {
func NewTask(service *taskservice.TaskService) *Task {
return &Task{service: service}
}
+14 -8
View File
@@ -1,8 +1,10 @@
package handler
import (
"kra/internal/service"
"errors"
"kra/internal/biz/system"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"strconv"
"time"
@@ -10,11 +12,11 @@ import (
)
type User struct {
service *service.UserService
auth *service.AuthService
service *systemservice.UserService
auth *systemservice.AuthService
}
func NewUser(user *service.UserService, auth *service.AuthService) *User {
func NewUser(user *systemservice.UserService, auth *systemservice.AuthService) *User {
return &User{service: user, auth: auth}
}
@@ -64,7 +66,7 @@ func (h *User) Create(c *gin.Context) {
}
result, err := h.service.CreateUserRequest(c.Request.Context(), &req)
if err != nil {
if service.IsPasswordPolicyError(err) {
if systemservice.IsPasswordPolicyError(err) {
Fail(c, err.Error())
return
}
@@ -141,7 +143,7 @@ func (h *User) ResetPassword(c *gin.Context) {
return
}
if err := h.service.ResetPassword(c.Request.Context(), req.ID, req.Password); err != nil {
if service.IsPasswordPolicyError(err) {
if systemservice.IsPasswordPolicyError(err) {
Fail(c, err.Error())
return
}
@@ -171,7 +173,7 @@ func (h *User) ChangePassword(c *gin.Context) {
return
}
if err := h.service.ChangePassword(c.Request.Context(), claims.ID, req.Password, req.NewPassword); err != nil {
if service.IsPasswordPolicyError(err) {
if systemservice.IsPasswordPolicyError(err) {
Fail(c, err.Error())
return
}
@@ -206,7 +208,11 @@ func (h *User) SetAuthorities(c *gin.Context) {
return
}
if err := h.service.SetUserAuthorities(c.Request.Context(), req.ID, req.AuthorityIDs); err != nil {
Fail(c, "修改失败")
if errors.Is(err, system.ErrAuthoritiesRequired) {
Fail(c, err.Error())
} else {
Fail(c, "修改失败")
}
return
}
Write(c, CodeSuccess, gin.H{}, "修改成功")
+3 -3
View File
@@ -8,15 +8,15 @@ import (
"strconv"
"time"
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
type Version struct{ service *service.VersionService }
type Version struct{ service *systemservice.VersionService }
func NewVersion(service *service.VersionService) *Version { return &Version{service: service} }
func NewVersion(service *systemservice.VersionService) *Version { return &Version{service: service} }
func versionStage(err error) (system.VersionStage, bool) {
var stageErr *system.VersionStageError
+69
View File
@@ -0,0 +1,69 @@
// Package httpx contains the stable JSON response contract shared by HTTP
// modules. It intentionally keeps the existing Gin adapter so callers can
// migrate without changing their handler flow.
package httpx
import (
"net/http"
"strings"
"time"
"github.com/gin-gonic/gin"
)
const (
CodeSuccess = 0
CodeError = 7
CodePasswordChangeRequired = 10001
)
type Response struct {
Code int `json:"code"`
Data any `json:"data"`
Msg string `json:"msg"`
}
type PageResult struct {
List any `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
func Write(c *gin.Context, code int, data any, message string) {
c.JSON(http.StatusOK, Response{Code: code, Data: data, Msg: message})
}
func OK(c *gin.Context) { Write(c, CodeSuccess, gin.H{}, "操作成功") }
func OKWithData(c *gin.Context, data any) { Write(c, CodeSuccess, data, "成功") }
func Fail(c *gin.Context, message string) { Write(c, CodeError, gin.H{}, message) }
func NoAuth(c *gin.Context, message string) {
c.AbortWithStatusJSON(http.StatusUnauthorized, Response{Code: CodeError, Data: nil, Msg: message})
}
func requestUsesHTTPS(request *http.Request) bool {
if request != nil && request.TLS != nil {
return true
}
if request == nil {
return false
}
forwarded := strings.SplitN(request.Header.Get("X-Forwarded-Proto"), ",", 2)[0]
return strings.EqualFold(strings.TrimSpace(forwarded), "https")
}
// SetTokenCookie is the shared transport-level cookie policy. It has no KRA
// business dependency, so handlers and middleware can use pkg/httpx directly.
func SetTokenCookie(c *gin.Context, value string, maxAge int) {
if c == nil {
return
}
cookie := &http.Cookie{Name: "x-token", Value: value, Path: "/", MaxAge: maxAge, Secure: requestUsesHTTPS(c.Request), HttpOnly: true, SameSite: http.SameSiteStrictMode}
if maxAge < 0 {
cookie.Expires = time.Unix(1, 0)
}
http.SetCookie(c.Writer, cookie)
}
+33
View File
@@ -0,0 +1,33 @@
package httpx
import (
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
)
func TestResponseHelpers(t *testing.T) {
gin.SetMode(gin.TestMode)
r := gin.New()
r.GET("/ok", OK)
r.GET("/fail", func(c *gin.Context) { Fail(c, "bad") })
r.GET("/auth", func(c *gin.Context) { NoAuth(c, "login") })
for _, tc := range []struct {
path string
statusCode int
body string
}{
{"/ok", 200, `{"code":0,"data":{},"msg":"操作成功"}`},
{"/fail", 200, `{"code":7,"data":{},"msg":"bad"}`},
{"/auth", 401, `{"code":7,"data":null,"msg":"login"}`},
} {
req := httptest.NewRequest("GET", tc.path, nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code != tc.statusCode || w.Body.String() != tc.body {
t.Fatalf("%s: status=%d body=%q", tc.path, w.Code, w.Body.String())
}
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ package middleware
import (
"context"
"kra/internal/biz/system"
httpx "kra/pkg/httpx"
httpx "kra/internal/server/httpx"
"kra/internal/config"
"kra/internal/utils/routepath"
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"errors"
"io"
"kra/internal/biz/system"
httpx "kra/pkg/httpx"
httpx "kra/internal/server/httpx"
"log/slog"
"mime"
"net/http"
+2 -2
View File
@@ -13,15 +13,15 @@ import (
"kra/internal/config"
"kra/internal/routecatalog"
"kra/internal/service"
"kra/internal/service/dto"
systemservice "kra/internal/service/system"
"github.com/gin-gonic/gin"
)
const ctxOperationAuditPersistFailedKey = "operation_audit_persist_failed"
func OperationAudit(runtime *config.Store, recorder *service.AuditRecorder) gin.HandlerFunc {
func OperationAudit(runtime *config.Store, recorder *systemservice.AuditRecorder) gin.HandlerFunc {
return func(c *gin.Context) {
if runtime == nil || recorder == nil {
c.Next()
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"context"
"errors"
"kra/internal/biz/system"
httpx "kra/pkg/httpx"
httpx "kra/internal/server/httpx"
"net/http"
"strconv"
"strings"
-4
View File
@@ -68,7 +68,3 @@ func redactJSON(raw []byte, contentType string, limit int) string {
}
func stringValue(value any) string { text, _ := value.(string); return text }
func isBootstrapPath(path string) bool {
return strings.HasSuffix(path, "/health") || strings.Contains(path, "/init/")
}
+1 -1
View File
@@ -3,7 +3,7 @@ package middleware
import (
"bytes"
"encoding/json"
httpx "kra/pkg/httpx"
httpx "kra/internal/server/httpx"
"log/slog"
"strings"
+3 -3
View File
@@ -1,8 +1,8 @@
package middleware
import (
"kra/internal/service"
httpx "kra/pkg/httpx"
httpx "kra/internal/server/httpx"
systemservice "kra/internal/service/system"
"net/http"
"strings"
"time"
@@ -10,7 +10,7 @@ import (
"github.com/gin-gonic/gin"
)
func SecurityRateLimit(settings *service.SecurityService) gin.HandlerFunc {
func SecurityRateLimit(settings *systemservice.SecurityService) gin.HandlerFunc {
return func(c *gin.Context) {
path := strings.TrimSuffix(c.Request.URL.Path, "/")
if !strings.HasSuffix(path, "/base/login") && !strings.HasSuffix(path, "/base/captcha") {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"encoding/hex"
"strings"
"kra/pkg/logging"
"kra/internal/logging"
"github.com/gin-gonic/gin"
"github.com/google/uuid"