Clean Up
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
|
||||
@@ -94,31 +92,3 @@ func (api *API) validateTokens(w *http.ResponseWriter, r *http.Request) (jwt.Tok
|
||||
|
||||
return jwt.ParseBytes([]byte(newAccessCookie))
|
||||
}
|
||||
|
||||
func (api *API) hasMinRoleDirective(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) {
|
||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
||||
accessToken, err := api.validateTokens(authContext.AuthResponse, authContext.AuthRequest)
|
||||
if err != nil {
|
||||
return nil, errors.New("Access Denied")
|
||||
}
|
||||
authContext.AccessToken = &accessToken
|
||||
|
||||
userRole, ok := accessToken.Get("role")
|
||||
if !ok {
|
||||
return nil, errors.New("Access Denied")
|
||||
}
|
||||
|
||||
if userRole == model.RoleAdmin.String() {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
if userRole == role.String() {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
return nil, errors.New("Role Not Authenticated")
|
||||
}
|
||||
|
||||
func (api *API) metaDirective(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
50
internal/api/directives.go
Normal file
50
internal/api/directives.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
/**
|
||||
* This is used to validate whether the users role is adequate for the requested resource.
|
||||
**/
|
||||
func (api *API) hasMinRoleDirective(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) {
|
||||
authContext := ctx.Value("auth").(*model.AuthContext)
|
||||
accessToken, err := api.validateTokens(authContext.AuthResponse, authContext.AuthRequest)
|
||||
if err != nil {
|
||||
return nil, errors.New("Access Denied")
|
||||
}
|
||||
authContext.AccessToken = &accessToken
|
||||
|
||||
userRole, ok := accessToken.Get("role")
|
||||
if !ok {
|
||||
return nil, errors.New("Access Denied")
|
||||
}
|
||||
|
||||
if userRole == model.RoleAdmin.String() {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
if userRole == role.String() {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
return nil, errors.New("Role Not Authenticated")
|
||||
}
|
||||
|
||||
/**
|
||||
* This is needed but not used. Meta is used for Gorm.
|
||||
**/
|
||||
func (api *API) metaDirective(ctx context.Context, obj interface{}, next graphql.Resolver, gorm *string) (res interface{}, err error) {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
/**
|
||||
* This overrides the response so fields with an @isPrivate directive are always nil.
|
||||
**/
|
||||
func (api *API) isPrivateDirective(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) {
|
||||
return nil, errors.New("Private Field")
|
||||
}
|
||||
@@ -8,7 +8,9 @@ import (
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
// Responsible for serving up static images / videos
|
||||
/**
|
||||
* Responsible for serving up static images / videos
|
||||
**/
|
||||
func (api *API) mediaHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
|
||||
@@ -3,9 +3,6 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
@@ -27,9 +24,8 @@ func multipleMiddleware(h http.HandlerFunc, m ...Middleware) http.HandlerFunc {
|
||||
* This is used for the graphQL endpoints that may require access to the
|
||||
* Request and ResponseWriter variables. These are used to get / set cookies.
|
||||
**/
|
||||
func (api *API) injectContextMiddleware(next http.Handler) http.Handler {
|
||||
func (api *API) contextMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
authContext := &model.AuthContext{
|
||||
AuthResponse: &w,
|
||||
AuthRequest: r,
|
||||
@@ -40,7 +36,6 @@ func (api *API) injectContextMiddleware(next http.Handler) http.Handler {
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -49,10 +44,10 @@ func (api *API) injectContextMiddleware(next http.Handler) http.Handler {
|
||||
**/
|
||||
func (api *API) authMiddleware(next http.Handler) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Validate Tokens
|
||||
accessToken, err := api.validateTokens(&w, r)
|
||||
if err != nil {
|
||||
errorJSON(w, "Invalid token.", http.StatusUnauthorized)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -64,16 +59,5 @@ func (api *API) authMiddleware(next http.Handler) http.HandlerFunc {
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func (api *API) logMiddleware(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
log.SetOutput(os.Stdout)
|
||||
log.Println(r.Method, r.URL)
|
||||
h.ServeHTTP(w, r)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package api
|
||||
|
||||
type APICredentials struct {
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type APIData interface{}
|
||||
|
||||
type APIMeta struct {
|
||||
Count int64 `json:"count"`
|
||||
Page int64 `json:"page"`
|
||||
}
|
||||
|
||||
type APIError struct {
|
||||
Message string `json:"message"`
|
||||
Code int64 `json:"code"`
|
||||
}
|
||||
|
||||
type APIResponse struct {
|
||||
Data APIData `json:"data,omitempty"`
|
||||
Meta *APIMeta `json:"meta,omitempty"`
|
||||
Error *APIError `json:"error,omitempty"`
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/99designs/gqlgen/graphql/playground"
|
||||
|
||||
@@ -12,7 +9,6 @@ import (
|
||||
)
|
||||
|
||||
func (api *API) registerRoutes() {
|
||||
|
||||
// Set up Directives
|
||||
graphConfig := generated.Config{
|
||||
Resolvers: &graph.Resolver{
|
||||
@@ -21,6 +17,7 @@ func (api *API) registerRoutes() {
|
||||
},
|
||||
Directives: generated.DirectiveRoot{
|
||||
Meta: api.metaDirective,
|
||||
IsPrivate: api.isPrivateDirective,
|
||||
HasMinRole: api.hasMinRoleDirective,
|
||||
},
|
||||
}
|
||||
@@ -28,31 +25,11 @@ func (api *API) registerRoutes() {
|
||||
|
||||
// Handle GraphQL
|
||||
api.Router.Handle("/playground", playground.Handler("GraphQL playground", "/query"))
|
||||
api.Router.Handle("/query", api.injectContextMiddleware(srv))
|
||||
api.Router.Handle("/query", api.contextMiddleware(srv))
|
||||
|
||||
// Handle Resource Route
|
||||
api.Router.HandleFunc("/media/", multipleMiddleware(
|
||||
api.mediaHandler,
|
||||
api.authMiddleware,
|
||||
))
|
||||
|
||||
}
|
||||
|
||||
func errorJSON(w http.ResponseWriter, err string, code int) {
|
||||
errStruct := &APIResponse{Error: &APIError{Message: err, Code: int64(code)}}
|
||||
responseJSON(w, errStruct, code)
|
||||
}
|
||||
|
||||
func responseJSON(w http.ResponseWriter, msg interface{}, code int) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.WriteHeader(code)
|
||||
json.NewEncoder(w).Encode(msg)
|
||||
}
|
||||
|
||||
func successJSON(w http.ResponseWriter, msg string, code int) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.WriteHeader(code)
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{"success": msg})
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/lestrrat-go/jwx/jwa"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/gorm"
|
||||
|
||||
@@ -61,115 +55,3 @@ func (auth *AuthManager) AuthenticateUser(user, password string) (model.User, bo
|
||||
return *foundUser, false
|
||||
}
|
||||
}
|
||||
|
||||
func (auth *AuthManager) ValidateJWTRefreshToken(refreshJWT string) (jwt.Token, error) {
|
||||
byteRefreshJWT := []byte(refreshJWT)
|
||||
|
||||
// Acquire Relevant Device
|
||||
unverifiedToken, err := jwt.ParseBytes(byteRefreshJWT)
|
||||
did, ok := unverifiedToken.Get("did")
|
||||
if !ok {
|
||||
return nil, errors.New("did does not exist")
|
||||
}
|
||||
deviceID, err := uuid.Parse(fmt.Sprintf("%v", did))
|
||||
if err != nil {
|
||||
return nil, errors.New("did does not parse")
|
||||
}
|
||||
device := &model.Device{ID: deviceID.String()}
|
||||
_, err = auth.DB.Device(device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify & Validate Token
|
||||
verifiedToken, err := jwt.ParseBytes(byteRefreshJWT,
|
||||
jwt.WithValidate(true),
|
||||
jwt.WithVerify(jwa.HS256, []byte(*device.RefreshKey)),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println("failed to parse payload: ", err)
|
||||
return nil, err
|
||||
}
|
||||
return verifiedToken, nil
|
||||
}
|
||||
|
||||
func (auth *AuthManager) ValidateJWTAccessToken(accessJWT string) (jwt.Token, error) {
|
||||
byteAccessJWT := []byte(accessJWT)
|
||||
verifiedToken, err := jwt.ParseBytes(byteAccessJWT,
|
||||
jwt.WithValidate(true),
|
||||
jwt.WithVerify(jwa.HS256, []byte(auth.Config.JWTSecret)),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return verifiedToken, nil
|
||||
}
|
||||
|
||||
func (auth *AuthManager) CreateJWTRefreshToken(user model.User, device model.Device) (string, error) {
|
||||
// Acquire Refresh Key
|
||||
byteKey := []byte(*device.RefreshKey)
|
||||
|
||||
// Create New Token
|
||||
tm := time.Now()
|
||||
t := jwt.New()
|
||||
t.Set(`did`, device.ID) // Device ID
|
||||
t.Set(jwt.SubjectKey, user.ID) // User ID
|
||||
t.Set(jwt.AudienceKey, `imagini`) // App ID
|
||||
t.Set(jwt.IssuedAtKey, tm) // Issued At
|
||||
|
||||
// iOS & Android = Never Expiring Refresh Token
|
||||
if device.Type != "iOS" && device.Type != "Android" {
|
||||
t.Set(jwt.ExpirationKey, tm.Add(time.Hour*24)) // 1 Day Access Key
|
||||
}
|
||||
|
||||
// Validate Token Creation
|
||||
_, err := json.MarshalIndent(t, "", " ")
|
||||
if err != nil {
|
||||
fmt.Printf("failed to generate JSON: %s\n", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Sign Token
|
||||
signed, err := jwt.Sign(t, jwa.HS256, byteKey)
|
||||
if err != nil {
|
||||
log.Printf("failed to sign token: %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Return Token
|
||||
return string(signed), nil
|
||||
}
|
||||
|
||||
func (auth *AuthManager) CreateJWTAccessToken(user model.User, device model.Device) (string, error) {
|
||||
// Create New Token
|
||||
tm := time.Now()
|
||||
t := jwt.New()
|
||||
t.Set(`did`, device.ID) // Device ID
|
||||
t.Set(`role`, user.Role.String()) // User Role (Admin / User)
|
||||
t.Set(jwt.SubjectKey, user.ID) // User ID
|
||||
t.Set(jwt.AudienceKey, `imagini`) // App ID
|
||||
t.Set(jwt.IssuedAtKey, tm) // Issued At
|
||||
t.Set(jwt.ExpirationKey, tm.Add(time.Hour*2)) // 2 Hour Access Key
|
||||
|
||||
// Validate Token Creation
|
||||
_, err := json.MarshalIndent(t, "", " ")
|
||||
if err != nil {
|
||||
fmt.Printf("failed to generate JSON: %s\n", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Use Server Key
|
||||
byteKey := []byte(auth.Config.JWTSecret)
|
||||
|
||||
// Sign Token
|
||||
signed, err := jwt.Sign(t, jwa.HS256, byteKey)
|
||||
if err != nil {
|
||||
log.Printf("failed to sign token: %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Return Token
|
||||
return string(signed), nil
|
||||
}
|
||||
|
||||
126
internal/auth/jwt.go
Normal file
126
internal/auth/jwt.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/lestrrat-go/jwx/jwa"
|
||||
"github.com/lestrrat-go/jwx/jwt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
func (auth *AuthManager) ValidateJWTRefreshToken(refreshJWT string) (jwt.Token, error) {
|
||||
byteRefreshJWT := []byte(refreshJWT)
|
||||
|
||||
// Acquire Relevant Device
|
||||
unverifiedToken, err := jwt.ParseBytes(byteRefreshJWT)
|
||||
did, ok := unverifiedToken.Get("did")
|
||||
if !ok {
|
||||
return nil, errors.New("did does not exist")
|
||||
}
|
||||
deviceID, err := uuid.Parse(fmt.Sprintf("%v", did))
|
||||
if err != nil {
|
||||
return nil, errors.New("did does not parse")
|
||||
}
|
||||
device := &model.Device{ID: deviceID.String()}
|
||||
_, err = auth.DB.Device(device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify & Validate Token
|
||||
verifiedToken, err := jwt.ParseBytes(byteRefreshJWT,
|
||||
jwt.WithValidate(true),
|
||||
jwt.WithVerify(jwa.HS256, []byte(*device.RefreshKey)),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println("failed to parse payload: ", err)
|
||||
return nil, err
|
||||
}
|
||||
return verifiedToken, nil
|
||||
}
|
||||
|
||||
func (auth *AuthManager) ValidateJWTAccessToken(accessJWT string) (jwt.Token, error) {
|
||||
byteAccessJWT := []byte(accessJWT)
|
||||
verifiedToken, err := jwt.ParseBytes(byteAccessJWT,
|
||||
jwt.WithValidate(true),
|
||||
jwt.WithVerify(jwa.HS256, []byte(auth.Config.JWTSecret)),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return verifiedToken, nil
|
||||
}
|
||||
|
||||
func (auth *AuthManager) CreateJWTRefreshToken(user model.User, device model.Device) (string, error) {
|
||||
// Acquire Refresh Key
|
||||
byteKey := []byte(*device.RefreshKey)
|
||||
|
||||
// Create New Token
|
||||
tm := time.Now()
|
||||
t := jwt.New()
|
||||
t.Set(`did`, device.ID) // Device ID
|
||||
t.Set(jwt.SubjectKey, user.ID) // User ID
|
||||
t.Set(jwt.AudienceKey, `imagini`) // App ID
|
||||
t.Set(jwt.IssuedAtKey, tm) // Issued At
|
||||
|
||||
// iOS & Android = Never Expiring Refresh Token
|
||||
if device.Type != "iOS" && device.Type != "Android" {
|
||||
t.Set(jwt.ExpirationKey, tm.Add(time.Hour*24)) // 1 Day Access Key
|
||||
}
|
||||
|
||||
// Validate Token Creation
|
||||
_, err := json.MarshalIndent(t, "", " ")
|
||||
if err != nil {
|
||||
fmt.Printf("failed to generate JSON: %s\n", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Sign Token
|
||||
signed, err := jwt.Sign(t, jwa.HS256, byteKey)
|
||||
if err != nil {
|
||||
log.Printf("failed to sign token: %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Return Token
|
||||
return string(signed), nil
|
||||
}
|
||||
|
||||
func (auth *AuthManager) CreateJWTAccessToken(user model.User, device model.Device) (string, error) {
|
||||
// Create New Token
|
||||
tm := time.Now()
|
||||
t := jwt.New()
|
||||
t.Set(`did`, device.ID) // Device ID
|
||||
t.Set(`role`, user.Role.String()) // User Role (Admin / User)
|
||||
t.Set(jwt.SubjectKey, user.ID) // User ID
|
||||
t.Set(jwt.AudienceKey, `imagini`) // App ID
|
||||
t.Set(jwt.IssuedAtKey, tm) // Issued At
|
||||
t.Set(jwt.ExpirationKey, tm.Add(time.Hour*2)) // 2 Hour Access Key
|
||||
|
||||
// Validate Token Creation
|
||||
_, err := json.MarshalIndent(t, "", " ")
|
||||
if err != nil {
|
||||
fmt.Printf("failed to generate JSON: %s\n", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Use Server Key
|
||||
byteKey := []byte(auth.Config.JWTSecret)
|
||||
|
||||
// Sign Token
|
||||
signed, err := jwt.Sign(t, jwa.HS256, byteKey)
|
||||
if err != nil {
|
||||
log.Printf("failed to sign token: %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Return Token
|
||||
return string(signed), nil
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"reichard.io/imagini/graph/model"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
func authenticateLDAPUser(user model.User, pw string) bool {
|
||||
return false
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"reichard.io/imagini/graph/model"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"reichard.io/imagini/graph/model"
|
||||
)
|
||||
|
||||
func authenticateLocalUser(user model.User, pw string) bool {
|
||||
bPassword :=[]byte(pw)
|
||||
err := bcrypt.CompareHashAndPassword([]byte(*user.Password), bPassword)
|
||||
if err == nil {
|
||||
log.Info("[auth] Authentication successfull: ", user.Username)
|
||||
return true
|
||||
}
|
||||
log.Warn("[auth] Authentication failed: ", user.Username)
|
||||
return false
|
||||
bPassword := []byte(pw)
|
||||
err := bcrypt.CompareHashAndPassword([]byte(*user.Password), bPassword)
|
||||
if err == nil {
|
||||
log.Info("[auth] Authentication successfull: ", user.Username)
|
||||
return true
|
||||
}
|
||||
log.Warn("[auth] Authentication failed: ", user.Username)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
DBType string
|
||||
DBName string
|
||||
DBPassword string
|
||||
DataPath string
|
||||
ConfigPath string
|
||||
JWTSecret string
|
||||
ListenPort string
|
||||
DBType string
|
||||
DBName string
|
||||
DBPassword string
|
||||
DataPath string
|
||||
ConfigPath string
|
||||
JWTSecret string
|
||||
ListenPort string
|
||||
}
|
||||
|
||||
func Load() *Config {
|
||||
return &Config{
|
||||
DBType: getEnv("DATABASE_TYPE", "SQLite"),
|
||||
DBName: getEnv("DATABASE_NAME", "imagini"),
|
||||
DBPassword: getEnv("DATABASE_PASSWORD", ""),
|
||||
ConfigPath: getEnv("CONFIG_PATH", "/config"),
|
||||
DataPath: getEnv("DATA_PATH", "/data"),
|
||||
JWTSecret: getEnv("JWT_SECRET", "58b9340c0472cf045db226bc445966524e780cd38bc3dd707afce80c95d4de6f"),
|
||||
ListenPort: getEnv("LISTEN_PORT", "8484"),
|
||||
}
|
||||
return &Config{
|
||||
DBType: getEnv("DATABASE_TYPE", "SQLite"),
|
||||
DBName: getEnv("DATABASE_NAME", "imagini"),
|
||||
DBPassword: getEnv("DATABASE_PASSWORD", ""),
|
||||
ConfigPath: getEnv("CONFIG_PATH", "/config"),
|
||||
DataPath: getEnv("DATA_PATH", "/data"),
|
||||
JWTSecret: getEnv("JWT_SECRET", "58b9340c0472cf045db226bc445966524e780cd38bc3dd707afce80c95d4de6f"),
|
||||
ListenPort: getEnv("LISTEN_PORT", "8484"),
|
||||
}
|
||||
}
|
||||
|
||||
func getEnv(key, fallback string) string {
|
||||
if value, ok := os.LookupEnv(key); ok {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
if value, ok := os.LookupEnv(key); ok {
|
||||
return value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ func (dbm *DBManager) bootstrapDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
func (dbm *DBManager) QueryBuilder(dest interface{}, params []byte) (int64, error) {
|
||||
// TODO:
|
||||
// - Where Filters
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package db
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrUserAlreadyExists = errors.New("user already exists")
|
||||
)
|
||||
@@ -1,38 +1,40 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Used to maintain a cache of user specific jwt secrets
|
||||
// This will prevent DB lookups on every request
|
||||
// May not actually be needed. Refresh Token is the only
|
||||
// token that will require proactive DB lookups.
|
||||
type SessionManager struct {
|
||||
mutex sync.Mutex
|
||||
values map[string]string
|
||||
mutex sync.Mutex
|
||||
values map[string]string
|
||||
}
|
||||
|
||||
func NewMgr() *SessionManager {
|
||||
return &SessionManager{}
|
||||
return &SessionManager{}
|
||||
}
|
||||
|
||||
func (sm *SessionManager) Set(key, value string) {
|
||||
sm.mutex.Lock()
|
||||
sm.values[key] = value
|
||||
sm.mutex.Unlock()
|
||||
sm.mutex.Lock()
|
||||
sm.values[key] = value
|
||||
sm.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (sm *SessionManager) Get(key string) string {
|
||||
sm.mutex.Lock()
|
||||
defer sm.mutex.Unlock()
|
||||
return sm.values[key]
|
||||
sm.mutex.Lock()
|
||||
defer sm.mutex.Unlock()
|
||||
return sm.values[key]
|
||||
}
|
||||
|
||||
func (sm *SessionManager) Delete(key string) {
|
||||
sm.mutex.Lock()
|
||||
defer sm.mutex.Unlock()
|
||||
_, exists := sm.values[key]
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
delete(sm.values, key)
|
||||
sm.mutex.Lock()
|
||||
defer sm.mutex.Unlock()
|
||||
_, exists := sm.values[key]
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
delete(sm.values, key)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user