feat(docker): Add Dockerfile and compose file
This commit is contained in:
75
app/config/yaml.go
Normal file
75
app/config/yaml.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/goccy/go-yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type YAMLConfig struct {
|
||||||
|
Server Server `yaml:"server"`
|
||||||
|
Database Database `yaml:"database"`
|
||||||
|
Targets []Target `yaml:"targets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
Port int `yaml:"port" env:"SERVER_PORT"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
Host string `yaml:"host" env:"DB_HOST"`
|
||||||
|
Port string `yaml:"port" env:"DB_PORT"`
|
||||||
|
User string `yaml:"user" env:"DB_USER"`
|
||||||
|
Password string `yaml:"password" env:"DB_PASSWORD"`
|
||||||
|
Database string `yaml:"database" env:"DB_DATABASE"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Target struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Group *string `yaml:"group"`
|
||||||
|
Records []Record `yaml:"records"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Record struct {
|
||||||
|
Record string `yaml:"record"`
|
||||||
|
Endpoints []Endpoint `yaml:"endpoints"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Endpoint struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Path string `yaml:"path"`
|
||||||
|
URL string `yaml:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadYAMLConfig(path string) (*YAMLConfig, error) {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var config YAMLConfig
|
||||||
|
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfig) JSON() string {
|
||||||
|
json, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(json)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfig) Map() *map[string]interface{} {
|
||||||
|
jsonData, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var mapData map[string]interface{}
|
||||||
|
if err := json.Unmarshal(jsonData, &mapData); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &mapData
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package database
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"git.secnex.io/secnex/gogwapi/config"
|
||||||
"git.secnex.io/secnex/gogwapi/utils"
|
"git.secnex.io/secnex/gogwapi/utils"
|
||||||
|
|
||||||
"git.secnex.io/secnex/masterlog"
|
"git.secnex.io/secnex/masterlog"
|
||||||
@@ -30,6 +31,16 @@ func NewDatabaseConfiguration(host, port, user, password, database string) *Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDatabaseConfigurationFromEnvAndConfig(config *config.YAMLConfig) *DatabaseConfiguration {
|
||||||
|
return &DatabaseConfiguration{
|
||||||
|
Host: config.Database.Host,
|
||||||
|
Port: config.Database.Port,
|
||||||
|
User: config.Database.User,
|
||||||
|
Password: config.Database.Password,
|
||||||
|
Database: config.Database.Database,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewDatabaseConfigurationFromEnv() *DatabaseConfiguration {
|
func NewDatabaseConfigurationFromEnv() *DatabaseConfiguration {
|
||||||
return &DatabaseConfiguration{
|
return &DatabaseConfiguration{
|
||||||
Host: utils.GetEnv("DB_HOST", "localhost"),
|
Host: utils.GetEnv("DB_HOST", "localhost"),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ go 1.25.3
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
git.secnex.io/secnex/masterlog v0.1.0
|
git.secnex.io/secnex/masterlog v0.1.0
|
||||||
|
github.com/goccy/go-yaml v1.18.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
golang.org/x/crypto v0.45.0
|
golang.org/x/crypto v0.45.0
|
||||||
gorm.io/driver/postgres v1.6.0
|
gorm.io/driver/postgres v1.6.0
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ git.secnex.io/secnex/masterlog v0.1.0/go.mod h1:OnDlwEzdkKMnqY+G5O9kHdhoJ6fH1llb
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||||
|
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
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/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
|||||||
48
app/main.go
48
app/main.go
@@ -1,30 +1,62 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.secnex.io/secnex/gogwapi/config"
|
||||||
"git.secnex.io/secnex/gogwapi/database"
|
"git.secnex.io/secnex/gogwapi/database"
|
||||||
"git.secnex.io/secnex/gogwapi/models"
|
"git.secnex.io/secnex/gogwapi/models"
|
||||||
|
"git.secnex.io/secnex/gogwapi/proxy"
|
||||||
|
|
||||||
"git.secnex.io/secnex/masterlog"
|
"git.secnex.io/secnex/masterlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
pseudonymizer := masterlog.NewPseudonymizerFromString("1234567890")
|
config, err := config.LoadYAMLConfig("../config.yaml")
|
||||||
// pseudonymizer := masterlog.NewPseudonymizerFromEnv("MASTERLOG_SECRET")
|
if err != nil {
|
||||||
masterlog.SetPseudonymizer(pseudonymizer)
|
masterlog.Error("failed to load config", map[string]interface{}{"error": err.Error()})
|
||||||
masterlog.AddSensitiveFields("user_id", "password", "email")
|
return
|
||||||
masterlog.SetLevel(masterlog.LevelInfo)
|
}
|
||||||
masterlog.AddEncoder(&masterlog.JSONEncoder{})
|
|
||||||
|
targets := config.Targets
|
||||||
|
masterlog.Info("Targets loaded", map[string]interface{}{"count": len(targets)})
|
||||||
|
for _, target := range targets {
|
||||||
|
targetDescription := target.Name
|
||||||
|
if target.Group != nil {
|
||||||
|
targetDescription = fmt.Sprintf("[%s] %s", *target.Group, target.Name)
|
||||||
|
}
|
||||||
|
masterlog.Info(targetDescription, map[string]interface{}{"target": target.Name, "group": *target.Group, "records": len(target.Records)})
|
||||||
|
}
|
||||||
|
|
||||||
allModels := []interface{}{
|
allModels := []interface{}{
|
||||||
&models.Endpoint{},
|
&models.Endpoint{},
|
||||||
}
|
}
|
||||||
|
|
||||||
dbConfig := database.NewDatabaseConfigurationFromEnv()
|
dbConfig := database.NewDatabaseConfigurationFromEnvAndConfig(config)
|
||||||
masterlog.Info("Connecting to database", map[string]interface{}{"host": dbConfig.Host, "port": dbConfig.Port, "database": dbConfig.Database})
|
masterlog.Info("Connecting to database", map[string]interface{}{"host": dbConfig.Host, "port": dbConfig.Port, "database": dbConfig.Database})
|
||||||
if err := dbConfig.Connect(allModels...); err != nil {
|
if err := dbConfig.Connect(allModels...); err != nil {
|
||||||
masterlog.Error("failed to connect to database", map[string]interface{}{"error": err.Error()})
|
masterlog.Error("failed to connect to database", map[string]interface{}{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
masterlog.Info("Connected to database!")
|
masterlog.Info("Connected to database!")
|
||||||
masterlog.Info("Starting server", map[string]interface{}{"port": ":3000"})
|
|
||||||
|
// Initialize reverse proxy
|
||||||
|
reverseProxy := proxy.NewReverseProxy(config)
|
||||||
|
|
||||||
|
// Setup HTTP server
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/", reverseProxy.ServeHTTP)
|
||||||
|
|
||||||
|
// Start server
|
||||||
|
addr := fmt.Sprintf(":%d", config.Server.Port)
|
||||||
|
masterlog.Info("Starting reverse proxy server", map[string]interface{}{
|
||||||
|
"port": config.Server.Port,
|
||||||
|
"address": addr,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := http.ListenAndServe(addr, mux); err != nil {
|
||||||
|
masterlog.Error("server failed to start", map[string]interface{}{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
app/models/domain.go
Normal file
24
app/models/domain.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Domain struct {
|
||||||
|
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||||
|
Name string `gorm:"not null;unique" json:"name"`
|
||||||
|
Verified bool `gorm:"not null;default:false" json:"verified"`
|
||||||
|
VerificationToken string `gorm:"not null;unique" json:"verification_token"`
|
||||||
|
CreatedAt time.Time `gorm:"not null;default:now()" json:"created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"not null;default:now()" json:"updated_at"`
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
||||||
|
|
||||||
|
Records []Record `gorm:"foreignKey:DomainID" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Domain) TableName() string {
|
||||||
|
return "domains"
|
||||||
|
}
|
||||||
@@ -9,10 +9,15 @@ import (
|
|||||||
|
|
||||||
type Endpoint struct {
|
type Endpoint struct {
|
||||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||||
URL string `gorm:"not null" json:"url"`
|
Path string `gorm:"not null;default:/" json:"path"`
|
||||||
|
RecordID uuid.UUID `gorm:"not null;uniqueIndex:idx_endpoint_record_id" json:"record_id"`
|
||||||
CreatedAt time.Time `gorm:"not null;default:now()" json:"created_at"`
|
CreatedAt time.Time `gorm:"not null;default:now()" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"not null;default:now()" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"not null;default:now()" json:"updated_at"`
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
||||||
|
|
||||||
|
Record Record `gorm:"foreignKey:RecordID" json:"-"`
|
||||||
|
|
||||||
|
EndpointGroups []EndpointGroup `gorm:"foreignKey:EndpointID" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Endpoint) TableName() string {
|
func (Endpoint) TableName() string {
|
||||||
|
|||||||
24
app/models/endpoint_group.go
Normal file
24
app/models/endpoint_group.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EndpointGroup struct {
|
||||||
|
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||||
|
GroupID uuid.UUID `gorm:"not null;uniqueIndex:idx_endpoint_group_group_id_endpoint_id" json:"group_id"`
|
||||||
|
EndpointID uuid.UUID `gorm:"not null;uniqueIndex:idx_endpoint_group_group_id_endpoint_id" json:"endpoint_id"`
|
||||||
|
CreatedAt time.Time `gorm:"not null;default:now()" json:"created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"not null;default:now()" json:"updated_at"`
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
||||||
|
|
||||||
|
Group Group `gorm:"foreignKey:GroupID" json:"-"`
|
||||||
|
Endpoint Endpoint `gorm:"foreignKey:EndpointID" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (EndpointGroup) TableName() string {
|
||||||
|
return "endpoint_groups"
|
||||||
|
}
|
||||||
23
app/models/group.go
Normal file
23
app/models/group.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Group struct {
|
||||||
|
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||||
|
Name string `gorm:"not null;unique" json:"name"`
|
||||||
|
Description *string `json:"description"`
|
||||||
|
CreatedAt time.Time `gorm:"not null;default:now()" json:"created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"not null;default:now()" json:"updated_at"`
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
||||||
|
|
||||||
|
EndpointGroups []EndpointGroup `gorm:"foreignKey:GroupID" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Group) TableName() string {
|
||||||
|
return "groups"
|
||||||
|
}
|
||||||
25
app/models/record.go
Normal file
25
app/models/record.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Record struct {
|
||||||
|
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||||
|
Record string `gorm:"not null;uniqueIndex:idx_record_domain_id" json:"record"`
|
||||||
|
DomainID uuid.UUID `gorm:"not null;uniqueIndex:idx_record_domain_id" json:"domain_id"`
|
||||||
|
CreatedAt time.Time `gorm:"not null;default:now()" json:"created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"not null;default:now()" json:"updated_at"`
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
|
||||||
|
|
||||||
|
Domain Domain `gorm:"foreignKey:DomainID" json:"-"`
|
||||||
|
|
||||||
|
Endpoints []Endpoint `gorm:"foreignKey:RecordID" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Record) TableName() string {
|
||||||
|
return "records"
|
||||||
|
}
|
||||||
104
app/proxy/reverse.go
Normal file
104
app/proxy/reverse.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.secnex.io/secnex/gogwapi/config"
|
||||||
|
"git.secnex.io/secnex/masterlog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReverseProxy struct {
|
||||||
|
config *config.YAMLConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReverseProxy(cfg *config.YAMLConfig) *ReverseProxy {
|
||||||
|
return &ReverseProxy{
|
||||||
|
config: cfg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TargetMatch struct {
|
||||||
|
URL *url.URL
|
||||||
|
Endpoint *config.Endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rp *ReverseProxy) findTarget(host string, path string) (*TargetMatch, error) {
|
||||||
|
for _, target := range rp.config.Targets {
|
||||||
|
for _, record := range target.Records {
|
||||||
|
expectedHost := fmt.Sprintf("%s.%s", record.Record, target.Name)
|
||||||
|
if host == expectedHost {
|
||||||
|
for _, endpoint := range record.Endpoints {
|
||||||
|
if endpoint.Path == "/" {
|
||||||
|
targetURL, err := url.Parse(endpoint.URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &TargetMatch{URL: targetURL, Endpoint: &endpoint}, nil
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(path, endpoint.Path) {
|
||||||
|
targetURL, err := url.Parse(endpoint.URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &TargetMatch{URL: targetURL, Endpoint: &endpoint}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no target found for host: %s, path: %s", host, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rp *ReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
host := r.Host
|
||||||
|
path := r.URL.Path
|
||||||
|
|
||||||
|
targetMatch, err := rp.findTarget(host, path)
|
||||||
|
if err != nil {
|
||||||
|
masterlog.Error("target not found", map[string]interface{}{
|
||||||
|
"host": host,
|
||||||
|
"path": path,
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
http.Error(w, "Service not found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
targetURL := targetMatch.URL
|
||||||
|
endpoint := targetMatch.Endpoint
|
||||||
|
|
||||||
|
// Transform the path: remove the endpoint prefix if it's not "/"
|
||||||
|
var transformedPath string
|
||||||
|
if endpoint.Path == "/" {
|
||||||
|
transformedPath = path
|
||||||
|
} else {
|
||||||
|
transformedPath = strings.TrimPrefix(path, endpoint.Path)
|
||||||
|
if transformedPath == "" {
|
||||||
|
transformedPath = "/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
masterlog.Info("proxying request", map[string]interface{}{
|
||||||
|
"host": host,
|
||||||
|
"original_path": path,
|
||||||
|
"transformed_path": transformedPath,
|
||||||
|
"endpoint_prefix": endpoint.Path,
|
||||||
|
"target": targetURL.String(),
|
||||||
|
})
|
||||||
|
|
||||||
|
proxy := httputil.NewSingleHostReverseProxy(targetURL)
|
||||||
|
|
||||||
|
// Create a new request with the transformed path
|
||||||
|
r.URL.Host = targetURL.Host
|
||||||
|
r.URL.Scheme = targetURL.Scheme
|
||||||
|
r.URL.Path = transformedPath
|
||||||
|
r.Header.Set("X-Forwarded-Host", host)
|
||||||
|
r.Header.Set("X-Forwarded-For", r.RemoteAddr)
|
||||||
|
r.Header.Set("X-Forwarded-Path", path) // Original path for debugging
|
||||||
|
|
||||||
|
proxy.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
41
app/repositories/domain.go
Normal file
41
app/repositories/domain.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package repositories
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.secnex.io/secnex/gogwapi/models"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DomainRepository interface {
|
||||||
|
Create(domain *models.Domain) error
|
||||||
|
Get(id string) (*models.Domain, error)
|
||||||
|
Update(domain *models.Domain) error
|
||||||
|
Delete(id string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type domainRepository struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDomainRepository(db *gorm.DB) DomainRepository {
|
||||||
|
return &domainRepository{db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *domainRepository) Create(domain *models.Domain) error {
|
||||||
|
return r.db.Create(domain).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *domainRepository) Get(name string) (*models.Domain, error) {
|
||||||
|
var domain models.Domain
|
||||||
|
if err := r.db.Where("name = ?", name).First(&domain).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &domain, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *domainRepository) Update(domain *models.Domain) error {
|
||||||
|
return r.db.Save(domain).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *domainRepository) Delete(id string) error {
|
||||||
|
return r.db.Delete(&models.Domain{}, id).Error
|
||||||
|
}
|
||||||
5
app/schema/domain.go
Normal file
5
app/schema/domain.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
type DomainSchema struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user