fix: env + session to new db format
This commit is contained in:
parent
38419a4ef4
commit
13c038effd
|
@ -5,6 +5,10 @@ import (
|
||||||
|
|
||||||
arangoDriver "github.com/arangodb/go-driver"
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
"github.com/authorizerdev/authorizer/server/constants"
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/providers"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/providers/arangodb"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/providers/mongodb"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/providers/sql"
|
||||||
"github.com/authorizerdev/authorizer/server/envstore"
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
|
@ -53,6 +57,7 @@ var (
|
||||||
IsArangoDB bool
|
IsArangoDB bool
|
||||||
IsMongoDB bool
|
IsMongoDB bool
|
||||||
Mgr Manager
|
Mgr Manager
|
||||||
|
Provider providers.Provider
|
||||||
Prefix = "authorizer_"
|
Prefix = "authorizer_"
|
||||||
Collections = CollectionList{
|
Collections = CollectionList{
|
||||||
User: Prefix + "users",
|
User: Prefix + "users",
|
||||||
|
@ -77,6 +82,27 @@ func InitDB() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if IsORMSupported {
|
||||||
|
Provider, err = sql.NewProvider()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("=> error setting sql provider:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsArangoDB {
|
||||||
|
Provider, err = arangodb.NewProvider()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("=> error setting arangodb provider:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsMongoDB {
|
||||||
|
Provider, err = mongodb.NewProvider()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("=> error setting arangodb provider:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("db type:", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType))
|
log.Println("db type:", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType))
|
||||||
|
|
||||||
switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
|
switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
|
||||||
|
|
11
server/db/models/env.go
Normal file
11
server/db/models/env.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
// Env model for db
|
||||||
|
type Env struct {
|
||||||
|
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb
|
||||||
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
||||||
|
EnvData []byte `gorm:"type:text" json:"env" bson:"env"`
|
||||||
|
Hash string `gorm:"type:hash" json:"hash" bson:"hash"`
|
||||||
|
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||||
|
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||||
|
}
|
21
server/db/models/model.go
Normal file
21
server/db/models/model.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
// Collections / Tables available for authorizer in the database
|
||||||
|
type CollectionList struct {
|
||||||
|
User string
|
||||||
|
VerificationRequest string
|
||||||
|
Session string
|
||||||
|
Env string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Prefix for table name / collection names
|
||||||
|
Prefix = "authorizer_"
|
||||||
|
// Collections / Tables available for authorizer in the database (used for dbs other than gorm)
|
||||||
|
Collections = CollectionList{
|
||||||
|
User: Prefix + "users",
|
||||||
|
VerificationRequest: Prefix + "verification_requests",
|
||||||
|
Session: Prefix + "sessions",
|
||||||
|
Env: Prefix + "env",
|
||||||
|
}
|
||||||
|
)
|
13
server/db/models/session.go
Normal file
13
server/db/models/session.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
// Session model for db
|
||||||
|
type Session struct {
|
||||||
|
Key string `json:"_key,omitempty" bson:"_key,omitempty"` // for arangodb
|
||||||
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
||||||
|
UserID string `gorm:"type:char(36),index:" json:"user_id" bson:"user_id"`
|
||||||
|
User User `json:"-" bson:"-"`
|
||||||
|
UserAgent string `json:"user_agent" bson:"user_agent"`
|
||||||
|
IP string `json:"ip" bson:"ip"`
|
||||||
|
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||||
|
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||||
|
}
|
24
server/db/models/user.go
Normal file
24
server/db/models/user.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
// User model for db
|
||||||
|
type User struct {
|
||||||
|
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb
|
||||||
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
||||||
|
|
||||||
|
Email string `gorm:"unique" json:"email" bson:"email"`
|
||||||
|
EmailVerifiedAt *int64 `json:"email_verified_at" bson:"email_verified_at"`
|
||||||
|
Password *string `gorm:"type:text" json:"password" bson:"password"`
|
||||||
|
SignupMethods string `json:"signup_methods" bson:"signup_methods"`
|
||||||
|
GivenName *string `json:"given_name" bson:"given_name"`
|
||||||
|
FamilyName *string `json:"family_name" bson:"family_name"`
|
||||||
|
MiddleName *string `json:"middle_name" bson:"middle_name"`
|
||||||
|
Nickname *string `json:"nickname" bson:"nickname"`
|
||||||
|
Gender *string `json:"gender" bson:"gender"`
|
||||||
|
Birthdate *string `json:"birthdate" bson:"birthdate"`
|
||||||
|
PhoneNumber *string `gorm:"unique" json:"phone_number" bson:"phone_number"`
|
||||||
|
PhoneNumberVerifiedAt *int64 `json:"phone_number_verified_at" bson:"phone_number_verified_at"`
|
||||||
|
Picture *string `gorm:"type:text" json:"picture" bson:"picture"`
|
||||||
|
Roles string `json:"roles" bson:"roles"`
|
||||||
|
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||||
|
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||||
|
}
|
13
server/db/models/verification_requests.go
Normal file
13
server/db/models/verification_requests.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
// VerificationRequest model for db
|
||||||
|
type VerificationRequest struct {
|
||||||
|
Key string `json:"_key,omitempty" bson:"_key"` // for arangodb
|
||||||
|
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id"`
|
||||||
|
Token string `gorm:"type:text" json:"token" bson:"token"`
|
||||||
|
Identifier string `gorm:"uniqueIndex:idx_email_identifier" json:"identifier" bson:"identifier"`
|
||||||
|
ExpiresAt int64 `json:"expires_at" bson:"expires_at"`
|
||||||
|
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at" bson:"created_at"`
|
||||||
|
UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"`
|
||||||
|
Email string `gorm:"uniqueIndex:idx_email_identifier" json:"email" bson:"email"`
|
||||||
|
}
|
123
server/db/providers/arangodb/arangodb.go
Normal file
123
server/db/providers/arangodb/arangodb.go
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
package arangodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/arangodb/go-driver"
|
||||||
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
|
"github.com/arangodb/go-driver/http"
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct {
|
||||||
|
db arangoDriver.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
// for this we need arangodb instance up and running
|
||||||
|
// for local testing we can use dockerized version of it
|
||||||
|
// docker run -p 8529:8529 -e ARANGO_ROOT_PASSWORD=root arangodb/arangodb:3.8.4
|
||||||
|
|
||||||
|
// NewProvider to initialize arangodb connection
|
||||||
|
func NewProvider() (*provider, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
conn, err := http.NewConnection(http.ConnectionConfig{
|
||||||
|
Endpoints: []string{envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
arangoClient, err := arangoDriver.NewClient(arangoDriver.ClientConfig{
|
||||||
|
Connection: conn,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var arangodb driver.Database
|
||||||
|
|
||||||
|
arangodb_exists, err := arangoClient.DatabaseExists(nil, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
||||||
|
|
||||||
|
if arangodb_exists {
|
||||||
|
log.Println(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName) + " db exists already")
|
||||||
|
arangodb, err = arangoClient.Database(nil, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arangodb, err = arangoClient.CreateDatabase(nil, envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.User)
|
||||||
|
if userCollectionExists {
|
||||||
|
log.Println(models.Collections.User + " collection exists already")
|
||||||
|
} else {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, models.Collections.User, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error creating collection("+models.Collections.User+"):", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userCollection, _ := arangodb.Collection(nil, models.Collections.User)
|
||||||
|
userCollection.EnsureHashIndex(ctx, []string{"email"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Unique: true,
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
userCollection.EnsureHashIndex(ctx, []string{"phone_number"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Unique: true,
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
verificationRequestCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.VerificationRequest)
|
||||||
|
if verificationRequestCollectionExists {
|
||||||
|
log.Println(models.Collections.VerificationRequest + " collection exists already")
|
||||||
|
} else {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, models.Collections.VerificationRequest, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error creating collection("+models.Collections.VerificationRequest+"):", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verificationRequestCollection, _ := arangodb.Collection(nil, models.Collections.VerificationRequest)
|
||||||
|
verificationRequestCollection.EnsureHashIndex(ctx, []string{"email", "identifier"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Unique: true,
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
verificationRequestCollection.EnsureHashIndex(ctx, []string{"token"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
sessionCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Session)
|
||||||
|
if sessionCollectionExists {
|
||||||
|
log.Println(models.Collections.Session + " collection exists already")
|
||||||
|
} else {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, models.Collections.Session, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error creating collection("+models.Collections.Session+"):", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionCollection, _ := arangodb.Collection(nil, models.Collections.Session)
|
||||||
|
sessionCollection.EnsureHashIndex(ctx, []string{"user_id"}, &arangoDriver.EnsureHashIndexOptions{
|
||||||
|
Sparse: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
configCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Env)
|
||||||
|
if configCollectionExists {
|
||||||
|
log.Println(models.Collections.Env + " collection exists already")
|
||||||
|
} else {
|
||||||
|
_, err = arangodb.CreateCollection(ctx, models.Collections.Env, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error creating collection("+models.Collections.Env+"):", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &provider{
|
||||||
|
db: arangodb,
|
||||||
|
}, err
|
||||||
|
}
|
73
server/db/providers/arangodb/env.go
Normal file
73
server/db/providers/arangodb/env.go
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package arangodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
arangoDriver "github.com/arangodb/go-driver"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEnv to save environment information in database
|
||||||
|
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||||
|
if env.ID == "" {
|
||||||
|
env.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
env.CreatedAt = time.Now().Unix()
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
configCollection, _ := p.db.Collection(nil, models.Collections.Env)
|
||||||
|
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(nil), env)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error adding config:", err)
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
env.Key = meta.Key
|
||||||
|
env.ID = meta.ID.String()
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEnv to update environment information in database
|
||||||
|
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
collection, _ := p.db.Collection(nil, models.Collections.Env)
|
||||||
|
meta, err := collection.UpdateDocument(nil, env.Key, env)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error updating config:", err)
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
|
||||||
|
env.Key = meta.Key
|
||||||
|
env.ID = meta.ID.String()
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnv to get environment information from database
|
||||||
|
func (p *provider) GetEnv() (models.Env, error) {
|
||||||
|
var env models.Env
|
||||||
|
query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.Env)
|
||||||
|
|
||||||
|
cursor, err := p.db.Query(nil, query, nil)
|
||||||
|
if err != nil {
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if !cursor.HasMore() {
|
||||||
|
if env.Key == "" {
|
||||||
|
return env, fmt.Errorf("config not found")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err := cursor.ReadDocument(nil, &env)
|
||||||
|
if err != nil {
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return env, nil
|
||||||
|
}
|
42
server/db/providers/arangodb/session.go
Normal file
42
server/db/providers/arangodb/session.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package arangodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddSession to save session information in database
|
||||||
|
func (p *provider) AddSession(session models.Session) error {
|
||||||
|
if session.ID == "" {
|
||||||
|
session.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
session.CreatedAt = time.Now().Unix()
|
||||||
|
session.UpdatedAt = time.Now().Unix()
|
||||||
|
sessionCollection, _ := p.db.Collection(nil, models.Collections.Session)
|
||||||
|
_, err := sessionCollection.CreateDocument(nil, session)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(`error saving session`, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSession to delete session information from database
|
||||||
|
func (p *provider) DeleteSession(userId string) error {
|
||||||
|
query := fmt.Sprintf(`FOR d IN %s FILTER d.user_id == @userId REMOVE { _key: d._key } IN %s`, models.Collections.Session, models.Collections.Session)
|
||||||
|
bindVars := map[string]interface{}{
|
||||||
|
"userId": userId,
|
||||||
|
}
|
||||||
|
cursor, err := p.db.Query(nil, query, bindVars)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("=> error deleting arangodb session:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer cursor.Close()
|
||||||
|
return nil
|
||||||
|
}
|
66
server/db/providers/mongodb/env.go
Normal file
66
server/db/providers/mongodb/env.go
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEnv to save environment information in database
|
||||||
|
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||||
|
if env.ID == "" {
|
||||||
|
env.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
env.CreatedAt = time.Now().Unix()
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
env.Key = env.ID
|
||||||
|
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||||
|
_, err := configCollection.InsertOne(nil, env)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error adding config:", err)
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEnv to update environment information in database
|
||||||
|
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||||
|
_, err := configCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions())
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error updating config:", err)
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnv to get environment information from database
|
||||||
|
func (p *provider) GetEnv() (models.Env, error) {
|
||||||
|
var env models.Env
|
||||||
|
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||||
|
cursor, err := configCollection.Find(nil, bson.M{}, options.Find())
|
||||||
|
if err != nil {
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
defer cursor.Close(nil)
|
||||||
|
|
||||||
|
for cursor.Next(nil) {
|
||||||
|
err := cursor.Decode(&env)
|
||||||
|
if err != nil {
|
||||||
|
return env, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if env.ID == "" {
|
||||||
|
return env, fmt.Errorf("config not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return env, nil
|
||||||
|
}
|
88
server/db/providers/mongodb/mongodb.go
Normal file
88
server/db/providers/mongodb/mongodb.go
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct {
|
||||||
|
db *mongo.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProvider to initialize mongodb connection
|
||||||
|
func NewProvider() (*provider, error) {
|
||||||
|
mongodbOptions := options.Client().ApplyURI(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL))
|
||||||
|
maxWait := time.Duration(5 * time.Second)
|
||||||
|
mongodbOptions.ConnectTimeout = &maxWait
|
||||||
|
mongoClient, err := mongo.NewClient(mongodbOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
err = mongoClient.Connect(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mongoClient.Ping(ctx, readpref.Primary())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mongodb := mongoClient.Database(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseName), options.Database())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, models.Collections.User, options.CreateCollection())
|
||||||
|
userCollection := mongodb.Collection(models.Collections.User, options.Collection())
|
||||||
|
userCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
mongo.IndexModel{
|
||||||
|
Keys: bson.M{"email": 1},
|
||||||
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
userCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
mongo.IndexModel{
|
||||||
|
Keys: bson.M{"phone_number": 1},
|
||||||
|
Options: options.Index().SetUnique(true).SetSparse(true).SetPartialFilterExpression(map[string]interface{}{
|
||||||
|
"phone_number": map[string]string{"$type": "string"},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, models.Collections.VerificationRequest, options.CreateCollection())
|
||||||
|
verificationRequestCollection := mongodb.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||||
|
verificationRequestCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
mongo.IndexModel{
|
||||||
|
Keys: bson.M{"email": 1, "identifier": 1},
|
||||||
|
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
verificationRequestCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
mongo.IndexModel{
|
||||||
|
Keys: bson.M{"token": 1},
|
||||||
|
Options: options.Index().SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, models.Collections.Session, options.CreateCollection())
|
||||||
|
sessionCollection := mongodb.Collection(models.Collections.Session, options.Collection())
|
||||||
|
sessionCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||||
|
mongo.IndexModel{
|
||||||
|
Keys: bson.M{"user_id": 1},
|
||||||
|
Options: options.Index().SetSparse(true),
|
||||||
|
},
|
||||||
|
}, options.CreateIndexes())
|
||||||
|
|
||||||
|
mongodb.CreateCollection(ctx, models.Collections.Env, options.CreateCollection())
|
||||||
|
|
||||||
|
return &provider{
|
||||||
|
db: mongodb,
|
||||||
|
}, nil
|
||||||
|
}
|
40
server/db/providers/mongodb/session.go
Normal file
40
server/db/providers/mongodb/session.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddSession to save session information in database
|
||||||
|
func (p *provider) AddSession(session models.Session) error {
|
||||||
|
if session.ID == "" {
|
||||||
|
session.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Key = session.ID
|
||||||
|
session.CreatedAt = time.Now().Unix()
|
||||||
|
session.UpdatedAt = time.Now().Unix()
|
||||||
|
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
||||||
|
_, err := sessionCollection.InsertOne(nil, session)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(`error saving session`, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSession to delete session information from database
|
||||||
|
func (p *provider) DeleteSession(userId string) error {
|
||||||
|
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
||||||
|
_, err := sessionCollection.DeleteMany(nil, bson.M{"user_id": userId}, options.Delete())
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error deleting session:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
41
server/db/providers/providers.go
Normal file
41
server/db/providers/providers.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package providers
|
||||||
|
|
||||||
|
import "github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
|
||||||
|
type Provider interface {
|
||||||
|
// AddUser to save user information in database
|
||||||
|
AddUser(user models.User) (models.User, error)
|
||||||
|
// UpdateUser to update user information in database
|
||||||
|
UpdateUser(user models.User) (models.User, error)
|
||||||
|
// DeleteUser to delete user information from database
|
||||||
|
DeleteUser(user models.User) error
|
||||||
|
// ListUsers to get list of users from database
|
||||||
|
ListUsers() ([]models.User, error)
|
||||||
|
// GetUserByEmail to get user information from database using email address
|
||||||
|
GetUserByEmail(email string) (models.User, error)
|
||||||
|
// GetUserByID to get user information from database using user ID
|
||||||
|
GetUserByID(id string) (models.User, error)
|
||||||
|
|
||||||
|
// AddVerification to save verification request in database
|
||||||
|
AddVerificationRequest(verification models.VerificationRequest) (models.VerificationRequest, error)
|
||||||
|
// GetVerificationRequestByToken to get verification request from database using token
|
||||||
|
GetVerificationRequestByToken(token string) (models.VerificationRequest, error)
|
||||||
|
// GetVerificationRequestByEmail to get verification request by email from database
|
||||||
|
GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error)
|
||||||
|
// ListVerificationRequests to get list of verification requests from database
|
||||||
|
ListVerificationRequests() ([]models.VerificationRequest, error)
|
||||||
|
// DeleteVerificationRequest to delete verification request from database
|
||||||
|
DeleteVerificationRequest(verificationRequest models.VerificationRequest) error
|
||||||
|
|
||||||
|
// AddSession to save session information in database
|
||||||
|
AddSession(session models.Session) error
|
||||||
|
// DeleteSession to delete session information from database
|
||||||
|
DeleteSession(userId string) error
|
||||||
|
|
||||||
|
// AddEnv to save environment information in database
|
||||||
|
AddEnv(env models.Env) (models.Env, error)
|
||||||
|
// UpdateEnv to update environment information in database
|
||||||
|
UpdateEnv(env models.Env) (models.Env, error)
|
||||||
|
// GetEnv to get environment information from database
|
||||||
|
GetEnv() (models.Env, error)
|
||||||
|
}
|
49
server/db/providers/sql/env.go
Normal file
49
server/db/providers/sql/env.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package sql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddEnv to save environment information in database
|
||||||
|
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||||
|
if env.ID == "" {
|
||||||
|
env.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
env.Key = env.ID
|
||||||
|
result := p.db.Create(&env)
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
log.Println("error adding config:", result.Error)
|
||||||
|
return env, result.Error
|
||||||
|
}
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateEnv to update environment information in database
|
||||||
|
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||||
|
env.UpdatedAt = time.Now().Unix()
|
||||||
|
result := p.db.Save(&env)
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
log.Println("error updating config:", result.Error)
|
||||||
|
return env, result.Error
|
||||||
|
}
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnv to get environment information from database
|
||||||
|
func (p *provider) GetEnv() (models.Env, error) {
|
||||||
|
var env models.Env
|
||||||
|
result := p.db.First(&env)
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
return env, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return env, nil
|
||||||
|
}
|
38
server/db/providers/sql/session.go
Normal file
38
server/db/providers/sql/session.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package sql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddSession to save session information in database
|
||||||
|
func (p *provider) AddSession(session models.Session) error {
|
||||||
|
if session.ID == "" {
|
||||||
|
session.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Key = session.ID
|
||||||
|
res := p.db.Clauses(
|
||||||
|
clause.OnConflict{
|
||||||
|
DoNothing: true,
|
||||||
|
}).Create(&session)
|
||||||
|
if res.Error != nil {
|
||||||
|
log.Println(`error saving session`, res.Error)
|
||||||
|
return res.Error
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSession to delete session information from database
|
||||||
|
func (p *provider) DeleteSession(userId string) error {
|
||||||
|
result := p.db.Where("user_id = ?", userId).Delete(&models.Session{})
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
log.Println(`error deleting session:`, result.Error)
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
53
server/db/providers/sql/sql.go
Normal file
53
server/db/providers/sql/sql.go
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package sql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/authorizerdev/authorizer/server/constants"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
|
"github.com/authorizerdev/authorizer/server/envstore"
|
||||||
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
|
"gorm.io/driver/sqlite"
|
||||||
|
"gorm.io/driver/sqlserver"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProvider returns a new SQL provider
|
||||||
|
func NewProvider() (*provider, error) {
|
||||||
|
var sqlDB *gorm.DB
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ormConfig := &gorm.Config{
|
||||||
|
NamingStrategy: schema.NamingStrategy{
|
||||||
|
TablePrefix: models.Prefix,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
switch envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseType) {
|
||||||
|
case constants.DbTypePostgres:
|
||||||
|
sqlDB, err = gorm.Open(postgres.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
|
break
|
||||||
|
case constants.DbTypeSqlite:
|
||||||
|
sqlDB, err = gorm.Open(sqlite.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
|
break
|
||||||
|
case constants.DbTypeMysql:
|
||||||
|
sqlDB, err = gorm.Open(mysql.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
|
break
|
||||||
|
case constants.DbTypeSqlserver:
|
||||||
|
sqlDB, err = gorm.Open(sqlserver.Open(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyDatabaseURL)), ormConfig)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{})
|
||||||
|
return &provider{
|
||||||
|
db: sqlDB,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/authorizerdev/authorizer/server/db"
|
"github.com/authorizerdev/authorizer/server/db"
|
||||||
|
"github.com/authorizerdev/authorizer/server/db/models"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,13 +19,18 @@ func StringSliceContains(s []string, e string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveSessionInDB saves sessions generated for a given user with meta information
|
// SaveSessionInDB saves sessions generated for a given user with meta information
|
||||||
// Not store token here as that could be security breach
|
// Do not store token here as that could be security breach
|
||||||
func SaveSessionInDB(userId string, c *gin.Context) {
|
func SaveSessionInDB(userId string, c *gin.Context) {
|
||||||
sessionData := db.Session{
|
sessionData := models.Session{
|
||||||
UserID: userId,
|
UserID: userId,
|
||||||
UserAgent: GetUserAgent(c.Request),
|
UserAgent: GetUserAgent(c.Request),
|
||||||
IP: GetIP(c.Request),
|
IP: GetIP(c.Request),
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Mgr.AddSession(sessionData)
|
err := db.Provider.AddSession(&sessionData)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("=> error saving session in db:", err)
|
||||||
|
} else {
|
||||||
|
log.Println("=> session saved in db:", sessionData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user