Merge pull request #194 from authorizerdev/feat/webhook
feat: add webhook apis + integrate in events
This commit is contained in:
commit
4f5a6c77f8
18
server/constants/webhook_event.go
Normal file
18
server/constants/webhook_event.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package constants
|
||||
|
||||
const (
|
||||
|
||||
// UserLoginWebhookEvent name for login event
|
||||
UserLoginWebhookEvent = `user.login`
|
||||
// UserCreatedWebhookEvent name for user creation event
|
||||
// This is triggered when user entry is created but still not verified
|
||||
UserCreatedWebhookEvent = `user.created`
|
||||
// UserSignUpWebhookEvent name for signup event
|
||||
UserSignUpWebhookEvent = `user.signup`
|
||||
// UserAccessRevokedWebhookEvent name for user access revoke event
|
||||
UserAccessRevokedWebhookEvent = `user.access_revoked`
|
||||
// UserAccessEnabledWebhookEvent name for user access enable event
|
||||
UserAccessEnabledWebhookEvent = `user.access_enabled`
|
||||
// UserDeletedWebhookEvent name for user deleted event
|
||||
UserDeletedWebhookEvent = `user.deleted`
|
||||
)
|
|
@ -6,6 +6,8 @@ type CollectionList struct {
|
|||
VerificationRequest string
|
||||
Session string
|
||||
Env string
|
||||
Webhook string
|
||||
WebhookLog string
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -17,5 +19,7 @@ var (
|
|||
VerificationRequest: Prefix + "verification_requests",
|
||||
Session: Prefix + "sessions",
|
||||
Env: Prefix + "env",
|
||||
Webhook: Prefix + "webhook",
|
||||
WebhookLog: Prefix + "webhook_log",
|
||||
}
|
||||
)
|
||||
|
|
35
server/db/models/webhook.go
Normal file
35
server/db/models/webhook.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
)
|
||||
|
||||
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||
|
||||
// Webhook model for db
|
||||
type Webhook struct {
|
||||
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||
EventName string `gorm:"unique" json:"event_name" bson:"event_name" cql:"event_name"`
|
||||
EndPoint string `gorm:"type:text" json:"endpoint" bson:"endpoint" cql:"endpoint"`
|
||||
Headers string `gorm:"type:text" json:"headers" bson:"headers" cql:"headers"`
|
||||
Enabled bool `json:"enabled" bson:"enabled" cql:"enabled"`
|
||||
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||
}
|
||||
|
||||
func (w *Webhook) AsAPIWebhook() *model.Webhook {
|
||||
headersMap := make(map[string]interface{})
|
||||
json.Unmarshal([]byte(w.Headers), &headersMap)
|
||||
return &model.Webhook{
|
||||
ID: w.ID,
|
||||
EventName: &w.EventName,
|
||||
Endpoint: &w.EndPoint,
|
||||
Headers: headersMap,
|
||||
Enabled: &w.Enabled,
|
||||
CreatedAt: &w.CreatedAt,
|
||||
UpdatedAt: &w.UpdatedAt,
|
||||
}
|
||||
}
|
30
server/db/models/webhook_log.go
Normal file
30
server/db/models/webhook_log.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package models
|
||||
|
||||
import "github.com/authorizerdev/authorizer/server/graph/model"
|
||||
|
||||
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
|
||||
|
||||
// WebhookLog model for db
|
||||
type WebhookLog struct {
|
||||
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
|
||||
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
|
||||
HttpStatus int64 `json:"http_status" bson:"http_status" cql:"http_status"`
|
||||
Response string `gorm:"type:text" json:"response" bson:"response" cql:"response"`
|
||||
Request string `gorm:"type:text" json:"request" bson:"request" cql:"request"`
|
||||
WebhookID string `gorm:"type:char(36),index:" json:"webhook_id" bson:"webhook_id" cql:"webhook_id"`
|
||||
Webhook Webhook `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" bson:"-" cql:"-"`
|
||||
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
|
||||
}
|
||||
|
||||
func (w *WebhookLog) AsAPIWebhookLog() *model.WebhookLog {
|
||||
return &model.WebhookLog{
|
||||
ID: w.ID,
|
||||
HTTPStatus: &w.HttpStatus,
|
||||
Response: &w.Response,
|
||||
Request: &w.Request,
|
||||
WebhookID: &w.WebhookID,
|
||||
CreatedAt: &w.CreatedAt,
|
||||
UpdatedAt: &w.UpdatedAt,
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package arangodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
@ -11,15 +12,15 @@ import (
|
|||
)
|
||||
|
||||
// AddEnv to save environment information in database
|
||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) AddEnv(ctx context.Context, 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)
|
||||
configCollection, _ := p.db.Collection(ctx, models.Collections.Env)
|
||||
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), env)
|
||||
if err != nil {
|
||||
return env, err
|
||||
}
|
||||
|
@ -29,10 +30,10 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// UpdateEnv to update environment information in database
|
||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) UpdateEnv(ctx context.Context, 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)
|
||||
collection, _ := p.db.Collection(ctx, models.Collections.Env)
|
||||
meta, err := collection.UpdateDocument(ctx, env.Key, env)
|
||||
if err != nil {
|
||||
return env, err
|
||||
}
|
||||
|
@ -43,11 +44,11 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// GetEnv to get environment information from database
|
||||
func (p *provider) GetEnv() (models.Env, error) {
|
||||
func (p *provider) GetEnv(ctx context.Context) (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)
|
||||
cursor, err := p.db.Query(ctx, query, nil)
|
||||
if err != nil {
|
||||
return env, err
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ func (p *provider) GetEnv() (models.Env, error) {
|
|||
}
|
||||
break
|
||||
}
|
||||
_, err := cursor.ReadDocument(nil, &env)
|
||||
_, err := cursor.ReadDocument(ctx, &env)
|
||||
if err != nil {
|
||||
return env, err
|
||||
}
|
||||
|
|
|
@ -107,6 +107,33 @@ func NewProvider() (*provider, error) {
|
|||
}
|
||||
}
|
||||
|
||||
webhookCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Webhook)
|
||||
if !webhookCollectionExists {
|
||||
_, err = arangodb.CreateCollection(ctx, models.Collections.Webhook, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
webhookCollection, _ := arangodb.Collection(nil, models.Collections.Webhook)
|
||||
webhookCollection.EnsureHashIndex(ctx, []string{"event_name"}, &arangoDriver.EnsureHashIndexOptions{
|
||||
Unique: true,
|
||||
Sparse: true,
|
||||
})
|
||||
|
||||
webhookLogCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.WebhookLog)
|
||||
if !webhookLogCollectionExists {
|
||||
_, err = arangodb.CreateCollection(ctx, models.Collections.WebhookLog, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
webhookLogCollection, _ := arangodb.Collection(nil, models.Collections.WebhookLog)
|
||||
webhookLogCollection.EnsureHashIndex(ctx, []string{"webhook_id"}, &arangoDriver.EnsureHashIndexOptions{
|
||||
Sparse: true,
|
||||
})
|
||||
|
||||
return &provider{
|
||||
db: arangodb,
|
||||
}, err
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package arangodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
@ -9,15 +10,15 @@ import (
|
|||
)
|
||||
|
||||
// AddSession to save session information in database
|
||||
func (p *provider) AddSession(session models.Session) error {
|
||||
func (p *provider) AddSession(ctx context.Context, 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)
|
||||
sessionCollection, _ := p.db.Collection(ctx, models.Collections.Session)
|
||||
_, err := sessionCollection.CreateDocument(ctx, session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -25,12 +26,12 @@ func (p *provider) AddSession(session models.Session) error {
|
|||
}
|
||||
|
||||
// DeleteSession to delete session information from database
|
||||
func (p *provider) DeleteSession(userId string) error {
|
||||
func (p *provider) DeleteSession(ctx context.Context, 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)
|
||||
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
)
|
||||
|
||||
// AddUser to save user information in database
|
||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
||||
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
if user.ID == "" {
|
||||
user.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||
|
||||
user.CreatedAt = time.Now().Unix()
|
||||
user.UpdatedAt = time.Now().Unix()
|
||||
userCollection, _ := p.db.Collection(nil, models.Collections.User)
|
||||
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(nil), user)
|
||||
userCollection, _ := p.db.Collection(ctx, models.Collections.User)
|
||||
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), user)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
@ -42,10 +42,10 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// UpdateUser to update user information in database
|
||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
||||
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
user.UpdatedAt = time.Now().Unix()
|
||||
collection, _ := p.db.Collection(nil, models.Collections.User)
|
||||
meta, err := collection.UpdateDocument(nil, user.Key, user)
|
||||
collection, _ := p.db.Collection(ctx, models.Collections.User)
|
||||
meta, err := collection.UpdateDocument(ctx, user.Key, user)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
@ -56,9 +56,9 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// DeleteUser to delete user information from database
|
||||
func (p *provider) DeleteUser(user models.User) error {
|
||||
collection, _ := p.db.Collection(nil, models.Collections.User)
|
||||
_, err := collection.RemoveDocument(nil, user.Key)
|
||||
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||
collection, _ := p.db.Collection(ctx, models.Collections.User)
|
||||
_, err := collection.RemoveDocument(ctx, user.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -67,13 +67,13 @@ func (p *provider) DeleteUser(user models.User) error {
|
|||
}
|
||||
|
||||
// ListUsers to get list of users from database
|
||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
||||
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||
var users []*model.User
|
||||
ctx := driver.WithQueryFullCount(context.Background())
|
||||
sctx := driver.WithQueryFullCount(ctx)
|
||||
|
||||
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.User, pagination.Offset, pagination.Limit)
|
||||
|
||||
cursor, err := p.db.Query(ctx, query, nil)
|
||||
cursor, err := p.db.Query(sctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||
|
||||
for {
|
||||
var user models.User
|
||||
meta, err := cursor.ReadDocument(nil, &user)
|
||||
meta, err := cursor.ReadDocument(ctx, &user)
|
||||
|
||||
if arangoDriver.IsNoMoreDocuments(err) {
|
||||
break
|
||||
|
@ -104,7 +104,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||
}
|
||||
|
||||
// GetUserByEmail to get user information from database using email address
|
||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
||||
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||
var user models.User
|
||||
|
||||
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email RETURN d", models.Collections.User)
|
||||
|
@ -112,7 +112,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||
"email": email,
|
||||
}
|
||||
|
||||
cursor, err := p.db.Query(nil, query, bindVars)
|
||||
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||
}
|
||||
break
|
||||
}
|
||||
_, err := cursor.ReadDocument(nil, &user)
|
||||
_, err := cursor.ReadDocument(ctx, &user)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||
}
|
||||
|
||||
// GetUserByID to get user information from database using user ID
|
||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
||||
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||
var user models.User
|
||||
|
||||
query := fmt.Sprintf("FOR d in %s FILTER d._id == @id LIMIT 1 RETURN d", models.Collections.User)
|
||||
|
@ -143,7 +143,7 @@ func (p *provider) GetUserByID(id string) (models.User, error) {
|
|||
"id": id,
|
||||
}
|
||||
|
||||
cursor, err := p.db.Query(nil, query, bindVars)
|
||||
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ func (p *provider) GetUserByID(id string) (models.User, error) {
|
|||
}
|
||||
break
|
||||
}
|
||||
_, err := cursor.ReadDocument(nil, &user)
|
||||
_, err := cursor.ReadDocument(ctx, &user)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
|
|
@ -12,15 +12,15 @@ import (
|
|||
)
|
||||
|
||||
// AddVerification to save verification request in database
|
||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
if verificationRequest.ID == "" {
|
||||
verificationRequest.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
verificationRequest.CreatedAt = time.Now().Unix()
|
||||
verificationRequest.UpdatedAt = time.Now().Unix()
|
||||
verificationRequestRequestCollection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
||||
meta, err := verificationRequestRequestCollection.CreateDocument(nil, verificationRequest)
|
||||
verificationRequestRequestCollection, _ := p.db.Collection(ctx, models.Collections.VerificationRequest)
|
||||
meta, err := verificationRequestRequestCollection.CreateDocument(ctx, verificationRequest)
|
||||
if err != nil {
|
||||
return verificationRequest, err
|
||||
}
|
||||
|
@ -31,14 +31,14 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||
}
|
||||
|
||||
// GetVerificationRequestByToken to get verification request from database using token
|
||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
query := fmt.Sprintf("FOR d in %s FILTER d.token == @token LIMIT 1 RETURN d", models.Collections.VerificationRequest)
|
||||
bindVars := map[string]interface{}{
|
||||
"token": token,
|
||||
}
|
||||
|
||||
cursor, err := p.db.Query(nil, query, bindVars)
|
||||
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||
if err != nil {
|
||||
return verificationRequest, err
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||
}
|
||||
break
|
||||
}
|
||||
_, err := cursor.ReadDocument(nil, &verificationRequest)
|
||||
_, err := cursor.ReadDocument(ctx, &verificationRequest)
|
||||
if err != nil {
|
||||
return verificationRequest, err
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||
}
|
||||
|
||||
// GetVerificationRequestByEmail to get verification request by email from database
|
||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
|
||||
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email FILTER d.identifier == @identifier LIMIT 1 RETURN d", models.Collections.VerificationRequest)
|
||||
|
@ -70,7 +70,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||
"identifier": identifier,
|
||||
}
|
||||
|
||||
cursor, err := p.db.Query(nil, query, bindVars)
|
||||
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||
if err != nil {
|
||||
return verificationRequest, err
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||
}
|
||||
break
|
||||
}
|
||||
_, err := cursor.ReadDocument(nil, &verificationRequest)
|
||||
_, err := cursor.ReadDocument(ctx, &verificationRequest)
|
||||
if err != nil {
|
||||
return verificationRequest, err
|
||||
}
|
||||
|
@ -93,12 +93,12 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||
}
|
||||
|
||||
// ListVerificationRequests to get list of verification requests from database
|
||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
var verificationRequests []*model.VerificationRequest
|
||||
ctx := driver.WithQueryFullCount(context.Background())
|
||||
sctx := driver.WithQueryFullCount(ctx)
|
||||
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.VerificationRequest, pagination.Offset, pagination.Limit)
|
||||
|
||||
cursor, err := p.db.Query(ctx, query, nil)
|
||||
cursor, err := p.db.Query(sctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||
|
||||
for {
|
||||
var verificationRequest models.VerificationRequest
|
||||
meta, err := cursor.ReadDocument(nil, &verificationRequest)
|
||||
meta, err := cursor.ReadDocument(ctx, &verificationRequest)
|
||||
|
||||
if driver.IsNoMoreDocuments(err) {
|
||||
break
|
||||
|
@ -130,7 +130,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||
}
|
||||
|
||||
// DeleteVerificationRequest to delete verification request from database
|
||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
||||
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||
collection, _ := p.db.Collection(nil, models.Collections.VerificationRequest)
|
||||
_, err := collection.RemoveDocument(nil, verificationRequest.Key)
|
||||
if err != nil {
|
||||
|
|
161
server/db/providers/arangodb/webhook.go
Normal file
161
server/db/providers/arangodb/webhook.go
Normal file
|
@ -0,0 +1,161 @@
|
|||
package arangodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
arangoDriver "github.com/arangodb/go-driver"
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AddWebhook to add webhook
|
||||
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
if webhook.ID == "" {
|
||||
webhook.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhook.Key = webhook.ID
|
||||
webhook.CreatedAt = time.Now().Unix()
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook)
|
||||
_, err := webhookCollection.CreateDocument(ctx, webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// UpdateWebhook to update webhook
|
||||
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook)
|
||||
meta, err := webhookCollection.UpdateDocument(ctx, webhook.Key, webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
webhook.Key = meta.Key
|
||||
webhook.ID = meta.ID.String()
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// ListWebhooks to list webhook
|
||||
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||
webhooks := []*model.Webhook{}
|
||||
|
||||
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.Webhook, pagination.Offset, pagination.Limit)
|
||||
|
||||
sctx := driver.WithQueryFullCount(ctx)
|
||||
cursor, err := p.db.Query(sctx, query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close()
|
||||
|
||||
paginationClone := pagination
|
||||
paginationClone.Total = cursor.Statistics().FullCount()
|
||||
|
||||
for {
|
||||
var webhook models.Webhook
|
||||
meta, err := cursor.ReadDocument(ctx, &webhook)
|
||||
|
||||
if arangoDriver.IsNoMoreDocuments(err) {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if meta.Key != "" {
|
||||
webhooks = append(webhooks, webhook.AsAPIWebhook())
|
||||
}
|
||||
}
|
||||
|
||||
return &model.Webhooks{
|
||||
Pagination: &paginationClone,
|
||||
Webhooks: webhooks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetWebhookByID to get webhook by id
|
||||
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||
var webhook models.Webhook
|
||||
query := fmt.Sprintf("FOR d in %s FILTER d._id == @webhook_id RETURN d", models.Collections.Webhook)
|
||||
bindVars := map[string]interface{}{
|
||||
"webhook_id": webhookID,
|
||||
}
|
||||
|
||||
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close()
|
||||
|
||||
for {
|
||||
if !cursor.HasMore() {
|
||||
if webhook.Key == "" {
|
||||
return nil, fmt.Errorf("webhook not found")
|
||||
}
|
||||
break
|
||||
}
|
||||
_, err := cursor.ReadDocument(ctx, &webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// GetWebhookByEventName to get webhook by event_name
|
||||
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||
var webhook models.Webhook
|
||||
query := fmt.Sprintf("FOR d in %s FILTER d.event_name == @event_name RETURN d", models.Collections.Webhook)
|
||||
bindVars := map[string]interface{}{
|
||||
"event_name": eventName,
|
||||
}
|
||||
|
||||
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close()
|
||||
|
||||
for {
|
||||
if !cursor.HasMore() {
|
||||
if webhook.Key == "" {
|
||||
return nil, fmt.Errorf("webhook not found")
|
||||
}
|
||||
break
|
||||
}
|
||||
_, err := cursor.ReadDocument(ctx, &webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// DeleteWebhook to delete webhook
|
||||
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||
webhookCollection, _ := p.db.Collection(ctx, models.Collections.Webhook)
|
||||
_, err := webhookCollection.RemoveDocument(ctx, webhook.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("FOR d in %s FILTER d.event_id == @event_id REMOVE { _key: d._key }", models.Collections.WebhookLog)
|
||||
bindVars := map[string]interface{}{
|
||||
"event_id": webhook.ID,
|
||||
}
|
||||
|
||||
cursor, err := p.db.Query(ctx, query, bindVars)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cursor.Close()
|
||||
|
||||
return nil
|
||||
}
|
74
server/db/providers/arangodb/webhook_log.go
Normal file
74
server/db/providers/arangodb/webhook_log.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package arangodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/arangodb/go-driver"
|
||||
arangoDriver "github.com/arangodb/go-driver"
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AddWebhookLog to add webhook log
|
||||
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||
if webhookLog.ID == "" {
|
||||
webhookLog.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhookLog.Key = webhookLog.ID
|
||||
webhookLog.CreatedAt = time.Now().Unix()
|
||||
webhookLog.UpdatedAt = time.Now().Unix()
|
||||
webhookLogCollection, _ := p.db.Collection(ctx, models.Collections.WebhookLog)
|
||||
_, err := webhookLogCollection.CreateDocument(ctx, webhookLog)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhookLog.AsAPIWebhookLog(), nil
|
||||
}
|
||||
|
||||
// ListWebhookLogs to list webhook logs
|
||||
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||
webhookLogs := []*model.WebhookLog{}
|
||||
bindVariables := map[string]interface{}{}
|
||||
|
||||
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.WebhookLog, pagination.Offset, pagination.Limit)
|
||||
|
||||
if webhookID != "" {
|
||||
query = fmt.Sprintf("FOR d in %s FILTER d.webhook_id == @webhookID SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.WebhookLog, pagination.Offset, pagination.Limit)
|
||||
bindVariables = map[string]interface{}{
|
||||
"webhook_id": webhookID,
|
||||
}
|
||||
}
|
||||
sctx := driver.WithQueryFullCount(ctx)
|
||||
cursor, err := p.db.Query(sctx, query, bindVariables)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close()
|
||||
|
||||
paginationClone := pagination
|
||||
paginationClone.Total = cursor.Statistics().FullCount()
|
||||
|
||||
for {
|
||||
var webhookLog models.WebhookLog
|
||||
meta, err := cursor.ReadDocument(ctx, &webhookLog)
|
||||
|
||||
if arangoDriver.IsNoMoreDocuments(err) {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if meta.Key != "" {
|
||||
webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog())
|
||||
}
|
||||
}
|
||||
|
||||
return &model.WebhookLogs{
|
||||
Pagination: &paginationClone,
|
||||
WebhookLogs: webhookLogs,
|
||||
}, nil
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package cassandradb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
@ -10,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
// AddEnv to save environment information in database
|
||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||
if env.ID == "" {
|
||||
env.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -27,7 +28,7 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// UpdateEnv to update environment information in database
|
||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||
env.UpdatedAt = time.Now().Unix()
|
||||
|
||||
updateEnvQuery := fmt.Sprintf("UPDATE %s SET env = '%s', updated_at = %d WHERE id = '%s'", KeySpace+"."+models.Collections.Env, env.EnvData, env.UpdatedAt, env.ID)
|
||||
|
@ -39,7 +40,7 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// GetEnv to get environment information from database
|
||||
func (p *provider) GetEnv() (models.Env, error) {
|
||||
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
|
||||
var env models.Env
|
||||
|
||||
query := fmt.Sprintf("SELECT id, env, hash, created_at, updated_at FROM %s LIMIT 1", KeySpace+"."+models.Collections.Env)
|
||||
|
|
|
@ -177,6 +177,28 @@ func NewProvider() (*provider, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
webhookCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, event_name text, endpoint text, enabled boolean, updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.Webhook)
|
||||
err = session.Query(webhookCollectionQuery).Exec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhookIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_webhook_event_name ON %s.%s (event_name)", KeySpace, models.Collections.Webhook)
|
||||
err = session.Query(webhookIndexQuery).Exec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
webhookLogCollectionQuery := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s.%s (id text, http_status bigint, response text, request text, webhook_id text,updated_at bigint, created_at bigint, PRIMARY KEY (id))", KeySpace, models.Collections.WebhookLog)
|
||||
err = session.Query(webhookLogCollectionQuery).Exec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhookLogIndexQuery := fmt.Sprintf("CREATE INDEX IF NOT EXISTS authorizer_webhook_log_webhook_id ON %s.%s (webhook_id)", KeySpace, models.Collections.WebhookLog)
|
||||
err = session.Query(webhookLogIndexQuery).Exec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &provider{
|
||||
db: session,
|
||||
}, err
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cassandradb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
@ -9,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
// AddSession to save session information in database
|
||||
func (p *provider) AddSession(session models.Session) error {
|
||||
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||
if session.ID == "" {
|
||||
session.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -26,7 +27,7 @@ func (p *provider) AddSession(session models.Session) error {
|
|||
}
|
||||
|
||||
// DeleteSession to delete session information from database
|
||||
func (p *provider) DeleteSession(userId string) error {
|
||||
func (p *provider) DeleteSession(ctx context.Context, userId string) error {
|
||||
deleteSessionQuery := fmt.Sprintf("DELETE FROM %s WHERE user_id = '%s'", KeySpace+"."+models.Collections.Session, userId)
|
||||
err := p.db.Query(deleteSessionQuery).Exec()
|
||||
if err != nil {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cassandradb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
@ -16,7 +17,7 @@ import (
|
|||
)
|
||||
|
||||
// AddUser to save user information in database
|
||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
||||
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
if user.ID == "" {
|
||||
user.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -79,7 +80,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// UpdateUser to update user information in database
|
||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
||||
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
user.UpdatedAt = time.Now().Unix()
|
||||
|
||||
bytes, err := json.Marshal(user)
|
||||
|
@ -97,9 +98,6 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||
|
||||
updateFields := ""
|
||||
for key, value := range userMap {
|
||||
if value != nil && key != "_id" {
|
||||
}
|
||||
|
||||
if key == "_id" {
|
||||
continue
|
||||
}
|
||||
|
@ -130,14 +128,14 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// DeleteUser to delete user information from database
|
||||
func (p *provider) DeleteUser(user models.User) error {
|
||||
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.User, user.ID)
|
||||
err := p.db.Query(query).Exec()
|
||||
return err
|
||||
}
|
||||
|
||||
// ListUsers to get list of users from database
|
||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
||||
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||
responseUsers := []*model.User{}
|
||||
paginationClone := pagination
|
||||
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.User)
|
||||
|
@ -171,7 +169,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||
}
|
||||
|
||||
// GetUserByEmail to get user information from database using email address
|
||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
||||
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||
var user models.User
|
||||
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE email = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, email)
|
||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
||||
|
@ -182,7 +180,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||
}
|
||||
|
||||
// GetUserByID to get user information from database using user ID
|
||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
||||
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||
var user models.User
|
||||
query := fmt.Sprintf("SELECT id, email, email_verified_at, password, signup_methods, given_name, family_name, middle_name, nickname, birthdate, phone_number, phone_number_verified_at, picture, roles, revoked_timestamp, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1", KeySpace+"."+models.Collections.User, id)
|
||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&user.ID, &user.Email, &user.EmailVerifiedAt, &user.Password, &user.SignupMethods, &user.GivenName, &user.FamilyName, &user.MiddleName, &user.Nickname, &user.Birthdate, &user.PhoneNumber, &user.PhoneNumberVerifiedAt, &user.Picture, &user.Roles, &user.RevokedTimestamp, &user.CreatedAt, &user.UpdatedAt)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cassandradb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
// AddVerification to save verification request in database
|
||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
if verificationRequest.ID == "" {
|
||||
verificationRequest.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -28,7 +29,7 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||
}
|
||||
|
||||
// GetVerificationRequestByToken to get verification request from database using token
|
||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE jwt_token = '%s' LIMIT 1`, KeySpace+"."+models.Collections.VerificationRequest, token)
|
||||
|
||||
|
@ -40,7 +41,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||
}
|
||||
|
||||
// GetVerificationRequestByEmail to get verification request by email from database
|
||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
query := fmt.Sprintf(`SELECT id, jwt_token, identifier, expires_at, email, nonce, redirect_uri, created_at, updated_at FROM %s WHERE email = '%s' AND identifier = '%s' LIMIT 1 ALLOW FILTERING`, KeySpace+"."+models.Collections.VerificationRequest, email, identifier)
|
||||
|
||||
|
@ -53,7 +54,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||
}
|
||||
|
||||
// ListVerificationRequests to get list of verification requests from database
|
||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
var verificationRequests []*model.VerificationRequest
|
||||
|
||||
paginationClone := pagination
|
||||
|
@ -89,7 +90,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||
}
|
||||
|
||||
// DeleteVerificationRequest to delete verification request from database
|
||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
||||
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.VerificationRequest, verificationRequest.ID)
|
||||
err := p.db.Query(query).Exec()
|
||||
if err != nil {
|
||||
|
|
152
server/db/providers/cassandradb/webhook.go
Normal file
152
server/db/providers/cassandradb/webhook.go
Normal file
|
@ -0,0 +1,152 @@
|
|||
package cassandradb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/gocql/gocql"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AddWebhook to add webhook
|
||||
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
if webhook.ID == "" {
|
||||
webhook.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhook.Key = webhook.ID
|
||||
webhook.CreatedAt = time.Now().Unix()
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
|
||||
insertQuery := fmt.Sprintf("INSERT INTO %s (id, event_name, endpoint, headers, enabled, created_at, updated_at) VALUES ('%s', '%s', '%s', '%s', %t, %d, %d)", KeySpace+"."+models.Collections.Webhook, webhook.ID, webhook.EventName, webhook.EndPoint, webhook.Headers, webhook.Enabled, webhook.CreatedAt, webhook.UpdatedAt)
|
||||
err := p.db.Query(insertQuery).Exec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// UpdateWebhook to update webhook
|
||||
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
|
||||
bytes, err := json.Marshal(webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// use decoder instead of json.Unmarshall, because it converts int64 -> float64 after unmarshalling
|
||||
decoder := json.NewDecoder(strings.NewReader(string(bytes)))
|
||||
decoder.UseNumber()
|
||||
webhookMap := map[string]interface{}{}
|
||||
err = decoder.Decode(&webhookMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updateFields := ""
|
||||
for key, value := range webhookMap {
|
||||
if key == "_id" {
|
||||
continue
|
||||
}
|
||||
|
||||
if value == nil {
|
||||
updateFields += fmt.Sprintf("%s = null,", key)
|
||||
continue
|
||||
}
|
||||
|
||||
valueType := reflect.TypeOf(value)
|
||||
if valueType.Name() == "string" {
|
||||
updateFields += fmt.Sprintf("%s = '%s', ", key, value.(string))
|
||||
} else {
|
||||
updateFields += fmt.Sprintf("%s = %v, ", key, value)
|
||||
}
|
||||
}
|
||||
updateFields = strings.Trim(updateFields, " ")
|
||||
updateFields = strings.TrimSuffix(updateFields, ",")
|
||||
|
||||
query := fmt.Sprintf("UPDATE %s SET %s WHERE id = '%s'", KeySpace+"."+models.Collections.Webhook, updateFields, webhook.ID)
|
||||
|
||||
err = p.db.Query(query).Exec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// ListWebhooks to list webhook
|
||||
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||
webhooks := []*model.Webhook{}
|
||||
paginationClone := pagination
|
||||
|
||||
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.Webhook)
|
||||
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// there is no offset in cassandra
|
||||
// so we fetch till limit + offset
|
||||
// and return the results from offset to limit
|
||||
query := fmt.Sprintf("SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.Webhook, pagination.Limit+pagination.Offset)
|
||||
|
||||
scanner := p.db.Query(query).Iter().Scanner()
|
||||
counter := int64(0)
|
||||
for scanner.Next() {
|
||||
if counter >= pagination.Offset {
|
||||
var webhook models.Webhook
|
||||
err := scanner.Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhooks = append(webhooks, webhook.AsAPIWebhook())
|
||||
}
|
||||
counter++
|
||||
}
|
||||
|
||||
return &model.Webhooks{
|
||||
Pagination: &paginationClone,
|
||||
Webhooks: webhooks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetWebhookByID to get webhook by id
|
||||
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||
var webhook models.Webhook
|
||||
query := fmt.Sprintf(`SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s WHERE id = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, webhookID)
|
||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// GetWebhookByEventName to get webhook by event_name
|
||||
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||
var webhook models.Webhook
|
||||
query := fmt.Sprintf(`SELECT id, event_name, endpoint, headers, enabled, created_at, updated_at FROM %s WHERE event_name = '%s' LIMIT 1`, KeySpace+"."+models.Collections.Webhook, eventName)
|
||||
err := p.db.Query(query).Consistency(gocql.One).Scan(&webhook.ID, &webhook.EventName, &webhook.EndPoint, &webhook.Headers, &webhook.Enabled, &webhook.CreatedAt, &webhook.UpdatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// DeleteWebhook to delete webhook
|
||||
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||
query := fmt.Sprintf("DELETE FROM %s WHERE id = '%s'", KeySpace+"."+models.Collections.Webhook, webhook.ID)
|
||||
err := p.db.Query(query).Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query = fmt.Sprintf("DELETE FROM %s WHERE webhook_id = '%s'", KeySpace+"."+models.Collections.WebhookLog, webhook.ID)
|
||||
err = p.db.Query(query).Exec()
|
||||
return err
|
||||
}
|
70
server/db/providers/cassandradb/webhook_log.go
Normal file
70
server/db/providers/cassandradb/webhook_log.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package cassandradb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/gocql/gocql"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AddWebhookLog to add webhook log
|
||||
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||
if webhookLog.ID == "" {
|
||||
webhookLog.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhookLog.Key = webhookLog.ID
|
||||
webhookLog.CreatedAt = time.Now().Unix()
|
||||
webhookLog.UpdatedAt = time.Now().Unix()
|
||||
|
||||
insertQuery := fmt.Sprintf("INSERT INTO %s (id, http_status, response, request, webhook_id, created_at, updated_at) VALUES ('%s', %d,'%s', '%s', '%s', %d, %d)", KeySpace+"."+models.Collections.WebhookLog, webhookLog.ID, webhookLog.HttpStatus, webhookLog.Response, webhookLog.Request, webhookLog.WebhookID, webhookLog.CreatedAt, webhookLog.UpdatedAt)
|
||||
err := p.db.Query(insertQuery).Exec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhookLog.AsAPIWebhookLog(), nil
|
||||
}
|
||||
|
||||
// ListWebhookLogs to list webhook logs
|
||||
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||
webhookLogs := []*model.WebhookLog{}
|
||||
paginationClone := pagination
|
||||
totalCountQuery := fmt.Sprintf(`SELECT COUNT(*) FROM %s`, KeySpace+"."+models.Collections.WebhookLog)
|
||||
// there is no offset in cassandra
|
||||
// so we fetch till limit + offset
|
||||
// and return the results from offset to limit
|
||||
query := fmt.Sprintf("SELECT id, http_status, response, request, webhook_id, created_at, updated_at FROM %s LIMIT %d", KeySpace+"."+models.Collections.WebhookLog, pagination.Limit+pagination.Offset)
|
||||
|
||||
if webhookID != "" {
|
||||
totalCountQuery = fmt.Sprintf(`SELECT COUNT(*) FROM %s WHERE webhook_id='%s'`, KeySpace+"."+models.Collections.WebhookLog, webhookID)
|
||||
query = fmt.Sprintf("SELECT id, http_status, response, request, webhook_id, created_at, updated_at FROM %s WHERE webhook_id = '%s' LIMIT %d", KeySpace+"."+models.Collections.WebhookLog, webhookID, pagination.Limit+pagination.Offset)
|
||||
}
|
||||
|
||||
err := p.db.Query(totalCountQuery).Consistency(gocql.One).Scan(&paginationClone.Total)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scanner := p.db.Query(query).Iter().Scanner()
|
||||
counter := int64(0)
|
||||
for scanner.Next() {
|
||||
if counter >= pagination.Offset {
|
||||
var webhookLog models.WebhookLog
|
||||
err := scanner.Scan(&webhookLog.ID, &webhookLog.HttpStatus, &webhookLog.Response, &webhookLog.Request, &webhookLog.WebhookID, &webhookLog.CreatedAt, &webhookLog.UpdatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog())
|
||||
}
|
||||
counter++
|
||||
}
|
||||
|
||||
return &model.WebhookLogs{
|
||||
Pagination: &paginationClone,
|
||||
WebhookLogs: webhookLogs,
|
||||
}, nil
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
// AddEnv to save environment information in database
|
||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||
if env.ID == "" {
|
||||
env.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -20,7 +21,7 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||
env.UpdatedAt = time.Now().Unix()
|
||||
env.Key = env.ID
|
||||
configCollection := p.db.Collection(models.Collections.Env, options.Collection())
|
||||
_, err := configCollection.InsertOne(nil, env)
|
||||
_, err := configCollection.InsertOne(ctx, env)
|
||||
if err != nil {
|
||||
return env, err
|
||||
}
|
||||
|
@ -28,10 +29,10 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// UpdateEnv to update environment information in database
|
||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) UpdateEnv(ctx context.Context, 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())
|
||||
_, err := configCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": env.ID}}, bson.M{"$set": env}, options.MergeUpdateOptions())
|
||||
if err != nil {
|
||||
return env, err
|
||||
}
|
||||
|
@ -39,14 +40,14 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// GetEnv to get environment information from database
|
||||
func (p *provider) GetEnv() (models.Env, error) {
|
||||
func (p *provider) GetEnv(ctx context.Context) (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())
|
||||
cursor, err := configCollection.Find(ctx, bson.M{}, options.Find())
|
||||
if err != nil {
|
||||
return env, err
|
||||
}
|
||||
defer cursor.Close(nil)
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
for cursor.Next(nil) {
|
||||
err := cursor.Decode(&env)
|
||||
|
|
|
@ -83,6 +83,24 @@ func NewProvider() (*provider, error) {
|
|||
|
||||
mongodb.CreateCollection(ctx, models.Collections.Env, options.CreateCollection())
|
||||
|
||||
mongodb.CreateCollection(ctx, models.Collections.Webhook, options.CreateCollection())
|
||||
webhookCollection := mongodb.Collection(models.Collections.Webhook, options.Collection())
|
||||
webhookCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.M{"event_name": 1},
|
||||
Options: options.Index().SetUnique(true).SetSparse(true),
|
||||
},
|
||||
}, options.CreateIndexes())
|
||||
|
||||
mongodb.CreateCollection(ctx, models.Collections.WebhookLog, options.CreateCollection())
|
||||
webhookLogCollection := mongodb.Collection(models.Collections.WebhookLog, options.Collection())
|
||||
webhookLogCollection.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.M{"webhook_id": 1},
|
||||
Options: options.Index().SetSparse(true),
|
||||
},
|
||||
}, options.CreateIndexes())
|
||||
|
||||
return &provider{
|
||||
db: mongodb,
|
||||
}, nil
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
|
@ -10,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
// AddSession to save session information in database
|
||||
func (p *provider) AddSession(session models.Session) error {
|
||||
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||
if session.ID == "" {
|
||||
session.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -19,7 +20,7 @@ func (p *provider) AddSession(session models.Session) error {
|
|||
session.CreatedAt = time.Now().Unix()
|
||||
session.UpdatedAt = time.Now().Unix()
|
||||
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
||||
_, err := sessionCollection.InsertOne(nil, session)
|
||||
_, err := sessionCollection.InsertOne(ctx, session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -27,9 +28,9 @@ func (p *provider) AddSession(session models.Session) error {
|
|||
}
|
||||
|
||||
// DeleteSession to delete session information from database
|
||||
func (p *provider) DeleteSession(userId string) error {
|
||||
func (p *provider) DeleteSession(ctx context.Context, userId string) error {
|
||||
sessionCollection := p.db.Collection(models.Collections.Session, options.Collection())
|
||||
_, err := sessionCollection.DeleteMany(nil, bson.M{"user_id": userId}, options.Delete())
|
||||
_, err := sessionCollection.DeleteMany(ctx, bson.M{"user_id": userId}, options.Delete())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
|
@ -13,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
// AddUser to save user information in database
|
||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
||||
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
if user.ID == "" {
|
||||
user.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -29,7 +30,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||
user.UpdatedAt = time.Now().Unix()
|
||||
user.Key = user.ID
|
||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||
_, err := userCollection.InsertOne(nil, user)
|
||||
_, err := userCollection.InsertOne(ctx, user)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
@ -38,10 +39,10 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// UpdateUser to update user information in database
|
||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
||||
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
user.UpdatedAt = time.Now().Unix()
|
||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||
_, err := userCollection.UpdateOne(nil, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
|
||||
_, err := userCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": user.ID}}, bson.M{"$set": user}, options.MergeUpdateOptions())
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
@ -49,9 +50,9 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// DeleteUser to delete user information from database
|
||||
func (p *provider) DeleteUser(user models.User) error {
|
||||
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||
_, err := userCollection.DeleteOne(nil, bson.M{"_id": user.ID}, options.Delete())
|
||||
_, err := userCollection.DeleteOne(ctx, bson.M{"_id": user.ID}, options.Delete())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ func (p *provider) DeleteUser(user models.User) error {
|
|||
}
|
||||
|
||||
// ListUsers to get list of users from database
|
||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
||||
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||
var users []*model.User
|
||||
opts := options.Find()
|
||||
opts.SetLimit(pagination.Limit)
|
||||
|
@ -70,20 +71,20 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||
paginationClone := pagination
|
||||
|
||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||
count, err := userCollection.CountDocuments(nil, bson.M{}, options.Count())
|
||||
count, err := userCollection.CountDocuments(ctx, bson.M{}, options.Count())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
paginationClone.Total = count
|
||||
|
||||
cursor, err := userCollection.Find(nil, bson.M{}, opts)
|
||||
cursor, err := userCollection.Find(ctx, bson.M{}, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(nil)
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
for cursor.Next(nil) {
|
||||
for cursor.Next(ctx) {
|
||||
var user models.User
|
||||
err := cursor.Decode(&user)
|
||||
if err != nil {
|
||||
|
@ -99,10 +100,10 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||
}
|
||||
|
||||
// GetUserByEmail to get user information from database using email address
|
||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
||||
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||
var user models.User
|
||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||
err := userCollection.FindOne(nil, bson.M{"email": email}).Decode(&user)
|
||||
err := userCollection.FindOne(ctx, bson.M{"email": email}).Decode(&user)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
@ -111,11 +112,11 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||
}
|
||||
|
||||
// GetUserByID to get user information from database using user ID
|
||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
||||
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||
var user models.User
|
||||
|
||||
userCollection := p.db.Collection(models.Collections.User, options.Collection())
|
||||
err := userCollection.FindOne(nil, bson.M{"_id": id}).Decode(&user)
|
||||
err := userCollection.FindOne(ctx, bson.M{"_id": id}).Decode(&user)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
// AddVerification to save verification request in database
|
||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
if verificationRequest.ID == "" {
|
||||
verificationRequest.ID = uuid.New().String()
|
||||
|
||||
|
@ -19,7 +20,7 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||
verificationRequest.UpdatedAt = time.Now().Unix()
|
||||
verificationRequest.Key = verificationRequest.ID
|
||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||
_, err := verificationRequestCollection.InsertOne(nil, verificationRequest)
|
||||
_, err := verificationRequestCollection.InsertOne(ctx, verificationRequest)
|
||||
if err != nil {
|
||||
return verificationRequest, err
|
||||
}
|
||||
|
@ -29,11 +30,11 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||
}
|
||||
|
||||
// GetVerificationRequestByToken to get verification request from database using token
|
||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
|
||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||
err := verificationRequestCollection.FindOne(nil, bson.M{"token": token}).Decode(&verificationRequest)
|
||||
err := verificationRequestCollection.FindOne(ctx, bson.M{"token": token}).Decode(&verificationRequest)
|
||||
if err != nil {
|
||||
return verificationRequest, err
|
||||
}
|
||||
|
@ -42,11 +43,11 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||
}
|
||||
|
||||
// GetVerificationRequestByEmail to get verification request by email from database
|
||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
|
||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||
err := verificationRequestCollection.FindOne(nil, bson.M{"email": email, "identifier": identifier}).Decode(&verificationRequest)
|
||||
err := verificationRequestCollection.FindOne(ctx, bson.M{"email": email, "identifier": identifier}).Decode(&verificationRequest)
|
||||
if err != nil {
|
||||
return verificationRequest, err
|
||||
}
|
||||
|
@ -55,7 +56,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||
}
|
||||
|
||||
// ListVerificationRequests to get list of verification requests from database
|
||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
var verificationRequests []*model.VerificationRequest
|
||||
|
||||
opts := options.Find()
|
||||
|
@ -65,17 +66,17 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||
|
||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||
|
||||
verificationRequestCollectionCount, err := verificationRequestCollection.CountDocuments(nil, bson.M{})
|
||||
verificationRequestCollectionCount, err := verificationRequestCollection.CountDocuments(ctx, bson.M{})
|
||||
paginationClone := pagination
|
||||
paginationClone.Total = verificationRequestCollectionCount
|
||||
|
||||
cursor, err := verificationRequestCollection.Find(nil, bson.M{}, opts)
|
||||
cursor, err := verificationRequestCollection.Find(ctx, bson.M{}, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(nil)
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
for cursor.Next(nil) {
|
||||
for cursor.Next(ctx) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
err := cursor.Decode(&verificationRequest)
|
||||
if err != nil {
|
||||
|
@ -91,9 +92,9 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||
}
|
||||
|
||||
// DeleteVerificationRequest to delete verification request from database
|
||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
||||
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||
verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection())
|
||||
_, err := verificationRequestCollection.DeleteOne(nil, bson.M{"_id": verificationRequest.ID}, options.Delete())
|
||||
_, err := verificationRequestCollection.DeleteOne(ctx, bson.M{"_id": verificationRequest.ID}, options.Delete())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
120
server/db/providers/mongodb/webhook.go
Normal file
120
server/db/providers/mongodb/webhook.go
Normal file
|
@ -0,0 +1,120 @@
|
|||
package mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// AddWebhook to add webhook
|
||||
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
if webhook.ID == "" {
|
||||
webhook.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhook.Key = webhook.ID
|
||||
webhook.CreatedAt = time.Now().Unix()
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
|
||||
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||
_, err := webhookCollection.InsertOne(ctx, webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// UpdateWebhook to update webhook
|
||||
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||
_, err := webhookCollection.UpdateOne(ctx, bson.M{"_id": bson.M{"$eq": webhook.ID}}, bson.M{"$set": webhook}, options.MergeUpdateOptions())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// ListWebhooks to list webhook
|
||||
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||
var webhooks []*model.Webhook
|
||||
opts := options.Find()
|
||||
opts.SetLimit(pagination.Limit)
|
||||
opts.SetSkip(pagination.Offset)
|
||||
opts.SetSort(bson.M{"created_at": -1})
|
||||
|
||||
paginationClone := pagination
|
||||
|
||||
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||
count, err := webhookCollection.CountDocuments(ctx, bson.M{}, options.Count())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
paginationClone.Total = count
|
||||
|
||||
cursor, err := webhookCollection.Find(ctx, bson.M{}, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
for cursor.Next(ctx) {
|
||||
var webhook models.Webhook
|
||||
err := cursor.Decode(&webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhooks = append(webhooks, webhook.AsAPIWebhook())
|
||||
}
|
||||
|
||||
return &model.Webhooks{
|
||||
Pagination: &paginationClone,
|
||||
Webhooks: webhooks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetWebhookByID to get webhook by id
|
||||
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||
var webhook models.Webhook
|
||||
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||
err := webhookCollection.FindOne(ctx, bson.M{"_id": webhookID}).Decode(&webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// GetWebhookByEventName to get webhook by event_name
|
||||
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||
var webhook models.Webhook
|
||||
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||
err := webhookCollection.FindOne(ctx, bson.M{"event_name": eventName}).Decode(&webhook)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// DeleteWebhook to delete webhook
|
||||
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||
webhookCollection := p.db.Collection(models.Collections.Webhook, options.Collection())
|
||||
_, err := webhookCollection.DeleteOne(nil, bson.M{"_id": webhook.ID}, options.Delete())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection())
|
||||
_, err = webhookLogCollection.DeleteOne(nil, bson.M{"webhook_id": webhook.ID}, options.Delete())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
74
server/db/providers/mongodb/webhook_log.go
Normal file
74
server/db/providers/mongodb/webhook_log.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
package mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// AddWebhookLog to add webhook log
|
||||
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||
if webhookLog.ID == "" {
|
||||
webhookLog.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhookLog.Key = webhookLog.ID
|
||||
webhookLog.CreatedAt = time.Now().Unix()
|
||||
webhookLog.UpdatedAt = time.Now().Unix()
|
||||
|
||||
webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection())
|
||||
_, err := webhookLogCollection.InsertOne(ctx, webhookLog)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhookLog.AsAPIWebhookLog(), nil
|
||||
}
|
||||
|
||||
// ListWebhookLogs to list webhook logs
|
||||
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||
webhookLogs := []*model.WebhookLog{}
|
||||
opts := options.Find()
|
||||
opts.SetLimit(pagination.Limit)
|
||||
opts.SetSkip(pagination.Offset)
|
||||
opts.SetSort(bson.M{"created_at": -1})
|
||||
|
||||
paginationClone := pagination
|
||||
query := bson.M{}
|
||||
|
||||
if webhookID != "" {
|
||||
query = bson.M{"webhook_id": webhookID}
|
||||
}
|
||||
|
||||
webhookLogCollection := p.db.Collection(models.Collections.WebhookLog, options.Collection())
|
||||
count, err := webhookLogCollection.CountDocuments(ctx, query, options.Count())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
paginationClone.Total = count
|
||||
|
||||
cursor, err := webhookLogCollection.Find(ctx, query, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
for cursor.Next(ctx) {
|
||||
var webhookLog models.WebhookLog
|
||||
err := cursor.Decode(&webhookLog)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhookLogs = append(webhookLogs, webhookLog.AsAPIWebhookLog())
|
||||
}
|
||||
|
||||
return &model.WebhookLogs{
|
||||
Pagination: &paginationClone,
|
||||
WebhookLogs: webhookLogs,
|
||||
}, nil
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package provider_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
|
@ -8,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
// AddEnv to save environment information in database
|
||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||
if env.ID == "" {
|
||||
env.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -19,13 +20,13 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// UpdateEnv to update environment information in database
|
||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||
env.UpdatedAt = time.Now().Unix()
|
||||
return env, nil
|
||||
}
|
||||
|
||||
// GetEnv to get environment information from database
|
||||
func (p *provider) GetEnv() (models.Env, error) {
|
||||
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
|
||||
var env models.Env
|
||||
|
||||
return env, nil
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package provider_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
|
@ -8,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
// AddSession to save session information in database
|
||||
func (p *provider) AddSession(session models.Session) error {
|
||||
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||
if session.ID == "" {
|
||||
session.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -19,6 +20,6 @@ func (p *provider) AddSession(session models.Session) error {
|
|||
}
|
||||
|
||||
// DeleteSession to delete session information from database
|
||||
func (p *provider) DeleteSession(userId string) error {
|
||||
func (p *provider) DeleteSession(ctx context.Context, userId string) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package provider_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
// AddUser to save user information in database
|
||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
||||
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
if user.ID == "" {
|
||||
user.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -31,30 +32,30 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// UpdateUser to update user information in database
|
||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
||||
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
user.UpdatedAt = time.Now().Unix()
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// DeleteUser to delete user information from database
|
||||
func (p *provider) DeleteUser(user models.User) error {
|
||||
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListUsers to get list of users from database
|
||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
||||
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetUserByEmail to get user information from database using email address
|
||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
||||
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||
var user models.User
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// GetUserByID to get user information from database using user ID
|
||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
||||
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||
var user models.User
|
||||
|
||||
return user, nil
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package provider_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
|
@ -9,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
// AddVerification to save verification request in database
|
||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
if verificationRequest.ID == "" {
|
||||
verificationRequest.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -21,25 +22,25 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||
}
|
||||
|
||||
// GetVerificationRequestByToken to get verification request from database using token
|
||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
|
||||
return verificationRequest, nil
|
||||
}
|
||||
|
||||
// GetVerificationRequestByEmail to get verification request by email from database
|
||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
|
||||
return verificationRequest, nil
|
||||
}
|
||||
|
||||
// ListVerificationRequests to get list of verification requests from database
|
||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// DeleteVerificationRequest to delete verification request from database
|
||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
||||
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||
return nil
|
||||
}
|
||||
|
|
49
server/db/providers/provider_template/webhook.go
Normal file
49
server/db/providers/provider_template/webhook.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package provider_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AddWebhook to add webhook
|
||||
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
if webhook.ID == "" {
|
||||
webhook.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhook.Key = webhook.ID
|
||||
webhook.CreatedAt = time.Now().Unix()
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// UpdateWebhook to update webhook
|
||||
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// ListWebhooks to list webhook
|
||||
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetWebhookByID to get webhook by id
|
||||
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetWebhookByEventName to get webhook by event_name
|
||||
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// DeleteWebhook to delete webhook
|
||||
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||
// Also delete webhook logs for given webhook id
|
||||
return nil
|
||||
}
|
27
server/db/providers/provider_template/webhook_log.go
Normal file
27
server/db/providers/provider_template/webhook_log.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package provider_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AddWebhookLog to add webhook log
|
||||
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||
if webhookLog.ID == "" {
|
||||
webhookLog.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhookLog.Key = webhookLog.ID
|
||||
webhookLog.CreatedAt = time.Now().Unix()
|
||||
webhookLog.UpdatedAt = time.Now().Unix()
|
||||
return webhookLog.AsAPIWebhookLog(), nil
|
||||
}
|
||||
|
||||
// ListWebhookLogs to list webhook logs
|
||||
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||
return nil, nil
|
||||
}
|
|
@ -1,44 +1,64 @@
|
|||
package providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
)
|
||||
|
||||
type Provider interface {
|
||||
// AddUser to save user information in database
|
||||
AddUser(user models.User) (models.User, error)
|
||||
AddUser(ctx context.Context, user models.User) (models.User, error)
|
||||
// UpdateUser to update user information in database
|
||||
UpdateUser(user models.User) (models.User, error)
|
||||
UpdateUser(ctx context.Context, user models.User) (models.User, error)
|
||||
// DeleteUser to delete user information from database
|
||||
DeleteUser(user models.User) error
|
||||
DeleteUser(ctx context.Context, user models.User) error
|
||||
// ListUsers to get list of users from database
|
||||
ListUsers(pagination model.Pagination) (*model.Users, error)
|
||||
ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error)
|
||||
// GetUserByEmail to get user information from database using email address
|
||||
GetUserByEmail(email string) (models.User, error)
|
||||
GetUserByEmail(ctx context.Context, email string) (models.User, error)
|
||||
// GetUserByID to get user information from database using user ID
|
||||
GetUserByID(id string) (models.User, error)
|
||||
GetUserByID(ctx context.Context, id string) (models.User, error)
|
||||
|
||||
// AddVerification to save verification request in database
|
||||
AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error)
|
||||
AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error)
|
||||
// GetVerificationRequestByToken to get verification request from database using token
|
||||
GetVerificationRequestByToken(token string) (models.VerificationRequest, error)
|
||||
GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error)
|
||||
// GetVerificationRequestByEmail to get verification request by email from database
|
||||
GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error)
|
||||
GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error)
|
||||
// ListVerificationRequests to get list of verification requests from database
|
||||
ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error)
|
||||
ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error)
|
||||
// DeleteVerificationRequest to delete verification request from database
|
||||
DeleteVerificationRequest(verificationRequest models.VerificationRequest) error
|
||||
DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error
|
||||
|
||||
// AddSession to save session information in database
|
||||
AddSession(session models.Session) error
|
||||
AddSession(ctx context.Context, session models.Session) error
|
||||
// DeleteSession to delete session information from database
|
||||
DeleteSession(userId string) error
|
||||
DeleteSession(ctx context.Context, userId string) error
|
||||
|
||||
// AddEnv to save environment information in database
|
||||
AddEnv(env models.Env) (models.Env, error)
|
||||
AddEnv(ctx context.Context, env models.Env) (models.Env, error)
|
||||
// UpdateEnv to update environment information in database
|
||||
UpdateEnv(env models.Env) (models.Env, error)
|
||||
UpdateEnv(ctx context.Context, env models.Env) (models.Env, error)
|
||||
// GetEnv to get environment information from database
|
||||
GetEnv() (models.Env, error)
|
||||
GetEnv(ctx context.Context) (models.Env, error)
|
||||
|
||||
// AddWebhook to add webhook
|
||||
AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error)
|
||||
// UpdateWebhook to update webhook
|
||||
UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error)
|
||||
// ListWebhooks to list webhook
|
||||
ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error)
|
||||
// GetWebhookByID to get webhook by id
|
||||
GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error)
|
||||
// GetWebhookByEventName to get webhook by event_name
|
||||
GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error)
|
||||
// DeleteWebhook to delete webhook
|
||||
DeleteWebhook(ctx context.Context, webhook *model.Webhook) error
|
||||
|
||||
// AddWebhookLog to add webhook log
|
||||
AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error)
|
||||
// ListWebhookLogs to list webhook logs
|
||||
ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
|
@ -8,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
// AddEnv to save environment information in database
|
||||
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||
if env.ID == "" {
|
||||
env.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -25,7 +26,7 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// UpdateEnv to update environment information in database
|
||||
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
||||
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
|
||||
env.UpdatedAt = time.Now().Unix()
|
||||
result := p.db.Save(&env)
|
||||
|
||||
|
@ -36,7 +37,7 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
|
|||
}
|
||||
|
||||
// GetEnv to get environment information from database
|
||||
func (p *provider) GetEnv() (models.Env, error) {
|
||||
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
|
||||
var env models.Env
|
||||
result := p.db.First(&env)
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ func NewProvider() (*provider, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{})
|
||||
err = sqlDB.AutoMigrate(&models.User{}, &models.VerificationRequest{}, &models.Session{}, &models.Env{}, &models.Webhook{}, models.WebhookLog{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
|
@ -9,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
// AddSession to save session information in database
|
||||
func (p *provider) AddSession(session models.Session) error {
|
||||
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
|
||||
if session.ID == "" {
|
||||
session.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -28,7 +29,7 @@ func (p *provider) AddSession(session models.Session) error {
|
|||
}
|
||||
|
||||
// DeleteSession to delete session information from database
|
||||
func (p *provider) DeleteSession(userId string) error {
|
||||
func (p *provider) DeleteSession(ctx context.Context, userId string) error {
|
||||
result := p.db.Where("user_id = ?", userId).Delete(&models.Session{})
|
||||
|
||||
if result.Error != nil {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
|
@ -12,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
// AddUser to save user information in database
|
||||
func (p *provider) AddUser(user models.User) (models.User, error) {
|
||||
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
if user.ID == "" {
|
||||
user.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -42,7 +43,7 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// UpdateUser to update user information in database
|
||||
func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
||||
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
|
||||
user.UpdatedAt = time.Now().Unix()
|
||||
|
||||
result := p.db.Save(&user)
|
||||
|
@ -55,7 +56,7 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
|
|||
}
|
||||
|
||||
// DeleteUser to delete user information from database
|
||||
func (p *provider) DeleteUser(user models.User) error {
|
||||
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
|
||||
result := p.db.Delete(&user)
|
||||
|
||||
if result.Error != nil {
|
||||
|
@ -66,7 +67,7 @@ func (p *provider) DeleteUser(user models.User) error {
|
|||
}
|
||||
|
||||
// ListUsers to get list of users from database
|
||||
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
|
||||
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
|
||||
var users []models.User
|
||||
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&users)
|
||||
if result.Error != nil {
|
||||
|
@ -94,7 +95,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
|
|||
}
|
||||
|
||||
// GetUserByEmail to get user information from database using email address
|
||||
func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
||||
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
|
||||
var user models.User
|
||||
result := p.db.Where("email = ?", email).First(&user)
|
||||
if result.Error != nil {
|
||||
|
@ -105,7 +106,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
|
|||
}
|
||||
|
||||
// GetUserByID to get user information from database using user ID
|
||||
func (p *provider) GetUserByID(id string) (models.User, error) {
|
||||
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
|
||||
var user models.User
|
||||
|
||||
result := p.db.Where("id = ?", id).First(&user)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
|
@ -10,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
// AddVerification to save verification request in database
|
||||
func (p *provider) AddVerificationRequest(verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
func (p *provider) AddVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) (models.VerificationRequest, error) {
|
||||
if verificationRequest.ID == "" {
|
||||
verificationRequest.ID = uuid.New().String()
|
||||
}
|
||||
|
@ -31,7 +32,7 @@ func (p *provider) AddVerificationRequest(verificationRequest models.Verificatio
|
|||
}
|
||||
|
||||
// GetVerificationRequestByToken to get verification request from database using token
|
||||
func (p *provider) GetVerificationRequestByToken(token string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByToken(ctx context.Context, token string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
result := p.db.Where("token = ?", token).First(&verificationRequest)
|
||||
|
||||
|
@ -43,7 +44,7 @@ func (p *provider) GetVerificationRequestByToken(token string) (models.Verificat
|
|||
}
|
||||
|
||||
// GetVerificationRequestByEmail to get verification request by email from database
|
||||
func (p *provider) GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) {
|
||||
func (p *provider) GetVerificationRequestByEmail(ctx context.Context, email string, identifier string) (models.VerificationRequest, error) {
|
||||
var verificationRequest models.VerificationRequest
|
||||
|
||||
result := p.db.Where("email = ? AND identifier = ?", email, identifier).First(&verificationRequest)
|
||||
|
@ -56,7 +57,7 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string
|
|||
}
|
||||
|
||||
// ListVerificationRequests to get list of verification requests from database
|
||||
func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
func (p *provider) ListVerificationRequests(ctx context.Context, pagination model.Pagination) (*model.VerificationRequests, error) {
|
||||
var verificationRequests []models.VerificationRequest
|
||||
|
||||
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&verificationRequests)
|
||||
|
@ -85,7 +86,7 @@ func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model
|
|||
}
|
||||
|
||||
// DeleteVerificationRequest to delete verification request from database
|
||||
func (p *provider) DeleteVerificationRequest(verificationRequest models.VerificationRequest) error {
|
||||
func (p *provider) DeleteVerificationRequest(ctx context.Context, verificationRequest models.VerificationRequest) error {
|
||||
result := p.db.Delete(&verificationRequest)
|
||||
|
||||
if result.Error != nil {
|
||||
|
|
104
server/db/providers/sql/webhook.go
Normal file
104
server/db/providers/sql/webhook.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AddWebhook to add webhook
|
||||
func (p *provider) AddWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
if webhook.ID == "" {
|
||||
webhook.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhook.Key = webhook.ID
|
||||
webhook.CreatedAt = time.Now().Unix()
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
res := p.db.Create(&webhook)
|
||||
if res.Error != nil {
|
||||
return nil, res.Error
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// UpdateWebhook to update webhook
|
||||
func (p *provider) UpdateWebhook(ctx context.Context, webhook models.Webhook) (*model.Webhook, error) {
|
||||
webhook.UpdatedAt = time.Now().Unix()
|
||||
|
||||
result := p.db.Save(&webhook)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// ListWebhooks to list webhook
|
||||
func (p *provider) ListWebhook(ctx context.Context, pagination model.Pagination) (*model.Webhooks, error) {
|
||||
var webhooks []models.Webhook
|
||||
|
||||
result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhooks)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
var total int64
|
||||
totalRes := p.db.Model(&models.Webhook{}).Count(&total)
|
||||
if totalRes.Error != nil {
|
||||
return nil, totalRes.Error
|
||||
}
|
||||
|
||||
paginationClone := pagination
|
||||
paginationClone.Total = total
|
||||
|
||||
responseWebhooks := []*model.Webhook{}
|
||||
for _, w := range webhooks {
|
||||
responseWebhooks = append(responseWebhooks, w.AsAPIWebhook())
|
||||
}
|
||||
return &model.Webhooks{
|
||||
Pagination: &paginationClone,
|
||||
Webhooks: responseWebhooks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetWebhookByID to get webhook by id
|
||||
func (p *provider) GetWebhookByID(ctx context.Context, webhookID string) (*model.Webhook, error) {
|
||||
var webhook models.Webhook
|
||||
|
||||
result := p.db.Where("id = ?", webhookID).First(&webhook)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// GetWebhookByEventName to get webhook by event_name
|
||||
func (p *provider) GetWebhookByEventName(ctx context.Context, eventName string) (*model.Webhook, error) {
|
||||
var webhook models.Webhook
|
||||
|
||||
result := p.db.Where("event_name = ?", eventName).First(&webhook)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
return webhook.AsAPIWebhook(), nil
|
||||
}
|
||||
|
||||
// DeleteWebhook to delete webhook
|
||||
func (p *provider) DeleteWebhook(ctx context.Context, webhook *model.Webhook) error {
|
||||
result := p.db.Delete(&models.Webhook{
|
||||
ID: webhook.ID,
|
||||
})
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
result = p.db.Where("webhook_id = ?", webhook.ID).Delete(&models.WebhookLog{})
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
return nil
|
||||
}
|
68
server/db/providers/sql/webhook_log.go
Normal file
68
server/db/providers/sql/webhook_log.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
// AddWebhookLog to add webhook log
|
||||
func (p *provider) AddWebhookLog(ctx context.Context, webhookLog models.WebhookLog) (*model.WebhookLog, error) {
|
||||
if webhookLog.ID == "" {
|
||||
webhookLog.ID = uuid.New().String()
|
||||
}
|
||||
|
||||
webhookLog.Key = webhookLog.ID
|
||||
webhookLog.CreatedAt = time.Now().Unix()
|
||||
webhookLog.UpdatedAt = time.Now().Unix()
|
||||
res := p.db.Clauses(
|
||||
clause.OnConflict{
|
||||
DoNothing: true,
|
||||
}).Create(&webhookLog)
|
||||
if res.Error != nil {
|
||||
return nil, res.Error
|
||||
}
|
||||
|
||||
return webhookLog.AsAPIWebhookLog(), nil
|
||||
}
|
||||
|
||||
// ListWebhookLogs to list webhook logs
|
||||
func (p *provider) ListWebhookLogs(ctx context.Context, pagination model.Pagination, webhookID string) (*model.WebhookLogs, error) {
|
||||
var webhookLogs []models.WebhookLog
|
||||
var result *gorm.DB
|
||||
var totalRes *gorm.DB
|
||||
var total int64
|
||||
|
||||
if webhookID != "" {
|
||||
result = p.db.Where("webhook_id = ?", webhookID).Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhookLogs)
|
||||
totalRes = p.db.Where("webhook_id = ?", webhookID).Model(&models.WebhookLog{}).Count(&total)
|
||||
} else {
|
||||
result = p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&webhookLogs)
|
||||
totalRes = p.db.Model(&models.WebhookLog{}).Count(&total)
|
||||
}
|
||||
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
if totalRes.Error != nil {
|
||||
return nil, totalRes.Error
|
||||
}
|
||||
|
||||
paginationClone := pagination
|
||||
paginationClone.Total = total
|
||||
|
||||
responseWebhookLogs := []*model.WebhookLog{}
|
||||
for _, w := range webhookLogs {
|
||||
responseWebhookLogs = append(responseWebhookLogs, w.AsAPIWebhookLog())
|
||||
}
|
||||
return &model.WebhookLogs{
|
||||
WebhookLogs: responseWebhookLogs,
|
||||
Pagination: &paginationClone,
|
||||
}, nil
|
||||
}
|
11
server/env/persist_env.go
vendored
11
server/env/persist_env.go
vendored
|
@ -1,6 +1,7 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"reflect"
|
||||
|
@ -58,7 +59,8 @@ func fixBackwardCompatibility(data map[string]interface{}) (bool, map[string]int
|
|||
// GetEnvData returns the env data from database
|
||||
func GetEnvData() (map[string]interface{}, error) {
|
||||
var result map[string]interface{}
|
||||
env, err := db.Provider.GetEnv()
|
||||
ctx := context.Background()
|
||||
env, err := db.Provider.GetEnv(ctx)
|
||||
// config not found in db
|
||||
if err != nil {
|
||||
log.Debug("Error while getting env data from db: ", err)
|
||||
|
@ -108,7 +110,8 @@ func GetEnvData() (map[string]interface{}, error) {
|
|||
|
||||
// PersistEnv persists the environment variables to the database
|
||||
func PersistEnv() error {
|
||||
env, err := db.Provider.GetEnv()
|
||||
ctx := context.Background()
|
||||
env, err := db.Provider.GetEnv(ctx)
|
||||
// config not found in db
|
||||
if err != nil {
|
||||
// AES encryption needs 32 bit key only, so we chop off last 4 characters from 36 bit uuid
|
||||
|
@ -137,7 +140,7 @@ func PersistEnv() error {
|
|||
EnvData: encryptedConfig,
|
||||
}
|
||||
|
||||
env, err = db.Provider.AddEnv(env)
|
||||
env, err = db.Provider.AddEnv(ctx, env)
|
||||
if err != nil {
|
||||
log.Debug("Error while persisting env data to db: ", err)
|
||||
return err
|
||||
|
@ -251,7 +254,7 @@ func PersistEnv() error {
|
|||
}
|
||||
|
||||
env.EnvData = encryptedConfig
|
||||
_, err = db.Provider.UpdateEnv(env)
|
||||
_, err = db.Provider.UpdateEnv(ctx, env)
|
||||
if err != nil {
|
||||
log.Debug("Failed to Update Config: ", err)
|
||||
return err
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,13 @@
|
|||
|
||||
package model
|
||||
|
||||
type AddWebhookRequest struct {
|
||||
EventName string `json:"event_name"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Headers map[string]interface{} `json:"headers"`
|
||||
}
|
||||
|
||||
type AdminLoginInput struct {
|
||||
AdminSecret string `json:"admin_secret"`
|
||||
}
|
||||
|
@ -100,6 +107,11 @@ type InviteMemberInput struct {
|
|||
RedirectURI *string `json:"redirect_uri"`
|
||||
}
|
||||
|
||||
type ListWebhookLogRequest struct {
|
||||
Pagination *PaginationInput `json:"pagination"`
|
||||
WebhookID *string `json:"webhook_id"`
|
||||
}
|
||||
|
||||
type LoginInput struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
|
@ -187,6 +199,17 @@ type SignUpInput struct {
|
|||
RedirectURI *string `json:"redirect_uri"`
|
||||
}
|
||||
|
||||
type TestEndpointRequest struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
EventName string `json:"event_name"`
|
||||
Headers map[string]interface{} `json:"headers"`
|
||||
}
|
||||
|
||||
type TestEndpointResponse struct {
|
||||
HTTPStatus *int64 `json:"http_status"`
|
||||
Response map[string]interface{} `json:"response"`
|
||||
}
|
||||
|
||||
type UpdateAccessInput struct {
|
||||
UserID string `json:"user_id"`
|
||||
}
|
||||
|
@ -263,6 +286,14 @@ type UpdateUserInput struct {
|
|||
Roles []*string `json:"roles"`
|
||||
}
|
||||
|
||||
type UpdateWebhookRequest struct {
|
||||
ID string `json:"id"`
|
||||
EventName *string `json:"event_name"`
|
||||
Endpoint *string `json:"endpoint"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Headers map[string]interface{} `json:"headers"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Email string `json:"email"`
|
||||
|
@ -319,3 +350,37 @@ type VerificationRequests struct {
|
|||
type VerifyEmailInput struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type Webhook struct {
|
||||
ID string `json:"id"`
|
||||
EventName *string `json:"event_name"`
|
||||
Endpoint *string `json:"endpoint"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
Headers map[string]interface{} `json:"headers"`
|
||||
CreatedAt *int64 `json:"created_at"`
|
||||
UpdatedAt *int64 `json:"updated_at"`
|
||||
}
|
||||
|
||||
type WebhookLog struct {
|
||||
ID string `json:"id"`
|
||||
HTTPStatus *int64 `json:"http_status"`
|
||||
Response *string `json:"response"`
|
||||
Request *string `json:"request"`
|
||||
WebhookID *string `json:"webhook_id"`
|
||||
CreatedAt *int64 `json:"created_at"`
|
||||
UpdatedAt *int64 `json:"updated_at"`
|
||||
}
|
||||
|
||||
type WebhookLogs struct {
|
||||
Pagination *Pagination `json:"pagination"`
|
||||
WebhookLogs []*WebhookLog `json:"webhook_logs"`
|
||||
}
|
||||
|
||||
type WebhookRequest struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type Webhooks struct {
|
||||
Pagination *Pagination `json:"pagination"`
|
||||
Webhooks []*Webhook `json:"webhooks"`
|
||||
}
|
||||
|
|
|
@ -324,6 +324,71 @@ input GenerateJWTKeysInput {
|
|||
type: String!
|
||||
}
|
||||
|
||||
type Webhook {
|
||||
id: ID!
|
||||
event_name: String
|
||||
endpoint: String
|
||||
enabled: Boolean
|
||||
headers: Map
|
||||
created_at: Int64
|
||||
updated_at: Int64
|
||||
}
|
||||
|
||||
type Webhooks {
|
||||
pagination: Pagination!
|
||||
webhooks: [Webhook!]!
|
||||
}
|
||||
|
||||
type WebhookLog {
|
||||
id: ID!
|
||||
http_status: Int64
|
||||
response: String
|
||||
request: String
|
||||
webhook_id: ID
|
||||
created_at: Int64
|
||||
updated_at: Int64
|
||||
}
|
||||
|
||||
type TestEndpointResponse {
|
||||
http_status: Int64
|
||||
response: Map
|
||||
}
|
||||
|
||||
input ListWebhookLogRequest {
|
||||
pagination: PaginationInput!
|
||||
webhook_id: String
|
||||
}
|
||||
|
||||
input AddWebhookRequest {
|
||||
event_name: String!
|
||||
endpoint: String!
|
||||
enabled: Boolean!
|
||||
headers: Map
|
||||
}
|
||||
|
||||
input UpdateWebhookRequest {
|
||||
id: ID!
|
||||
event_name: String
|
||||
endpoint: String
|
||||
enabled: Boolean
|
||||
headers: Map
|
||||
}
|
||||
|
||||
input WebhookRequest {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
input TestEndpointRequest {
|
||||
endpoint: String!
|
||||
event_name: String!
|
||||
headers: Map
|
||||
}
|
||||
|
||||
type WebhookLogs {
|
||||
pagination: Pagination!
|
||||
webhook_logs: [WebhookLog!]!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
signup(params: SignUpInput!): AuthResponse!
|
||||
login(params: LoginInput!): AuthResponse!
|
||||
|
@ -346,6 +411,10 @@ type Mutation {
|
|||
_revoke_access(param: UpdateAccessInput!): Response!
|
||||
_enable_access(param: UpdateAccessInput!): Response!
|
||||
_generate_jwt_keys(params: GenerateJWTKeysInput!): GenerateJWTKeysResponse!
|
||||
_add_webhook(params: AddWebhookRequest!): Response!
|
||||
_update_webhook(params: UpdateWebhookRequest!): Response!
|
||||
_delete_webhook(params: WebhookRequest!): Response!
|
||||
_test_endpoint(params: TestEndpointRequest!): TestEndpointResponse!
|
||||
}
|
||||
|
||||
type Query {
|
||||
|
@ -358,4 +427,7 @@ type Query {
|
|||
_verification_requests(params: PaginatedInput): VerificationRequests!
|
||||
_admin_session: Response!
|
||||
_env: Env!
|
||||
_webhook(params: WebhookRequest!): Webhook!
|
||||
_webhooks(params: PaginatedInput): Webhooks!
|
||||
_webhook_logs(params: ListWebhookLogRequest!): WebhookLogs!
|
||||
}
|
||||
|
|
|
@ -91,6 +91,22 @@ func (r *mutationResolver) GenerateJwtKeys(ctx context.Context, params model.Gen
|
|||
return resolvers.GenerateJWTKeysResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) AddWebhook(ctx context.Context, params model.AddWebhookRequest) (*model.Response, error) {
|
||||
return resolvers.AddWebhookResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) UpdateWebhook(ctx context.Context, params model.UpdateWebhookRequest) (*model.Response, error) {
|
||||
return resolvers.UpdateWebhookResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) DeleteWebhook(ctx context.Context, params model.WebhookRequest) (*model.Response, error) {
|
||||
return resolvers.DeleteWebhookResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) TestEndpoint(ctx context.Context, params model.TestEndpointRequest) (*model.TestEndpointResponse, error) {
|
||||
return resolvers.TestEndpointResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *queryResolver) Meta(ctx context.Context) (*model.Meta, error) {
|
||||
return resolvers.MetaResolver(ctx)
|
||||
}
|
||||
|
@ -123,6 +139,18 @@ func (r *queryResolver) Env(ctx context.Context) (*model.Env, error) {
|
|||
return resolvers.EnvResolver(ctx)
|
||||
}
|
||||
|
||||
func (r *queryResolver) Webhook(ctx context.Context, params model.WebhookRequest) (*model.Webhook, error) {
|
||||
return resolvers.WebhookResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *queryResolver) Webhooks(ctx context.Context, params *model.PaginatedInput) (*model.Webhooks, error) {
|
||||
return resolvers.WebhooksResolver(ctx, params)
|
||||
}
|
||||
|
||||
func (r *queryResolver) WebhookLogs(ctx context.Context, params model.ListWebhookLogRequest) (*model.WebhookLogs, error) {
|
||||
return resolvers.WebhookLogsResolver(ctx, params)
|
||||
}
|
||||
|
||||
// Mutation returns generated.MutationResolver implementation.
|
||||
func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ func AuthorizeHandler() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
userID := claims.Subject
|
||||
user, err := db.Provider.GetUserByID(userID)
|
||||
user, err := db.Provider.GetUserByID(gc, userID)
|
||||
if err != nil {
|
||||
if isQuery {
|
||||
gc.Redirect(http.StatusFound, loginURL)
|
||||
|
|
|
@ -28,21 +28,21 @@ import (
|
|||
|
||||
// OAuthCallbackHandler handles the OAuth callback for various oauth providers
|
||||
func OAuthCallbackHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
provider := c.Param("oauth_provider")
|
||||
state := c.Request.FormValue("state")
|
||||
return func(ctx *gin.Context) {
|
||||
provider := ctx.Param("oauth_provider")
|
||||
state := ctx.Request.FormValue("state")
|
||||
|
||||
sessionState, err := memorystore.Provider.GetState(state)
|
||||
if sessionState == "" || err != nil {
|
||||
log.Debug("Invalid oauth state: ", state)
|
||||
c.JSON(400, gin.H{"error": "invalid oauth state"})
|
||||
ctx.JSON(400, gin.H{"error": "invalid oauth state"})
|
||||
}
|
||||
// contains random token, redirect url, role
|
||||
sessionSplit := strings.Split(state, "___")
|
||||
|
||||
if len(sessionSplit) < 3 {
|
||||
log.Debug("Unable to get redirect url from state: ", state)
|
||||
c.JSON(400, gin.H{"error": "invalid redirect url"})
|
||||
ctx.JSON(400, gin.H{"error": "invalid redirect url"})
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
scopes := strings.Split(sessionSplit[3], ",")
|
||||
|
||||
user := models.User{}
|
||||
code := c.Request.FormValue("code")
|
||||
code := ctx.Request.FormValue("code")
|
||||
switch provider {
|
||||
case constants.AuthRecipeMethodGoogle:
|
||||
user, err = processGoogleUserInfo(code)
|
||||
|
@ -74,23 +74,24 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
|
||||
if err != nil {
|
||||
log.Debug("Failed to process user info: ", err)
|
||||
c.JSON(400, gin.H{"error": err.Error()})
|
||||
ctx.JSON(400, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
existingUser, err := db.Provider.GetUserByEmail(user.Email)
|
||||
existingUser, err := db.Provider.GetUserByEmail(ctx, user.Email)
|
||||
log := log.WithField("user", user.Email)
|
||||
isSignUp := false
|
||||
|
||||
if err != nil {
|
||||
isSignupDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get signup disabled env variable: ", err)
|
||||
c.JSON(400, gin.H{"error": err.Error()})
|
||||
ctx.JSON(400, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if isSignupDisabled {
|
||||
log.Debug("Failed to signup as disabled")
|
||||
c.JSON(400, gin.H{"error": "signup is disabled for this instance"})
|
||||
ctx.JSON(400, gin.H{"error": "signup is disabled for this instance"})
|
||||
return
|
||||
}
|
||||
// user not registered, register user and generate session token
|
||||
|
@ -113,19 +114,20 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
|
||||
if hasProtectedRole {
|
||||
log.Debug("Signup is not allowed with protected roles:", inputRoles)
|
||||
c.JSON(400, gin.H{"error": "invalid role"})
|
||||
ctx.JSON(400, gin.H{"error": "invalid role"})
|
||||
return
|
||||
}
|
||||
|
||||
user.Roles = strings.Join(inputRoles, ",")
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
user, _ = db.Provider.AddUser(user)
|
||||
user, _ = db.Provider.AddUser(ctx, user)
|
||||
isSignUp = true
|
||||
} else {
|
||||
user = existingUser
|
||||
if user.RevokedTimestamp != nil {
|
||||
log.Debug("User access revoked at: ", user.RevokedTimestamp)
|
||||
c.JSON(400, gin.H{"error": "user access has been revoked"})
|
||||
ctx.JSON(400, gin.H{"error": "user access has been revoked"})
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -175,7 +177,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
|
||||
if hasProtectedRole {
|
||||
log.Debug("Invalid role. User is using protected unassigned role")
|
||||
c.JSON(400, gin.H{"error": "invalid role"})
|
||||
ctx.JSON(400, gin.H{"error": "invalid role"})
|
||||
return
|
||||
} else {
|
||||
user.Roles = existingUser.Roles + "," + strings.Join(unasignedRoles, ",")
|
||||
|
@ -184,18 +186,18 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
user.Roles = existingUser.Roles
|
||||
}
|
||||
|
||||
user, err = db.Provider.UpdateUser(user)
|
||||
user, err = db.Provider.UpdateUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
c.JSON(500, gin.H{"error": err.Error()})
|
||||
ctx.JSON(500, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
authToken, err := token.CreateAuthToken(c, user, inputRoles, scopes, provider)
|
||||
authToken, err := token.CreateAuthToken(ctx, user, inputRoles, scopes, provider)
|
||||
if err != nil {
|
||||
log.Debug("Failed to create auth token: ", err)
|
||||
c.JSON(500, gin.H{"error": err.Error()})
|
||||
ctx.JSON(500, gin.H{"error": err.Error()})
|
||||
}
|
||||
|
||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||
|
@ -206,7 +208,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + stateValue + "&id_token=" + authToken.IDToken.Token
|
||||
|
||||
sessionKey := provider + ":" + user.ID
|
||||
cookie.SetSession(c, authToken.FingerPrintHash)
|
||||
cookie.SetSession(ctx, authToken.FingerPrintHash)
|
||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
|
||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
|
||||
|
||||
|
@ -215,18 +217,25 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
|||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
||||
}
|
||||
|
||||
go db.Provider.AddSession(models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(c.Request),
|
||||
IP: utils.GetIP(c.Request),
|
||||
})
|
||||
go func() {
|
||||
if isSignUp {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, provider, user)
|
||||
} else {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, provider, user)
|
||||
}
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(ctx.Request),
|
||||
IP: utils.GetIP(ctx.Request),
|
||||
})
|
||||
}()
|
||||
if strings.Contains(redirectURL, "?") {
|
||||
redirectURL = redirectURL + "&" + params
|
||||
} else {
|
||||
redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&")
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusFound, redirectURL)
|
||||
ctx.Redirect(http.StatusFound, redirectURL)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
"github.com/authorizerdev/authorizer/server/token"
|
||||
)
|
||||
|
||||
// Revoke handler to revoke refresh token
|
||||
func RevokeHandler() gin.HandlerFunc {
|
||||
// RevokeRefreshTokenHandler handler to revoke refresh token
|
||||
func RevokeRefreshTokenHandler() gin.HandlerFunc {
|
||||
return func(gc *gin.Context) {
|
||||
var reqBody map[string]string
|
||||
if err := gc.BindJSON(&reqBody); err != nil {
|
|
@ -190,7 +190,7 @@ func TokenHandler() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
user, err := db.Provider.GetUserByID(userID)
|
||||
user, err := db.Provider.GetUserByID(gc, userID)
|
||||
if err != nil {
|
||||
log.Debug("Error getting user: ", err)
|
||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||
|
|
|
@ -31,7 +31,7 @@ func UserInfoHandler() gin.HandlerFunc {
|
|||
}
|
||||
|
||||
userID := claims["sub"].(string)
|
||||
user, err := db.Provider.GetUserByID(userID)
|
||||
user, err := db.Provider.GetUserByID(gc, userID)
|
||||
if err != nil {
|
||||
log.Debug("Error getting user: ", err)
|
||||
gc.JSON(http.StatusUnauthorized, gin.H{
|
||||
|
|
|
@ -33,7 +33,7 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(tokenInQuery)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(c, tokenInQuery)
|
||||
if err != nil {
|
||||
log.Debug("Error getting verification request: ", err)
|
||||
errorRes["error_description"] = err.Error()
|
||||
|
@ -58,7 +58,7 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
user, err := db.Provider.GetUserByEmail(verificationRequest.Email)
|
||||
user, err := db.Provider.GetUserByEmail(c, verificationRequest.Email)
|
||||
if err != nil {
|
||||
log.Debug("Error getting user: ", err)
|
||||
errorRes["error_description"] = err.Error()
|
||||
|
@ -66,14 +66,16 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
isSignUp := false
|
||||
// update email_verified_at in users table
|
||||
if user.EmailVerifiedAt == nil {
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
db.Provider.UpdateUser(user)
|
||||
isSignUp = true
|
||||
db.Provider.UpdateUser(c, user)
|
||||
}
|
||||
// delete from verification table
|
||||
db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||
db.Provider.DeleteVerificationRequest(c, verificationRequest)
|
||||
|
||||
state := strings.TrimSpace(c.Query("state"))
|
||||
redirectURL := strings.TrimSpace(c.Query("redirect_uri"))
|
||||
|
@ -131,11 +133,19 @@ func VerifyEmailHandler() gin.HandlerFunc {
|
|||
redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&")
|
||||
}
|
||||
|
||||
go db.Provider.AddSession(models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(c.Request),
|
||||
IP: utils.GetIP(c.Request),
|
||||
})
|
||||
go func() {
|
||||
if isSignUp {
|
||||
utils.RegisterEvent(c, constants.UserSignUpWebhookEvent, loginMethod, user)
|
||||
} else {
|
||||
utils.RegisterEvent(c, constants.UserLoginWebhookEvent, loginMethod, user)
|
||||
}
|
||||
|
||||
db.Provider.AddSession(c, models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(c.Request),
|
||||
IP: utils.GetIP(c.Request),
|
||||
})
|
||||
}()
|
||||
|
||||
c.Redirect(http.StatusTemporaryRedirect, redirectURL)
|
||||
}
|
||||
|
|
54
server/resolvers/add_webhook.go
Normal file
54
server/resolvers/add_webhook.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/authorizerdev/authorizer/server/validators"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// AddWebhookResolver resolver for add webhook mutation
|
||||
func AddWebhookResolver(ctx context.Context, params model.AddWebhookRequest) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.IsSuperAdmin(gc) {
|
||||
log.Debug("Not logged in as super admin")
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
if !validators.IsValidWebhookEventName(params.EventName) {
|
||||
log.Debug("Invalid Event Name: ", params.EventName)
|
||||
return nil, fmt.Errorf("invalid event name %s", params.EventName)
|
||||
}
|
||||
|
||||
headerBytes, err := json.Marshal(params.Headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = db.Provider.AddWebhook(ctx, models.Webhook{
|
||||
EventName: params.EventName,
|
||||
EndPoint: params.Endpoint,
|
||||
Enabled: params.Enabled,
|
||||
Headers: string(headerBytes),
|
||||
})
|
||||
if err != nil {
|
||||
log.Debug("Failed to add webhook: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.Response{
|
||||
Message: `Webhook added successfully`,
|
||||
}, nil
|
||||
}
|
|
@ -58,7 +58,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||
return res, err
|
||||
}
|
||||
|
||||
env, err := db.Provider.GetEnv()
|
||||
env, err := db.Provider.GetEnv(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get env: ", err)
|
||||
return res, err
|
||||
|
@ -71,7 +71,7 @@ func AdminSignupResolver(ctx context.Context, params model.AdminSignupInput) (*m
|
|||
}
|
||||
|
||||
env.EnvData = envData
|
||||
if _, err := db.Provider.UpdateEnv(env); err != nil {
|
||||
if _, err := db.Provider.UpdateEnv(ctx, env); err != nil {
|
||||
log.Debug("Failed to update env: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
|
@ -32,15 +33,13 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod
|
|||
"email": params.Email,
|
||||
})
|
||||
|
||||
user, err := db.Provider.GetUserByEmail(params.Email)
|
||||
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user from DB: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
go memorystore.Provider.DeleteAllUserSessions(user.ID)
|
||||
|
||||
err = db.Provider.DeleteUser(user)
|
||||
err = db.Provider.DeleteUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to delete user: ", err)
|
||||
return res, err
|
||||
|
@ -50,5 +49,10 @@ func DeleteUserResolver(ctx context.Context, params model.DeleteUserInput) (*mod
|
|||
Message: `user deleted successfully`,
|
||||
}
|
||||
|
||||
go func() {
|
||||
memorystore.Provider.DeleteAllUserSessions(user.ID)
|
||||
utils.RegisterEvent(ctx, constants.UserDeletedWebhookEvent, "", user)
|
||||
}()
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
|
49
server/resolvers/delete_webhook.go
Normal file
49
server/resolvers/delete_webhook.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// DeleteWebhookResolver resolver to delete webhook and its relevant logs
|
||||
func DeleteWebhookResolver(ctx context.Context, params model.WebhookRequest) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.IsSuperAdmin(gc) {
|
||||
log.Debug("Not logged in as super admin")
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
if params.ID == "" {
|
||||
log.Debug("webhookID is required")
|
||||
return nil, fmt.Errorf("webhook ID required")
|
||||
}
|
||||
|
||||
log := log.WithField("webhook_id", params.ID)
|
||||
|
||||
webhook, err := db.Provider.GetWebhookByID(ctx, params.ID)
|
||||
if err != nil {
|
||||
log.Debug("failed to get webhook: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = db.Provider.DeleteWebhook(ctx, webhook)
|
||||
if err != nil {
|
||||
log.Debug("failed to delete webhook: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.Response{
|
||||
Message: "Webhook deleted successfully",
|
||||
}, nil
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
|
@ -31,7 +32,7 @@ func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
|
|||
"user_id": params.UserID,
|
||||
})
|
||||
|
||||
user, err := db.Provider.GetUserByID(params.UserID)
|
||||
user, err := db.Provider.GetUserByID(ctx, params.UserID)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user from DB: ", err)
|
||||
return res, err
|
||||
|
@ -39,7 +40,7 @@ func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
|
|||
|
||||
user.RevokedTimestamp = nil
|
||||
|
||||
user, err = db.Provider.UpdateUser(user)
|
||||
user, err = db.Provider.UpdateUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
return res, err
|
||||
|
@ -49,5 +50,7 @@ func EnableAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
|
|||
Message: `user access enabled successfully`,
|
||||
}
|
||||
|
||||
go utils.RegisterEvent(ctx, constants.UserAccessEnabledWebhookEvent, "", user)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||
log := log.WithFields(log.Fields{
|
||||
"email": params.Email,
|
||||
})
|
||||
_, err = db.Provider.GetUserByEmail(params.Email)
|
||||
_, err = db.Provider.GetUserByEmail(ctx, params.Email)
|
||||
if err != nil {
|
||||
log.Debug("User not found: ", err)
|
||||
return res, fmt.Errorf(`user with this email not found`)
|
||||
|
@ -71,7 +71,7 @@ func ForgotPasswordResolver(ctx context.Context, params model.ForgotPasswordInpu
|
|||
log.Debug("Failed to create verification token", err)
|
||||
return res, err
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: constants.VerificationTypeForgotPassword,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
|
|
@ -70,7 +70,7 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
|||
// for each emails check if emails exists in db
|
||||
newEmails := []string{}
|
||||
for _, email := range emails {
|
||||
_, err := db.Provider.GetUserByEmail(email)
|
||||
_, err := db.Provider.GetUserByEmail(ctx, email)
|
||||
if err != nil {
|
||||
log.Debugf("User with %s email not found, so inviting user", email)
|
||||
newEmails = append(newEmails, email)
|
||||
|
@ -140,13 +140,13 @@ func InviteMembersResolver(ctx context.Context, params model.InviteMemberInput)
|
|||
|
||||
}
|
||||
|
||||
user, err = db.Provider.AddUser(user)
|
||||
user, err = db.Provider.AddUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debugf("Error adding user: %s, err: %v", email, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = db.Provider.AddVerificationRequest(verificationRequest)
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, verificationRequest)
|
||||
if err != nil {
|
||||
log.Debugf("Error adding verification request: %s, err: %v", email, err)
|
||||
return nil, err
|
||||
|
|
|
@ -45,7 +45,7 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||
"email": params.Email,
|
||||
})
|
||||
params.Email = strings.ToLower(params.Email)
|
||||
user, err := db.Provider.GetUserByEmail(params.Email)
|
||||
user, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by email: ", err)
|
||||
return res, fmt.Errorf(`user with this email not found`)
|
||||
|
@ -126,11 +126,14 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||
memorystore.Provider.SetUserSession(sessionStoreKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
||||
}
|
||||
|
||||
go db.Provider.AddSession(models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
})
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
})
|
||||
}()
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||
}
|
||||
|
||||
// find user with email
|
||||
existingUser, err := db.Provider.GetUserByEmail(params.Email)
|
||||
existingUser, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
||||
if err != nil {
|
||||
isSignupDisabled, err := memorystore.Provider.GetBoolStoreEnvVariable(constants.EnvKeyDisableSignUp)
|
||||
if err != nil {
|
||||
|
@ -99,7 +99,8 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||
}
|
||||
|
||||
user.Roles = strings.Join(inputRoles, ",")
|
||||
user, _ = db.Provider.AddUser(user)
|
||||
user, _ = db.Provider.AddUser(ctx, user)
|
||||
go utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodMagicLinkLogin, user)
|
||||
} else {
|
||||
user = existingUser
|
||||
// There multiple scenarios with roles here in magic link login
|
||||
|
@ -163,7 +164,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||
}
|
||||
|
||||
user.SignupMethods = signupMethod
|
||||
user, _ = db.Provider.UpdateUser(user)
|
||||
user, _ = db.Provider.UpdateUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
}
|
||||
|
@ -205,7 +206,7 @@ func MagicLinkLoginResolver(ctx context.Context, params model.MagicLinkLoginInpu
|
|||
if err != nil {
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
|
|
@ -38,7 +38,7 @@ func ProfileResolver(ctx context.Context) (*model.User, error) {
|
|||
log := log.WithFields(log.Fields{
|
||||
"user_id": userID,
|
||||
})
|
||||
user, err := db.Provider.GetUserByID(userID)
|
||||
user, err := db.Provider.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user: ", err)
|
||||
return res, err
|
||||
|
|
|
@ -39,14 +39,14 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
|||
return res, fmt.Errorf("invalid identifier")
|
||||
}
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(params.Email, params.Identifier)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, params.Email, params.Identifier)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get verification request: ", err)
|
||||
return res, fmt.Errorf(`verification request not found`)
|
||||
}
|
||||
|
||||
// delete current verification and create new one
|
||||
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||
err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest)
|
||||
if err != nil {
|
||||
log.Debug("Failed to delete verification request: ", err)
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func ResendVerifyEmailResolver(ctx context.Context, params model.ResendVerifyEma
|
|||
if err != nil {
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: params.Identifier,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
|
|
@ -39,7 +39,7 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
|
|||
return res, fmt.Errorf(`basic authentication is disabled for this instance`)
|
||||
}
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(ctx, params.Token)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get verification request: ", err)
|
||||
return res, fmt.Errorf(`invalid token`)
|
||||
|
@ -72,7 +72,7 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
|
|||
log := log.WithFields(log.Fields{
|
||||
"email": email,
|
||||
})
|
||||
user, err := db.Provider.GetUserByEmail(email)
|
||||
user, err := db.Provider.GetUserByEmail(ctx, email)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user: ", err)
|
||||
return res, err
|
||||
|
@ -94,13 +94,13 @@ func ResetPasswordResolver(ctx context.Context, params model.ResetPasswordInput)
|
|||
}
|
||||
|
||||
// delete from verification table
|
||||
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||
err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest)
|
||||
if err != nil {
|
||||
log.Debug("Failed to delete verification request: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
_, err = db.Provider.UpdateUser(user)
|
||||
_, err = db.Provider.UpdateUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
return res, err
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
|
@ -32,7 +33,7 @@ func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
|
|||
log := log.WithFields(log.Fields{
|
||||
"user_id": params.UserID,
|
||||
})
|
||||
user, err := db.Provider.GetUserByID(params.UserID)
|
||||
user, err := db.Provider.GetUserByID(ctx, params.UserID)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by ID: ", err)
|
||||
return res, err
|
||||
|
@ -41,13 +42,16 @@ func RevokeAccessResolver(ctx context.Context, params model.UpdateAccessInput) (
|
|||
now := time.Now().Unix()
|
||||
user.RevokedTimestamp = &now
|
||||
|
||||
user, err = db.Provider.UpdateUser(user)
|
||||
user, err = db.Provider.UpdateUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
go memorystore.Provider.DeleteAllUserSessions(user.ID)
|
||||
go func() {
|
||||
memorystore.Provider.DeleteAllUserSessions(user.ID)
|
||||
utils.RegisterEvent(ctx, constants.UserAccessRevokedWebhookEvent, "", user)
|
||||
}()
|
||||
|
||||
res = &model.Response{
|
||||
Message: `user access revoked successfully`,
|
||||
|
|
|
@ -46,7 +46,7 @@ func SessionResolver(ctx context.Context, params *model.SessionQueryInput) (*mod
|
|||
"user_id": userID,
|
||||
})
|
||||
|
||||
user, err := db.Provider.GetUserByID(userID)
|
||||
user, err := db.Provider.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
"email": params.Email,
|
||||
})
|
||||
// find user with email
|
||||
existingUser, err := db.Provider.GetUserByEmail(params.Email)
|
||||
existingUser, err := db.Provider.GetUserByEmail(ctx, params.Email)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by email: ", err)
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
}
|
||||
user, err = db.Provider.AddUser(user)
|
||||
user, err = db.Provider.AddUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to add user: ", err)
|
||||
return res, err
|
||||
|
@ -193,7 +193,7 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
log.Debug("Failed to create verification token: ", err)
|
||||
return res, err
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
@ -207,7 +207,10 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
}
|
||||
|
||||
// exec it as go routin so that we can reduce the api latency
|
||||
go email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||
go func() {
|
||||
email.SendVerificationMail(params.Email, verificationToken, hostname)
|
||||
utils.RegisterEvent(ctx, constants.UserCreatedWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
}()
|
||||
|
||||
res = &model.AuthResponse{
|
||||
Message: `Verification email has been sent. Please check your inbox`,
|
||||
|
@ -225,12 +228,6 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
return res, err
|
||||
}
|
||||
|
||||
go db.Provider.AddSession(models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
})
|
||||
|
||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||
if expiresIn <= 0 {
|
||||
expiresIn = 1
|
||||
|
@ -252,6 +249,15 @@ func SignupResolver(ctx context.Context, params model.SignUpInput) (*model.AuthR
|
|||
res.RefreshToken = &authToken.RefreshToken.Token
|
||||
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
|
||||
}
|
||||
|
||||
go func() {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, constants.AuthRecipeMethodBasicAuth, user)
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
})
|
||||
}()
|
||||
}
|
||||
|
||||
return res, nil
|
||||
|
|
109
server/resolvers/test_endpoint.go
Normal file
109
server/resolvers/test_endpoint.go
Normal file
|
@ -0,0 +1,109 @@
|
|||
package resolvers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/authorizerdev/authorizer/server/validators"
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// TestEndpointResolver resolver to test webhook endpoints
|
||||
func TestEndpointResolver(ctx context.Context, params model.TestEndpointRequest) (*model.TestEndpointResponse, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.IsSuperAdmin(gc) {
|
||||
log.Debug("Not logged in as super admin")
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
if !validators.IsValidWebhookEventName(params.EventName) {
|
||||
log.Debug("Invalid event name: ", params.EventName)
|
||||
return nil, fmt.Errorf("invalid event_name %s", params.EventName)
|
||||
}
|
||||
|
||||
user := model.User{
|
||||
ID: uuid.NewString(),
|
||||
Email: "test_endpoint@foo.com",
|
||||
EmailVerified: true,
|
||||
SignupMethods: constants.AuthRecipeMethodMagicLinkLogin,
|
||||
GivenName: utils.NewStringRef("Foo"),
|
||||
FamilyName: utils.NewStringRef("Bar"),
|
||||
}
|
||||
|
||||
userBytes, err := json.Marshal(user)
|
||||
if err != nil {
|
||||
log.Debug("error marshalling user obj: ", err)
|
||||
return nil, err
|
||||
}
|
||||
userMap := map[string]interface{}{}
|
||||
err = json.Unmarshal(userBytes, &userMap)
|
||||
if err != nil {
|
||||
log.Debug("error un-marshalling user obj: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqBody := map[string]interface{}{
|
||||
"event_name": constants.UserLoginWebhookEvent,
|
||||
"user": userMap,
|
||||
}
|
||||
|
||||
if params.EventName == constants.UserLoginWebhookEvent {
|
||||
reqBody["auth_recipe"] = constants.AuthRecipeMethodMagicLinkLogin
|
||||
}
|
||||
|
||||
requestBody, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
log.Debug("error marshalling requestBody obj: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", params.Endpoint, bytes.NewBuffer(requestBody))
|
||||
if err != nil {
|
||||
log.Debug("error creating post request: ", err)
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
for key, val := range params.Headers {
|
||||
req.Header.Set(key, val.(string))
|
||||
}
|
||||
client := &http.Client{Timeout: time.Second * 30}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Debug("error making request: ", err)
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Debug("error reading response: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := map[string]interface{}{}
|
||||
if err := json.Unmarshal(body, &response); err != nil {
|
||||
log.Debug("error un-marshalling response: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statusCode := int64(resp.StatusCode)
|
||||
return &model.TestEndpointResponse{
|
||||
HTTPStatus: &statusCode,
|
||||
Response: response,
|
||||
}, nil
|
||||
}
|
|
@ -287,7 +287,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||
}
|
||||
|
||||
// Fetch the current db store and update it
|
||||
env, err := db.Provider.GetEnv()
|
||||
env, err := db.Provider.GetEnv(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get env: ", err)
|
||||
return res, err
|
||||
|
@ -314,7 +314,7 @@ func UpdateEnvResolver(ctx context.Context, params model.UpdateEnvInput) (*model
|
|||
}
|
||||
|
||||
env.EnvData = encryptedConfig
|
||||
_, err = db.Provider.UpdateEnv(env)
|
||||
_, err = db.Provider.UpdateEnv(ctx, env)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update env: ", err)
|
||||
return res, err
|
||||
|
|
|
@ -55,7 +55,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||
"user_id": userID,
|
||||
})
|
||||
|
||||
user, err := db.Provider.GetUserByID(userID)
|
||||
user, err := db.Provider.GetUserByID(ctx, userID)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by id: ", err)
|
||||
return res, err
|
||||
|
@ -135,7 +135,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||
return res, fmt.Errorf("invalid new email address")
|
||||
}
|
||||
// check if user with new email exists
|
||||
_, err := db.Provider.GetUserByEmail(newEmail)
|
||||
_, err := db.Provider.GetUserByEmail(ctx, newEmail)
|
||||
// err = nil means user exists
|
||||
if err == nil {
|
||||
log.Debug("Failed to get user by email: ", newEmail)
|
||||
|
@ -168,7 +168,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||
log.Debug("Failed to create verification token: ", err)
|
||||
return res, err
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
@ -186,7 +186,7 @@ func UpdateProfileResolver(ctx context.Context, params model.UpdateProfileInput)
|
|||
|
||||
}
|
||||
}
|
||||
_, err = db.Provider.UpdateUser(user)
|
||||
_, err = db.Provider.UpdateUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
return res, err
|
||||
|
|
|
@ -50,7 +50,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||
return res, fmt.Errorf("please enter atleast one param to update")
|
||||
}
|
||||
|
||||
user, err := db.Provider.GetUserByID(params.ID)
|
||||
user, err := db.Provider.GetUserByID(ctx, params.ID)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by id: ", err)
|
||||
return res, fmt.Errorf(`User not found`)
|
||||
|
@ -105,7 +105,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||
}
|
||||
newEmail := strings.ToLower(*params.Email)
|
||||
// check if user with new email exists
|
||||
_, err = db.Provider.GetUserByEmail(newEmail)
|
||||
_, err = db.Provider.GetUserByEmail(ctx, newEmail)
|
||||
// err = nil means user exists
|
||||
if err == nil {
|
||||
log.Debug("User with email already exists: ", newEmail)
|
||||
|
@ -130,7 +130,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||
if err != nil {
|
||||
log.Debug("Failed to create verification token: ", err)
|
||||
}
|
||||
_, err = db.Provider.AddVerificationRequest(models.VerificationRequest{
|
||||
_, err = db.Provider.AddVerificationRequest(ctx, models.VerificationRequest{
|
||||
Token: verificationToken,
|
||||
Identifier: verificationType,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 30).Unix(),
|
||||
|
@ -189,7 +189,7 @@ func UpdateUserResolver(ctx context.Context, params model.UpdateUserInput) (*mod
|
|||
user.Roles = rolesToSave
|
||||
}
|
||||
|
||||
user, err = db.Provider.UpdateUser(user)
|
||||
user, err = db.Provider.UpdateUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
return res, err
|
||||
|
|
93
server/resolvers/update_webhook.go
Normal file
93
server/resolvers/update_webhook.go
Normal file
|
@ -0,0 +1,93 @@
|
|||
package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/authorizerdev/authorizer/server/validators"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// UpdateWebhookResolver resolver for update webhook mutation
|
||||
func UpdateWebhookResolver(ctx context.Context, params model.UpdateWebhookRequest) (*model.Response, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.IsSuperAdmin(gc) {
|
||||
log.Debug("Not logged in as super admin")
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
webhook, err := db.Provider.GetWebhookByID(ctx, params.ID)
|
||||
if err != nil {
|
||||
log.Debug("failed to get webhook: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
headersString := ""
|
||||
if webhook.Headers != nil {
|
||||
headerBytes, err := json.Marshal(webhook.Headers)
|
||||
if err != nil {
|
||||
log.Debug("failed to marshall source headers: ", err)
|
||||
}
|
||||
headersString = string(headerBytes)
|
||||
}
|
||||
|
||||
webhookDetails := models.Webhook{
|
||||
ID: webhook.ID,
|
||||
Key: webhook.ID,
|
||||
EventName: utils.StringValue(webhook.EventName),
|
||||
EndPoint: utils.StringValue(webhook.Endpoint),
|
||||
Enabled: utils.BoolValue(webhook.Enabled),
|
||||
Headers: headersString,
|
||||
CreatedAt: *webhook.CreatedAt,
|
||||
}
|
||||
|
||||
if params.EventName != nil && webhookDetails.EventName != utils.StringValue(params.EventName) {
|
||||
if isValid := validators.IsValidWebhookEventName(utils.StringValue(params.EventName)); !isValid {
|
||||
log.Debug("invalid event name: ", utils.StringValue(params.EventName))
|
||||
return nil, fmt.Errorf("invalid event name %s", utils.StringValue(params.EventName))
|
||||
}
|
||||
webhookDetails.EventName = utils.StringValue(params.EventName)
|
||||
}
|
||||
|
||||
if params.Endpoint != nil && webhookDetails.EndPoint != utils.StringValue(params.Endpoint) {
|
||||
webhookDetails.EventName = utils.StringValue(params.EventName)
|
||||
}
|
||||
|
||||
if params.Enabled != nil && webhookDetails.Enabled != utils.BoolValue(params.Enabled) {
|
||||
webhookDetails.Enabled = utils.BoolValue(params.Enabled)
|
||||
}
|
||||
|
||||
if params.Headers != nil {
|
||||
for key, val := range params.Headers {
|
||||
webhook.Headers[key] = val
|
||||
}
|
||||
|
||||
headerBytes, err := json.Marshal(webhook.Headers)
|
||||
if err != nil {
|
||||
log.Debug("failed to marshall headers: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
webhookDetails.Headers = string(headerBytes)
|
||||
}
|
||||
|
||||
_, err = db.Provider.UpdateWebhook(ctx, webhookDetails)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.Response{
|
||||
Message: `Webhook updated successfully.`,
|
||||
}, nil
|
||||
}
|
|
@ -28,7 +28,7 @@ func UsersResolver(ctx context.Context, params *model.PaginatedInput) (*model.Us
|
|||
|
||||
pagination := utils.GetPagination(params)
|
||||
|
||||
res, err := db.Provider.ListUsers(pagination)
|
||||
res, err := db.Provider.ListUsers(ctx, pagination)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get users: ", err)
|
||||
return nil, err
|
||||
|
|
|
@ -28,7 +28,7 @@ func VerificationRequestsResolver(ctx context.Context, params *model.PaginatedIn
|
|||
|
||||
pagination := utils.GetPagination(params)
|
||||
|
||||
res, err := db.Provider.ListVerificationRequests(pagination)
|
||||
res, err := db.Provider.ListVerificationRequests(ctx, pagination)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get verification requests: ", err)
|
||||
return nil, err
|
||||
|
|
|
@ -29,7 +29,7 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
|
|||
return res, err
|
||||
}
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(params.Token)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByToken(ctx, params.Token)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get verification request by token: ", err)
|
||||
return res, fmt.Errorf(`invalid token: %s`, err.Error())
|
||||
|
@ -52,22 +52,26 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
|
|||
log := log.WithFields(log.Fields{
|
||||
"email": email,
|
||||
})
|
||||
user, err := db.Provider.GetUserByEmail(email)
|
||||
user, err := db.Provider.GetUserByEmail(ctx, email)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get user by email: ", err)
|
||||
return res, err
|
||||
}
|
||||
|
||||
// update email_verified_at in users table
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
user, err = db.Provider.UpdateUser(user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
return res, err
|
||||
isSignUp := false
|
||||
if user.EmailVerifiedAt == nil {
|
||||
isSignUp = true
|
||||
// update email_verified_at in users table
|
||||
now := time.Now().Unix()
|
||||
user.EmailVerifiedAt = &now
|
||||
user, err = db.Provider.UpdateUser(ctx, user)
|
||||
if err != nil {
|
||||
log.Debug("Failed to update user: ", err)
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
// delete from verification table
|
||||
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||
err = db.Provider.DeleteVerificationRequest(gc, verificationRequest)
|
||||
if err != nil {
|
||||
log.Debug("Failed to delete verification request: ", err)
|
||||
return res, err
|
||||
|
@ -86,12 +90,19 @@ func VerifyEmailResolver(ctx context.Context, params model.VerifyEmailInput) (*m
|
|||
return res, err
|
||||
}
|
||||
|
||||
go db.Provider.AddSession(models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
})
|
||||
go func() {
|
||||
if isSignUp {
|
||||
utils.RegisterEvent(ctx, constants.UserSignUpWebhookEvent, loginMethod, user)
|
||||
} else {
|
||||
utils.RegisterEvent(ctx, constants.UserLoginWebhookEvent, loginMethod, user)
|
||||
}
|
||||
|
||||
db.Provider.AddSession(ctx, models.Session{
|
||||
UserID: user.ID,
|
||||
UserAgent: utils.GetUserAgent(gc.Request),
|
||||
IP: utils.GetIP(gc.Request),
|
||||
})
|
||||
}()
|
||||
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
|
||||
if expiresIn <= 0 {
|
||||
expiresIn = 1
|
||||
|
|
33
server/resolvers/webhook.go
Normal file
33
server/resolvers/webhook.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// WebhookResolver resolver for getting webhook by identifier
|
||||
func WebhookResolver(ctx context.Context, params model.WebhookRequest) (*model.Webhook, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.IsSuperAdmin(gc) {
|
||||
log.Debug("Not logged in as super admin")
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
webhook, err := db.Provider.GetWebhookByID(ctx, params.ID)
|
||||
if err != nil {
|
||||
log.Debug("error getting webhook: ", err)
|
||||
return nil, err
|
||||
}
|
||||
return webhook, nil
|
||||
}
|
37
server/resolvers/webhook_logs.go
Normal file
37
server/resolvers/webhook_logs.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// WebhookLogsResolver resolver for getting the list of webhook_logs based on pagination & webhook identifier
|
||||
func WebhookLogsResolver(ctx context.Context, params model.ListWebhookLogRequest) (*model.WebhookLogs, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.IsSuperAdmin(gc) {
|
||||
log.Debug("Not logged in as super admin")
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
pagination := utils.GetPagination(&model.PaginatedInput{
|
||||
Pagination: params.Pagination,
|
||||
})
|
||||
|
||||
webhookLogs, err := db.Provider.ListWebhookLogs(ctx, pagination, utils.StringValue(params.WebhookID))
|
||||
if err != nil {
|
||||
log.Debug("failed to get webhook logs: ", err)
|
||||
return nil, err
|
||||
}
|
||||
return webhookLogs, nil
|
||||
}
|
35
server/resolvers/webhooks.go
Normal file
35
server/resolvers/webhooks.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package resolvers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/token"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// WebhooksResolver resolver for getting the list of webhooks based on pagination
|
||||
func WebhooksResolver(ctx context.Context, params *model.PaginatedInput) (*model.Webhooks, error) {
|
||||
gc, err := utils.GinContextFromContext(ctx)
|
||||
if err != nil {
|
||||
log.Debug("Failed to get GinContext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.IsSuperAdmin(gc) {
|
||||
log.Debug("Not logged in as super admin")
|
||||
return nil, fmt.Errorf("unauthorized")
|
||||
}
|
||||
|
||||
pagination := utils.GetPagination(params)
|
||||
|
||||
webhooks, err := db.Provider.ListWebhook(ctx, pagination)
|
||||
if err != nil {
|
||||
log.Debug("failed to get webhook logs: ", err)
|
||||
return nil, err
|
||||
}
|
||||
return webhooks, nil
|
||||
}
|
|
@ -32,7 +32,7 @@ func InitRouter(log *logrus.Logger) *gin.Engine {
|
|||
router.GET("/userinfo", handlers.UserInfoHandler())
|
||||
router.GET("/logout", handlers.LogoutHandler())
|
||||
router.POST("/oauth/token", handlers.TokenHandler())
|
||||
router.POST("/oauth/revoke", handlers.RevokeHandler())
|
||||
router.POST("/oauth/revoke", handlers.RevokeRefreshTokenHandler())
|
||||
|
||||
router.LoadHTMLGlob("templates/*")
|
||||
// login page app related routes.
|
||||
|
|
39
server/test/add_webhook_test.go
Normal file
39
server/test/add_webhook_test.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/crypto"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func addWebhookTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run("should add webhook", func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||
assert.NoError(t, err)
|
||||
h, err := crypto.EncryptPassword(adminSecret)
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
||||
|
||||
for _, eventType := range s.TestInfo.TestEventTypes {
|
||||
webhook, err := resolvers.AddWebhookResolver(ctx, model.AddWebhookRequest{
|
||||
EventName: eventType,
|
||||
Endpoint: s.TestInfo.WebhookEndpoint,
|
||||
Enabled: true,
|
||||
Headers: map[string]interface{}{
|
||||
"x-test": "foo",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, webhook)
|
||||
assert.NotEmpty(t, webhook.Message)
|
||||
}
|
||||
})
|
||||
}
|
50
server/test/delete_webhook_test.go
Normal file
50
server/test/delete_webhook_test.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/crypto"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func deleteWebhookTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run("should delete webhook", func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||
assert.NoError(t, err)
|
||||
h, err := crypto.EncryptPassword(adminSecret)
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
||||
|
||||
// get all webhooks
|
||||
webhooks, err := db.Provider.ListWebhook(ctx, model.Pagination{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
for _, w := range webhooks.Webhooks {
|
||||
res, err := resolvers.DeleteWebhookResolver(ctx, model.WebhookRequest{
|
||||
ID: w.ID,
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res)
|
||||
assert.NotEmpty(t, res.Message)
|
||||
}
|
||||
|
||||
webhooks, err = db.Provider.ListWebhook(ctx, model.Pagination{})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, webhooks.Webhooks, 0)
|
||||
|
||||
webhookLogs, err := db.Provider.ListWebhookLogs(ctx, model.Pagination{
|
||||
Limit: 10,
|
||||
}, "")
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, webhookLogs.WebhookLogs, 0)
|
||||
})
|
||||
}
|
|
@ -22,7 +22,7 @@ func enableAccessTest(t *testing.T, s TestSetup) {
|
|||
Email: email,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
|
|
@ -26,7 +26,7 @@ func forgotPasswordTest(t *testing.T, s TestSetup) {
|
|||
})
|
||||
assert.Nil(t, err, "no errors for forgot password")
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeForgotPassword)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeForgotPassword)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, verificationRequest.Identifier, constants.VerificationTypeForgotPassword)
|
||||
|
|
|
@ -29,7 +29,7 @@ func loginTests(t *testing.T, s TestSetup) {
|
|||
|
||||
assert.NotNil(t, err, "should fail because email is not verified")
|
||||
assert.Nil(t, res)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||
n, err := utils.EncryptNonce(verificationRequest.Nonce)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, n)
|
||||
|
|
|
@ -24,7 +24,7 @@ func logoutTests(t *testing.T, s TestSetup) {
|
|||
Email: email,
|
||||
})
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
|
|
@ -29,7 +29,7 @@ func magicLinkLoginTests(t *testing.T, s TestSetup) {
|
|||
})
|
||||
assert.Nil(t, err, "signup should be successful")
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
|
|
@ -26,7 +26,7 @@ func profileTests(t *testing.T, s TestSetup) {
|
|||
_, err := resolvers.ProfileResolver(ctx)
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
|
|
@ -26,7 +26,7 @@ func resetPasswordTest(t *testing.T, s TestSetup) {
|
|||
})
|
||||
assert.Nil(t, err, "no errors for forgot password")
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeForgotPassword)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeForgotPassword)
|
||||
assert.Nil(t, err, "should get forgot password request")
|
||||
|
||||
_, err = resolvers.ResetPasswordResolver(ctx, model.ResetPasswordInput{
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
|
@ -12,14 +14,15 @@ import (
|
|||
func TestResolvers(t *testing.T) {
|
||||
databases := map[string]string{
|
||||
constants.DbTypeSqlite: "../../data.db",
|
||||
// constants.DbTypeArangodb: "http://localhost:8529",
|
||||
// constants.DbTypeMongodb: "mongodb://localhost:27017",
|
||||
// constants.DbTypeArangodb: "http://localhost:8529",
|
||||
// constants.DbTypeMongodb: "mongodb://localhost:27017",
|
||||
// constants.DbTypeCassandraDB: "127.0.0.1:9042",
|
||||
}
|
||||
|
||||
for dbType, dbURL := range databases {
|
||||
s := testSetup()
|
||||
defer s.Server.Close()
|
||||
ctx := context.Background()
|
||||
|
||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseURL, dbURL)
|
||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyDatabaseType, dbType)
|
||||
|
@ -29,19 +32,24 @@ func TestResolvers(t *testing.T) {
|
|||
}
|
||||
|
||||
// clean the persisted config for test to use fresh config
|
||||
envData, err := db.Provider.GetEnv()
|
||||
envData, err := db.Provider.GetEnv(ctx)
|
||||
if err == nil {
|
||||
envData.EnvData = ""
|
||||
db.Provider.UpdateEnv(envData)
|
||||
db.Provider.UpdateEnv(ctx, envData)
|
||||
}
|
||||
env.PersistEnv()
|
||||
|
||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyEnv, "test")
|
||||
memorystore.Provider.UpdateEnvVariable(constants.EnvKeyIsProd, false)
|
||||
t.Run("should pass tests for "+dbType, func(t *testing.T) {
|
||||
// admin tests
|
||||
// admin resolvers tests
|
||||
adminSignupTests(t, s)
|
||||
addWebhookTest(t, s) // add webhooks for all the system events
|
||||
testEndpointTest(t, s)
|
||||
verificationRequestsTest(t, s)
|
||||
updateWebhookTest(t, s)
|
||||
webhookTest(t, s)
|
||||
webhooksTest(t, s)
|
||||
usersTest(t, s)
|
||||
deleteUserTest(t, s)
|
||||
updateUserTest(t, s)
|
||||
|
@ -54,7 +62,7 @@ func TestResolvers(t *testing.T) {
|
|||
enableAccessTest(t, s)
|
||||
generateJWTkeyTest(t, s)
|
||||
|
||||
// user tests
|
||||
// user resolvers tests
|
||||
loginTests(t, s)
|
||||
signupTests(t, s)
|
||||
forgotPasswordTest(t, s)
|
||||
|
@ -69,6 +77,10 @@ func TestResolvers(t *testing.T) {
|
|||
metaTests(t, s)
|
||||
inviteUserTest(t, s)
|
||||
validateJwtTokenTest(t, s)
|
||||
|
||||
time.Sleep(5 * time.Second) // add sleep for webhooklogs to get generated as they are async
|
||||
webhookLogsTest(t, s) // get logs after above resolver tests are done
|
||||
deleteWebhookTest(t, s) // delete webhooks (admin resolver)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func revokeAccessTest(t *testing.T, s TestSetup) {
|
|||
Email: email,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
|
|
@ -29,7 +29,7 @@ func sessionTests(t *testing.T, s TestSetup) {
|
|||
_, err := resolvers.SessionResolver(ctx, &model.SessionQueryInput{})
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
|
|
@ -57,7 +57,7 @@ func signupTests(t *testing.T, s TestSetup) {
|
|||
|
||||
assert.NotNil(t, err, "should throw duplicate email error")
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, email, verificationRequest.Email)
|
||||
cleanData(email)
|
||||
|
|
|
@ -21,8 +21,10 @@ import (
|
|||
|
||||
// common user data to share across tests
|
||||
type TestData struct {
|
||||
Email string
|
||||
Password string
|
||||
Email string
|
||||
Password string
|
||||
WebhookEndpoint string
|
||||
TestEventTypes []string
|
||||
}
|
||||
|
||||
type TestSetup struct {
|
||||
|
@ -33,30 +35,31 @@ type TestSetup struct {
|
|||
}
|
||||
|
||||
func cleanData(email string) {
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
ctx := context.Background()
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||
if err == nil {
|
||||
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||
err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest)
|
||||
}
|
||||
|
||||
verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeForgotPassword)
|
||||
verificationRequest, err = db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeForgotPassword)
|
||||
if err == nil {
|
||||
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||
err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest)
|
||||
}
|
||||
|
||||
verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeUpdateEmail)
|
||||
verificationRequest, err = db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeUpdateEmail)
|
||||
if err == nil {
|
||||
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||
err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest)
|
||||
}
|
||||
|
||||
verificationRequest, err = db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeMagicLinkLogin)
|
||||
verificationRequest, err = db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeMagicLinkLogin)
|
||||
if err == nil {
|
||||
err = db.Provider.DeleteVerificationRequest(verificationRequest)
|
||||
err = db.Provider.DeleteVerificationRequest(ctx, verificationRequest)
|
||||
}
|
||||
|
||||
dbUser, err := db.Provider.GetUserByEmail(email)
|
||||
dbUser, err := db.Provider.GetUserByEmail(ctx, email)
|
||||
if err == nil {
|
||||
db.Provider.DeleteUser(dbUser)
|
||||
db.Provider.DeleteSession(dbUser.ID)
|
||||
db.Provider.DeleteUser(ctx, dbUser)
|
||||
db.Provider.DeleteSession(ctx, dbUser.ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,8 +77,10 @@ func createContext(s TestSetup) (*http.Request, context.Context) {
|
|||
|
||||
func testSetup() TestSetup {
|
||||
testData := TestData{
|
||||
Email: fmt.Sprintf("%d_authorizer_tester@yopmail.com", time.Now().Unix()),
|
||||
Password: "Test@123",
|
||||
Email: fmt.Sprintf("%d_authorizer_tester@yopmail.com", time.Now().Unix()),
|
||||
Password: "Test@123",
|
||||
WebhookEndpoint: "https://62cbc6738042b16aa7c22df2.mockapi.io/api/v1/webhook",
|
||||
TestEventTypes: []string{constants.UserAccessEnabledWebhookEvent, constants.UserAccessRevokedWebhookEvent, constants.UserCreatedWebhookEvent, constants.UserDeletedWebhookEvent, constants.UserLoginWebhookEvent, constants.UserSignUpWebhookEvent},
|
||||
}
|
||||
|
||||
err := os.Setenv(constants.EnvKeyEnvPath, "../../.env.test")
|
||||
|
|
37
server/test/test_endpoint_test.go
Normal file
37
server/test/test_endpoint_test.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/crypto"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testEndpointTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run("should test endpoint", func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||
assert.NoError(t, err)
|
||||
h, err := crypto.EncryptPassword(adminSecret)
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
||||
|
||||
res, err := resolvers.TestEndpointResolver(ctx, model.TestEndpointRequest{
|
||||
Endpoint: s.TestInfo.WebhookEndpoint,
|
||||
EventName: constants.UserLoginWebhookEvent,
|
||||
Headers: map[string]interface{}{
|
||||
"x-test": "test",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res)
|
||||
assert.GreaterOrEqual(t, int64(201), *res.HTTPStatus)
|
||||
assert.NotEmpty(t, res.Response)
|
||||
})
|
||||
}
|
|
@ -29,7 +29,7 @@ func updateProfileTests(t *testing.T, s TestSetup) {
|
|||
})
|
||||
assert.NotNil(t, err, "unauthorized")
|
||||
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||
verifyRes, err := resolvers.VerifyEmailResolver(ctx, model.VerifyEmailInput{
|
||||
Token: verificationRequest.Token,
|
||||
})
|
||||
|
|
60
server/test/update_webhook_test.go
Normal file
60
server/test/update_webhook_test.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/crypto"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func updateWebhookTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run("should update webhook", func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||
assert.NoError(t, err)
|
||||
h, err := crypto.EncryptPassword(adminSecret)
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
||||
// get webhook
|
||||
webhook, err := db.Provider.GetWebhookByEventName(ctx, constants.UserDeletedWebhookEvent)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, webhook)
|
||||
webhook.Headers["x-new-test"] = "new-test"
|
||||
|
||||
res, err := resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{
|
||||
ID: webhook.ID,
|
||||
Headers: webhook.Headers,
|
||||
Enabled: utils.NewBoolRef(false),
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, res)
|
||||
assert.NotEmpty(t, res.Message)
|
||||
|
||||
updatedWebhook, err := db.Provider.GetWebhookByEventName(ctx, constants.UserDeletedWebhookEvent)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, updatedWebhook)
|
||||
assert.Equal(t, webhook.ID, updatedWebhook.ID)
|
||||
assert.Equal(t, utils.StringValue(webhook.EventName), utils.StringValue(updatedWebhook.EventName))
|
||||
assert.Equal(t, utils.StringValue(webhook.Endpoint), utils.StringValue(updatedWebhook.Endpoint))
|
||||
assert.Len(t, updatedWebhook.Headers, 2)
|
||||
assert.False(t, utils.BoolValue(updatedWebhook.Enabled))
|
||||
|
||||
res, err = resolvers.UpdateWebhookResolver(ctx, model.UpdateWebhookRequest{
|
||||
ID: webhook.ID,
|
||||
Headers: webhook.Headers,
|
||||
Enabled: utils.NewBoolRef(true),
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, res)
|
||||
assert.NotEmpty(t, res.Message)
|
||||
})
|
||||
}
|
|
@ -24,7 +24,7 @@ func verifyEmailTest(t *testing.T, s TestSetup) {
|
|||
user := *res.User
|
||||
assert.Equal(t, email, user.Email)
|
||||
assert.Nil(t, res.AccessToken, "access token should be nil")
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(email, constants.VerificationTypeBasicAuthSignup)
|
||||
verificationRequest, err := db.Provider.GetVerificationRequestByEmail(ctx, email, constants.VerificationTypeBasicAuthSignup)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, email, verificationRequest.Email)
|
||||
|
||||
|
|
45
server/test/webhook_logs_test.go
Normal file
45
server/test/webhook_logs_test.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/crypto"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func webhookLogsTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run("should get webhook logs", func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||
assert.NoError(t, err)
|
||||
h, err := crypto.EncryptPassword(adminSecret)
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
||||
|
||||
webhooks, err := resolvers.WebhooksResolver(ctx, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, webhooks)
|
||||
|
||||
webhookLogs, err := resolvers.WebhookLogsResolver(ctx, model.ListWebhookLogRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Greater(t, len(webhookLogs.WebhookLogs), 1)
|
||||
|
||||
for _, w := range webhooks.Webhooks {
|
||||
webhookLogs, err := resolvers.WebhookLogsResolver(ctx, model.ListWebhookLogRequest{
|
||||
WebhookID: &w.ID,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.GreaterOrEqual(t, len(webhookLogs.WebhookLogs), 1)
|
||||
for _, wl := range webhookLogs.WebhookLogs {
|
||||
assert.Equal(t, utils.StringValue(wl.WebhookID), w.ID)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
42
server/test/webhook_test.go
Normal file
42
server/test/webhook_test.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/crypto"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/authorizerdev/authorizer/server/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func webhookTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run("should get webhook", func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||
assert.NoError(t, err)
|
||||
h, err := crypto.EncryptPassword(adminSecret)
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
||||
|
||||
// get webhook by event name
|
||||
webhook, err := db.Provider.GetWebhookByEventName(ctx, constants.UserCreatedWebhookEvent)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, webhook)
|
||||
|
||||
res, err := resolvers.WebhookResolver(ctx, model.WebhookRequest{
|
||||
ID: webhook.ID,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, res.ID, webhook.ID)
|
||||
assert.Equal(t, utils.StringValue(res.Endpoint), utils.StringValue(webhook.Endpoint))
|
||||
assert.Equal(t, utils.StringValue(res.EventName), utils.StringValue(webhook.EventName))
|
||||
assert.Equal(t, utils.BoolValue(res.Enabled), utils.BoolValue(webhook.Enabled))
|
||||
assert.Len(t, res.Headers, len(webhook.Headers))
|
||||
})
|
||||
}
|
29
server/test/webhooks_test.go
Normal file
29
server/test/webhooks_test.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/crypto"
|
||||
"github.com/authorizerdev/authorizer/server/memorystore"
|
||||
"github.com/authorizerdev/authorizer/server/resolvers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func webhooksTest(t *testing.T, s TestSetup) {
|
||||
t.Helper()
|
||||
t.Run("should get webhooks", func(t *testing.T) {
|
||||
req, ctx := createContext(s)
|
||||
adminSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)
|
||||
assert.NoError(t, err)
|
||||
h, err := crypto.EncryptPassword(adminSecret)
|
||||
assert.NoError(t, err)
|
||||
req.Header.Set("Cookie", fmt.Sprintf("%s=%s", constants.AdminCookieName, h))
|
||||
|
||||
webhooks, err := resolvers.WebhooksResolver(ctx, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, webhooks)
|
||||
assert.Len(t, webhooks.Webhooks, len(s.TestInfo.TestEventTypes))
|
||||
})
|
||||
}
|
|
@ -4,3 +4,27 @@ package utils
|
|||
func NewStringRef(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
// StringValue returns the value of the given string ref
|
||||
func StringValue(r *string, defaultValue ...string) string {
|
||||
if r != nil {
|
||||
return *r
|
||||
}
|
||||
if len(defaultValue) > 0 {
|
||||
return defaultValue[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewBoolRef returns a reference to a bool with given value
|
||||
func NewBoolRef(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
// BoolValue returns the value of the given bool ref
|
||||
func BoolValue(r *bool) bool {
|
||||
if r == nil {
|
||||
return false
|
||||
}
|
||||
return *r
|
||||
}
|
||||
|
|
96
server/utils/webhook.go
Normal file
96
server/utils/webhook.go
Normal file
|
@ -0,0 +1,96 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/constants"
|
||||
"github.com/authorizerdev/authorizer/server/db"
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func RegisterEvent(ctx context.Context, eventName string, authRecipe string, user models.User) error {
|
||||
webhook, err := db.Provider.GetWebhookByEventName(ctx, eventName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !BoolValue(webhook.Enabled) {
|
||||
return nil
|
||||
}
|
||||
|
||||
userBytes, err := json.Marshal(user.AsAPIUser())
|
||||
if err != nil {
|
||||
log.Debug("error marshalling user obj: ", err)
|
||||
return err
|
||||
}
|
||||
userMap := map[string]interface{}{}
|
||||
err = json.Unmarshal(userBytes, &userMap)
|
||||
if err != nil {
|
||||
log.Debug("error un-marshalling user obj: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
reqBody := map[string]interface{}{
|
||||
"event_name": eventName,
|
||||
"user": userMap,
|
||||
}
|
||||
|
||||
if eventName == constants.UserLoginWebhookEvent || eventName == constants.UserSignUpWebhookEvent {
|
||||
reqBody["auth_recipe"] = authRecipe
|
||||
}
|
||||
|
||||
requestBody, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
log.Debug("error marshalling requestBody obj: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
requestBytesBuffer := bytes.NewBuffer(requestBody)
|
||||
req, err := http.NewRequest("POST", StringValue(webhook.Endpoint), requestBytesBuffer)
|
||||
if err != nil {
|
||||
log.Debug("error creating webhook post request: ", err)
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
if webhook.Headers != nil {
|
||||
for key, val := range webhook.Headers {
|
||||
req.Header.Set(key, val.(string))
|
||||
}
|
||||
}
|
||||
|
||||
client := &http.Client{Timeout: time.Second * 30}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Debug("error making request: ", err)
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
responseBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Debug("error reading response: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
statusCode := int64(resp.StatusCode)
|
||||
_, err = db.Provider.AddWebhookLog(ctx, models.WebhookLog{
|
||||
HttpStatus: statusCode,
|
||||
Request: string(requestBody),
|
||||
Response: string(responseBytes),
|
||||
WebhookID: webhook.ID,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Debug("failed to add webhook log: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user