You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
7.5 KiB
220 lines
7.5 KiB
package main
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.devices.local/mawas/golang-api-skeleton/cmd"
|
|
"git.devices.local/mawas/golang-api-skeleton/lib/cache"
|
|
"git.devices.local/mawas/golang-api-skeleton/lib/common"
|
|
"git.devices.local/mawas/golang-api-skeleton/lib/config"
|
|
"git.devices.local/mawas/golang-api-skeleton/lib/database"
|
|
"git.devices.local/mawas/golang-api-skeleton/lib/utils"
|
|
"git.devices.local/mawas/golang-api-skeleton/models"
|
|
"git.devices.local/mawas/golang-api-skeleton/repositories"
|
|
"git.devices.local/mawas/golang-api-skeleton/services"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// https://towardsdatascience.com/building-restful-apis-in-golang-e3fe6e3f8f95
|
|
// https://www.voile.com/voile-straps.html
|
|
|
|
// FIXME how to set unique index for username to make soft deletes possible but disallow duplicates... also how to cache a username which got delete and recerated... user ID would get overwritten, maybe pre/suffix deleted username?
|
|
// TODO use badgerdb for permissions? path:[token1, token2...]
|
|
// TODO add database loadbalancing feature... so allow more hosts use first as default and other ones as fallback
|
|
// TODO usrid and username for cli user is hardcoded.. no need to live in database
|
|
// TODO get-stats cli command... which means unix socket support to communicate with server
|
|
// TODO data versioning which will be used as reference from the log, also with predictive analytics for restore which means versioning of reference objects needs to be considered
|
|
// TODO request body store as reference for log
|
|
// TODO because their is a badgerdb cache which tokens are existing or which userids are existing make an existence check at uuid generation just do be sure
|
|
|
|
var (
|
|
Version string // allows to set version on build
|
|
APPName string // allows to overwrite app name on build
|
|
APPDescription string // allows to overwrite app description on build
|
|
)
|
|
|
|
func main() {
|
|
log.SetFormatter(&log.JSONFormatter{})
|
|
log.SetOutput(os.Stdout)
|
|
hostname, err := os.Hostname()
|
|
if err != nil {
|
|
hostname = "unknown"
|
|
}
|
|
contextLogger := log.WithFields(log.Fields{
|
|
"host": hostname,
|
|
"version": Version,
|
|
"app": APPName,
|
|
})
|
|
// cobra sets env if flag is given so that viper can pick it up
|
|
cfgFile, flagCfg, err := cmd.Initialize(Version, APPName, APPDescription)
|
|
if err != nil {
|
|
os.Exit(1)
|
|
}
|
|
// config priority: flags > env > config file
|
|
if err := config.Initialize(APPName, cfgFile, flagCfg); err != nil {
|
|
contextLogger.WithFields(log.Fields{
|
|
"module": "config",
|
|
}).Fatal(err)
|
|
}
|
|
|
|
// bootstrap cache
|
|
c, err := cache.Bootstrap()
|
|
if err != nil {
|
|
contextLogger.WithFields(log.Fields{
|
|
"module": "cache",
|
|
}).Fatal(err)
|
|
}
|
|
defer c.Close()
|
|
db, err := database.Connect(database.Credentials{
|
|
Host: viper.GetString("database.host"),
|
|
Port: viper.GetInt("database.port"),
|
|
Dialect: viper.GetString("database.dialect"),
|
|
Database: viper.GetString("database.database"),
|
|
User: viper.GetString("database.user"),
|
|
Password: viper.GetString("database.password"),
|
|
MaxOpenConn: viper.GetInt("database.port"),
|
|
MaxIdleConn: viper.GetInt("database.port"),
|
|
MaxLifeTime: viper.GetInt("database.port"),
|
|
Debug: true,
|
|
})
|
|
if err != nil {
|
|
contextLogger.WithFields(log.Fields{
|
|
"module": "database",
|
|
}).Fatal(err)
|
|
}
|
|
|
|
db.AutoMigrate(&models.User{})
|
|
db.AutoMigrate(&models.Token{})
|
|
userRepo := repositories.NewUserRepository(db, common.GUID{}, "", nil)
|
|
userService := services.NewUserService(userRepo)
|
|
|
|
// Prefill cache
|
|
// TODO also add deleted users to cache for old references
|
|
if userData, err := userService.ReadAll(); err != nil {
|
|
contextLogger.WithFields(log.Fields{
|
|
"module": "userService",
|
|
}).Fatal(err)
|
|
} else {
|
|
for i := range userData {
|
|
if err := c.Set("user:"+userData[i].ID.String(), userData[i].Username); err != nil { // userID -> username mapping
|
|
contextLogger.WithFields(log.Fields{
|
|
"module": "cache",
|
|
}).Fatal(err)
|
|
}
|
|
if err := c.Set("user:"+userData[i].Username, userData[i].ID.String()); err != nil { // username -> userID mapping
|
|
contextLogger.WithFields(log.Fields{
|
|
"module": "cache",
|
|
}).Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
var userID common.GUID
|
|
firstname := strings.ToLower(utils.RandString(utils.RandInt(5, 10)))
|
|
lastname := strings.ToLower(utils.RandString(utils.RandInt(6, 14)))
|
|
username := string([]byte(firstname)[0]) + lastname
|
|
user1 := &models.User{
|
|
Username: username,
|
|
Firstname: strings.ToUpper(string([]byte(firstname)[0])) + string([]byte(firstname)[1:]),
|
|
Lastname: strings.ToUpper(string([]byte(lastname)[0])) + string([]byte(lastname)[1:]),
|
|
Email: username + "@acme.inc",
|
|
}
|
|
if result, err := userService.Create(user1); err != nil {
|
|
panic(err)
|
|
} else {
|
|
utils.PrettyPrintJSON(result)
|
|
if err := c.Set("user:"+result.ID.String(), result.Username); err != nil { // userID -> username mapping
|
|
contextLogger.WithFields(log.Fields{
|
|
"module": "cache",
|
|
}).Fatal(err)
|
|
}
|
|
if err := c.Set("user:"+result.Username, result.ID.String()); err != nil { // username -> userID mapping
|
|
contextLogger.WithFields(log.Fields{
|
|
"module": "cache",
|
|
}).Fatal(err)
|
|
}
|
|
userID = result.ID
|
|
}
|
|
|
|
userRepo = repositories.NewUserRepository(db, userID, username, c)
|
|
userService = services.NewUserService(userRepo)
|
|
// userID db context?
|
|
// k := common.UsernameContextKey("username")
|
|
// ctx := context.WithValue(context.Background(), "username", username)
|
|
// db = db.WithContext(ctx)
|
|
// db = db.Set("username", username)
|
|
// fmt.Println(db.Get("username"))
|
|
|
|
// create example token
|
|
tokenRepo := repositories.NewTokenRepository(db, userID, username, c)
|
|
tokenService := services.NewTokenService(tokenRepo)
|
|
token1 := &models.Token{
|
|
ExpiresAt: time.Now().Add(24 * time.Hour),
|
|
UserID: userID,
|
|
Active: true,
|
|
}
|
|
if result1, err := tokenService.Create(token1); err != nil {
|
|
panic(err)
|
|
} else {
|
|
utils.PrettyPrintJSON(result1)
|
|
}
|
|
|
|
result1, err := tokenService.ReadAll()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
utils.PrettyPrintJSON(result1)
|
|
|
|
result, err := userService.ReadAll()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
utils.PrettyPrintJSON(result)
|
|
|
|
firstname2 := strings.ToLower(utils.RandString(utils.RandInt(5, 10)))
|
|
lastname2 := strings.ToLower(utils.RandString(utils.RandInt(6, 14)))
|
|
username2 := string([]byte(firstname2)[0]) + lastname2
|
|
user2 := &models.User{
|
|
Username: username2,
|
|
Firstname: strings.ToUpper(string([]byte(firstname2)[0])) + string([]byte(firstname2)[1:]),
|
|
Lastname: strings.ToUpper(string([]byte(lastname2)[0])) + string([]byte(lastname2)[1:]),
|
|
Email: username2 + "@acme.inc",
|
|
}
|
|
if result, err := userService.Create(user2); err != nil {
|
|
panic(err)
|
|
} else {
|
|
utils.PrettyPrintJSON(result)
|
|
result3, err := userService.ReadByID(result.Username)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
utils.PrettyPrintJSON(result3)
|
|
}
|
|
|
|
// db, _ := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
|
|
// userRepo := user.NewRepository(db)
|
|
// userService := user.NewService(userRepo)
|
|
// user1 := &user.User{
|
|
// Username: "jdoe",
|
|
// Firstname: "Joe",
|
|
// Lastname: "Doe",
|
|
// Email: "jdoe@acme.inc",
|
|
// }
|
|
// result, err := userService.Create(user1)
|
|
// if err != nil {
|
|
// panic(err)
|
|
// }
|
|
// fmt.Println(result)
|
|
|
|
// fmt.Println("main.go --> Environment:", viper.GetString("application.environment"))
|
|
// fmt.Println("main.go --> Listen:", viper.GetString("application.listenaddress"))
|
|
// fmt.Println("main.go --> Database Port: ", viper.GetInt("database.port"))
|
|
// fmt.Println("main.go --> Application Port:", viper.GetInt("application.port"))
|
|
// contextLogger.WithFields(log.Fields{
|
|
// "module": "config",
|
|
// }).Fatal("ADSADSASd")
|
|
|
|
}
|