stage commit (pagination, sorting, a lil bit refactored)
This commit is contained in:
parent
848dd5df8a
commit
7ed9f67c37
@ -1,15 +0,0 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"system-trace/core/auth"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func InitAuth(app *fiber.App, version *fiber.Router) {
|
||||
v := *version
|
||||
g := v.Group("/auth")
|
||||
{
|
||||
g.Post("/login", auth.ReqTokens)
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"system-trace/core/app/controllers"
|
||||
_ "system-trace/core/docs"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/swagger"
|
||||
)
|
||||
|
||||
func Init(app *fiber.App) {
|
||||
app.Get("/swagger/*", swagger.HandlerDefault)
|
||||
v1 := app.Group("/v1")
|
||||
{
|
||||
controllers.InitAuth(app, &v1)
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"os"
|
||||
"system-trace/core/app/constants"
|
||||
"system-trace/core/app/router"
|
||||
"system-trace/core/app/router/middlewares"
|
||||
"system-trace/core/environment"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
)
|
||||
|
||||
var Instance *fiber.App
|
||||
|
||||
func Serve() {
|
||||
Instance = initServer()
|
||||
Instance.Use(recover.New())
|
||||
Instance.Use(cors.New())
|
||||
Instance.Use(middlewares.ValidateSession)
|
||||
router.Init(Instance)
|
||||
Instance.Use(func(c *fiber.Ctx) error {
|
||||
return c.
|
||||
Status(fiber.StatusNotFound).
|
||||
JSON(fiber.Map{
|
||||
"error": constants.NOT_FOUND,
|
||||
})
|
||||
})
|
||||
Instance.Listen(":" + os.Getenv("APP_PORT"))
|
||||
}
|
||||
|
||||
func initServer() *fiber.App {
|
||||
debug := environment.IsDebug()
|
||||
|
||||
return fiber.New(fiber.Config{
|
||||
JSONEncoder: json.Marshal,
|
||||
JSONDecoder: json.Unmarshal,
|
||||
CaseSensitive: true,
|
||||
EnablePrintRoutes: debug,
|
||||
Prefork: true,
|
||||
AppName: "System Trace API",
|
||||
ErrorHandler: func(c *fiber.Ctx, err error) error {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": err.Error(),
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
package constants
|
||||
|
||||
const (
|
||||
AUTH_FAILED = "User with specified email and password not found"
|
||||
AUTH_FAILED = "User with specified E-Mail and password not found"
|
||||
NOT_FOUND = "Wrong request method or path"
|
||||
UNAUTHORIZED = "Unauthorized"
|
||||
)
|
||||
42
constants/permissions/permissions.go
Normal file
42
constants/permissions/permissions.go
Normal file
@ -0,0 +1,42 @@
|
||||
package permissions
|
||||
|
||||
const (
|
||||
DASHBOARD_READ = "DASHBOARD_READ"
|
||||
SETTINGS_READ = "SETTINGS_READ"
|
||||
SETTINGS_UPDATE = "SETTINGS_UPDATE"
|
||||
LOGS_READ = "LOGS_READ"
|
||||
TASKS_READ = "TASKS_READ"
|
||||
TASKS_UPDATE = "TASKS_UPDATE"
|
||||
USERS_READ = "USERS_READ"
|
||||
USERS_CREATE = "USERS_CREATE"
|
||||
USERS_UPDATE = "USERS_UPDATE"
|
||||
USERS_DELETE = "USERS_DELETE"
|
||||
USERS_BLOCK = "USERS_BLOCK"
|
||||
GROUPS_READ = "GROUPS_READ"
|
||||
GROUPS_CREATE = "GROUPS_CREATE"
|
||||
GROUPS_UPDATE = "GROUPS_UPDATE"
|
||||
GROUPS_DELETE = "GROUPS_DELETE"
|
||||
)
|
||||
|
||||
var All = map[string]int8{
|
||||
DASHBOARD_READ: 1,
|
||||
|
||||
SETTINGS_READ: 2,
|
||||
SETTINGS_UPDATE: 3,
|
||||
|
||||
LOGS_READ: 4,
|
||||
|
||||
TASKS_READ: 5,
|
||||
TASKS_UPDATE: 6,
|
||||
|
||||
USERS_READ: 7,
|
||||
USERS_CREATE: 9,
|
||||
USERS_UPDATE: 10,
|
||||
USERS_DELETE: 11,
|
||||
USERS_BLOCK: 12,
|
||||
|
||||
GROUPS_READ: 13,
|
||||
GROUPS_CREATE: 14,
|
||||
GROUPS_UPDATE: 15,
|
||||
GROUPS_DELETE: 16,
|
||||
}
|
||||
@ -1,16 +1,22 @@
|
||||
package auth
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"system-trace/core/database"
|
||||
"system-trace/core/database/entities"
|
||||
"system-trace/core/types"
|
||||
)
|
||||
|
||||
func GetPair(p *PairTokens) (*entities.AuthToken, error) {
|
||||
aut := new(entities.AuthToken)
|
||||
type AuthToken struct {
|
||||
UserID int32
|
||||
AccessToken string `bun:"type:varchar"`
|
||||
RefreshToken string `bun:"type:varchar"`
|
||||
IsRevoked bool `bun:",default:false"`
|
||||
}
|
||||
|
||||
func GetPairOfTokens(p *types.PairTokens) (*AuthToken, error) {
|
||||
aut := new(AuthToken)
|
||||
|
||||
ctx := context.Background()
|
||||
err := database.PG.NewSelect().
|
||||
err := PG.NewSelect().
|
||||
Model(aut).
|
||||
Where("access_token = ?", p.AccessToken).
|
||||
Where("refresh_token = ?", p.RefreshToken).
|
||||
@ -20,13 +26,29 @@ func GetPair(p *PairTokens) (*entities.AuthToken, error) {
|
||||
return aut, err
|
||||
}
|
||||
|
||||
func RevokePair(p *PairTokens) error {
|
||||
aut := entities.AuthToken{
|
||||
func InsertPairOfTokens(id int32, at, rt string) error {
|
||||
p := AuthToken{
|
||||
UserID: id,
|
||||
AccessToken: at,
|
||||
RefreshToken: rt,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
_, err := PG.NewInsert().
|
||||
Model(&p).
|
||||
Returning("NULL").
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func RevokePairOfTokens(p *types.PairTokens) error {
|
||||
aut := AuthToken{
|
||||
IsRevoked: true,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
_, err := database.PG.NewUpdate().
|
||||
_, err := PG.NewUpdate().
|
||||
Model(&aut).
|
||||
Column("is_revoked").
|
||||
Where("access_token = ?", p.AccessToken).
|
||||
@ -35,19 +57,3 @@ func RevokePair(p *PairTokens) error {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func insertPair(id int32, at, rt string) error {
|
||||
p := entities.AuthToken{
|
||||
UserID: id,
|
||||
AccessToken: at,
|
||||
RefreshToken: rt,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
_, err := database.PG.NewInsert().
|
||||
Model(&p).
|
||||
Returning("NULL").
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
@ -6,7 +6,6 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"system-trace/core/database/entities"
|
||||
"system-trace/core/environment"
|
||||
"time"
|
||||
|
||||
@ -41,7 +40,6 @@ func Connect() {
|
||||
if environment.IsDebug() {
|
||||
db.AddQueryHook(bundebug.NewQueryHook(
|
||||
bundebug.WithVerbose(true),
|
||||
bundebug.FromEnv("BUNDEBUG"),
|
||||
))
|
||||
}
|
||||
|
||||
@ -57,12 +55,12 @@ func Connect() {
|
||||
|
||||
func createSchema(db *bun.DB) error {
|
||||
models := []interface{}{
|
||||
(*entities.Group)(nil),
|
||||
(*entities.GroupPermission)(nil),
|
||||
(*entities.User)(nil),
|
||||
(*entities.Session)(nil),
|
||||
(*entities.Server)(nil),
|
||||
(*entities.AuthToken)(nil),
|
||||
(*Group)(nil),
|
||||
(*GroupPermission)(nil),
|
||||
(*User)(nil),
|
||||
(*Session)(nil),
|
||||
(*Server)(nil),
|
||||
(*AuthToken)(nil),
|
||||
}
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
package entities
|
||||
|
||||
type AuthToken struct {
|
||||
UserID int32
|
||||
AccessToken string `bun:"type:varchar"`
|
||||
RefreshToken string `bun:"type:varchar"`
|
||||
IsRevoked bool `bun:",default:false"`
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
package entities
|
||||
|
||||
import "time"
|
||||
|
||||
type Group struct {
|
||||
ID int32 `bun:",pk,autoincrement"`
|
||||
IssuerID int32 `bun:",notnull"`
|
||||
Issuer *User `bun:"rel:belongs-to,join:issuer_id=id"`
|
||||
Name string `bun:",notnull,unique"`
|
||||
GroupID int32 `bun:",notnull"`
|
||||
Users []*User `bun:"rel:has-many,join:id=group_id"`
|
||||
Permissions []*GroupPermission `bun:"rel:has-many,join:id=group_id"`
|
||||
CreatedAt time.Time `bun:",notnull,default:current_timestamp"`
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time `bun:",soft_delete,nullzero"`
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
ID int64 `bun:",pk,autoincrement"`
|
||||
Hostname string `bun:",notnull"`
|
||||
IP string `bun:",notnull"`
|
||||
IsOnline bool `bun:",notnull,default:true"`
|
||||
LastOnline time.Time
|
||||
CreatedAt time.Time `bun:",notnull,default:current_timestamp"`
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
var _ bun.BeforeAppendModelHook = (*Server)(nil)
|
||||
|
||||
func (s *Server) BeforeAppendModel(ctx context.Context, query bun.Query) error {
|
||||
switch query.(type) {
|
||||
case *bun.InsertQuery:
|
||||
s.LastOnline = time.Now()
|
||||
case *bun.UpdateQuery:
|
||||
s.UpdatedAt = time.Now()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID int32 `bun:",pk,autoincrement"`
|
||||
Email string `bun:",notnull,unique"`
|
||||
PasswordHash string `bun:",notnull,type:varchar(64)"`
|
||||
PasswordLength int8 `bun:",notnull"`
|
||||
RealName string `bun:",notnull"`
|
||||
GroupID int32 `bun:",notnull"`
|
||||
Group *Group `bun:"rel:belongs-to,join:group_id=id"`
|
||||
IsRequiredToSetPassword bool `bun:",notnull,default:true"`
|
||||
IsActive bool `bun:",notnull,default:true"`
|
||||
LastLogin time.Time
|
||||
CreatedAt time.Time `bun:",notnull,default:current_timestamp"`
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time `bun:",soft_delete,nullzero"`
|
||||
}
|
||||
|
||||
var _ bun.BeforeAppendModelHook = (*User)(nil)
|
||||
|
||||
func (u *User) BeforeAppendModel(ctx context.Context, query bun.Query) error {
|
||||
switch query.(type) {
|
||||
case *bun.UpdateQuery:
|
||||
u.UpdatedAt = time.Now()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
95
database/group.go
Normal file
95
database/group.go
Normal file
@ -0,0 +1,95 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"system-trace/core/types"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type Group struct {
|
||||
ID int32 `bun:",pk,autoincrement"`
|
||||
IssuerID int32 `bun:",notnull" json:"issuerId"`
|
||||
Issuer *User `bun:"rel:belongs-to,join:issuer_id=id" json:"issuer"`
|
||||
Name string `bun:",notnull,unique" json:"name"`
|
||||
Users []*User `bun:"rel:has-many,join:id=group_id,array" json:"users"`
|
||||
Permissions []*GroupPermission `bun:"rel:has-many,join:id=group_id,array" json:"permissions"`
|
||||
CreatedAt time.Time `bun:",notnull,default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
DeletedAt time.Time `bun:",soft_delete,nullzero" json:"-"`
|
||||
}
|
||||
|
||||
var _ bun.BeforeAppendModelHook = (*Group)(nil)
|
||||
|
||||
func (g *Group) BeforeAppendModel(ctx context.Context, query bun.Query) error {
|
||||
switch query.(type) {
|
||||
case *bun.UpdateQuery:
|
||||
g.UpdatedAt = time.Now()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindGroups(p *types.Pagination, ob *types.OrderBy) (groups *[]Group, cursor *types.Cursor, err error) {
|
||||
ctx := context.Background()
|
||||
groups = new([]Group)
|
||||
count, err := PG.NewSelect().
|
||||
Model(groups).
|
||||
Relation("Users").
|
||||
Relation("Permissions").
|
||||
Offset(p.Page*p.Count - p.Count).
|
||||
Limit(p.Count).
|
||||
Order(fmt.Sprintf("%s %s", ob.Key, ob.Order)).
|
||||
ScanAndCount(ctx)
|
||||
|
||||
return groups, &types.Cursor{
|
||||
Count: len(*groups),
|
||||
CurrentPage: p.Page,
|
||||
TotalPages: math.Ceil(float64(count) / float64(p.Count)),
|
||||
TotalRows: float64(count),
|
||||
}, err
|
||||
}
|
||||
|
||||
func FindGroupByID(id int) (group *Group, err error) {
|
||||
ctx := context.Background()
|
||||
group = new(Group)
|
||||
err = PG.NewSelect().
|
||||
Model(group).
|
||||
Where("id = ?", id).
|
||||
Scan(ctx)
|
||||
|
||||
return group, err
|
||||
}
|
||||
|
||||
func InsertGroup(g *Group) error {
|
||||
ctx := context.Background()
|
||||
_, err := PG.NewInsert().
|
||||
Model(g).
|
||||
Returning("NULL").
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func UpdateGroup(g *Group, cols []string) error {
|
||||
ctx := context.Background()
|
||||
_, err := PG.NewUpdate().
|
||||
Model(g).
|
||||
Column(cols...).
|
||||
WherePK().
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteGroup(id int) error {
|
||||
ctx := context.Background()
|
||||
_, err := PG.NewDelete().
|
||||
Model(new(Group)).
|
||||
Where("id = ?", id).
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package entities
|
||||
package database
|
||||
|
||||
type GroupPermission struct {
|
||||
GroupID int32 `bun:",notnull" json:"-"`
|
||||
Value int8 `bun:",notnull"`
|
||||
Value int8 `bun:",notnull" json:"value"`
|
||||
}
|
||||
30
database/server.go
Normal file
30
database/server.go
Normal file
@ -0,0 +1,30 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
ID int64 `bun:",pk,autoincrement"`
|
||||
Hostname string `bun:",notnull" json:"hostname"`
|
||||
IP string `bun:",notnull"`
|
||||
IsOnline bool `bun:",notnull,default:true" json:"isOnline"`
|
||||
LastOnline time.Time `json:"lastOnline"`
|
||||
CreatedAt time.Time `bun:",notnull,default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
var _ bun.BeforeAppendModelHook = (*Server)(nil)
|
||||
|
||||
func (s *Server) BeforeAppendModel(ctx context.Context, query bun.Query) error {
|
||||
switch query.(type) {
|
||||
case *bun.InsertQuery:
|
||||
s.LastOnline = time.Now()
|
||||
case *bun.UpdateQuery:
|
||||
s.UpdatedAt = time.Now()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package entities
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -9,13 +9,13 @@ import (
|
||||
|
||||
type Session struct {
|
||||
ID int64 `bun:",pk,autoincrement"`
|
||||
IssuerID int32 `bun:",notnull"`
|
||||
Issuer *User `bun:"rel:belongs-to,join:issuer_id=id"`
|
||||
Configuration map[string]interface{} `bun:"type:jsonb"`
|
||||
CreatedAt time.Time `bun:",notnull,default:current_timestamp"`
|
||||
FinishedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time `bun:",soft_delete,nullzero"`
|
||||
IssuerID int32 `bun:",notnull" json:"issuerId"`
|
||||
Issuer *User `bun:"rel:belongs-to,join:issuer_id=id" json:"issuer"`
|
||||
Configuration map[string]interface{} `bun:"type:jsonb" json:"configuration"`
|
||||
CreatedAt time.Time `bun:",notnull,default:current_timestamp" json:"createdAt"`
|
||||
FinishedAt time.Time `json:"finishedAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
DeletedAt time.Time `bun:",soft_delete,nullzero" json:"-"`
|
||||
}
|
||||
|
||||
var _ bun.BeforeAppendModelHook = (*Session)(nil)
|
||||
112
database/user.go
Normal file
112
database/user.go
Normal file
@ -0,0 +1,112 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"system-trace/core/types"
|
||||
"system-trace/core/utils"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID int32 `bun:",pk,autoincrement"`
|
||||
Email string `bun:",notnull,unique" json:"email"`
|
||||
PasswordHash string `bun:",notnull,type:varchar(64)" json:"-"`
|
||||
PasswordLength int8 `bun:",notnull" json:"passwordLength"`
|
||||
RealName string `bun:",notnull" json:"realName"`
|
||||
GroupID int32 `bun:",notnull" json:"groupId"`
|
||||
Group *Group `bun:"rel:belongs-to,join:group_id=id" json:"group"`
|
||||
IsRequiredToSetPassword bool `bun:",notnull,default:true" json:"isRequiredToSetPassword"`
|
||||
IsActive bool `bun:",notnull,default:true" json:"isActive"`
|
||||
LastLogin time.Time `json:"lastLogin"`
|
||||
CreatedAt time.Time `bun:",notnull,default:current_timestamp" json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
DeletedAt time.Time `bun:",soft_delete,nullzero" json:"deletedAt"`
|
||||
}
|
||||
|
||||
var _ bun.BeforeAppendModelHook = (*User)(nil)
|
||||
|
||||
func (u *User) BeforeAppendModel(ctx context.Context, query bun.Query) error {
|
||||
switch query.(type) {
|
||||
case *bun.UpdateQuery:
|
||||
u.UpdatedAt = time.Now()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FindByEmailAndPassword(email, password string) (*User, error) {
|
||||
passwordHash := utils.SHA256(password)
|
||||
ctx := context.Background()
|
||||
u := new(User)
|
||||
err := PG.NewSelect().
|
||||
Model(u).
|
||||
Where("email = ?", email).
|
||||
Where("password_hash = ?", passwordHash).
|
||||
Scan(ctx)
|
||||
|
||||
return u, err
|
||||
}
|
||||
|
||||
func FindUsers(p *types.Pagination, ob *types.OrderBy) (users *[]User, cursor *types.Cursor, err error) {
|
||||
ctx := context.Background()
|
||||
users = new([]User)
|
||||
count, err := PG.NewSelect().
|
||||
Model(users).
|
||||
Relation("Group").
|
||||
Offset(p.Page*p.Count - p.Count).
|
||||
Limit(p.Count).
|
||||
Order(fmt.Sprintf("%s %s", ob.Key, ob.Order)).
|
||||
ScanAndCount(ctx)
|
||||
|
||||
return users, &types.Cursor{
|
||||
Count: len(*users),
|
||||
CurrentPage: p.Page,
|
||||
TotalPages: math.Ceil(float64(count) / float64(p.Count)),
|
||||
TotalRows: float64(count),
|
||||
}, err
|
||||
}
|
||||
|
||||
func FindUserByID(id int) (user *User, err error) {
|
||||
ctx := context.Background()
|
||||
user = new(User)
|
||||
err = PG.NewSelect().
|
||||
Model(user).
|
||||
Where("id = ?", id).
|
||||
Scan(ctx)
|
||||
|
||||
return user, err
|
||||
}
|
||||
|
||||
func InsertUser(u *User) error {
|
||||
ctx := context.Background()
|
||||
_, err := PG.NewInsert().
|
||||
Model(u).
|
||||
Returning("NULL").
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func UpdateUser(u *User, cols []string) error {
|
||||
ctx := context.Background()
|
||||
_, err := PG.NewUpdate().
|
||||
Model(u).
|
||||
Column(cols...).
|
||||
WherePK().
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func DeleteUser(id int) error {
|
||||
ctx := context.Background()
|
||||
_, err := PG.NewDelete().
|
||||
Model(new(User)).
|
||||
Where("id = ?", id).
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
433
docs/docs.go
433
docs/docs.go
@ -34,7 +34,7 @@ const docTemplate = `{
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/auth.AuthBody"
|
||||
"$ref": "#/definitions/types.AuthBody"
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -44,10 +44,410 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/groups": {
|
||||
"get": {
|
||||
"description": "Returns array of groups and count",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Get groups (with pagination)",
|
||||
"parameters": [
|
||||
{
|
||||
"maximum": 100,
|
||||
"minimum": 10,
|
||||
"type": "integer",
|
||||
"description": "Count of rows",
|
||||
"name": "count",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Rows to skip",
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/types.JSONPagination"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create group with specified data",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Create group",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Request body",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.Group"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"description": "Update group with specified data",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Update group",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Request body",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.Group"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/groups/:id": {
|
||||
"get": {
|
||||
"description": "Returns group instance",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Get group by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "Group ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.Group"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete group by ID",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Delete group",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "Group ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/permissions": {
|
||||
"get": {
|
||||
"description": "Returns key-value map with permissions",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"summary": "Get list of permissions",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users": {
|
||||
"get": {
|
||||
"description": "Returns array of users and count",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Get users (with pagination)",
|
||||
"parameters": [
|
||||
{
|
||||
"maximum": 100,
|
||||
"minimum": 10,
|
||||
"type": "integer",
|
||||
"description": "Count of rows",
|
||||
"name": "count",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Rows to skip",
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/types.JSONPagination"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create user with specified data",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Create user",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Request body",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"description": "Update user with specified data",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Update user",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Request body",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/:id": {
|
||||
"get": {
|
||||
"description": "Returns user instance",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Get user by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete user by ID",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Delete user",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"auth.AuthBody": {
|
||||
"database.Group": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"deletedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"issuer": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
},
|
||||
"issuerID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/database.GroupPermission"
|
||||
}
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"users": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.GroupPermission": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"value": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"deletedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"$ref": "#/definitions/database.Group"
|
||||
},
|
||||
"groupID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"isActive": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isRequiredToSetPassword": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"lastLogin": {
|
||||
"type": "string"
|
||||
},
|
||||
"passwordHash": {
|
||||
"type": "string"
|
||||
},
|
||||
"passwordLength": {
|
||||
"type": "integer"
|
||||
},
|
||||
"realName": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.AuthBody": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"email",
|
||||
@ -60,15 +460,38 @@ const docTemplate = `{
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"example": "Aasdfgh1!"
|
||||
"example": "Aasdfg1!"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.Cursor": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"currentPage": {
|
||||
"type": "integer"
|
||||
},
|
||||
"totalPages": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.JSONPagination": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cursor": {
|
||||
"$ref": "#/definitions/types.Cursor"
|
||||
},
|
||||
"data": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"Bearer": {
|
||||
"accessToken=...;refreshToken=...": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"name": "Cookie",
|
||||
"in": "header"
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/auth.AuthBody"
|
||||
"$ref": "#/definitions/types.AuthBody"
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -36,10 +36,410 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/groups": {
|
||||
"get": {
|
||||
"description": "Returns array of groups and count",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Get groups (with pagination)",
|
||||
"parameters": [
|
||||
{
|
||||
"maximum": 100,
|
||||
"minimum": 10,
|
||||
"type": "integer",
|
||||
"description": "Count of rows",
|
||||
"name": "count",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Rows to skip",
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/types.JSONPagination"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create group with specified data",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Create group",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Request body",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.Group"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"description": "Update group with specified data",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Update group",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Request body",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.Group"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/groups/:id": {
|
||||
"get": {
|
||||
"description": "Returns group instance",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Get group by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "Group ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.Group"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete group by ID",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"groups"
|
||||
],
|
||||
"summary": "Delete group",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "Group ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/permissions": {
|
||||
"get": {
|
||||
"description": "Returns key-value map with permissions",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"summary": "Get list of permissions",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users": {
|
||||
"get": {
|
||||
"description": "Returns array of users and count",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Get users (with pagination)",
|
||||
"parameters": [
|
||||
{
|
||||
"maximum": 100,
|
||||
"minimum": 10,
|
||||
"type": "integer",
|
||||
"description": "Count of rows",
|
||||
"name": "count",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Rows to skip",
|
||||
"name": "offset",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/types.JSONPagination"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "Create user with specified data",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Create user",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Request body",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"description": "Update user with specified data",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Update user",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Request body",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/:id": {
|
||||
"get": {
|
||||
"description": "Returns user instance",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Get user by ID",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"description": "Delete user by ID",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"users"
|
||||
],
|
||||
"summary": "Delete user",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"auth.AuthBody": {
|
||||
"database.Group": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"deletedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"issuer": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
},
|
||||
"issuerID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/database.GroupPermission"
|
||||
}
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"users": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/database.User"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.GroupPermission": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"value": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database.User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"createdAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"deletedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"group": {
|
||||
"$ref": "#/definitions/database.Group"
|
||||
},
|
||||
"groupID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"isActive": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isRequiredToSetPassword": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"lastLogin": {
|
||||
"type": "string"
|
||||
},
|
||||
"passwordHash": {
|
||||
"type": "string"
|
||||
},
|
||||
"passwordLength": {
|
||||
"type": "integer"
|
||||
},
|
||||
"realName": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.AuthBody": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"email",
|
||||
@ -52,15 +452,38 @@
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"example": "Aasdfgh1!"
|
||||
"example": "Aasdfg1!"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.Cursor": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"currentPage": {
|
||||
"type": "integer"
|
||||
},
|
||||
"totalPages": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"types.JSONPagination": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cursor": {
|
||||
"$ref": "#/definitions/types.Cursor"
|
||||
},
|
||||
"data": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"Bearer": {
|
||||
"accessToken=...;refreshToken=...": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"name": "Cookie",
|
||||
"in": "header"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,91 @@
|
||||
basePath: /v1
|
||||
definitions:
|
||||
auth.AuthBody:
|
||||
database.Group:
|
||||
properties:
|
||||
createdAt:
|
||||
type: string
|
||||
deletedAt:
|
||||
type: string
|
||||
id:
|
||||
type: integer
|
||||
issuer:
|
||||
$ref: '#/definitions/database.User'
|
||||
issuerID:
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
permissions:
|
||||
items:
|
||||
$ref: '#/definitions/database.GroupPermission'
|
||||
type: array
|
||||
updatedAt:
|
||||
type: string
|
||||
users:
|
||||
items:
|
||||
$ref: '#/definitions/database.User'
|
||||
type: array
|
||||
type: object
|
||||
database.GroupPermission:
|
||||
properties:
|
||||
value:
|
||||
type: integer
|
||||
type: object
|
||||
database.User:
|
||||
properties:
|
||||
createdAt:
|
||||
type: string
|
||||
deletedAt:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
group:
|
||||
$ref: '#/definitions/database.Group'
|
||||
groupID:
|
||||
type: integer
|
||||
id:
|
||||
type: integer
|
||||
isActive:
|
||||
type: boolean
|
||||
isRequiredToSetPassword:
|
||||
type: boolean
|
||||
lastLogin:
|
||||
type: string
|
||||
passwordHash:
|
||||
type: string
|
||||
passwordLength:
|
||||
type: integer
|
||||
realName:
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
type: object
|
||||
types.AuthBody:
|
||||
properties:
|
||||
email:
|
||||
example: john@proton.mail
|
||||
type: string
|
||||
password:
|
||||
example: Aasdfgh1!
|
||||
example: Aasdfg1!
|
||||
type: string
|
||||
required:
|
||||
- email
|
||||
- password
|
||||
type: object
|
||||
types.Cursor:
|
||||
properties:
|
||||
count:
|
||||
type: integer
|
||||
currentPage:
|
||||
type: integer
|
||||
totalPages:
|
||||
type: number
|
||||
type: object
|
||||
types.JSONPagination:
|
||||
properties:
|
||||
cursor:
|
||||
$ref: '#/definitions/types.Cursor'
|
||||
data: {}
|
||||
type: object
|
||||
info:
|
||||
contact:
|
||||
name: https://peresvet.it
|
||||
@ -27,7 +101,7 @@ paths:
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/auth.AuthBody'
|
||||
$ref: '#/definitions/types.AuthBody'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@ -36,9 +110,216 @@ paths:
|
||||
summary: Request pair of tokens
|
||||
tags:
|
||||
- auth
|
||||
/groups:
|
||||
get:
|
||||
description: Returns array of groups and count
|
||||
parameters:
|
||||
- description: Count of rows
|
||||
in: query
|
||||
maximum: 100
|
||||
minimum: 10
|
||||
name: count
|
||||
required: true
|
||||
type: integer
|
||||
- description: Rows to skip
|
||||
in: query
|
||||
name: offset
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/types.JSONPagination'
|
||||
summary: Get groups (with pagination)
|
||||
tags:
|
||||
- groups
|
||||
patch:
|
||||
description: Update group with specified data
|
||||
parameters:
|
||||
- description: Request body
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/database.Group'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
summary: Update group
|
||||
tags:
|
||||
- groups
|
||||
post:
|
||||
description: Create group with specified data
|
||||
parameters:
|
||||
- description: Request body
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/database.Group'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
summary: Create group
|
||||
tags:
|
||||
- groups
|
||||
/groups/:id:
|
||||
delete:
|
||||
description: Delete group by ID
|
||||
parameters:
|
||||
- description: Group ID
|
||||
in: path
|
||||
minimum: 1
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
summary: Delete group
|
||||
tags:
|
||||
- groups
|
||||
get:
|
||||
description: Returns group instance
|
||||
parameters:
|
||||
- description: Group ID
|
||||
in: path
|
||||
minimum: 1
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/database.Group'
|
||||
summary: Get group by ID
|
||||
tags:
|
||||
- groups
|
||||
/permissions:
|
||||
get:
|
||||
description: Returns key-value map with permissions
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
additionalProperties:
|
||||
type: integer
|
||||
type: object
|
||||
summary: Get list of permissions
|
||||
/users:
|
||||
get:
|
||||
description: Returns array of users and count
|
||||
parameters:
|
||||
- description: Count of rows
|
||||
in: query
|
||||
maximum: 100
|
||||
minimum: 10
|
||||
name: count
|
||||
required: true
|
||||
type: integer
|
||||
- description: Rows to skip
|
||||
in: query
|
||||
name: offset
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/types.JSONPagination'
|
||||
summary: Get users (with pagination)
|
||||
tags:
|
||||
- users
|
||||
patch:
|
||||
description: Update user with specified data
|
||||
parameters:
|
||||
- description: Request body
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/database.User'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
summary: Update user
|
||||
tags:
|
||||
- users
|
||||
post:
|
||||
description: Create user with specified data
|
||||
parameters:
|
||||
- description: Request body
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/database.User'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
summary: Create user
|
||||
tags:
|
||||
- users
|
||||
/users/:id:
|
||||
delete:
|
||||
description: Delete user by ID
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
minimum: 1
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
summary: Delete user
|
||||
tags:
|
||||
- users
|
||||
get:
|
||||
description: Returns user instance
|
||||
parameters:
|
||||
- description: User ID
|
||||
in: path
|
||||
minimum: 1
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/database.User'
|
||||
summary: Get user by ID
|
||||
tags:
|
||||
- users
|
||||
securityDefinitions:
|
||||
Bearer:
|
||||
accessToken=...;refreshToken=...:
|
||||
in: header
|
||||
name: Authorization
|
||||
name: Cookie
|
||||
type: apiKey
|
||||
swagger: "2.0"
|
||||
|
||||
2
go.mod
2
go.mod
@ -3,13 +3,11 @@ module system-trace/core
|
||||
go 1.22.3
|
||||
|
||||
require (
|
||||
github.com/go-playground/validator v9.31.0+incompatible
|
||||
github.com/go-playground/validator/v10 v10.20.0
|
||||
github.com/goccy/go-json v0.10.2
|
||||
github.com/gofiber/fiber v1.14.6
|
||||
github.com/gofiber/fiber/v2 v2.52.4
|
||||
github.com/gofiber/swagger v1.0.0
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/swaggo/swag v1.16.3
|
||||
|
||||
16
go.sum
16
go.sum
@ -27,13 +27,12 @@ github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA=
|
||||
github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
@ -46,8 +45,6 @@ github.com/gofiber/swagger v1.0.0 h1:BzUzDS9ZT6fDUa692kxmfOjc1DZiloLiPK/W5z1H1tc
|
||||
github.com/gofiber/swagger v1.0.0/go.mod h1:QrYNF1Yrc7ggGK6ATsJ6yfH/8Zi5bu9lA7wB8TmCecg=
|
||||
github.com/gofiber/utils v0.0.10 h1:3Mr7X7JdCUo7CWf/i5sajSaDmArEDtti8bM1JUVso2U=
|
||||
github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo=
|
||||
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/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
@ -66,6 +63,7 @@ github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ib
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
@ -84,13 +82,16 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@ -105,6 +106,7 @@ github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
|
||||
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
|
||||
github.com/tetratelabs/wazero v1.7.0 h1:jg5qPydno59wqjpGrHph81lbtHzTrWzwwtD4cD88+hQ=
|
||||
github.com/tetratelabs/wazero v1.7.0/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=
|
||||
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
|
||||
github.com/uptrace/bun v1.2.1 h1:2ENAcfeCfaY5+2e7z5pXrzFKy3vS8VXvkCag6N2Yzfk=
|
||||
@ -130,10 +132,14 @@ github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAh
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
github.com/wasilibs/go-re2 v1.5.2 h1:fDO2TJrRzRrv3jD0gzOvmZ2UM4Yt9YXOEdLrlNc/Ies=
|
||||
github.com/wasilibs/go-re2 v1.5.2/go.mod h1:UqqxQ1O99boQUm1r61H/IYGiGQOS/P88K7hU5nLNkEg=
|
||||
github.com/wasilibs/nottinygc v0.4.0 h1:h1TJMihMC4neN6Zq+WKpLxgd9xCFMw7O9ETLwY2exJQ=
|
||||
github.com/wasilibs/nottinygc v0.4.0/go.mod h1:oDcIotskuYNMpqMF23l7Z8uzD4TC0WXHK8jetlB3HIo=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
@ -151,6 +157,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
@ -161,6 +168,7 @@ golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
|
||||
7
main.go
7
main.go
@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"system-trace/core/app"
|
||||
"system-trace/core/database"
|
||||
"system-trace/core/environment"
|
||||
"system-trace/core/validators"
|
||||
@ -11,13 +10,13 @@ import (
|
||||
// @version 1.0
|
||||
// @contact.name https://peresvet.it
|
||||
// @BasePath /v1
|
||||
// @securityDefinitions.apikey Bearer
|
||||
// @securityDefinitions.apikey accessToken=...;refreshToken=...
|
||||
// @in header
|
||||
// @name Authorization
|
||||
// @name Cookie
|
||||
// @externalDocs.description OpenAPI
|
||||
func main() {
|
||||
environment.Load()
|
||||
validators.RegisterValidators()
|
||||
database.Connect()
|
||||
app.Serve()
|
||||
serveApp()
|
||||
}
|
||||
|
||||
@ -3,15 +3,17 @@ package middlewares
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"system-trace/core/app/constants"
|
||||
"system-trace/core/auth"
|
||||
"system-trace/core/constants"
|
||||
"system-trace/core/database"
|
||||
"system-trace/core/modules/auth"
|
||||
"system-trace/core/types"
|
||||
"system-trace/core/utils"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func ValidateSession(c *fiber.Ctx) error {
|
||||
p := new(auth.PairTokens)
|
||||
p := new(types.PairTokens)
|
||||
if err := c.CookieParser(p); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": err.Error(),
|
||||
@ -26,7 +28,7 @@ func ValidateSession(c *fiber.Ctx) error {
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func validatePair(c *fiber.Ctx, p *auth.PairTokens) bool {
|
||||
func validatePair(c *fiber.Ctx, p *types.PairTokens) bool {
|
||||
if len(p.AccessToken) <= 0 || len(p.RefreshToken) <= 0 {
|
||||
return false
|
||||
}
|
||||
@ -39,12 +41,12 @@ func validatePair(c *fiber.Ctx, p *auth.PairTokens) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
pt, err := auth.GetPair(p)
|
||||
pt, err := database.GetPairOfTokens(p)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
err = auth.RevokePair(p)
|
||||
err = database.RevokePairOfTokens(p)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
21
parsers/order_by.go
Normal file
21
parsers/order_by.go
Normal file
@ -0,0 +1,21 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
"system-trace/core/types"
|
||||
"system-trace/core/validators"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func ParseOrder(c *fiber.Ctx) (*types.OrderBy, error) {
|
||||
ob := new(types.OrderBy)
|
||||
if err := c.QueryParser(ob); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := validators.Validate(c, ob); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ob, nil
|
||||
}
|
||||
21
parsers/pagination.go
Normal file
21
parsers/pagination.go
Normal file
@ -0,0 +1,21 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
"system-trace/core/types"
|
||||
"system-trace/core/validators"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func ParsePagination(c *fiber.Ctx) (*types.Pagination, error) {
|
||||
p := new(types.Pagination)
|
||||
if err := c.QueryParser(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := validators.Validate(c, p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
44
router.go
Normal file
44
router.go
Normal file
@ -0,0 +1,44 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "system-trace/core/docs"
|
||||
"system-trace/core/services"
|
||||
"system-trace/core/services/auth"
|
||||
"system-trace/core/services/groups"
|
||||
"system-trace/core/services/users"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/swagger"
|
||||
)
|
||||
|
||||
func initRouter(app *fiber.App) {
|
||||
app.Get("/swagger/*", swagger.HandlerDefault)
|
||||
v1 := app.Group("/v1")
|
||||
{
|
||||
|
||||
v1.Get("/permissions", services.GetPermissions)
|
||||
|
||||
ag := v1.Group("/auth")
|
||||
{
|
||||
ag.Post("/login", auth.ReqTokensHandler)
|
||||
}
|
||||
|
||||
gg := v1.Group("/groups")
|
||||
{
|
||||
gg.Get("", groups.GetGroupsHandler)
|
||||
gg.Get("/:id", groups.GetGroupByIDHandler)
|
||||
gg.Post("", groups.CreateGroupHandler)
|
||||
gg.Patch("", groups.UpdateGroupHandler)
|
||||
gg.Delete("/:id", groups.DeleteGroupHandler)
|
||||
}
|
||||
|
||||
ug := v1.Group("/users")
|
||||
{
|
||||
ug.Get("", users.GetUsersHandler)
|
||||
ug.Get("/:id", users.GetUserByIDHandler)
|
||||
ug.Post("", users.CreateUserHandler)
|
||||
ug.Patch("", users.UpdateUserHandler)
|
||||
ug.Delete("/:id", users.DeleteUserHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
58
server.go
Normal file
58
server.go
Normal file
@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"system-trace/core/constants"
|
||||
"system-trace/core/environment"
|
||||
"system-trace/core/types"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
)
|
||||
|
||||
var Instance *fiber.App
|
||||
|
||||
func serveApp() {
|
||||
Instance = initServer()
|
||||
Instance.Use(recover.New())
|
||||
Instance.Use(cors.New())
|
||||
// Instance.Use(middlewares.ValidateSession)
|
||||
initRouter(Instance)
|
||||
Instance.Use(func(c *fiber.Ctx) error {
|
||||
return c.
|
||||
Status(fiber.StatusNotFound).
|
||||
JSON(types.JSONError{
|
||||
Error: constants.NOT_FOUND,
|
||||
})
|
||||
})
|
||||
printRoutes(Instance)
|
||||
Instance.Listen(":" + os.Getenv("APP_PORT"))
|
||||
}
|
||||
|
||||
func initServer() *fiber.App {
|
||||
return fiber.New(fiber.Config{
|
||||
JSONEncoder: json.Marshal,
|
||||
JSONDecoder: json.Unmarshal,
|
||||
CaseSensitive: true,
|
||||
Prefork: true,
|
||||
AppName: "System Trace API",
|
||||
ErrorHandler: func(c *fiber.Ctx, err error) error {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func printRoutes(app *fiber.App) {
|
||||
debug := environment.IsDebug()
|
||||
|
||||
if !fiber.IsChild() && debug {
|
||||
data, _ := json.MarshalIndent(app.GetRoutes(true), "", " ")
|
||||
fmt.Print(string(data))
|
||||
}
|
||||
}
|
||||
@ -2,34 +2,41 @@ package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"system-trace/core/app/constants"
|
||||
"system-trace/core/users"
|
||||
"system-trace/core/constants"
|
||||
"system-trace/core/database"
|
||||
"system-trace/core/services/users"
|
||||
"system-trace/core/types"
|
||||
"system-trace/core/validators"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// ReqTokens godoc
|
||||
// MARK: ReqTokens godoc
|
||||
// @Summary Request pair of tokens
|
||||
// @Description Returns pair of access and refresh tokens
|
||||
// @Tags auth
|
||||
// @Produce json
|
||||
// @Param request body AuthBody true "Request body"
|
||||
// @Header 200 {string} Token "accessToken=..."
|
||||
// @Param request body types.AuthBody true "Request body"
|
||||
// @Header 200 {string} Set-Cookie "accessToken=..."
|
||||
// @Header 200 {string} Set-Cookie "refreshToken=..."
|
||||
// @Success 200
|
||||
// @Router /auth/login [post]
|
||||
func ReqTokens(c *fiber.Ctx) error {
|
||||
ab := new(AuthBody)
|
||||
func ReqTokensHandler(c *fiber.Ctx) error {
|
||||
ab := new(types.AuthBody)
|
||||
if err := c.BodyParser(ab); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validators.Validate(c, ab); err != nil {
|
||||
return err
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
u, err := users.FindByEmailAndPassword(ab.Email, ab.Password)
|
||||
if err := validators.Validate(c, ab); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
u, err := database.FindByEmailAndPassword(ab.Email, ab.Password)
|
||||
if err != nil {
|
||||
e := err.Error()
|
||||
if e == "sql: no rows in result set" {
|
||||
@ -37,17 +44,18 @@ func ReqTokens(c *fiber.Ctx) error {
|
||||
}
|
||||
return c.
|
||||
Status(fiber.StatusBadRequest).
|
||||
JSON(fiber.Map{
|
||||
"error": e,
|
||||
JSON(types.JSONError{
|
||||
Error: e,
|
||||
})
|
||||
}
|
||||
|
||||
if u != nil {
|
||||
err = GeneratePairAndSetCookie(c, u.ID)
|
||||
if err != nil {
|
||||
return c.
|
||||
Status(fiber.StatusBadRequest).
|
||||
JSON(fiber.Map{
|
||||
"error": err.Error(),
|
||||
JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -55,8 +63,8 @@ func ReqTokens(c *fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return c.
|
||||
Status(fiber.StatusBadRequest).
|
||||
JSON(fiber.Map{
|
||||
"error": err.Error(),
|
||||
JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
@ -75,7 +83,7 @@ func GeneratePairAndSetCookie(c *fiber.Ctx, id int32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setCookie(c *fiber.Ctx, p *PairTokens) {
|
||||
func setCookie(c *fiber.Ctx, p *types.PairTokens) {
|
||||
// Access token
|
||||
atc := new(fiber.Cookie)
|
||||
atc.Name = "accessToken"
|
||||
@ -2,7 +2,9 @@ package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"system-trace/core/app/constants"
|
||||
"system-trace/core/constants"
|
||||
"system-trace/core/database"
|
||||
"system-trace/core/types"
|
||||
"system-trace/core/utils"
|
||||
"time"
|
||||
|
||||
@ -14,18 +16,18 @@ const (
|
||||
RefreshTokenLifetime int8 = 24
|
||||
)
|
||||
|
||||
func genPair(id int32) (*PairTokens, error) {
|
||||
func genPair(id int32) (*types.PairTokens, error) {
|
||||
at, rt, err := genTokens(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = insertPair(id, at, rt)
|
||||
err = database.InsertPairOfTokens(id, at, rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := PairTokens{
|
||||
p := types.PairTokens{
|
||||
AccessToken: at,
|
||||
RefreshToken: rt,
|
||||
}
|
||||
160
services/groups/groups.go
Normal file
160
services/groups/groups.go
Normal file
@ -0,0 +1,160 @@
|
||||
package groups
|
||||
|
||||
import (
|
||||
"system-trace/core/database"
|
||||
"system-trace/core/parsers"
|
||||
"system-trace/core/types"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// MARK: GetGroups godoc
|
||||
// @Summary Get groups (with pagination)
|
||||
// @Description Returns array of groups and count
|
||||
// @Tags groups
|
||||
// @Produce json
|
||||
// @Param count query int true "Count of rows" minimum(10) maximum(100)
|
||||
// @Param offset query int true "Rows to skip" minumum(0)
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200 {object} types.JSONPagination
|
||||
// @Router /groups [get]
|
||||
func GetGroupsHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
p, err := parsers.ParsePagination(c)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
ob, err := parsers.ParseOrder(c)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
groups, cursor, err := database.FindGroups(p, ob)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(types.JSONPagination{
|
||||
Data: groups,
|
||||
Cursor: cursor,
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: GetGroupByID godoc
|
||||
// @Summary Get group by ID
|
||||
// @Description Returns group instance
|
||||
// @Tags groups
|
||||
// @Produce json
|
||||
// @Param id path int true "Group ID" minimum(1)
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200 {object} database.Group
|
||||
// @Router /groups/:id [get]
|
||||
func GetGroupByIDHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
id, err := c.ParamsInt("id")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
group, err := database.FindGroupByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(group)
|
||||
}
|
||||
|
||||
// MARK: CreateGroup godoc
|
||||
// @Summary Create group
|
||||
// @Description Create group with specified data
|
||||
// @Tags groups
|
||||
// @Produce json
|
||||
// @Param request body database.Group true "Request body"
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200
|
||||
// @Router /groups [post]
|
||||
func CreateGroupHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
g := new(database.Group)
|
||||
if err := c.BodyParser(g); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
err := database.InsertGroup(g)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
// MARK: UpdateGroup godoc
|
||||
// @Summary Update group
|
||||
// @Description Update group with specified data
|
||||
// @Tags groups
|
||||
// @Produce json
|
||||
// @Param request body database.Group true "Request body"
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200
|
||||
// @Router /groups [patch]
|
||||
func UpdateGroupHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
g := new(database.Group)
|
||||
if err := c.BodyParser(g); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
err := database.UpdateGroup(g, []string{"*"})
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
// MARK: DeleteGroup godoc
|
||||
// @Summary Delete group
|
||||
// @Description Delete group by ID
|
||||
// @Tags groups
|
||||
// @Produce json
|
||||
// @Param id path int true "Group ID" minimum(1)
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200
|
||||
// @Router /groups/:id [delete]
|
||||
func DeleteGroupHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
id, err := c.ParamsInt("id")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
err = database.DeleteGroup(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
18
services/misc.go
Normal file
18
services/misc.go
Normal file
@ -0,0 +1,18 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"system-trace/core/constants/permissions"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// MARK: GetPermissions godoc
|
||||
// @Summary Get list of permissions
|
||||
// @Description Returns key-value map with permissions
|
||||
// @Produce json
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200 {object} map[string]int8
|
||||
// @Router /permissions [get]
|
||||
func GetPermissions(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(permissions.All)
|
||||
}
|
||||
166
services/users/users.go
Normal file
166
services/users/users.go
Normal file
@ -0,0 +1,166 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"system-trace/core/database"
|
||||
"system-trace/core/parsers"
|
||||
"system-trace/core/types"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// MARK: GetUsers godoc
|
||||
// @Summary Get users (with pagination)
|
||||
// @Description Returns array of users and count
|
||||
// @Tags users
|
||||
// @Produce json
|
||||
// @Param count query int true "Count of rows" minimum(10) maximum(100)
|
||||
// @Param offset query int true "Rows to skip" minumum(0)
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200 {object} types.JSONPagination
|
||||
// @Router /users [get]
|
||||
func GetUsersHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
p, err := parsers.ParsePagination(c)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
ob, err := parsers.ParseOrder(c)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
users, cursor, err := database.FindUsers(p, ob)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(types.JSONPagination{
|
||||
Data: users,
|
||||
Cursor: cursor,
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: GetUserByID godoc
|
||||
// @Summary Get user by ID
|
||||
// @Description Returns user instance
|
||||
// @Tags users
|
||||
// @Produce json
|
||||
// @Param id path int true "User ID" minimum(1)
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200 {object} database.User
|
||||
// @Router /users/:id [get]
|
||||
func GetUserByIDHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
id, err := c.ParamsInt("id")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
user, err := database.FindUserByID(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(user)
|
||||
}
|
||||
|
||||
// MARK: CreateUser godoc
|
||||
// @Summary Create user
|
||||
// @Description Create user with specified data
|
||||
// @Tags users
|
||||
// @Produce json
|
||||
// @Param request body database.User true "Request body"
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200
|
||||
// @Router /users [post]
|
||||
func CreateUserHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
u := new(database.User)
|
||||
if err := c.BodyParser(u); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
err := database.InsertUser(u)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
// MARK: UpdateUser godoc
|
||||
// @Summary Update user
|
||||
// @Description Update user with specified data
|
||||
// @Tags users
|
||||
// @Produce json
|
||||
// @Param request body database.User true "Request body"
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200
|
||||
// @Router /users [patch]
|
||||
func UpdateUserHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
u := new(database.User)
|
||||
if err := c.BodyParser(u); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
err := database.UpdateUser(u, []string{"*"})
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
// MARK: DeleteUser godoc
|
||||
// @Summary Delete user
|
||||
// @Description Delete user by ID
|
||||
// @Tags users
|
||||
// @Produce json
|
||||
// @Param id path int true "User ID" minimum(1)
|
||||
// @Header 200 {string} Token "accessToken=...;refreshToken=..."
|
||||
// @Success 200
|
||||
// @Router /users/:id [delete]
|
||||
func DeleteUserHandler(c *fiber.Ctx) error {
|
||||
// TODO permission validate
|
||||
id, err := c.ParamsInt("id")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
err = database.DeleteUser(id)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(types.JSONError{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusOK)
|
||||
}
|
||||
|
||||
func SetLoginTime(u *database.User) error {
|
||||
u.LastLogin = time.Now()
|
||||
return database.UpdateUser(u, []string{"last_login"})
|
||||
}
|
||||
6
types/order_by.go
Normal file
6
types/order_by.go
Normal file
@ -0,0 +1,6 @@
|
||||
package types
|
||||
|
||||
type OrderBy struct {
|
||||
Key string `validate:"required"`
|
||||
Order string `validate:"required,endswith=sc"`
|
||||
}
|
||||
13
types/pagination.go
Normal file
13
types/pagination.go
Normal file
@ -0,0 +1,13 @@
|
||||
package types
|
||||
|
||||
type Pagination struct {
|
||||
Count int `query:"count" validate:"required,min=10,max=100"`
|
||||
Page int `query:"page" validate:"required,min=1"`
|
||||
}
|
||||
|
||||
type Cursor struct {
|
||||
Count int `json:"count"`
|
||||
CurrentPage int `json:"currentPage"`
|
||||
TotalPages float64 `json:"totalPages"`
|
||||
TotalRows float64 `json:"totalRows"`
|
||||
}
|
||||
10
types/response.go
Normal file
10
types/response.go
Normal file
@ -0,0 +1,10 @@
|
||||
package types
|
||||
|
||||
type JSONPagination struct {
|
||||
Data interface{} `json:"data"`
|
||||
Cursor *Cursor `json:"cursor"`
|
||||
}
|
||||
|
||||
type JSONError struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package auth
|
||||
package types
|
||||
|
||||
type PairTokens struct {
|
||||
AccessToken string `json:"accessToken" cookie:"accessToken"`
|
||||
32
users/sql.go
32
users/sql.go
@ -1,32 +0,0 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"context"
|
||||
"system-trace/core/database"
|
||||
"system-trace/core/database/entities"
|
||||
"system-trace/core/utils"
|
||||
)
|
||||
|
||||
func FindByEmailAndPassword(email, password string) (*entities.User, error) {
|
||||
passwordHash := utils.SHA256(password)
|
||||
ctx := context.Background()
|
||||
u := new(entities.User)
|
||||
err := database.PG.NewSelect().
|
||||
Model(u).
|
||||
Where("email = ?", email).
|
||||
Where("password_hash = ?", passwordHash).
|
||||
Scan(ctx)
|
||||
|
||||
return u, err
|
||||
}
|
||||
|
||||
func UpdateUser(u *entities.User, cols []string) error {
|
||||
ctx := context.Background()
|
||||
_, err := database.PG.NewUpdate().
|
||||
Model(u).
|
||||
Column(cols...).
|
||||
WherePK().
|
||||
Exec(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"system-trace/core/database/entities"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func Get(c *fiber.Ctx) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetLoginTime(u *entities.User) error {
|
||||
u.LastLogin = time.Now()
|
||||
return UpdateUser(u, []string{"last_login"})
|
||||
}
|
||||
@ -36,7 +36,7 @@ func Validate(c *fiber.Ctx, data interface{}) error {
|
||||
|
||||
for _, err := range errs {
|
||||
errMsgs = append(errMsgs, fmt.Sprintf(
|
||||
"field '%s' needs to implement '%s' rule",
|
||||
"validator:'%s'/'%s'",
|
||||
err.FailedField,
|
||||
err.Tag,
|
||||
))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user