chore: Adds user creation route.
This commit is contained in:
parent
c7b71e754f
commit
1237a31f8b
29 changed files with 630 additions and 63 deletions
|
@ -1,11 +0,0 @@
|
|||
meta {
|
||||
name: Get All Scopes
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://127.0.0.1:8080/api/v1/static/getScopes
|
||||
body: none
|
||||
auth: none
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
meta {
|
||||
name: Get Tunnels
|
||||
type: http
|
||||
seq: 3
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://127.0.0.1:8080/api/v1/tunnels
|
||||
body: json
|
||||
auth: none
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"token": "641d968c3bfdf78f2df86cae106349c4c95a8dd73512ee34b296379b6cd908c87b078f1f674b43c9e3394c8b233840512d88efdecf47dc63be93276f56c"
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
meta {
|
||||
name: Log In
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://127.0.0.1:8080/api/v1/users/login
|
||||
body: json
|
||||
auth: none
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"username": "guest",
|
||||
"password": "guest"
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"version": "1",
|
||||
"name": "Passyfire Base Routes",
|
||||
"type": "collection",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
".git"
|
||||
]
|
||||
}
|
26
backend/api/constants/permission_nodes.go
Normal file
26
backend/api/constants/permission_nodes.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package constants
|
||||
|
||||
var DefaultPermissionNodes []string = []string{
|
||||
"routes.add",
|
||||
"routes.remove",
|
||||
"routes.start",
|
||||
"routes.stop",
|
||||
"routes.edit",
|
||||
"routes.visible",
|
||||
"routes.visibleConn",
|
||||
|
||||
"backends.add",
|
||||
"backends.remove",
|
||||
"backends.start",
|
||||
"backends.stop",
|
||||
"backends.edit",
|
||||
"backends.visible",
|
||||
"backends.secretVis",
|
||||
|
||||
"permissions.see",
|
||||
|
||||
"users.add",
|
||||
"users.remove",
|
||||
"users.lookup",
|
||||
"users.edit",
|
||||
}
|
176
backend/api/controllers/v1/users/create.go
Normal file
176
backend/api/controllers/v1/users/create.go
Normal file
|
@ -0,0 +1,176 @@
|
|||
package users
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
|
||||
"git.terah.dev/imterah/hermes/api/constants"
|
||||
"git.terah.dev/imterah/hermes/api/dbcore"
|
||||
"git.terah.dev/imterah/hermes/api/jwtcore"
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type UserCreationRequest struct {
|
||||
Name string `validate:"required"`
|
||||
Email string `validate:"required"`
|
||||
Password string `validate:"required"`
|
||||
Username string `validate:"required"`
|
||||
|
||||
// TODO: implement support
|
||||
ExistingUserToken string `json:"token"`
|
||||
IsBot bool
|
||||
}
|
||||
|
||||
var (
|
||||
signupEnabled bool
|
||||
unsafeSignup bool
|
||||
forceNoExpiryTokens bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
signupEnabled = os.Getenv("HERMES_SIGNUP_ENABLED") != ""
|
||||
unsafeSignup = os.Getenv("HERMES_UNSAFE_ADMIN_SIGNUP_ENABLED") != ""
|
||||
forceNoExpiryTokens = os.Getenv("HERMES_FORCE_DISABLE_REFRESH_TOKEN_EXPIRY") != ""
|
||||
}
|
||||
|
||||
func CreateUser(c *gin.Context) {
|
||||
var req UserCreationRequest
|
||||
|
||||
if !signupEnabled && !unsafeSignup {
|
||||
c.JSON(http.StatusForbidden, gin.H{
|
||||
"error": "Signing up is not enabled at this time.",
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.BindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": fmt.Sprintf("Failed to parse body: %s", err.Error()),
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := validator.New().Struct(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": fmt.Sprintf("Failed to validate body: %s", err.Error()),
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var user *dbcore.User
|
||||
userRequest := dbcore.DB.Where("email = ? OR username = ?", req.Email, req.Username).Find(&user)
|
||||
|
||||
if userRequest.Error != nil {
|
||||
log.Warnf("failed to find if user exists or not: %s", userRequest.Error)
|
||||
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to find if user exists",
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
userExists := userRequest.RowsAffected > 0
|
||||
|
||||
if userExists {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "User already exists",
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
passwordHashed, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("Failed to generate password for client upon signup: %s", err.Error())
|
||||
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to generate password hash",
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
permissions := []dbcore.Permission{}
|
||||
|
||||
for _, permission := range constants.DefaultPermissionNodes {
|
||||
permissionEnabledState := false
|
||||
|
||||
if unsafeSignup || strings.HasPrefix(permission, "routes.") || permission == "permissions.see" {
|
||||
permissionEnabledState = true
|
||||
}
|
||||
|
||||
permissions = append(permissions, dbcore.Permission{
|
||||
PermissionNode: permission,
|
||||
HasPermission: permissionEnabledState,
|
||||
})
|
||||
}
|
||||
|
||||
tokenRandomData := make([]byte, 80)
|
||||
|
||||
if _, err := rand.Read(tokenRandomData); err != nil {
|
||||
log.Warnf("Failed to read random data to use as token: %s", err.Error())
|
||||
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to generate refresh token",
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
user = &dbcore.User{
|
||||
Email: req.Email,
|
||||
Username: req.Username,
|
||||
Name: req.Name,
|
||||
IsBot: &req.IsBot,
|
||||
Password: base64.StdEncoding.EncodeToString(passwordHashed),
|
||||
Permissions: permissions,
|
||||
Tokens: []dbcore.Token{
|
||||
{
|
||||
Token: base64.StdEncoding.EncodeToString(tokenRandomData),
|
||||
DisableExpiry: forceNoExpiryTokens,
|
||||
CreationIPAddr: c.ClientIP(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if result := dbcore.DB.Create(&user); result.Error != nil {
|
||||
log.Warnf("Failed to create user: %s", result.Error.Error())
|
||||
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to add user into database",
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
jwt, err := jwtcore.Generate(user.ID)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf("Failed to generate JWT: %s", err.Error())
|
||||
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "Failed to generate refresh token",
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"token": jwt,
|
||||
"refreshToken": base64.StdEncoding.EncodeToString(tokenRandomData),
|
||||
})
|
||||
}
|
133
backend/api/dbcore/db.go
Normal file
133
backend/api/dbcore/db.go
Normal file
|
@ -0,0 +1,133 @@
|
|||
package dbcore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Backend struct {
|
||||
gorm.Model
|
||||
|
||||
UserID uint
|
||||
|
||||
Name string
|
||||
Description *string
|
||||
Backend string
|
||||
BackendParameters string
|
||||
|
||||
Proxies []Proxy
|
||||
}
|
||||
|
||||
type Proxy struct {
|
||||
gorm.Model
|
||||
|
||||
BackendID uint
|
||||
UserID uint
|
||||
|
||||
Name string
|
||||
Description *string
|
||||
Protocol string
|
||||
SourceIP string
|
||||
SourcePort uint16
|
||||
DestinationPort uint16
|
||||
AutoStart bool
|
||||
}
|
||||
|
||||
type Permission struct {
|
||||
gorm.Model
|
||||
|
||||
PermissionNode string
|
||||
HasPermission bool
|
||||
UserID uint
|
||||
}
|
||||
|
||||
type Token struct {
|
||||
gorm.Model
|
||||
|
||||
UserID uint
|
||||
|
||||
Token string
|
||||
DisableExpiry bool
|
||||
CreationIPAddr string
|
||||
}
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
|
||||
Email string `gorm:"unique"`
|
||||
Username string `gorm:"unique"`
|
||||
Name string
|
||||
Password string
|
||||
IsBot *bool
|
||||
|
||||
Permissions []Permission
|
||||
OwnedProxies []Proxy
|
||||
OwnedBackends []Backend
|
||||
Tokens []Token
|
||||
}
|
||||
|
||||
var DB *gorm.DB
|
||||
|
||||
func InitializeDatabaseDialector() (gorm.Dialector, error) {
|
||||
databaseBackend := os.Getenv("HERMES_DATABASE_BACKEND")
|
||||
|
||||
switch databaseBackend {
|
||||
case "sqlite":
|
||||
filePath := os.Getenv("HERMES_SQLITE_FILEPATH")
|
||||
|
||||
if filePath == "" {
|
||||
return nil, fmt.Errorf("sqlite database file not specified (missing HERMES_SQLITE_FILEPATH)")
|
||||
}
|
||||
|
||||
return sqlite.Open(filePath), nil
|
||||
case "":
|
||||
return nil, fmt.Errorf("no database backend specified in environment variables (missing HERMES_DATABASE_BACKEND)")
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown database backend specified: %s", os.Getenv(databaseBackend))
|
||||
}
|
||||
}
|
||||
|
||||
func InitializeDatabase(config *gorm.Config) error {
|
||||
var err error
|
||||
|
||||
dialector, err := InitializeDatabaseDialector()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize physical database: %s", err)
|
||||
}
|
||||
|
||||
DB, err = gorm.Open(dialector, config)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open database: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DoDatabaseMigrations(db *gorm.DB) error {
|
||||
if err := db.AutoMigrate(&Proxy{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(&Backend{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(&Permission{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(&Token{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(&User{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
59
backend/api/jwtcore/jwt.go
Normal file
59
backend/api/jwtcore/jwt.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package jwtcore
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
var JWTKey []byte
|
||||
|
||||
func SetupJWT() error {
|
||||
var err error
|
||||
jwtDataString := os.Getenv("HERMES_JWT_SECRET")
|
||||
|
||||
if jwtDataString == "" {
|
||||
return fmt.Errorf("JWT secret isn't set (missing HERMES_JWT_SECRET)")
|
||||
}
|
||||
|
||||
if os.Getenv("HERMES_JWT_BASE64_ENCODED") != "" {
|
||||
JWTKey, err = base64.StdEncoding.DecodeString(jwtDataString)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode base64 JWT: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
JWTKey = []byte(jwtDataString)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Parse(tokenString string, options ...jwt.ParserOption) (*jwt.Token, error) {
|
||||
return jwt.Parse(tokenString, JWTKeyCallback, options...)
|
||||
}
|
||||
|
||||
func Generate(uid uint) (string, error) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(3 * time.Minute)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
Audience: []string{strconv.Itoa(int(uid))},
|
||||
})
|
||||
|
||||
signedToken, err := token.SignedString(JWTKey)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return signedToken, nil
|
||||
}
|
||||
|
||||
func JWTKeyCallback(*jwt.Token) (interface{}, error) {
|
||||
return JWTKey, nil
|
||||
}
|
102
backend/api/main.go
Normal file
102
backend/api/main.go
Normal file
|
@ -0,0 +1,102 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.terah.dev/imterah/hermes/api/controllers/v1/users"
|
||||
"git.terah.dev/imterah/hermes/api/dbcore"
|
||||
"git.terah.dev/imterah/hermes/api/jwtcore"
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logLevel := os.Getenv("HERMES_LOG_LEVEL")
|
||||
developmentMode := false
|
||||
|
||||
if os.Getenv("HERMES_DEVELOPMENT_MODE") != "" {
|
||||
developmentMode = true
|
||||
}
|
||||
|
||||
if logLevel != "" {
|
||||
switch logLevel {
|
||||
case "debug":
|
||||
log.SetLevel(log.DebugLevel)
|
||||
|
||||
case "info":
|
||||
log.SetLevel(log.InfoLevel)
|
||||
|
||||
case "warn":
|
||||
log.SetLevel(log.WarnLevel)
|
||||
|
||||
case "error":
|
||||
log.SetLevel(log.ErrorLevel)
|
||||
|
||||
case "fatal":
|
||||
log.SetLevel(log.FatalLevel)
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Hermes is initializing...")
|
||||
log.Debug("Initializing database and opening it...")
|
||||
|
||||
err := dbcore.InitializeDatabase(&gorm.Config{})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to initialize database: %s", err)
|
||||
}
|
||||
|
||||
log.Debug("Running database migrations...")
|
||||
|
||||
if err := dbcore.DoDatabaseMigrations(dbcore.DB); err != nil {
|
||||
log.Fatalf("Failed to run database migrations: %s", err)
|
||||
}
|
||||
|
||||
log.Debug("Initializing the JWT subsystem...")
|
||||
|
||||
if err := jwtcore.SetupJWT(); err != nil {
|
||||
log.Fatalf("Failed to initialize the JWT subsystem: %s", err.Error())
|
||||
}
|
||||
|
||||
log.Debug("Initializing API...")
|
||||
|
||||
if !developmentMode {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
engine := gin.Default()
|
||||
|
||||
listeningAddress := os.Getenv("HERMES_LISTENING_ADDRESS")
|
||||
|
||||
if listeningAddress == "" {
|
||||
if developmentMode {
|
||||
listeningAddress = "localhost:8000"
|
||||
} else {
|
||||
listeningAddress = "0.0.0.0:8000"
|
||||
}
|
||||
}
|
||||
|
||||
trustedProxiesString := os.Getenv("HERMES_TRUSTED_HTTP_PROXIES")
|
||||
|
||||
if trustedProxiesString != "" {
|
||||
trustedProxies := strings.Split(trustedProxiesString, ",")
|
||||
|
||||
engine.ForwardedByClientIP = true
|
||||
engine.SetTrustedProxies(trustedProxies)
|
||||
} else {
|
||||
engine.ForwardedByClientIP = false
|
||||
engine.SetTrustedProxies(nil)
|
||||
}
|
||||
|
||||
// Initialize routes
|
||||
engine.POST("/api/v1/users/create", users.CreateUser)
|
||||
|
||||
log.Infof("Listening on: %s", listeningAddress)
|
||||
err = engine.Run(listeningAddress)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Error running web server: %s", err.Error())
|
||||
}
|
||||
}
|
|
@ -1,2 +1,8 @@
|
|||
HERMES_DATABASE_BACKEND=sqlite
|
||||
HERMES_SQLITE_FILEPATH=../.tmp/sqlite.db
|
||||
HERMES_JWT_SECRET=thisisnotproductionreadydonotusethisinproduction
|
||||
HERMES_LOG_LEVEL=debug
|
||||
HERMES_DEVELOPMENT_MODE=true
|
||||
HERMES_SIGNUP_ENABLED=true
|
||||
HERMES_UNSAFE_ADMIN_SIGNUP_ENABLED=true
|
||||
HERMES_FORCE_DISABLE_REFRESH_TOKEN_EXPIRY=true
|
||||
|
|
|
@ -4,20 +4,50 @@ go 1.23.3
|
|||
|
||||
require (
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.12.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.1 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.10.0 // indirect
|
||||
github.com/charmbracelet/log v0.4.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.10.0 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.23.0 // indirect
|
||||
github.com/goccy/go-json v0.10.4 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/urfave/cli/v2 v2.27.5 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/arch v0.12.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
google.golang.org/protobuf v1.36.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/sqlite v1.5.7 // indirect
|
||||
gorm.io/gorm v1.25.12 // indirect
|
||||
)
|
||||
|
|
|
@ -1,40 +1,127 @@
|
|||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/bytedance/sonic v1.12.6 h1:/isNmCUF2x3Sh8RAp/4mh4ZGkcFAX/hLrzrK3AvpRzk=
|
||||
github.com/bytedance/sonic v1.12.6/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E=
|
||||
github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
|
||||
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
|
||||
github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
|
||||
github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA=
|
||||
github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
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/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
|
||||
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
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=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
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/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
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/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg=
|
||||
golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
|
||||
google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
|
||||
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
|
2
init.sh
2
init.sh
|
@ -28,8 +28,10 @@ if [ ! -d "backend-legacy/node_modules" ]; then
|
|||
popd > /dev/null
|
||||
fi
|
||||
|
||||
set -a
|
||||
source backend-legacy/.env
|
||||
source backend/.env
|
||||
set +a
|
||||
|
||||
on_exit() {
|
||||
cd $(git rev-parse --show-toplevel)
|
||||
|
|
|
@ -5,15 +5,16 @@ meta {
|
|||
}
|
||||
|
||||
post {
|
||||
url: http://127.0.0.1:3000/api/v1/users/create
|
||||
url: http://127.0.0.1:8000/api/v1/users/create
|
||||
body: json
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Greysoh Hofuh",
|
||||
"email": "greyson@hofers.cloud",
|
||||
"name": "Test User",
|
||||
"email": "test@example.com",
|
||||
"username": "testuser",
|
||||
"password": "hunter123"
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "1",
|
||||
"name": "NextNet API",
|
||||
"name": "Hermes",
|
||||
"type": "collection"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue