Initial
This commit is contained in:
106
app/lib/cfg/cfg.go
Normal file
106
app/lib/cfg/cfg.go
Normal file
@ -0,0 +1,106 @@
|
||||
package cfg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type ServiceConfig struct {
|
||||
Address string `yaml:"address"`
|
||||
Port int `yaml:"port"`
|
||||
}
|
||||
|
||||
type DatabaseConfig struct {
|
||||
Host string `yaml:"host"`
|
||||
Port string `yaml:"port"`
|
||||
Name string `yaml:"name"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password" json:"-"`
|
||||
DebugSQL bool `yaml:"debugSQL"`
|
||||
}
|
||||
|
||||
type ApplicationConfig struct {
|
||||
LogLevel string `yaml:"logLevel"`
|
||||
LogFile string `yaml:"logFile"`
|
||||
Debug bool `yaml:"debug"`
|
||||
DebugPrint bool `yaml:"debugPrint"`
|
||||
DisableSendMail bool `yaml:"disableSendMail"`
|
||||
IsProduction bool `yaml:"isProduction"`
|
||||
MetricsPrefix string `yaml:"metricsPrefix"`
|
||||
}
|
||||
|
||||
type S3StorageConfig struct {
|
||||
AccessKey string `yaml:"accessKey"`
|
||||
SecretKey string `yaml:"secretKey"`
|
||||
RegionName string `yaml:"regionName"`
|
||||
EndpointUrl string `yaml:"endpointUrl"`
|
||||
BucketName string `yaml:"bucketName"`
|
||||
CertPath string `yaml:"certPath"`
|
||||
}
|
||||
|
||||
type CertConfig struct {
|
||||
FinaDemoCaCert string `yaml:"finaDemoCaCert"`
|
||||
FinaProdCaCert string `yaml:"finaProdCaCert"`
|
||||
DemoCertOib string `yaml:"demoCertOib"`
|
||||
}
|
||||
|
||||
type configStruct struct {
|
||||
Service ServiceConfig `yaml:"service"`
|
||||
Database DatabaseConfig `yaml:"database"`
|
||||
Application ApplicationConfig `yaml:"application"`
|
||||
S3Storage S3StorageConfig `yaml:"s3storage"`
|
||||
Cert CertConfig `yaml:"cert"`
|
||||
}
|
||||
|
||||
const ENV_PREFIX = "FISKALATOR"
|
||||
const ENV_CONFIG = ENV_PREFIX + "_CONFIG"
|
||||
const DEFAULT_CONFIG_FILE = "config.yaml"
|
||||
|
||||
var Config configStruct
|
||||
|
||||
func panicWithError(err error) {
|
||||
panic("Config file error: " + err.Error())
|
||||
}
|
||||
|
||||
func readFile(cfgFile string, cfg *configStruct) {
|
||||
f, err := os.Open(cfgFile)
|
||||
if err != nil {
|
||||
panicWithError(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
decoder := yaml.NewDecoder(f)
|
||||
err = decoder.Decode(cfg)
|
||||
if err != nil {
|
||||
panicWithError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func readEnv(cfg *configStruct) {
|
||||
err := envconfig.Process(ENV_PREFIX, cfg)
|
||||
if err != nil {
|
||||
panicWithError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Init() {
|
||||
cfgFile := os.Getenv(ENV_CONFIG)
|
||||
if cfgFile == "" {
|
||||
cfgFile = DEFAULT_CONFIG_FILE
|
||||
}
|
||||
|
||||
readFile(cfgFile, &Config)
|
||||
readEnv(&Config)
|
||||
|
||||
maskedCfg := Config
|
||||
maskedCfg.Database.Password = "**password hidden**"
|
||||
maskedCfg.S3Storage.AccessKey = "**access key hidden**"
|
||||
maskedCfg.S3Storage.SecretKey = "**secret key hidden**"
|
||||
|
||||
fmt.Println("--- CONFIG -------------------------------")
|
||||
fmt.Printf("%+v\n", maskedCfg)
|
||||
fmt.Println("------------------------------------------")
|
||||
}
|
||||
65
app/lib/db/db.go
Normal file
65
app/lib/db/db.go
Normal file
@ -0,0 +1,65 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"repo-pattern/app/lib/cfg"
|
||||
"repo-pattern/app/lib/logging"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
gormLogger "gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
const CONNECTION_MAX_IDLE_TIME = time.Minute * 1
|
||||
const DB_CONNECTION_TIMEOUT = 5
|
||||
|
||||
var DBConn *gorm.DB
|
||||
|
||||
func ConnectToDb(config *cfg.DatabaseConfig) (*gorm.DB, error) {
|
||||
var connectionString = strings.Join([]string{
|
||||
"postgres://",
|
||||
config.Username, ":",
|
||||
config.Password, "@",
|
||||
config.Host, ":",
|
||||
config.Port, "/",
|
||||
config.Name,
|
||||
"?sslmode=disable",
|
||||
"&TimeZone=UTC",
|
||||
"&connect_timeout=", strconv.Itoa(DB_CONNECTION_TIMEOUT),
|
||||
}, "")
|
||||
|
||||
var logLevel gormLogger.LogLevel
|
||||
if config.DebugSQL {
|
||||
logLevel = gormLogger.Info
|
||||
} else {
|
||||
logLevel = gormLogger.Silent
|
||||
}
|
||||
|
||||
conn, err := gorm.Open(postgres.Open(connectionString), &gorm.Config{
|
||||
Logger: gormLogger.Default.LogMode(logLevel),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func InitDB() *gorm.DB {
|
||||
var err error
|
||||
DBConn, err = ConnectToDb(&cfg.Config.Database)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("Error connecting to database: %s. Terminating!", err)
|
||||
logging.Log.Error(msg)
|
||||
panic(msg)
|
||||
}
|
||||
|
||||
// set connection autodisconnect after idle time
|
||||
db, _ := DBConn.DB()
|
||||
db.SetConnMaxIdleTime(CONNECTION_MAX_IDLE_TIME)
|
||||
|
||||
return DBConn
|
||||
}
|
||||
39
app/lib/helpers/factory.go
Normal file
39
app/lib/helpers/factory.go
Normal file
@ -0,0 +1,39 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Factory struct {
|
||||
dbConn *gorm.DB
|
||||
}
|
||||
|
||||
func NewFactory(dbConn *gorm.DB) *Factory {
|
||||
return &Factory{
|
||||
dbConn: dbConn,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Factory) CreateModel(model interface{}) {
|
||||
if f.dbConn == nil {
|
||||
panic("Factory created without db connection. Unable to create model.")
|
||||
}
|
||||
f.dbConn.Create(model)
|
||||
}
|
||||
|
||||
func MergeValuesToModel(model interface{}, values map[string]any) {
|
||||
st := reflect.ValueOf(model).Elem()
|
||||
|
||||
for key, value := range values {
|
||||
field := st.FieldByName(key)
|
||||
var v reflect.Value
|
||||
if value != nil {
|
||||
v = reflect.ValueOf(value)
|
||||
} else {
|
||||
v = reflect.Zero(field.Type())
|
||||
}
|
||||
field.Set(v)
|
||||
}
|
||||
}
|
||||
27
app/lib/helpers/util.go
Normal file
27
app/lib/helpers/util.go
Normal file
@ -0,0 +1,27 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
func UTCNow() time.Time {
|
||||
utc, _ := time.LoadLocation("UTC")
|
||||
return time.Now().In(utc)
|
||||
}
|
||||
|
||||
// UNUSED allows unused variables to be included in Go programs
|
||||
func UNUSED(x ...interface{}) {}
|
||||
|
||||
func StructToMap(data interface{}) (map[string]interface{}, error) {
|
||||
dataBytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapData := make(map[string]interface{})
|
||||
err = json.Unmarshal(dataBytes, &mapData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mapData, nil
|
||||
}
|
||||
70
app/lib/helpers/util_test.go
Normal file
70
app/lib/helpers/util_test.go
Normal file
@ -0,0 +1,70 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_StructToMap(t *testing.T) {
|
||||
t.Run("Convert simple struct to map", func(t *testing.T) {
|
||||
type User struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age"`
|
||||
Height float32 `json:"height"`
|
||||
}
|
||||
|
||||
user := &User{
|
||||
Name: "Pero",
|
||||
Age: 66,
|
||||
Height: 187.6,
|
||||
}
|
||||
result, _ := StructToMap(user)
|
||||
|
||||
expected := make(map[string]interface{})
|
||||
expected["name"] = "Pero"
|
||||
expected["age"] = 66
|
||||
expected["height"] = 187.6
|
||||
|
||||
assert.Equal(t, fmt.Sprintf("%v", result), fmt.Sprintf("%v", expected))
|
||||
})
|
||||
|
||||
t.Run("Convert nested struct to map", func(t *testing.T) {
|
||||
type Address struct {
|
||||
City string `json:"city"`
|
||||
PostalCode int `json:"postalCode"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string `json:"name"`
|
||||
Age int `json:"age"`
|
||||
Height float32 `json:"height"`
|
||||
Address Address `json:"address"`
|
||||
}
|
||||
|
||||
user := &User{
|
||||
Name: "Pero",
|
||||
Age: 66,
|
||||
Height: 187.6,
|
||||
Address: Address{
|
||||
City: "Zagreb",
|
||||
PostalCode: 10020,
|
||||
},
|
||||
}
|
||||
result, _ := StructToMap(user)
|
||||
|
||||
address := make(map[string]interface{})
|
||||
address["city"] = "Zagreb"
|
||||
address["postalCode"] = 10020
|
||||
|
||||
expected := make(map[string]interface{})
|
||||
expected["name"] = "Pero"
|
||||
expected["age"] = 66
|
||||
expected["height"] = 187.6
|
||||
expected["address"] = make(map[string]interface{})
|
||||
expected["address"] = address
|
||||
|
||||
assert.Equal(t, fmt.Sprintf("%v", result), fmt.Sprintf("%v", expected))
|
||||
})
|
||||
}
|
||||
65
app/lib/logging/logging.go
Normal file
65
app/lib/logging/logging.go
Normal file
@ -0,0 +1,65 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"repo-pattern/app/lib/cfg"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var Log *zap.Logger = nil
|
||||
|
||||
func Init() {
|
||||
var err error
|
||||
|
||||
logConfig := zap.NewProductionConfig()
|
||||
logConfig.Level, err = zap.ParseAtomicLevel(cfg.Config.Application.LogLevel)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logConfig.OutputPaths = []string{
|
||||
cfg.Config.Application.LogFile,
|
||||
"stderr",
|
||||
}
|
||||
|
||||
Log, err = logConfig.Build()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
/*
|
||||
logLevel, err := logrus.ParseLevel(cfg.Config.Application.LogLevel)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Invalid configured logLevel: %s\n", cfg.Config.Application.LogLevel))
|
||||
}
|
||||
|
||||
Log.SetLevel(logLevel)
|
||||
|
||||
Log.SetFormatter(&logrus.TextFormatter{
|
||||
FullTimestamp: true,
|
||||
TimestampFormat: "2006-01-02 15:04:05",
|
||||
PadLevelText: true,
|
||||
DisableQuote: true,
|
||||
})
|
||||
|
||||
LogFile := cfg.Config.Application.LogFile
|
||||
file, err := os.OpenFile(
|
||||
LogFile,
|
||||
os.O_CREATE|os.O_WRONLY|os.O_APPEND,
|
||||
0655,
|
||||
)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("Failed to log to file %s: %s", cfg.Config.Application.LogFile, err)
|
||||
Log.Warning(msg)
|
||||
panic(msg)
|
||||
}
|
||||
|
||||
mw := io.MultiWriter(os.Stdout, file)
|
||||
Log.SetOutput(mw)
|
||||
|
||||
configJson, err := json.Marshal(cfg.Config)
|
||||
if err == nil {
|
||||
Info(fmt.Sprintf("Using config: %s", configJson))
|
||||
}
|
||||
*/
|
||||
}
|
||||
20
app/main.go
Normal file
20
app/main.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"repo-pattern/app/lib/cfg"
|
||||
"repo-pattern/app/lib/db"
|
||||
"repo-pattern/app/lib/logging"
|
||||
"repo-pattern/app/repository"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg.Init()
|
||||
logging.Init()
|
||||
defer logging.Log.Sync()
|
||||
|
||||
db := db.InitDB()
|
||||
repository.Dao = repository.CreateDAO(db)
|
||||
|
||||
fmt.Println("Running...")
|
||||
}
|
||||
23
app/models/api_key.go
Normal file
23
app/models/api_key.go
Normal file
@ -0,0 +1,23 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ApiKey struct {
|
||||
Key uuid.UUID `gorm:"type(uuid);unique;default:uuid_generate_v4()"`
|
||||
CompanyId uuid.UUID `gorm:"type(uuid)" faker:"-"`
|
||||
ActiveFrom *time.Time `faker:"-"`
|
||||
ActiveTo *time.Time `faker:"-"`
|
||||
LastUsed *time.Time
|
||||
CreatedAt time.Time `faker:"-"`
|
||||
UpdatedAt time.Time `faker:"-"`
|
||||
|
||||
Company Company `faker:"-"`
|
||||
}
|
||||
|
||||
func (m *ApiKey) TableName() string {
|
||||
return "api_keys"
|
||||
}
|
||||
28
app/models/cert.go
Normal file
28
app/models/cert.go
Normal file
@ -0,0 +1,28 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Cert struct {
|
||||
Id uuid.UUID `gorm:"type(uuid);unique;default:uuid_generate_v4()"`
|
||||
CompanyId uuid.UUID `gorm:"type(uuid)" faker:"-"`
|
||||
Company Company `faker:"-"`
|
||||
Alive bool `faker:"-"`
|
||||
SerialNumber string
|
||||
Issuer string
|
||||
Subject string
|
||||
ValidAfter time.Time `faker:"-"`
|
||||
ValidBefore time.Time `faker:"-"`
|
||||
CertFile string
|
||||
KeyFile string
|
||||
KeyPassword string
|
||||
CreatedAt time.Time `faker:"-"`
|
||||
UpdatedAt time.Time `faker:"-"`
|
||||
}
|
||||
|
||||
func (m *Cert) TableName() string {
|
||||
return "certificates"
|
||||
}
|
||||
30
app/models/company.go
Normal file
30
app/models/company.go
Normal file
@ -0,0 +1,30 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/mozillazg/go-slugify"
|
||||
)
|
||||
|
||||
type Company struct {
|
||||
Id uuid.UUID `gorm:"type(uuid);unique;default:uuid_generate_v4()"`
|
||||
CertificateId *uuid.UUID `gorm:"type(uuid)" faker:"-"`
|
||||
Name string `faker:"name"`
|
||||
Address string
|
||||
City string
|
||||
Email string `faker:"email"`
|
||||
Oib string `faker:"-"`
|
||||
TaxSystem bool
|
||||
IsActive bool `faker:"-"`
|
||||
CreatedAt time.Time `faker:"-"`
|
||||
UpdatedAt time.Time `faker:"-"`
|
||||
}
|
||||
|
||||
func (m *Company) TableName() string {
|
||||
return "companies"
|
||||
}
|
||||
|
||||
func (m *Company) SlugifyName() string {
|
||||
return slugify.Slugify(m.Name)
|
||||
}
|
||||
27
app/models/fisk_log_item.go
Normal file
27
app/models/fisk_log_item.go
Normal file
@ -0,0 +1,27 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
type FiskLogItem struct {
|
||||
Id uuid.UUID `gorm:"type(uuid);unique"`
|
||||
ApiKeyId uuid.UUID `gorm:"type(uuid)"`
|
||||
CompanyId uuid.UUID `gorm:"type(uuid)"`
|
||||
IsDemo bool
|
||||
RequestData datatypes.JSONMap `gorm:"type:jsonb;not null"`
|
||||
ResponseData *datatypes.JSONMap `gorm:"type:jsonb"`
|
||||
IznosUkupno int
|
||||
Zki *string
|
||||
Jir *uuid.UUID `gorm:"type(uuid)"`
|
||||
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (m *FiskLogItem) TableName() string {
|
||||
return "fisk_log"
|
||||
}
|
||||
89
app/repository/api_keys.go
Normal file
89
app/repository/api_keys.go
Normal file
@ -0,0 +1,89 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"repo-pattern/app/lib/helpers"
|
||||
"repo-pattern/app/models"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ApiKeysRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
type ApiKeysFilter struct {
|
||||
Key *uuid.UUID
|
||||
CompanyId *uuid.UUID
|
||||
IsActive *bool
|
||||
CompanyIsActive *bool
|
||||
}
|
||||
|
||||
func CreateApiKeysRepository(db *gorm.DB) *ApiKeysRepository {
|
||||
return &ApiKeysRepository{db}
|
||||
}
|
||||
|
||||
func applyApiKeyFilter(db *gorm.DB, query *gorm.DB, filter *ApiKeysFilter) *gorm.DB {
|
||||
if filter.Key != nil {
|
||||
query.Where("key = ?", *filter.Key)
|
||||
}
|
||||
if filter.IsActive != nil {
|
||||
now := helpers.UTCNow()
|
||||
if *filter.IsActive {
|
||||
query.Where("active_from IS NULL OR active_from <= ?", now)
|
||||
query.Where("active_to IS NULL OR active_to >= ?", now)
|
||||
} else {
|
||||
query.Where(
|
||||
"active_from IS NOT NULL AND active_from >= ?", now,
|
||||
).Or(
|
||||
"active_to IS NOT NULL AND active_to =< ?", now,
|
||||
)
|
||||
}
|
||||
}
|
||||
if filter.CompanyId != nil {
|
||||
query.Where("company_id = ?", *filter.CompanyId)
|
||||
}
|
||||
if filter.CompanyIsActive != nil {
|
||||
query.Joins("Company").Where(
|
||||
map[string]interface{}{"Company.is_active": *filter.CompanyIsActive},
|
||||
)
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
func (r *ApiKeysRepository) New(companyId uuid.UUID) *models.ApiKey {
|
||||
now := helpers.UTCNow()
|
||||
return &models.ApiKey{
|
||||
CompanyId: companyId,
|
||||
ActiveFrom: &now,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ApiKeysRepository) Get(filter *ApiKeysFilter) *models.ApiKey {
|
||||
var api_key models.ApiKey
|
||||
|
||||
query := r.db.Model(&models.ApiKey{})
|
||||
applyApiKeyFilter(r.db, query, filter)
|
||||
|
||||
result := query.First(&api_key).Joins("Company")
|
||||
if result.Error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &api_key
|
||||
}
|
||||
|
||||
func (r *ApiKeysRepository) Save(model *models.ApiKey) {
|
||||
model.UpdatedAt = helpers.UTCNow()
|
||||
|
||||
// we don't have standard model Id, but Key as primary key.
|
||||
// this could be possible reason for save not assigning generated key uuid
|
||||
// to model.Key. but this works.
|
||||
if model.Key == uuid.Nil {
|
||||
r.db.Create(model)
|
||||
} else {
|
||||
r.db.Save(model)
|
||||
}
|
||||
}
|
||||
101
app/repository/certs.go
Normal file
101
app/repository/certs.go
Normal file
@ -0,0 +1,101 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"repo-pattern/app/lib/helpers"
|
||||
"repo-pattern/app/models"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CertRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
type CertFilter struct {
|
||||
Alive *bool
|
||||
Id *uuid.UUID
|
||||
CompanyId *uuid.UUID
|
||||
CompanyIsActive *bool
|
||||
}
|
||||
|
||||
func CreateCertRepository(db *gorm.DB) *CertRepository {
|
||||
return &CertRepository{db}
|
||||
}
|
||||
|
||||
func applyCertFilter(db *gorm.DB, query *gorm.DB, filter *CertFilter) *gorm.DB {
|
||||
if filter.Id != nil {
|
||||
query.Where("certificates.id = ?", *filter.Id)
|
||||
}
|
||||
if filter.Alive == nil {
|
||||
query.Where("certificates.alive = TRUE")
|
||||
} else {
|
||||
query.Where("certificates.alive = ?", *filter.Alive)
|
||||
}
|
||||
if filter.CompanyId != nil {
|
||||
query.Where("certificates.company_id = ?", *filter.CompanyId)
|
||||
}
|
||||
if filter.CompanyIsActive != nil {
|
||||
query.Joins("LEFT JOIN companies on companies.is_active = TRUE")
|
||||
// query.Joins("Company").Where(
|
||||
// map[string]interface{}{"Company.is_active": *filter.CompanyIsActive},
|
||||
// )
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
func (r *CertRepository) New(companyId uuid.UUID) *models.Cert {
|
||||
now := helpers.UTCNow()
|
||||
return &models.Cert{
|
||||
Alive: true,
|
||||
CompanyId: companyId,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *CertRepository) Get(filter *CertFilter) *models.Cert {
|
||||
var cert models.Cert
|
||||
|
||||
query := r.db.Model(&models.Cert{})
|
||||
applyCertFilter(r.db, query, filter)
|
||||
|
||||
result := query.First(&cert).Joins("Company")
|
||||
if result.Error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &cert
|
||||
}
|
||||
|
||||
func (r *CertRepository) GetForCompany(companyId uuid.UUID) *models.Cert {
|
||||
isAlive := true
|
||||
filter := CertFilter{
|
||||
Alive: &isAlive,
|
||||
CompanyId: &companyId,
|
||||
}
|
||||
return r.Get(&filter)
|
||||
}
|
||||
|
||||
func (r *CertRepository) Save(model *models.Cert) {
|
||||
model.UpdatedAt = helpers.UTCNow()
|
||||
r.db.Save(model)
|
||||
}
|
||||
|
||||
func (r *CertRepository) Exists(filter *CertFilter) bool {
|
||||
var row models.Cert
|
||||
|
||||
query := r.db.Model(&models.Cert{})
|
||||
query = applyCertFilter(r.db, query, filter)
|
||||
result := query.Select("certificates.id").First(&row)
|
||||
|
||||
return !errors.Is(result.Error, gorm.ErrRecordNotFound) && result.Error == nil
|
||||
}
|
||||
|
||||
func (r *CertRepository) Delete(filter *CertFilter) {
|
||||
query := r.db.Model(&models.Cert{})
|
||||
applyCertFilter(r.db, query, filter)
|
||||
|
||||
query.Update("alive", false).Joins("Company")
|
||||
}
|
||||
57
app/repository/companies.go
Normal file
57
app/repository/companies.go
Normal file
@ -0,0 +1,57 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"repo-pattern/app/lib/helpers"
|
||||
"repo-pattern/app/models"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type CompanyRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
type CompanyFilter struct {
|
||||
Id *uuid.UUID
|
||||
}
|
||||
|
||||
func CreateCompanyRepository(db *gorm.DB) *CompanyRepository {
|
||||
return &CompanyRepository{db}
|
||||
}
|
||||
|
||||
func applyCompanyFilter(db *gorm.DB, query *gorm.DB, filter *CompanyFilter) *gorm.DB {
|
||||
if filter.Id != nil {
|
||||
query.Where("id = ?", *filter.Id)
|
||||
}
|
||||
query.Where("is_active = ?", true)
|
||||
return query
|
||||
}
|
||||
|
||||
func (r *CompanyRepository) New() *models.Company {
|
||||
now := helpers.UTCNow()
|
||||
return &models.Company{
|
||||
IsActive: true,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *CompanyRepository) Get(filter *CompanyFilter) *models.Company {
|
||||
var company models.Company
|
||||
|
||||
query := r.db.Model(&models.Company{})
|
||||
applyCompanyFilter(r.db, query, filter)
|
||||
|
||||
result := query.First(&company)
|
||||
if result.Error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &company
|
||||
}
|
||||
|
||||
func (r *CompanyRepository) Save(model *models.Company) {
|
||||
model.UpdatedAt = helpers.UTCNow()
|
||||
r.db.Save(model)
|
||||
}
|
||||
23
app/repository/dao.go
Normal file
23
app/repository/dao.go
Normal file
@ -0,0 +1,23 @@
|
||||
package repository
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type DAO struct {
|
||||
db *gorm.DB
|
||||
ApiKeysRepository *ApiKeysRepository
|
||||
CertRepository *CertRepository
|
||||
CompanyRepository *CompanyRepository
|
||||
FiskLogRepository *FiskLogRepository
|
||||
}
|
||||
|
||||
var Dao DAO
|
||||
|
||||
func CreateDAO(db *gorm.DB) DAO {
|
||||
return DAO{
|
||||
db: db,
|
||||
ApiKeysRepository: CreateApiKeysRepository(db),
|
||||
CertRepository: CreateCertRepository(db),
|
||||
CompanyRepository: CreateCompanyRepository(db),
|
||||
FiskLogRepository: CreateFiskLogRepository(db),
|
||||
}
|
||||
}
|
||||
29
app/repository/fisk_log.go
Normal file
29
app/repository/fisk_log.go
Normal file
@ -0,0 +1,29 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"repo-pattern/app/lib/helpers"
|
||||
"repo-pattern/app/models"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type FiskLogRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func CreateFiskLogRepository(db *gorm.DB) *FiskLogRepository {
|
||||
return &FiskLogRepository{db}
|
||||
}
|
||||
|
||||
func (r *FiskLogRepository) New(model models.FiskLogItem) *models.FiskLogItem {
|
||||
now := helpers.UTCNow()
|
||||
model.CreatedAt = now
|
||||
model.UpdatedAt = now
|
||||
return &model
|
||||
}
|
||||
|
||||
func (r *FiskLogRepository) Save(model *models.FiskLogItem) error {
|
||||
model.UpdatedAt = helpers.UTCNow()
|
||||
result := r.db.Save(model)
|
||||
return result.Error
|
||||
}
|
||||
Reference in New Issue
Block a user