first commit

This commit is contained in:
kandrusyak
2023-07-14 14:54:41 +03:00
commit 7b03922374
29 changed files with 839 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.idea
build
.env

4
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,4 @@
include:
- project: 'astra/microservice-ci'
ref: main
file: '/templates/microservice.yaml'

24
Dockerfile Normal file
View File

@@ -0,0 +1,24 @@
FROM kandrusyak/go-build as build
LABEL authors="andrusyakka@dopcore.com"
WORKDIR /app
ENV CGO_ENABLED 1
COPY go.mod ./
RUN go mod download
COPY . ./
RUN go build -o ./app
FROM alpine:edge
WORKDIR /
COPY --from=build /app /app
EXPOSE 8080
CMD ["/app/app"]

41
config/config.go Normal file
View File

@@ -0,0 +1,41 @@
package config
import (
"os"
)
type ServerConfig struct {
Port string
ConnectionString string
}
type MSHosts struct {
UsersHost string
}
type Config struct {
Server ServerConfig
MSHosts MSHosts
}
func New() *Config {
return &Config{
Server: ServerConfig{
Port: getEnv("PORT", "8080"),
ConnectionString: getEnv("CONNECTION_STRING", "test.db"),
},
MSHosts: MSHosts{
UsersHost: getEnv("ASTRA-USERS", "http://localhost:8082"),
},
}
}
func getEnv(key string, defaultVal string) string {
if value, exists := os.LookupEnv(key); exists {
return value
}
return defaultVal
}
var Env = New()

23
deploy/.helmignore Normal file
View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

24
deploy/Chart.yaml Normal file
View File

@@ -0,0 +1,24 @@
apiVersion: v2
name: astra-users
appVersion: latest
description: A Helm chart to deploy app - astra
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
engine: gotpl
maintainers:
- name: DOP

View File

@@ -0,0 +1 @@
192.168.1.112:8888

View File

@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "astra-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "astra-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "astra-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "astra-frontend.labels" -}}
helm.sh/chart: {{ include "astra-frontend.chart" . }}
{{ include "astra-frontend.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "astra-frontend.selectorLabels" -}}
app.kubernetes.io/name: {{ include "astra-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "astra-frontend.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "astra-frontend.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.app.fullName }}
spec:
replicas: {{ .Values.replicas }}
revisionHistoryLimit: 10
selector:
matchLabels:
app: {{ .Values.app.fullName }}
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: {{ .Values.app.fullName }}
spec:
imagePullSecrets:
- name: {{ .Values.images.pullSecret }}
containers:
- name: {{ .Values.app.fullName }}
env:
- name: TZ
value: Europe/Moscow
- name: PORT
value: {{ .Values.app.server.port | quote }}
- name: CONNECTION_STRING
value: /app/test.db
{{- .Values.envs | toYaml | nindent 12 }}
image: {{ .Values.app.image }}:{{ .Chart.AppVersion }}
imagePullPolicy: Always
ports:
- name: http
containerPort: {{ .Values.app.server.port }}
protocol: TCP

28
deploy/templates/hpa.yaml Normal file
View File

@@ -0,0 +1,28 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include ".Values.app.fullName" . }}
labels:
app: {{ include ".Values.app.fullName" . }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include ".Values.app.fullName" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,61 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include ".Values.app.fullName" . -}}
{{- $svcPort := .Values.app.server.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
app: {{ $fullName }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.app.fullName }}
namespace: default
spec:
ports:
- port: {{ .Values.app.server.port }}
protocol: TCP
targetPort: {{ .Values.app.server.port }}
selector:
app: {{ .Values.app.fullName }}
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}

View File

@@ -0,0 +1,16 @@
app:
fullName: ${CI_PROJECT_TITLE}
image: docker-registry.dopcore.com/${CI_PROJECT_PATH}
server:
port: ${SERVICE_PORT}
replicas: ${SERVICE_REPLICAS}
images:
pullSecret: regcred
ingress:
enabled: false
autoscaling:
enabled: false

23
go.mod Normal file
View File

@@ -0,0 +1,23 @@
module astra-events
go 1.21rc1
require (
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/labstack/echo/v4 v4.10.2 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-sqlite3 v1.14.17 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.3.0 // indirect
gorm.io/driver/sqlite v1.5.2 // indirect
gorm.io/gorm v1.25.2 // indirect
)

51
go.sum Normal file
View File

@@ -0,0 +1,51 @@
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/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.5.2 h1:TpQ+/dqCY4uCigCFyrfnrJnrW9zjpelWVoEVNy5qJkc=
gorm.io/driver/sqlite v1.5.2/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=

71
handler/event.go Normal file
View File

@@ -0,0 +1,71 @@
package handler
import (
"astra-events/model"
"astra-events/services"
"github.com/labstack/echo/v4"
"net/http"
"strconv"
)
func (h *Handler) CreateEvent(c echo.Context) (err error) {
newEvent := new(model.Event)
event := new(model.CreateEvent)
authorId, err := strconv.Atoi(c.Request().Header.Get("UserId"))
if err != nil {
return c.NoContent(http.StatusUnauthorized)
}
if err = c.Bind(event); err != nil {
return c.NoContent(http.StatusBadRequest)
}
// TODO: Add gorutine
employee, err := services.GetUser(event.EmployeeId, c.Request().Header)
if err != nil {
return c.HTML(http.StatusBadGateway, err.Error())
}
author, err := services.GetUser(uint(authorId), c.Request().Header)
if err != nil {
return c.HTML(http.StatusBadGateway, err.Error())
}
newEvent.Start = event.Start
newEvent.End = event.End
newEvent.AuthorId = uint(authorId)
newEvent.EmployeeId = event.EmployeeId
newEvent.MemberId = event.MemberId
newEvent.MedicalCardId = event.MedicalCardId
newEvent.Status = event.Status
h.DB.Begin()
tx := h.DB.Create(&newEvent)
if tx.RowsAffected == 0 {
h.DB.Rollback()
return c.NoContent(http.StatusBadGateway)
}
eventsServices := []model.EventsServices{}
for _, service := range event.Services {
eventsServices = append(eventsServices, model.EventsServices{EventId: newEvent.ID, ServiceId: service})
}
tx = h.DB.Create(eventsServices)
if tx.RowsAffected == 0 {
h.DB.Rollback()
return c.NoContent(http.StatusBadGateway)
}
h.DB.Commit()
newEvent.Services = event.Services
newEvent.Author = *author
newEvent.Employee = *employee
return c.JSON(http.StatusCreated, newEvent)
}

7
handler/handler.go Normal file
View File

@@ -0,0 +1,7 @@
package handler
import "gorm.io/gorm"
type Handler struct {
DB *gorm.DB
}

46
main.go Normal file
View File

@@ -0,0 +1,46 @@
package main
import (
"astra-events/config"
"astra-events/handler"
"astra-events/model"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
func main() {
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Info, // Log level
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
ParameterizedQueries: true, // Don't include params in the SQL log
Colorful: false, // Disable color
},
)
db, err := gorm.Open(sqlite.Open(config.Env.Server.ConnectionString), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic("failed to connect database")
}
e := echo.New()
e.Use(middleware.Logger())
db.AutoMigrate(&model.Event{}, &model.EventsServices{})
var h = &handler.Handler{DB: db}
e.POST("/", h.CreateEvent)
e.Logger.Fatal(e.Start(":" + config.Env.Server.Port))
}

7
model/card.go Normal file
View File

@@ -0,0 +1,7 @@
package model
import "gorm.io/gorm"
type Card struct {
gorm.Model
}

32
model/event.go Normal file
View File

@@ -0,0 +1,32 @@
package model
import (
"gorm.io/gorm"
"time"
)
type Event struct {
gorm.Model
Start time.Time `json:"start"`
End time.Time `json:"end"`
Author User `json:"author" gorm:"-"`
AuthorId uint `json:"-"`
Employee User `json:"employee" gorm:"-"`
EmployeeId uint `json:"-"`
Member PD `json:"member" gorm:"-"`
MemberId uint `json:"-"`
Status string `json:"status"`
MedicalCard Card `json:"medicalCard" gorm:"-"`
MedicalCardId uint `json:"-"`
Services []uint `json:"services" gorm:"-"`
}
type CreateEvent struct {
Start time.Time `json:"start"`
End time.Time `json:"end"`
EmployeeId uint `json:"employee_id"`
MemberId uint `json:"member_id"`
Status string `json:"status"`
MedicalCardId uint `json:"medical_card_id"`
Services []uint `json:"services"`
}

9
model/events_services.go Normal file
View File

@@ -0,0 +1,9 @@
package model
import "gorm.io/gorm"
type EventsServices struct {
gorm.Model
EventId uint
ServiceId uint
}

7
model/pd.go Normal file
View File

@@ -0,0 +1,7 @@
package model
import "gorm.io/gorm"
type PD struct {
gorm.Model
}

7
model/service.go Normal file
View File

@@ -0,0 +1,7 @@
package model
import "gorm.io/gorm"
type Service struct {
gorm.Model
}

20
model/user.go Normal file
View File

@@ -0,0 +1,20 @@
package model
import "gorm.io/gorm"
type (
User struct {
gorm.Model
UserName string `json:"userName" gorm:"unique"`
Password string `json:"password,omitempty"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
)
type APIUser struct {
UserName string `json:"userName" gorm:"unique"`
Password string `json:"password,omitempty"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}

105
pkg/api/apiCall.go Normal file
View File

@@ -0,0 +1,105 @@
package api
import (
"bytes"
"encoding/json"
"io"
"net/http"
)
func PostRequest(url string, model any, header http.Header) ([]byte, error) {
uJson, err := json.Marshal(model)
if err != nil {
return nil, err
}
client := http.Client{}
req, err := http.NewRequest("POST", url, bytes.NewReader(uJson))
req.Header = header
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return data, nil
}
func GetRequest(url string, header http.Header, args ...string) ([]byte, error, *http.Response) {
client := http.Client{}
req, err := http.NewRequest("GET", url, nil)
if len(args) > 0 {
req.URL.RawQuery = args[0]
}
req.Header = header
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, err, nil
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err, nil
}
return data, nil, resp
}
func PatchRequest(url string, model any, header http.Header) ([]byte, error) {
uJson, err := json.Marshal(model)
if err != nil {
return nil, err
}
client := http.Client{}
req, err := http.NewRequest("PATCH", url, bytes.NewReader(uJson))
req.Header = header
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return data, nil
}
func DeleteRequest(url string, header http.Header) ([]byte, error) {
client := http.Client{}
req, err := http.NewRequest("DELETE", url, nil)
req.Header = header
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return data, nil
}

27
pkg/utils/query.go Normal file
View File

@@ -0,0 +1,27 @@
package utils
import (
"github.com/labstack/echo/v4"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
func ApplySort(tx *gorm.DB, column string, isDesc bool) {
tx.Order(clause.OrderByColumn{
Column: clause.Column{Name: column},
Desc: isDesc,
})
}
func ApplyFilters(tx *gorm.DB, column string, value string) {
if column != "" && value != "" {
tx.Where(column + " LIKE '%" + value + "%'")
}
}
func ApplyIdFilter(c echo.Context, tx *gorm.DB) {
id := c.Param("id")
if id != "" {
tx.Where("id = ?", id)
}
}

52
pkg/utils/url.go Normal file
View File

@@ -0,0 +1,52 @@
package utils
import (
"net/url"
"strconv"
"strings"
)
func GetQueryParam(query url.Values, key string, defaultVal string) string {
data := query.Get(key)
if data == "" {
return defaultVal
}
return data
}
func GetPaginationParams(query url.Values) (int, int) {
offset := GetQueryParam(query, "offset", "0")
limit := GetQueryParam(query, "limit", "10")
limitInt, err := strconv.Atoi(limit)
if err != nil {
limitInt = 10
}
offsetInt, err := strconv.Atoi(offset)
if err != nil {
offsetInt = 0
}
return limitInt, offsetInt
}
func GetFilterParams(query url.Values) (string, bool, string, string) {
sort := GetQueryParam(query, "sort", "id:asc")
filter := GetQueryParam(query, "filter", ":")
filters := strings.Split(filter, ":")
sorts := strings.Split(sort, ":")
isDesc := false
if sorts[1] == "desc" {
isDesc = true
}
return sorts[0], isDesc, filters[0], filters[1]
}

33
services/users.go Normal file
View File

@@ -0,0 +1,33 @@
package services
import (
"astra-events/config"
"astra-events/model"
"astra-events/pkg/api"
"encoding/json"
"errors"
"net/http"
"strconv"
)
func GetUser(ID uint, header http.Header) (*model.User, error) {
id := strconv.Itoa(int(ID))
data, err, _ := api.GetRequest(
config.Env.MSHosts.UsersHost+"/"+id,
header)
if err != nil {
return nil, errors.New("Error Request to Users Service")
}
u := new(model.User)
err = json.Unmarshal(data, &u)
if err != nil {
return nil, errors.New("Bad Response from Users Service")
}
return u, nil
}

BIN
test.db Normal file

Binary file not shown.