Prepare databases
This commit is contained in:
parent
3beb6eef8a
commit
3ca5db4649
14 changed files with 330 additions and 40 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
/config.yaml
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
|
|
96
cmd/root.go
96
cmd/root.go
|
@ -2,10 +2,16 @@ package cmd
|
|||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.1in9.net/raider/wroofauth/internal/logger"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "wroofauth",
|
||||
|
@ -31,13 +37,89 @@ func Execute() {
|
|||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is ./config.yaml)")
|
||||
|
||||
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.wroofauth.yaml)")
|
||||
viper.SetDefault("development", false)
|
||||
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
viper.BindEnv("development", "DEV")
|
||||
|
||||
logger.StartLogger()
|
||||
|
||||
viper.SetDefault("mongo.uri", "mongodb://localhost:27017")
|
||||
viper.SetDefault("mongo.database", "wroofauth")
|
||||
viper.SetDefault("mongo.collection.users", "users")
|
||||
viper.SetDefault("mongo.collection.clients", "clients")
|
||||
viper.SetDefault("mongo.collection.groups", "groups")
|
||||
|
||||
viper.BindEnv("mongo.uri", "MONGO_URI", "MONGODB_URI")
|
||||
viper.BindEnv("mongo.database", "MONGO_DATABASE", "MONGODB_DATABASE")
|
||||
|
||||
viper.SetDefault("redis.addr", "localhost:6379")
|
||||
viper.SetDefault("redis.username", "")
|
||||
viper.SetDefault("redis.password", "")
|
||||
viper.SetDefault("redis.db", 0)
|
||||
|
||||
viper.BindEnv("redis.addr", "REDIS_ADDRESS", "REDIS_ADDR")
|
||||
viper.BindEnv("redis.password", "REDIS_PASSWORD", "REDIS_PASS")
|
||||
viper.BindEnv("redis.db", "REDIS_DB")
|
||||
|
||||
/*viper.SetDefault("http.wyrd_url", "http://localhost:3001")
|
||||
viper.SetDefault("http.frontend_url", "http://localhost:3000")
|
||||
viper.BindEnv("http.wyrd_url", "WYRD_URL")
|
||||
viper.BindEnv("http.frontend_url", "WYRD_FRONTEND_URL")*/
|
||||
|
||||
/*viper.SetDefault("crypto.keys", jwk.NewSet())
|
||||
viper.SetDefault("crypto.keyfile", nil)
|
||||
viper.SetDefault("crypto.use_key", "")
|
||||
viper.BindEnv("crypto.keyfile", "WYRD_KEYFILE")*/
|
||||
|
||||
viper.SetDefault("totp.issuer", "WroofAuth") // Used for 2fa issuer value
|
||||
|
||||
cobra.OnInitialize(loadConfig)
|
||||
}
|
||||
|
||||
func loadConfig() {
|
||||
if etcdUrl, found := os.LookupEnv("ETCD_URL"); found {
|
||||
etcdPath, found := os.LookupEnv("ETCD_WROOF_CONFIG")
|
||||
|
||||
if !found {
|
||||
etcdPath = "/config/wroofauth.json"
|
||||
}
|
||||
viper.SetConfigType("json")
|
||||
|
||||
viper.AddRemoteProvider("etcd3", etcdUrl, etcdPath)
|
||||
err := viper.ReadRemoteConfig()
|
||||
|
||||
if err != nil {
|
||||
logger.Sugar.Fatal(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(time.Second * 5)
|
||||
|
||||
err := viper.WatchRemoteConfig()
|
||||
if err != nil {
|
||||
logger.Sugar.Fatal("unable to read remote config: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if cfgFile != "" {
|
||||
viper.SetConfigFile(cfgFile)
|
||||
} else {
|
||||
viper.AddConfigPath(".")
|
||||
viper.SetConfigName("config")
|
||||
}
|
||||
|
||||
err := viper.ReadInConfig()
|
||||
if err != nil {
|
||||
logger.Logger.Fatal("failed to load config", zap.Error(err))
|
||||
}
|
||||
|
||||
logger.StartLogger() // Restart Logger, as we may have changed our loglevel
|
||||
|
||||
logger.Sugar.Info("Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
|
|
14
cmd/serve.go
14
cmd/serve.go
|
@ -1,6 +1,10 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.1in9.net/raider/wroofauth/internal/database"
|
||||
"git.1in9.net/raider/wroofauth/internal/entities"
|
||||
"git.1in9.net/raider/wroofauth/internal/server"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -16,7 +20,17 @@ Cobra is a CLI library for Go that empowers applications.
|
|||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx := context.Background()
|
||||
|
||||
database.MongoConnect(ctx)
|
||||
database.RedisConnect(ctx)
|
||||
|
||||
entities.SetupEntityDatabases()
|
||||
|
||||
server.Serve()
|
||||
|
||||
database.MongoDisconnect(ctx)
|
||||
database.RedisDisconnect()
|
||||
},
|
||||
}
|
||||
|
||||
|
|
7
go.mod
7
go.mod
|
@ -4,8 +4,11 @@ go 1.18
|
|||
|
||||
require (
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/bsm/redislock v0.9.4 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
|
@ -19,6 +22,7 @@ require (
|
|||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pquerna/otp v1.4.0 // indirect
|
||||
github.com/redis/go-redis/v9 v9.2.1 // indirect
|
||||
github.com/rs/cors v1.7.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
|
@ -37,7 +41,8 @@ require (
|
|||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||
go.mongodb.org/mongo-driver v1.12.1 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/net v0.15.0 // indirect
|
||||
|
|
13
go.sum
13
go.sum
|
@ -81,6 +81,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bsm/redislock v0.9.4 h1:X/Wse1DPpiQgHbVYRE9zv6m070UcKoOGekgvpNhiSvw=
|
||||
github.com/bsm/redislock v0.9.4/go.mod h1:Epf7AJLiSFwLCiZcfi6pWFO/8eAYrYpQXFxEDPoDeAk=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
|
@ -88,9 +90,12 @@ github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1P
|
|||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
|
@ -124,6 +129,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
|
@ -469,6 +476,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
|
|||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
|
||||
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
|
@ -591,10 +600,14 @@ go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+
|
|||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
|
|
16
internal/database/locker.go
Normal file
16
internal/database/locker.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/bsm/redislock"
|
||||
)
|
||||
|
||||
var (
|
||||
Locker *redislock.Client
|
||||
LockBackoff = redislock.LimitRetry(redislock.LinearBackoff(100*time.Millisecond), 5)
|
||||
)
|
||||
|
||||
func setupLocker() {
|
||||
Locker = redislock.New(Redis)
|
||||
}
|
|
@ -3,48 +3,53 @@ package database
|
|||
import (
|
||||
"context"
|
||||
|
||||
"git.1in9.net/raider/wroofauth/internal/logger"
|
||||
"github.com/spf13/viper"
|
||||
"go.mongodb.org/mongo-driver/event"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var dbClient *mongo.Client
|
||||
var MongoDatabase *mongo.Database
|
||||
var Mongo *mongo.Database
|
||||
|
||||
func MongoConnect(ctx context.Context) {
|
||||
logger.Logger.Info("establishing connection to mongoDB...")
|
||||
|
||||
func Connect() {
|
||||
cmdMonitor := &event.CommandMonitor{
|
||||
Started: func(_ context.Context, evt *event.CommandStartedEvent) {
|
||||
// TODO: Log
|
||||
logger.Logger.Debug("mongoDB command running", zap.String("command", evt.Command.String()))
|
||||
},
|
||||
}
|
||||
|
||||
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(viper.GetString("mongo.uri")).SetMonitor(cmdMonitor))
|
||||
client, err := mongo.Connect(ctx, options.Client().ApplyURI(viper.GetString("mongo.uri")).SetMonitor(cmdMonitor))
|
||||
if err != nil {
|
||||
// TODO: Log
|
||||
panic(err)
|
||||
logger.Logger.Fatal("unable to connect to MongoDB", zap.Error(err))
|
||||
}
|
||||
|
||||
err = client.Ping(context.TODO(), readpref.Nearest())
|
||||
err = client.Ping(ctx, readpref.Nearest())
|
||||
if err != nil {
|
||||
// TODO: Log
|
||||
panic(err)
|
||||
logger.Logger.Fatal("unable to ping to MongoDB", zap.Error(err))
|
||||
}
|
||||
|
||||
logger.Logger.Info("mongoDB connection established")
|
||||
|
||||
dbClient = client
|
||||
|
||||
MongoDatabase = client.Database(viper.GetString("mongo.database"))
|
||||
Mongo = client.Database(viper.GetString("mongo.database"))
|
||||
|
||||
//UserCollection = Database.Collection(viper.GetString("mongo.collection.users"))
|
||||
//ClientCollection = Database.Collection(viper.GetString("mongo.collection.clients"))
|
||||
//GroupCollection = Database.Collection(viper.GetString("mongo.collection.groups"))
|
||||
}
|
||||
|
||||
func Disconnect() {
|
||||
err := dbClient.Disconnect(context.TODO())
|
||||
func MongoDisconnect(ctx context.Context) {
|
||||
err := dbClient.Disconnect(ctx)
|
||||
if err != nil {
|
||||
// TODO: Log
|
||||
panic(err)
|
||||
logger.Logger.Warn("failed to gracefully disconnect MongoDB", zap.Error(err))
|
||||
}
|
||||
|
||||
logger.Logger.Info("mongoDB gracefully disconnected")
|
||||
}
|
||||
|
|
40
internal/database/redis.go
Normal file
40
internal/database/redis.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.1in9.net/raider/wroofauth/internal/logger"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var Redis *redis.Client
|
||||
|
||||
func RedisConnect(ctx context.Context) {
|
||||
logger.Logger.Info("establishing connection to redis...")
|
||||
|
||||
Redis = redis.NewClient(&redis.Options{
|
||||
Addr: viper.GetString("redis.addr"),
|
||||
Username: viper.GetString("redis.username"),
|
||||
Password: viper.GetString("redis.password"),
|
||||
DB: viper.GetInt("redis.db"),
|
||||
})
|
||||
|
||||
err := Redis.Ping(ctx).Err()
|
||||
if err != nil {
|
||||
logger.Logger.Fatal("unable to ping to redis", zap.Error(err))
|
||||
}
|
||||
|
||||
setupLocker()
|
||||
|
||||
logger.Logger.Info("redis connection established")
|
||||
}
|
||||
|
||||
func RedisDisconnect() {
|
||||
err := Redis.Close()
|
||||
if err != nil {
|
||||
logger.Logger.Warn("failed to gracefully disconnect redis", zap.Error(err))
|
||||
}
|
||||
logger.Logger.Info("redis gracefully disconnected")
|
||||
}
|
|
@ -1,8 +1,15 @@
|
|||
package entities
|
||||
|
||||
import "go.mongodb.org/mongo-driver/bson/primitive"
|
||||
import (
|
||||
"git.1in9.net/raider/wroofauth/internal/entities/user"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type Entity interface {
|
||||
GetType() string
|
||||
GetID() primitive.ObjectID
|
||||
}
|
||||
|
||||
func SetupEntityDatabases() {
|
||||
user.SetupCollection()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,77 @@
|
|||
package user
|
||||
|
||||
func GetByIdentification(identification string) (*User, error) {
|
||||
return nil, nil
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.1in9.net/raider/wroofauth/internal/database"
|
||||
"git.1in9.net/raider/wroofauth/internal/logger"
|
||||
"github.com/spf13/viper"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var collection *mongo.Collection
|
||||
|
||||
func SetupCollection() {
|
||||
collection = database.Mongo.Collection(viper.GetString("mongo.collection.users"))
|
||||
}
|
||||
|
||||
func (u *User) Persist(ctx context.Context) error {
|
||||
return Persist(ctx, u)
|
||||
}
|
||||
|
||||
func Persist(ctx context.Context, user *User) error {
|
||||
if user == nil {
|
||||
logger.Logger.Panic("trying to persist null-pointer")
|
||||
}
|
||||
|
||||
// TODO: Validate?
|
||||
|
||||
upsert := true
|
||||
|
||||
_, err := collection.ReplaceOne(ctx, bson.M{"_id": user.ID}, user, &options.ReplaceOptions{Upsert: &upsert})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetById(ctx context.Context, id primitive.ObjectID) (*User, error) {
|
||||
res := collection.FindOne(ctx, bson.M{"_id": id})
|
||||
if res.Err() != nil {
|
||||
return nil, res.Err()
|
||||
}
|
||||
|
||||
var user User
|
||||
err := res.Decode(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func GetByIdentification(ctx context.Context, identification string) (*User, error) {
|
||||
res := collection.FindOne(ctx, bson.D{
|
||||
{Key: "$or",
|
||||
Value: bson.A{
|
||||
bson.D{{Key: "username", Value: identification}},
|
||||
bson.D{{Key: "email", Value: identification}},
|
||||
},
|
||||
},
|
||||
})
|
||||
if res.Err() != nil {
|
||||
return nil, res.Err()
|
||||
}
|
||||
|
||||
var user User
|
||||
err := res.Decode(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
|
@ -8,10 +9,12 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bsm/redislock"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/crypto/argon2"
|
||||
|
||||
"git.1in9.net/raider/wroofauth/internal/database"
|
||||
"git.1in9.net/raider/wroofauth/internal/parameters"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
@ -50,6 +53,12 @@ func (u *User) GetID() primitive.ObjectID {
|
|||
return u.ID
|
||||
}
|
||||
|
||||
func (u *User) Lock(ctx context.Context) (*redislock.Lock, error) {
|
||||
return database.Locker.Obtain(ctx, u.ID.Hex(), 100*time.Millisecond, &redislock.Options{
|
||||
RetryStrategy: database.LockBackoff,
|
||||
})
|
||||
}
|
||||
|
||||
func (u *User) GetFriendlyIdentifier() string {
|
||||
if u.Username != nil {
|
||||
return *u.Username
|
||||
|
|
21
internal/logger/logger.go
Normal file
21
internal/logger/logger.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
Logger *zap.Logger
|
||||
Sugar *zap.SugaredLogger
|
||||
)
|
||||
|
||||
func StartLogger() {
|
||||
Logger, _ = zap.NewProduction()
|
||||
|
||||
if viper.GetBool("development") {
|
||||
Logger, _ = zap.NewDevelopment()
|
||||
}
|
||||
|
||||
Sugar = Logger.Sugar()
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package machines
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
|
@ -49,7 +50,7 @@ type Session struct {
|
|||
User *user.User
|
||||
}
|
||||
|
||||
func NewSession() *Session {
|
||||
func NewSession(ctx context.Context) *Session {
|
||||
return &Session{
|
||||
State: SessionState_EMPTY,
|
||||
AuthenticationMethod: AuthenticationMethod_NONE,
|
||||
|
@ -58,7 +59,7 @@ func NewSession() *Session {
|
|||
}
|
||||
|
||||
// s.Validate checks if the session is in a valid state
|
||||
func (s *Session) Validate() error {
|
||||
func (s *Session) Validate(ctx context.Context) error {
|
||||
if s.IsAnyAuthenticated() {
|
||||
if s.User == nil {
|
||||
// We can only be here if a user is set
|
||||
|
@ -84,7 +85,7 @@ func (s *Session) IsAnyAuthenticated() bool {
|
|||
return strings.HasPrefix(string(s.State), "AUTHENTICATED_")
|
||||
}
|
||||
|
||||
func (s *Session) performPreflight() error {
|
||||
func (s *Session) performPreflight(ctx context.Context) error {
|
||||
// TODO: Do Preflight Checks.
|
||||
|
||||
// TODO: Do PASSWORD_EXPIRED check
|
||||
|
@ -103,12 +104,12 @@ func (s *Session) performPreflight() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) HandleIdentification(identification string) error {
|
||||
func (s *Session) HandleIdentification(ctx context.Context, identification string) error {
|
||||
if s.State != SessionState_EMPTY {
|
||||
return ErrIllegalStateAction // This step may only run on EMPTY sessions
|
||||
}
|
||||
|
||||
user, err := user.GetByIdentification(identification)
|
||||
user, err := user.GetByIdentification(ctx, identification)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -126,7 +127,7 @@ func (s *Session) HandleIdentification(identification string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) HandlePassword(password string) error {
|
||||
func (s *Session) HandlePassword(ctx context.Context, password string) error {
|
||||
if s.State != SessionState_UNAUTHENTICATED {
|
||||
return ErrIllegalStateAction // This step may only run on UNAUTHENTICATED sessions
|
||||
}
|
||||
|
@ -142,7 +143,7 @@ func (s *Session) HandlePassword(password string) error {
|
|||
if !s.User.Needs2FA() {
|
||||
// No 2fa, jump to AUTHENTICATED_PENDING for preflight
|
||||
s.State = SessionState_AUTHENTICATED_PENDING
|
||||
return s.performPreflight()
|
||||
return s.performPreflight(ctx)
|
||||
}
|
||||
|
||||
s.State = SessionState_AWAITING_FACTOR
|
||||
|
@ -151,7 +152,7 @@ func (s *Session) HandlePassword(password string) error {
|
|||
|
||||
// TODO: Passkey action
|
||||
|
||||
func (s *Session) HandleTOTP(otp string) error {
|
||||
func (s *Session) HandleTOTP(ctx context.Context, otp string) error {
|
||||
if s.State != SessionState_AWAITING_FACTOR {
|
||||
return ErrIllegalStateAction
|
||||
}
|
||||
|
@ -166,10 +167,10 @@ func (s *Session) HandleTOTP(otp string) error {
|
|||
|
||||
// Good to go for preflight.
|
||||
s.State = SessionState_AUTHENTICATED_PENDING
|
||||
return s.performPreflight()
|
||||
return s.performPreflight(ctx)
|
||||
}
|
||||
|
||||
func (s *Session) HandleLock() error {
|
||||
func (s *Session) HandleLock(ctx context.Context) error {
|
||||
if !s.IsAnyAuthenticated() {
|
||||
return ErrIllegalStateAction
|
||||
}
|
||||
|
@ -177,7 +178,7 @@ func (s *Session) HandleLock() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) HandleLogout() error {
|
||||
func (s *Session) HandleLogout(ctx context.Context) error {
|
||||
if !s.IsAnyAuthenticated() {
|
||||
return ErrIllegalStateAction
|
||||
}
|
||||
|
@ -185,7 +186,7 @@ func (s *Session) HandleLogout() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Session) Destroy() error {
|
||||
func (s *Session) Destroy(ctx context.Context) error {
|
||||
// TODO: Destroy Session
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
package server
|
||||
|
||||
import "log"
|
||||
|
||||
func Serve() {
|
||||
log.Println("hello")
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue