Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #26 from swibly/feat/extra-user-props
Browse files Browse the repository at this point in the history
feat: `Country` and `Language` fields to `User`
devkcud authored Jun 8, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 962626a + ae7a89a commit 66cb742
Showing 6 changed files with 91 additions and 15 deletions.
8 changes: 8 additions & 0 deletions internal/controller/http/v1/auth.go
Original file line number Diff line number Diff line change
@@ -35,6 +35,14 @@ func RegisterHandler(ctx *gin.Context) {
return
}

if errs := utils.ValidateStruct(&body); errs != nil {
err := utils.ValidateErrorMessage(errs[0])

log.Print(err)
ctx.JSON(http.StatusBadRequest, gin.H{"error": gin.H{err.Param: err.Message}})
return
}

user, err := service.User.CreateUser(body.FirstName, body.LastName, body.Username, body.Email, body.Password)

if err == nil {
6 changes: 6 additions & 0 deletions internal/model/dto/user.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dto

import "github.com/devkcud/arkhon-foundation/arkhon-api/pkg/language"

type UserRegister struct {
FirstName string `validate:"required,min=3" json:"firstname"`
LastName string `validate:"required,min=3" json:"lastname"`
@@ -29,4 +31,8 @@ type UserUpdate struct {

// NOTE: Notification and Show structs will be in another method/route to update
// due to the nature of structs being a pain in the ass to work with :/

Country string `validate:"omitempty" json:"country"`

Language language.Language `validate:"omitempty,mustbesupportedlanguage" json:"language"`
}
29 changes: 16 additions & 13 deletions internal/model/user.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package model
import (
"time"

"github.com/devkcud/arkhon-foundation/arkhon-api/pkg/language"
"gorm.io/gorm"
)

@@ -28,23 +29,25 @@ type User struct {
// TODO: Add comments, the last implementation was wacky to say the least.

Notification struct {
InApp int `gorm:"default:1" json:"inapp"`
Email int `gorm:"default:-1" json:"email"`
InApp int `gorm:"default:1"`
Email int `gorm:"default:-1"`
// SMS int `gorm:"default:-1"` // NOTE: Not sure if we want to send SMS, it can get expensive
} `gorm:"embedded;embeddedPrefix:notify_"`

Show struct {
Profile int `gorm:"default:1" json:"profile"`
Image int `gorm:"default:1" json:"image"`
Comments int `gorm:"default:1" json:"comments"`
Favorites int `gorm:"default:1" json:"favorites"`
Projects int `gorm:"default:1" json:"projects"`
Components int `gorm:"default:1" json:"components"`
Followers int `gorm:"default:1" json:"followers"`
Following int `gorm:"default:1" json:"following"`
Inventory int `gorm:"default:-1" json:"inventory"`
Formations int `gorm:"default:1" json:"formations"`
Profile int `gorm:"default:1"`
Image int `gorm:"default:1"`
Comments int `gorm:"default:1"`
Favorites int `gorm:"default:1"`
Projects int `gorm:"default:1"`
Components int `gorm:"default:1"`
Followers int `gorm:"default:1"`
Following int `gorm:"default:1"`
Inventory int `gorm:"default:-1"`
Formations int `gorm:"default:1"`
} `gorm:"embedded;embeddedPrefix:show_"`

// TODO: Implement enums Language, Theme and Country (country shouldnt be an enum)
Country string // Country can be anything really

Language language.Language `gorm:"type:enum_language;default:pt"`
}
27 changes: 25 additions & 2 deletions pkg/db/postgres.go
Original file line number Diff line number Diff line change
@@ -3,16 +3,35 @@ package db
import (
"fmt"
"log"
"strings"

"github.com/devkcud/arkhon-foundation/arkhon-api/config"
"github.com/devkcud/arkhon-foundation/arkhon-api/internal/model"
"github.com/devkcud/arkhon-foundation/arkhon-api/pkg/language"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)

var Postgres *gorm.DB

func typeCheckAndCreate(db *gorm.DB, typeName string, values []string) error {
var typeExists bool
err := db.Raw("SELECT EXISTS (SELECT 1 FROM pg_type WHERE typname =?)", typeName).Scan(&typeExists).Error
if err != nil {
return fmt.Errorf("error checking type existence: %w", err)
}

if !typeExists {
err := db.Exec("CREATE TYPE %s AS ENUM (%s)", typeName, strings.Join(values, ", ")).Error
if err != nil {
return fmt.Errorf("error creating type: %w", err)
}
}

return nil
}

func Load() {
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=5432 sslmode=%s", config.Postgres.Host, config.Postgres.User, config.Postgres.Password, config.Postgres.DB, config.Postgres.SSLMode)
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
@@ -27,6 +46,12 @@ func Load() {

log.Print("Loaded Database")

if err := typeCheckAndCreate(Postgres, "enum_language", language.ArrayString); err != nil {
log.Fatal(err)
}

log.Print("Loaded migrations")

if err := Postgres.AutoMigrate(
&model.User{},
&model.Follower{},
@@ -43,6 +68,4 @@ func Load() {
{Name: config.Permissions.ManageProjects},
{Name: config.Permissions.ManageStore},
})

log.Print("Loaded migrations")
}
19 changes: 19 additions & 0 deletions pkg/language/general.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package language

type Language string

// NOTE: Some languages might not be available at launch of the API, like Russian or Portuguese (which are planned at the moment)

// Officially supported
const (
PT Language = "pt" // Portuguese
EN Language = "en" // English
RU Language = "ru" // Russian
)

// Some utilities

var (
Array = []Language{PT, EN, RU}
ArrayString = []string{string(PT), string(EN), string(RU)}
)
17 changes: 17 additions & 0 deletions pkg/utils/validator.go
Original file line number Diff line number Diff line change
@@ -3,7 +3,9 @@ package utils
import (
"fmt"
"regexp"
"strings"

"github.com/devkcud/arkhon-foundation/arkhon-api/pkg/language"
"github.com/go-playground/validator/v10"
)

@@ -21,6 +23,16 @@ func (pe ParamError) Error() string {
func newValidator() *validator.Validate {
vv := validator.New()

vv.RegisterValidation("mustbesupportedlanguage", func(fl validator.FieldLevel) bool {
lang := fl.Field().String()

if lang != string(language.EN) && lang != string(language.PT) && lang != string(language.RU) {
return false
}

return true
})

vv.RegisterValidation("username", func(fl validator.FieldLevel) bool {
if fl.Field().Len() > 32 {
return false
@@ -95,6 +107,11 @@ func ValidateErrorMessage(fe validator.FieldError) ParamError {
Param: fe.Field(),
Message: fmt.Sprintf("%s is required", fe.Field()),
}
case "mustbesupportedlanguage":
return ParamError{
Param: fe.Field(),
Message: fmt.Sprintf("%s must be %s", fe.Field(), strings.Join(language.ArrayString, ", ")),
}
case "username":
return ParamError{
Param: fe.Field(),

0 comments on commit 66cb742

Please sign in to comment.