From 28ef2dc1fdcd999497f43d3d41804ca036ea91fb Mon Sep 17 00:00:00 2001 From: d3m0k1d Date: Fri, 3 Apr 2026 22:48:31 +0300 Subject: [PATCH] chore: add sqlite init and config, add repository for sql --- backend/cmd/main.go | 37 +++++++++++++++++++ backend/go.mod | 8 ++++ backend/go.sum | 16 ++++++++ backend/internal/config/config.go | 20 ++++++++++ backend/internal/config/types.go | 11 +++++- backend/internal/handlers/agents.go | 35 ++++++++++++++++++ backend/internal/handlers/handlers.go | 19 ++++++++++ backend/internal/repository/repository.go | 11 ++++++ .../internal/storage/{db.go => clickhouse.go} | 0 backend/internal/storage/migrations.go | 3 ++ backend/internal/storage/sqlite.go | 33 +++++++++++++++++ backend/internal/utils/token_gen.go | 14 +++++++ 12 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 backend/internal/handlers/handlers.go create mode 100644 backend/internal/repository/repository.go rename backend/internal/storage/{db.go => clickhouse.go} (100%) create mode 100644 backend/internal/storage/migrations.go create mode 100644 backend/internal/storage/sqlite.go create mode 100644 backend/internal/utils/token_gen.go diff --git a/backend/cmd/main.go b/backend/cmd/main.go index e022326..06bd01c 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -1,7 +1,13 @@ package cmd import ( + "log" + "os" + "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/docs" + "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/config" + "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/handlers" + "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/storage" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" @@ -13,6 +19,24 @@ import ( // @description Type "Bearer" followed by a space and the JWT token. func main() { + cfg_path, ok := os.LookupEnv("CONFIG_FILE") + if !ok { + cfg_path = "/etc/hellreign/config.yml" + } + cfg, err := config.ImportSettings(cfg_path) + if err != nil { + log.Fatalf("Err loading config") + } + + db, err := storage.Open(cfg.Database.Token_db) + if err != nil { + log.Fatalf("Err opening database") + } + defer db.Close() + + h := handlers.New(db) + agents := handlers.AgentsGroup{Handlers: h} + router := gin.Default() docs.SwaggerInfo.BasePath = "/api/v1" docs.SwaggerInfo.Title = "HellreigN" @@ -20,4 +44,17 @@ func main() { docs.SwaggerInfo.Description = "API for HellreigN" docs.SwaggerInfo.Schemes = []string{"http"} router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + + v1 := router.Group("/api/v1") + { + agentsGroup := v1.Group("/agents") + { + agentsGroup.GET("", agents.List) + agentsGroup.GET("/:id", agents.GetByID) + agentsGroup.POST("", agents.Create) + } + + } + + log.Fatal(router.Run(":8080")) } diff --git a/backend/go.mod b/backend/go.mod index 6502ed5..610e4e0 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -11,6 +11,7 @@ require ( github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/cloudwego/base64x v0.1.6 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/gin-contrib/sse v1.1.1 // indirect github.com/gin-gonic/gin v1.12.0 // indirect @@ -30,6 +31,7 @@ require ( github.com/go-playground/validator/v10 v10.30.2 // indirect github.com/goccy/go-json v0.10.6 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect @@ -38,9 +40,11 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/ncruces/go-strftime v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.3.0 // indirect github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.59.0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/swaggo/files v1.0.1 // indirect github.com/swaggo/gin-swagger v1.6.1 // indirect github.com/swaggo/swag v1.16.6 // indirect @@ -59,4 +63,8 @@ require ( google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + modernc.org/libc v1.70.0 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect + modernc.org/sqlite v1.48.1 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index b30e1a5..0e88875 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -21,6 +21,8 @@ github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko= @@ -60,6 +62,8 @@ github.com/goccy/go-json v0.10.6/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PU github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -80,6 +84,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM= github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -87,6 +93,8 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -165,5 +173,13 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +modernc.org/libc v1.70.0 h1:U58NawXqXbgpZ/dcdS9kMshu08aiA6b7gusEusqzNkw= +modernc.org/libc v1.70.0/go.mod h1:OVmxFGP1CI/Z4L3E0Q3Mf1PDE0BucwMkcXjjLntvHJo= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/sqlite v1.48.1 h1:S85iToyU6cgeojybE2XJlSbcsvcWkQ6qqNXJHtW5hWA= +modernc.org/sqlite v1.48.1/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go index d912156..baef47d 100644 --- a/backend/internal/config/config.go +++ b/backend/internal/config/config.go @@ -1 +1,21 @@ package config + +import ( + "fmt" + "gopkg.in/yaml.v3" + "os" +) + +func ImportSettings(path string) (*HellreigN, error) { + data, err := os.ReadFile(path) + if err != nil { + fmt.Println(err) + } + var cfg HellreigN + + if err := yaml.Unmarshal(data, &cfg); err != nil { + return nil, err + } + + return &cfg, nil +} diff --git a/backend/internal/config/types.go b/backend/internal/config/types.go index 809bc99..cb25d0d 100644 --- a/backend/internal/config/types.go +++ b/backend/internal/config/types.go @@ -1,4 +1,13 @@ package config -type Config struct { +type HellreigN struct { + Database Databases `yaml:"database"` } + +type Databases struct { + Token_db string `yaml:"token_db"` + Clickhouse_host string `yaml:"clickhouse_host"` + Clickhouse_user string `yaml:"clickhouse_user"` + Clickhouse_password string `yaml:"clickhouse_password"` +} + diff --git a/backend/internal/handlers/agents.go b/backend/internal/handlers/agents.go index 5ac8282..9bd6f4e 100644 --- a/backend/internal/handlers/agents.go +++ b/backend/internal/handlers/agents.go @@ -1 +1,36 @@ package handlers + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +// AgentsGroup — группа хэндлеров для агентов +type AgentsGroup struct { + *Handlers +} + +// List GET /api/v1/agents +func (ag *AgentsGroup) List(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"message": "Agents list"}) +} + +// GetByID GET /api/v1/agents/:id +func (ag *AgentsGroup) GetByID(c *gin.Context) { + id := c.Param("id") + + c.JSON(http.StatusOK, gin.H{"id": id}) +} + +// Create POST /api/v1/agents +func (ag *AgentsGroup) Create(c *gin.Context) { + var body struct { + Name string `json:"name" binding:"required"` + } + if err := c.ShouldBindJSON(&body); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusCreated, gin.H{"name": body.Name}) +} diff --git a/backend/internal/handlers/handlers.go b/backend/internal/handlers/handlers.go new file mode 100644 index 0000000..465dae2 --- /dev/null +++ b/backend/internal/handlers/handlers.go @@ -0,0 +1,19 @@ +package handlers + +import ( + "database/sql" + + "gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/repository" +) + +type Handlers struct { + DB *sql.DB + Repo *repository.Repository +} + +func New(db *sql.DB) *Handlers { + return &Handlers{ + DB: db, + Repo: repository.New(db), + } +} diff --git a/backend/internal/repository/repository.go b/backend/internal/repository/repository.go new file mode 100644 index 0000000..8af44aa --- /dev/null +++ b/backend/internal/repository/repository.go @@ -0,0 +1,11 @@ +package repository + +import "database/sql" + +type Repository struct { + DB *sql.DB +} + +func New(db *sql.DB) *Repository { + return &Repository{DB: db} +} diff --git a/backend/internal/storage/db.go b/backend/internal/storage/clickhouse.go similarity index 100% rename from backend/internal/storage/db.go rename to backend/internal/storage/clickhouse.go diff --git a/backend/internal/storage/migrations.go b/backend/internal/storage/migrations.go new file mode 100644 index 0000000..f9623ec --- /dev/null +++ b/backend/internal/storage/migrations.go @@ -0,0 +1,3 @@ +package storage + +const CreateSqlite = `` diff --git a/backend/internal/storage/sqlite.go b/backend/internal/storage/sqlite.go new file mode 100644 index 0000000..1b6ac0b --- /dev/null +++ b/backend/internal/storage/sqlite.go @@ -0,0 +1,33 @@ +package storage + +import ( + "database/sql" + "fmt" + _ "modernc.org/sqlite" + "strings" +) + +var pragmas = map[string]string{ + `journal_mode`: `wal`, + `synchronous`: `normal`, + `busy_timeout`: `30000`, +} + +func buildSqliteDsn(path string, pragmas map[string]string) string { + pragmastrs := make([]string, len(pragmas)) + i := 0 + for k, v := range pragmas { + pragmastrs[i] = (fmt.Sprintf(`pragma=%s(%s)`, k, v)) + i++ + } + return path + "?" + "mode=rwc&" + strings.Join(pragmastrs, "&") +} + +func Open(path string) (*sql.DB, error) { + dsn := buildSqliteDsn(path, pragmas) + db, err := sql.Open("sqlite", dsn) + if err != nil { + return nil, err + } + return db, nil +} diff --git a/backend/internal/utils/token_gen.go b/backend/internal/utils/token_gen.go new file mode 100644 index 0000000..a9eeb97 --- /dev/null +++ b/backend/internal/utils/token_gen.go @@ -0,0 +1,14 @@ +package initial + +import ( + "crypto/rand" + "encoding/hex" +) + +func RandomToken() (string, error) { + token := make([]byte, 32) + if _, err := rand.Read(token); err != nil { + return "", err + } + return hex.EncodeToString(token), nil +}