From a1633885574ad10b668a1304ee03da7e082c1dfd Mon Sep 17 00:00:00 2001 From: Ymnuk Date: Wed, 19 Jul 2023 12:05:56 +0300 Subject: [PATCH] =?UTF-8?q?=D0=93=D0=B5=D0=BD=D0=B5=D1=80=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=80=D0=BE=D1=83=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=B4=D0=BB=D1=8F=20=D1=83=D1=87=D0=B5=D1=82?= =?UTF-8?q?=D0=BE=D0=BA=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example.yml | 8 +++++++- lib/backend.go | 2 +- lib/exec-commands.go | 3 +++ lib/prepare-metadata.go | 15 +++++++++++---- lib/template.go | 4 ++++ lib/tmpl/backend/db/db.tmpl | 9 +++++++++ lib/tmpl/backend/db/model/base-int.tmpl | 11 +++-------- lib/tmpl/backend/db/model/base.tmpl | 2 +- lib/tmpl/backend/db/model/model.tmpl | 14 ++++++++++++-- lib/tmpl/backend/db/model/role.tmpl | 2 +- lib/tmpl/backend/db/model/user-role.tmpl | 2 +- lib/tmpl/backend/db/model/user.tmpl | 1 + lib/tmpl/backend/lib/config.tmpl | 7 +++++-- lib/tmpl/backend/main.tmpl | 5 +++++ lib/tmpl/backend/route/api/auth/index.tmpl | 12 ++++++++++++ lib/tmpl/backend/route/api/user/delete.tmpl | 14 ++++++++++++++ lib/tmpl/backend/route/api/user/get.tmpl | 14 ++++++++++++++ lib/tmpl/backend/route/api/user/list-users.tmpl | 13 +++++++++++++ lib/tmpl/backend/route/api/user/post.tmpl | 14 ++++++++++++++ lib/tmpl/backend/route/api/user/put.tmpl | 15 +++++++++++++++ lib/tmpl/backend/route/api/user/role/index.tmpl | 13 +++++++++++++ main.go | 1 + structs/db.go | 3 +++ 23 files changed, 163 insertions(+), 21 deletions(-) diff --git a/example.yml b/example.yml index 03606ef..3c014bf 100644 --- a/example.yml +++ b/example.yml @@ -11,18 +11,22 @@ licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.html host: example.com basePath: /api db: + sqlite: true tables: - name: test___test_1 pk: uuid fields: - name: f1 + recursive: true - name: test2 pk: int fields: - name: f1 - name: f2 fks: - - name: test1 + - name: test___test_1 + tableName: test___test_1 + backend: config: - name: nominatim @@ -31,3 +35,5 @@ backend: - name: tile_server type: string help: Tile server for download tiles map + +frontend: diff --git a/lib/backend.go b/lib/backend.go index 4511ec9..6dd6645 100644 --- a/lib/backend.go +++ b/lib/backend.go @@ -127,7 +127,7 @@ func generateModelBase() { if err := PrepareTmplFile("tmpl/backend/main.tmpl", Project, filepath.Join(AppConfig.OutdirBackend, "main.go")); err != nil { log.Fatal(err) } - if err := PrepareTmplFile("tmpl/backend/lib/config.tmpl", Project.Backend, filepath.Join(AppConfig.OutdirBackend, "lib", "config.go")); err != nil { + if err := PrepareTmplFile("tmpl/backend/lib/config.tmpl", Project, filepath.Join(AppConfig.OutdirBackend, "lib", "config.go")); err != nil { log.Fatal(err) } diff --git a/lib/exec-commands.go b/lib/exec-commands.go index fe890ee..3941e6f 100644 --- a/lib/exec-commands.go +++ b/lib/exec-commands.go @@ -19,6 +19,9 @@ func execCommands() { log.Fatal(err) } else { strs := strings.Split(string(buff), "\n") + if Project.DB.SQLite { + strs = append(strs, "gorm.io/driver/sqlite") + } if len(strs) > 0 { for _, str := range strs { cmd := exec.Command("go", "get", str) diff --git a/lib/prepare-metadata.go b/lib/prepare-metadata.go index 810bc22..c365550 100644 --- a/lib/prepare-metadata.go +++ b/lib/prepare-metadata.go @@ -40,7 +40,7 @@ func PrepareMetadata(project *structs.Project) { } if project.DB.Tables[i].Recursive { project.DB.Tables[i].FkFields = append(project.DB.Tables[i].FkFields, structs.Field{ - Name: "parent_id", + Name: "parent", Description: "Recursive foreign key for self table", }) switch project.DB.Tables[i].Pk { @@ -61,8 +61,13 @@ func PrepareMetadata(project *structs.Project) { } if project.DB.Tables[i].FKs[j].TableID == uuid.Nil && project.DB.Tables[i].FKs[j].TableName != "" { for k := range project.DB.Tables { - if project.DB.Tables[i].Name == project.DB.Tables[i].FKs[j].TableName { + if project.DB.Tables[k].Name == project.DB.Tables[i].FKs[j].TableName { project.DB.Tables[i].FKs[j].TableID = project.DB.Tables[k].ID + project.DB.Tables[i].FKs[j].Type = project.DB.Tables[k].Pk + /*project.DB.Tables[i].FkFields = append(project.DB.Tables[i].FkFields, structs.Field{ + Name: fmt.Sprintf("%s", project.DB.Tables[k].Name), + Type: project.DB.Tables[k].Pk, + })*/ } } } @@ -70,6 +75,7 @@ func PrepareMetadata(project *structs.Project) { for k := range project.DB.Tables { if project.DB.Tables[k].ID == project.DB.Tables[i].FKs[j].TableID { project.DB.Tables[i].FKs[j].TableName = project.DB.Tables[k].Name + project.DB.Tables[k].Children = append(project.DB.Tables[k].Children, project.DB.Tables[i].Name) } } } @@ -77,8 +83,9 @@ func PrepareMetadata(project *structs.Project) { log.Fatalf("Error foreign key for '%s' table", project.DB.Tables[i].FKs[j].TableID.String()) } project.DB.Tables[i].FkFields = append(project.DB.Tables[i].FkFields, structs.Field{ - Name: fmt.Sprintf("%s_id", strings.ToLower(project.DB.Tables[i].FKs[j].TableName)), - Description: fmt.Sprintf("Foreign key for \"%s\" table", project.DB.Tables[i].FKs[j].TableName), + Name: fmt.Sprintf("%s", strings.ToLower(project.DB.Tables[i].FKs[j].TableName)), + Type: project.DB.Tables[i].Pk, + Description: fmt.Sprintf("Foreign key for \\\"%s\\\" table", project.DB.Tables[i].FKs[j].TableName), }) } } diff --git a/lib/template.go b/lib/template.go index 253686e..8caa2d6 100644 --- a/lib/template.go +++ b/lib/template.go @@ -100,6 +100,8 @@ func fieldType(field *structs.Field) string { return "*int" case "bigint": return "*int64" + case "uuid": + return "*uuid.UUID" default: log.Fatalf("Unknow format %s", field.Type) } @@ -124,6 +126,8 @@ func fieldTypeDB(field *structs.Field) string { return "INT" case "bigint": return "BIGINT" + case "uuid": + return "UUID" default: log.Fatalf("Unknow format %s", field.Type) } diff --git a/lib/tmpl/backend/db/db.tmpl b/lib/tmpl/backend/db/db.tmpl index 80153d2..00b07fa 100644 --- a/lib/tmpl/backend/db/db.tmpl +++ b/lib/tmpl/backend/db/db.tmpl @@ -13,6 +13,7 @@ import ( "gorm.io/driver/mysql" "gorm.io/driver/postgres" "gorm.io/gorm" + {{ if .DB.SQLite }}"gorm.io/driver/sqlite"{{ end }} "gorm.io/gorm/logger" ) @@ -53,6 +54,14 @@ func DBConnect() { if err != nil { log.Fatal(err) } + {{ if .DB.SQLite }} + case "sqlite": + dsn := lib.AppConfig.DbPath + DB, err = gorm.Open(sqlite.Open(dsn), &conf) + if err != nil { + log.Fatal(err) + } + {{ end }} default: log.Fatal("Server DB not set") } diff --git a/lib/tmpl/backend/db/model/base-int.tmpl b/lib/tmpl/backend/db/model/base-int.tmpl index 2c8e6a7..4fcdbf5 100644 --- a/lib/tmpl/backend/db/model/base-int.tmpl +++ b/lib/tmpl/backend/db/model/base-int.tmpl @@ -2,16 +2,11 @@ package model -import ( - "time" - - "gorm.io/gorm" -) - +import "time" type BaseInt struct { - ID uint64 `gorm:"type:autoIncrement;primaryKey" json:"id,omitempty"` + ID uint64 `gorm:"primaryKey" json:"id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty"` - DeletedAt gorm.DeletedAt `sql:"index" json:"deletedAt"` + // DeletedAt *time.Time `sql:"index" json:"deletedAt"` } diff --git a/lib/tmpl/backend/db/model/base.tmpl b/lib/tmpl/backend/db/model/base.tmpl index 2bb6553..a20ea3e 100644 --- a/lib/tmpl/backend/db/model/base.tmpl +++ b/lib/tmpl/backend/db/model/base.tmpl @@ -13,7 +13,7 @@ type Base struct { ID uuid.UUID `gorm:"type:uuid;primary_key;" json:"id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty"` - DeletedAt gorm.DeletedAt `sql:"index" json:"deletedAt"` + // DeletedAt *time.Time `sql:"index" json:"deletedAt"` } // BeforeCreate will set a UUID rather than numeric ID. diff --git a/lib/tmpl/backend/db/model/model.tmpl b/lib/tmpl/backend/db/model/model.tmpl index de7dd56..07c8e0a 100644 --- a/lib/tmpl/backend/db/model/model.tmpl +++ b/lib/tmpl/backend/db/model/model.tmpl @@ -3,20 +3,30 @@ package model import ( - "time" +// "time" uuid "github.com/satori/go.uuid" ) - +// {{ fieldNamePrepare .Name }} {{ .Description}} type {{ fieldNamePrepare .Name }} struct { {{ if eq .Pk "uuid" }} Base {{ else }} BaseInt {{ end }} + {{ range $index, $field := .Fields }} {{ fieldName $field }} {{ fieldType $field }} {{ fieldDescript $field }} {{ end }} + + {{ range $index, $field := .Children }} + {{ fieldNamePrepare $field }} []{{ fieldNamePrepare $field }} + {{ end }} + + {{ range $index, $field := .FkFields }} + {{ fieldName $field }}ID {{ fieldType $field }} {{ fieldDescript $field }} + {{ fieldName $field }} *{{ if eq $field.Name "Parent" }}{{ fieldNamePrepare $.Name }}{{ else }}{{ fieldName $field }}{{ end }} {{ fieldDescript $field }} + {{ end }} } {{ $varNameField := fieldNamePrepare .Name }} diff --git a/lib/tmpl/backend/db/model/role.tmpl b/lib/tmpl/backend/db/model/role.tmpl index 4724b89..c39db52 100644 --- a/lib/tmpl/backend/db/model/role.tmpl +++ b/lib/tmpl/backend/db/model/role.tmpl @@ -1,6 +1,6 @@ package model -// Роли пользователей +// Role Роли пользователей type Role struct { Base Name string `gorm:"type:varchar(20);comment:Название роли" json:"name"` diff --git a/lib/tmpl/backend/db/model/user-role.tmpl b/lib/tmpl/backend/db/model/user-role.tmpl index d306e8a..370a8fc 100644 --- a/lib/tmpl/backend/db/model/user-role.tmpl +++ b/lib/tmpl/backend/db/model/user-role.tmpl @@ -2,7 +2,7 @@ package model import uuid "github.com/satori/go.uuid" -// Связь пользователя и роли +// UserRole Связь пользователя и роли type UserRole struct { Base UserID uuid.UUID `gorm:"column:id_user"` diff --git a/lib/tmpl/backend/db/model/user.tmpl b/lib/tmpl/backend/db/model/user.tmpl index e408090..4f2e5d7 100644 --- a/lib/tmpl/backend/db/model/user.tmpl +++ b/lib/tmpl/backend/db/model/user.tmpl @@ -10,6 +10,7 @@ import ( "gorm.io/gorm" ) +// User Пользователи type User struct { Base Login string `json:"login"` diff --git a/lib/tmpl/backend/lib/config.tmpl b/lib/tmpl/backend/lib/config.tmpl index 3d627a2..a994636 100644 --- a/lib/tmpl/backend/lib/config.tmpl +++ b/lib/tmpl/backend/lib/config.tmpl @@ -3,8 +3,11 @@ package lib var AppConfig struct { Env string `arg:"-e,env:ENV" default:"prod" help:"Environment for application. dev or prod. Default prod"` MigrateDB bool `arg:"-m,--migrate,env:DB_MIGRATE" default:"false" help:"Run migrate Database"` - DBInstance string `arg:"--db-instance,env:DB_INSTANCE" default:"postgres" help:"postgres (PostgreSQL) or mysql (MySQL/MariaDB)"` + DBInstance string `arg:"--db-instance,env:DB_INSTANCE" default:"{{ if .DB.SQLite }}sqlite{{ else }}postgres{{ end }}" help:"postgres (PostgreSQL) or mysql (MySQL/MariaDB){{ if .DB.SQLite }} or sqlite (SQLite3){{ end }}"` DbName string `arg:"--db-name,env:DB_NAME" default:"dbname" help:"Database name for connect"` + {{ if .DB.SQLite }} + DbPath string `arg:"--db-path,env:DB_PATH" default:"./{{ .Name }}.db" help:"Path to database for SQLite3"` + {{ end }} DbAddress string `arg:"--db-host,env:DB_HOST" default:"localhost" help:"Database host for connect"` DbPort string `arg:"--db-port,env:DB_PORT" default:"5432" help:"Database port for connect"` DbLogin string `arg:"--db-login,env:DB_LOGIN" default:"db" help:"Database login for connect"` @@ -17,7 +20,7 @@ var AppConfig struct { LdapPassword string `arg:"--ldap-pwd,env:LDAP_PWD" help:"Ldap password for credential"` LdapSearchBase string `arg:"--ldap-search-base,env:LDAP_SEARCH_BASE" help:"Ldap search base for search users"` - {{ range $index, $field := .Config }} + {{ range $index, $field := .Backend.Config }} {{ configParamName $field }} {{ configParamType $field }} {{ configParamTag $field }} {{ end }} } \ No newline at end of file diff --git a/lib/tmpl/backend/main.tmpl b/lib/tmpl/backend/main.tmpl index 983dfbd..c0b0932 100644 --- a/lib/tmpl/backend/main.tmpl +++ b/lib/tmpl/backend/main.tmpl @@ -39,6 +39,11 @@ var e *echo.Echo // @host {{ .Host }} // @BasePath {{ .BasePath }} + +// @securityDefinitions.apikey BearerAuth +// @in header +// @name Authorization + func main() { arg.MustParse(&lib.AppConfig) diff --git a/lib/tmpl/backend/route/api/auth/index.tmpl b/lib/tmpl/backend/route/api/auth/index.tmpl index 79224e2..2569bd7 100644 --- a/lib/tmpl/backend/route/api/auth/index.tmpl +++ b/lib/tmpl/backend/route/api/auth/index.tmpl @@ -20,6 +20,18 @@ func Init(c *echo.Group) { c.POST("/login", login) } +// Authenticate auth +// @Summary Authenticate in system +// @Description Get authentication data +// @Tags users +// @Accept json +// @Produce json +// @Param body body model.User true "query params" +// @Success 200 {object} structs.Result +// @Failure 400 {object} structs.Result +// @Failure 404 {object} structs.Result +// @Failure 500 {object} structs.Result +// @Router /api/auth [post] func login(c echo.Context) error { var err error var userForm model.User diff --git a/lib/tmpl/backend/route/api/user/delete.tmpl b/lib/tmpl/backend/route/api/user/delete.tmpl index d2a2eca..cd685f1 100644 --- a/lib/tmpl/backend/route/api/user/delete.tmpl +++ b/lib/tmpl/backend/route/api/user/delete.tmpl @@ -13,6 +13,20 @@ import ( uuid "github.com/satori/go.uuid" ) +// DeleteUser deleteUser +// @Summary Удаление пользователя +// @Description Удаление информации о пользователе +// @Tags users +// @Accept json +// @Produce json +// @Param id path string true "Идентификатор пользователя" +// @Success 200 {object} structs.Result +// @Failure 400 {object} structs.Result +// @Failure 401 {object} structs.Result +// @Failure 404 {object} structs.Result +// @Failure 500 {object} structs.Result +// @Router /api/user/{id} [delete] +// @Security BearerAuth func delete(c echo.Context) error { user := c.Get("user").(*jwt.Token) diff --git a/lib/tmpl/backend/route/api/user/get.tmpl b/lib/tmpl/backend/route/api/user/get.tmpl index c040604..e306fbe 100644 --- a/lib/tmpl/backend/route/api/user/get.tmpl +++ b/lib/tmpl/backend/route/api/user/get.tmpl @@ -11,6 +11,20 @@ import ( uuid "github.com/satori/go.uuid" ) +// GetUser getUser +// @Summary Получить пользователя +// @Description Получения информации о пользователе по его id +// @Tags users +// @Accept json +// @Produce json +// @Param id path string true "Идентификатор пользователя" +// @Success 200 {object} model.User +// @Failure 400 {object} structs.Result +// @Failure 401 {object} structs.Result +// @Failure 404 {object} structs.Result +// @Failure 500 {object} structs.Result +// @Router /api/user/{id} [get] +// @Security BearerAuth func get(c echo.Context) error { id := uuid.FromStringOrNil(c.Param("id")) diff --git a/lib/tmpl/backend/route/api/user/list-users.tmpl b/lib/tmpl/backend/route/api/user/list-users.tmpl index 9483289..13b48c5 100644 --- a/lib/tmpl/backend/route/api/user/list-users.tmpl +++ b/lib/tmpl/backend/route/api/user/list-users.tmpl @@ -12,6 +12,19 @@ import ( "github.com/labstack/echo/v4" ) +// ListUsers listUsers +// @Summary Получить пользователя +// @Description Возвращает список пользователей +// @Tags users +// @Accept json +// @Produce json +// @Success 200 {object} []model.User +// @Failure 400 {object} structs.Result +// @Failure 401 {object} structs.Result +// @Failure 404 {object} structs.Result +// @Failure 500 {object} structs.Result +// @Router /api/user [get] +// @Security BearerAuth func listUsers(c echo.Context) error { user := c.Get("user").(*jwt.Token) diff --git a/lib/tmpl/backend/route/api/user/post.tmpl b/lib/tmpl/backend/route/api/user/post.tmpl index 5e3ce0e..0500caf 100644 --- a/lib/tmpl/backend/route/api/user/post.tmpl +++ b/lib/tmpl/backend/route/api/user/post.tmpl @@ -14,6 +14,20 @@ import ( "github.com/labstack/echo/v4" ) +// CreateUser createUser +// @Summary Создать пользователя +// @Description Добавление нового пользователя в систему +// @Tags users +// @Accept json +// @Produce json +// @Param body body model.User true "Описание нового пользователя" +// @Success 200 {object} model.User +// @Failure 400 {object} structs.Result +// @Failure 401 {object} structs.Result +// @Failure 404 {object} structs.Result +// @Failure 500 {object} structs.Result +// @Router /api/user [post] +// @Security BearerAuth func post(c echo.Context) error { user := c.Get("user").(*jwt.Token) diff --git a/lib/tmpl/backend/route/api/user/put.tmpl b/lib/tmpl/backend/route/api/user/put.tmpl index e3b41b9..2b6072b 100644 --- a/lib/tmpl/backend/route/api/user/put.tmpl +++ b/lib/tmpl/backend/route/api/user/put.tmpl @@ -15,6 +15,21 @@ import ( uuid "github.com/satori/go.uuid" ) +// UpdateUser updateUser +// @Summary Обновление пользователя +// @Description Обновление информации о пользователе, а так же смена пароля при необходимости +// @Tags users +// @Accept json +// @Produce json +// @Param id path string true "Идентификатор пользователя" +// @Param body body model.User true "Описание существующего пользователя" +// @Success 200 {object} model.User +// @Failure 400 {object} structs.Result +// @Failure 401 {object} structs.Result +// @Failure 404 {object} structs.Result +// @Failure 500 {object} structs.Result +// @Router /api/user/{id} [post] +// @Security BearerAuth func put(c echo.Context) error { user := c.Get("user").(*jwt.Token) diff --git a/lib/tmpl/backend/route/api/user/role/index.tmpl b/lib/tmpl/backend/route/api/user/role/index.tmpl index a7ef8bb..da126f3 100644 --- a/lib/tmpl/backend/route/api/user/role/index.tmpl +++ b/lib/tmpl/backend/route/api/user/role/index.tmpl @@ -16,6 +16,19 @@ func Init(c *echo.Group) { } +// ListRoles listRoles +// @Summary Список ролей для пользователей в системе +// @Description Получить список пролей для отображения и назначения пользователям +// @Tags users +// @Accept json +// @Produce json +// @Success 200 {object} structs.Result +// @Failure 400 {object} structs.Result +// @Failure 401 {object} structs.Result +// @Failure 404 {object} structs.Result +// @Failure 500 {object} structs.Result +// @Router /api/user/roles [get] +// @Security BearerAuth func listRoles(c echo.Context) error { var err error tx := db.BeginTransation() diff --git a/main.go b/main.go index 870ca70..64379ed 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,7 @@ func main() { } else { log.Fatal("Ошибка открытия файла") } + lib.PrepareMetadata(lib.Project) lib.Generate() } diff --git a/structs/db.go b/structs/db.go index 89e63f5..7029c42 100644 --- a/structs/db.go +++ b/structs/db.go @@ -3,6 +3,7 @@ package structs import uuid "github.com/satori/go.uuid" type DB struct { + SQLite bool `yaml:"sqlite,omitempty"` Tables []Table `yaml:"tables,omitempty"` Description string `yaml:"description,omitempty" json:"nescription,omitempty"` } @@ -18,6 +19,7 @@ type Table struct { Recursive bool `yaml:"recursive,omitempty" json:"recursive,omitempty"` // Рекурсивная таблица FKs []FK `yaml:"fks,omitempty" json:"fks,omitempty"` // Внешние ключи FkFields []Field `yaml:"-" json:"-"` // Поля с описанием внешних ключей + Children []string `yaml:"-" json:"-"` // Дочерние (подчиненные) таблицы } // Описание поля @@ -34,6 +36,7 @@ type Field struct { type FK struct { ID uuid.UUID `yaml:"id,omitempty" json:"id,omitempty"` // Идентификатор внешнего ключа Name string `yaml:"name,omitempty" json:"name,omitempty"` // Название ключа + Type string `yaml:"-"` // Тип первичного ключа TableID uuid.UUID `yaml:"idTable,omitempty" json:"idTable,omitempty"` // Идентификатор таблицы, на которую ссылаемся TableName string `yaml:"tableName,omitempty" json:"tableName,omitempty"` // Название таблицы, на которую ссылаемся Description string `yaml:"description,omitempty" json:"description,omitempty"` // Описание внешнего ключа