diff --git a/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Get All Scopes.bru b/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Get All Scopes.bru deleted file mode 100644 index 6ae13c6..0000000 --- a/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Get All Scopes.bru +++ /dev/null @@ -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 -} diff --git a/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Get Tunnels.bru b/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Get Tunnels.bru deleted file mode 100644 index a1746a1..0000000 --- a/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Get Tunnels.bru +++ /dev/null @@ -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" - } -} diff --git a/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Log In.bru b/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Log In.bru deleted file mode 100644 index 0ecdb33..0000000 --- a/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/Log In.bru +++ /dev/null @@ -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" - } -} diff --git a/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/bruno.json b/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/bruno.json deleted file mode 100644 index 0fdaa19..0000000 --- a/backend-legacy/routes/Passyfire Base Routes/Passyfire Base Routes/bruno.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "version": "1", - "name": "Passyfire Base Routes", - "type": "collection", - "ignore": [ - "node_modules", - ".git" - ] -} \ No newline at end of file diff --git a/backend/api/constants/permission_nodes.go b/backend/api/constants/permission_nodes.go new file mode 100644 index 0000000..a62a606 --- /dev/null +++ b/backend/api/constants/permission_nodes.go @@ -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", +} diff --git a/backend/api/controllers/v1/users/create.go b/backend/api/controllers/v1/users/create.go new file mode 100644 index 0000000..48a846b --- /dev/null +++ b/backend/api/controllers/v1/users/create.go @@ -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), + }) +} diff --git a/backend/api/dbcore/db.go b/backend/api/dbcore/db.go new file mode 100644 index 0000000..57d7583 --- /dev/null +++ b/backend/api/dbcore/db.go @@ -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 +} diff --git a/backend/api/jwtcore/jwt.go b/backend/api/jwtcore/jwt.go new file mode 100644 index 0000000..01809c0 --- /dev/null +++ b/backend/api/jwtcore/jwt.go @@ -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 +} diff --git a/backend/api/main.go b/backend/api/main.go new file mode 100644 index 0000000..c18ed84 --- /dev/null +++ b/backend/api/main.go @@ -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()) + } +} diff --git a/backend/dev.env b/backend/dev.env index f9c0512..8d127a3 100644 --- a/backend/dev.env +++ b/backend/dev.env @@ -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 diff --git a/backend/go.mod b/backend/go.mod index 16b90c9..9a70c61 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -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 ) diff --git a/backend/go.sum b/backend/go.sum index b0830af..819c0c6 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -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= diff --git a/init.sh b/init.sh index 66330a0..530c458 100644 --- a/init.sh +++ b/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) diff --git a/backend-legacy/routes/NextNet API/Backend/Create.bru b/routes/Hermes API/Backend/Create.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Backend/Create.bru rename to routes/Hermes API/Backend/Create.bru diff --git a/backend-legacy/routes/NextNet API/Backend/Lookup.bru b/routes/Hermes API/Backend/Lookup.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Backend/Lookup.bru rename to routes/Hermes API/Backend/Lookup.bru diff --git a/backend-legacy/routes/NextNet API/Backend/Remove.bru b/routes/Hermes API/Backend/Remove.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Backend/Remove.bru rename to routes/Hermes API/Backend/Remove.bru diff --git a/backend-legacy/routes/NextNet API/Forward/Create.bru b/routes/Hermes API/Forward/Create.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Forward/Create.bru rename to routes/Hermes API/Forward/Create.bru diff --git a/backend-legacy/routes/NextNet API/Forward/Get Inbound Connections.bru b/routes/Hermes API/Forward/Get Inbound Connections.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Forward/Get Inbound Connections.bru rename to routes/Hermes API/Forward/Get Inbound Connections.bru diff --git a/backend-legacy/routes/NextNet API/Forward/Lookup.bru b/routes/Hermes API/Forward/Lookup.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Forward/Lookup.bru rename to routes/Hermes API/Forward/Lookup.bru diff --git a/backend-legacy/routes/NextNet API/Forward/Remove.bru b/routes/Hermes API/Forward/Remove.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Forward/Remove.bru rename to routes/Hermes API/Forward/Remove.bru diff --git a/backend-legacy/routes/NextNet API/Forward/Start.bru b/routes/Hermes API/Forward/Start.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Forward/Start.bru rename to routes/Hermes API/Forward/Start.bru diff --git a/backend-legacy/routes/NextNet API/Forward/Stop.bru b/routes/Hermes API/Forward/Stop.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Forward/Stop.bru rename to routes/Hermes API/Forward/Stop.bru diff --git a/backend-legacy/routes/NextNet API/Get Permissions.bru b/routes/Hermes API/Get Permissions.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Get Permissions.bru rename to routes/Hermes API/Get Permissions.bru diff --git a/backend-legacy/routes/NextNet API/Users/Create.bru b/routes/Hermes API/Users/Create.bru similarity index 50% rename from backend-legacy/routes/NextNet API/Users/Create.bru rename to routes/Hermes API/Users/Create.bru index 31a8f46..bd63237 100644 --- a/backend-legacy/routes/NextNet API/Users/Create.bru +++ b/routes/Hermes API/Users/Create.bru @@ -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" } } diff --git a/backend-legacy/routes/NextNet API/Users/Log In.bru b/routes/Hermes API/Users/Log In.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Users/Log In.bru rename to routes/Hermes API/Users/Log In.bru diff --git a/backend-legacy/routes/NextNet API/Users/Lookup.bru b/routes/Hermes API/Users/Lookup.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Users/Lookup.bru rename to routes/Hermes API/Users/Lookup.bru diff --git a/backend-legacy/routes/NextNet API/Users/Remove.bru b/routes/Hermes API/Users/Remove.bru similarity index 100% rename from backend-legacy/routes/NextNet API/Users/Remove.bru rename to routes/Hermes API/Users/Remove.bru diff --git a/backend-legacy/routes/NextNet API/bruno.json b/routes/Hermes API/bruno.json similarity index 62% rename from backend-legacy/routes/NextNet API/bruno.json rename to routes/Hermes API/bruno.json index af51919..4da5f41 100644 --- a/backend-legacy/routes/NextNet API/bruno.json +++ b/routes/Hermes API/bruno.json @@ -1,5 +1,5 @@ { "version": "1", - "name": "NextNet API", + "name": "Hermes", "type": "collection" -} \ No newline at end of file +} diff --git a/backend-legacy/routes/NextNet API/runroute.sh b/routes/Hermes API/runroute.sh similarity index 100% rename from backend-legacy/routes/NextNet API/runroute.sh rename to routes/Hermes API/runroute.sh