Skip to content

Commit 4f5a6c7

Browse files
authored
Merge pull request #194 from authorizerdev/feat/webhook
feat: add webhook apis + integrate in events
2 parents 6a74a50 + 018a13a commit 4f5a6c7

File tree

101 files changed

+4669
-460
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+4669
-460
lines changed

server/constants/webhook_event.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package constants
2+
3+
const (
4+
5+
// UserLoginWebhookEvent name for login event
6+
UserLoginWebhookEvent = `user.login`
7+
// UserCreatedWebhookEvent name for user creation event
8+
// This is triggered when user entry is created but still not verified
9+
UserCreatedWebhookEvent = `user.created`
10+
// UserSignUpWebhookEvent name for signup event
11+
UserSignUpWebhookEvent = `user.signup`
12+
// UserAccessRevokedWebhookEvent name for user access revoke event
13+
UserAccessRevokedWebhookEvent = `user.access_revoked`
14+
// UserAccessEnabledWebhookEvent name for user access enable event
15+
UserAccessEnabledWebhookEvent = `user.access_enabled`
16+
// UserDeletedWebhookEvent name for user deleted event
17+
UserDeletedWebhookEvent = `user.deleted`
18+
)

server/db/models/model.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ type CollectionList struct {
66
VerificationRequest string
77
Session string
88
Env string
9+
Webhook string
10+
WebhookLog string
911
}
1012

1113
var (
@@ -17,5 +19,7 @@ var (
1719
VerificationRequest: Prefix + "verification_requests",
1820
Session: Prefix + "sessions",
1921
Env: Prefix + "env",
22+
Webhook: Prefix + "webhook",
23+
WebhookLog: Prefix + "webhook_log",
2024
}
2125
)

server/db/models/webhook.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package models
2+
3+
import (
4+
"encoding/json"
5+
6+
"github.com/authorizerdev/authorizer/server/graph/model"
7+
)
8+
9+
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
10+
11+
// Webhook model for db
12+
type Webhook struct {
13+
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
14+
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
15+
EventName string `gorm:"unique" json:"event_name" bson:"event_name" cql:"event_name"`
16+
EndPoint string `gorm:"type:text" json:"endpoint" bson:"endpoint" cql:"endpoint"`
17+
Headers string `gorm:"type:text" json:"headers" bson:"headers" cql:"headers"`
18+
Enabled bool `json:"enabled" bson:"enabled" cql:"enabled"`
19+
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
20+
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
21+
}
22+
23+
func (w *Webhook) AsAPIWebhook() *model.Webhook {
24+
headersMap := make(map[string]interface{})
25+
json.Unmarshal([]byte(w.Headers), &headersMap)
26+
return &model.Webhook{
27+
ID: w.ID,
28+
EventName: &w.EventName,
29+
Endpoint: &w.EndPoint,
30+
Headers: headersMap,
31+
Enabled: &w.Enabled,
32+
CreatedAt: &w.CreatedAt,
33+
UpdatedAt: &w.UpdatedAt,
34+
}
35+
}

server/db/models/webhook_log.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package models
2+
3+
import "github.com/authorizerdev/authorizer/server/graph/model"
4+
5+
// Note: any change here should be reflected in providers/casandra/provider.go as it does not have model support in collection creation
6+
7+
// WebhookLog model for db
8+
type WebhookLog struct {
9+
Key string `json:"_key,omitempty" bson:"_key,omitempty" cql:"_key,omitempty"` // for arangodb
10+
ID string `gorm:"primaryKey;type:char(36)" json:"_id" bson:"_id" cql:"id"`
11+
HttpStatus int64 `json:"http_status" bson:"http_status" cql:"http_status"`
12+
Response string `gorm:"type:text" json:"response" bson:"response" cql:"response"`
13+
Request string `gorm:"type:text" json:"request" bson:"request" cql:"request"`
14+
WebhookID string `gorm:"type:char(36),index:" json:"webhook_id" bson:"webhook_id" cql:"webhook_id"`
15+
Webhook Webhook `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-" bson:"-" cql:"-"`
16+
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at"`
17+
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at"`
18+
}
19+
20+
func (w *WebhookLog) AsAPIWebhookLog() *model.WebhookLog {
21+
return &model.WebhookLog{
22+
ID: w.ID,
23+
HTTPStatus: &w.HttpStatus,
24+
Response: &w.Response,
25+
Request: &w.Request,
26+
WebhookID: &w.WebhookID,
27+
CreatedAt: &w.CreatedAt,
28+
UpdatedAt: &w.UpdatedAt,
29+
}
30+
}

server/db/providers/arangodb/env.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package arangodb
22

33
import (
4+
"context"
45
"fmt"
56
"time"
67

@@ -11,15 +12,15 @@ import (
1112
)
1213

1314
// AddEnv to save environment information in database
14-
func (p *provider) AddEnv(env models.Env) (models.Env, error) {
15+
func (p *provider) AddEnv(ctx context.Context, env models.Env) (models.Env, error) {
1516
if env.ID == "" {
1617
env.ID = uuid.New().String()
1718
}
1819

1920
env.CreatedAt = time.Now().Unix()
2021
env.UpdatedAt = time.Now().Unix()
21-
configCollection, _ := p.db.Collection(nil, models.Collections.Env)
22-
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(nil), env)
22+
configCollection, _ := p.db.Collection(ctx, models.Collections.Env)
23+
meta, err := configCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), env)
2324
if err != nil {
2425
return env, err
2526
}
@@ -29,10 +30,10 @@ func (p *provider) AddEnv(env models.Env) (models.Env, error) {
2930
}
3031

3132
// UpdateEnv to update environment information in database
32-
func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
33+
func (p *provider) UpdateEnv(ctx context.Context, env models.Env) (models.Env, error) {
3334
env.UpdatedAt = time.Now().Unix()
34-
collection, _ := p.db.Collection(nil, models.Collections.Env)
35-
meta, err := collection.UpdateDocument(nil, env.Key, env)
35+
collection, _ := p.db.Collection(ctx, models.Collections.Env)
36+
meta, err := collection.UpdateDocument(ctx, env.Key, env)
3637
if err != nil {
3738
return env, err
3839
}
@@ -43,11 +44,11 @@ func (p *provider) UpdateEnv(env models.Env) (models.Env, error) {
4344
}
4445

4546
// GetEnv to get environment information from database
46-
func (p *provider) GetEnv() (models.Env, error) {
47+
func (p *provider) GetEnv(ctx context.Context) (models.Env, error) {
4748
var env models.Env
4849
query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.Env)
4950

50-
cursor, err := p.db.Query(nil, query, nil)
51+
cursor, err := p.db.Query(ctx, query, nil)
5152
if err != nil {
5253
return env, err
5354
}
@@ -60,7 +61,7 @@ func (p *provider) GetEnv() (models.Env, error) {
6061
}
6162
break
6263
}
63-
_, err := cursor.ReadDocument(nil, &env)
64+
_, err := cursor.ReadDocument(ctx, &env)
6465
if err != nil {
6566
return env, err
6667
}

server/db/providers/arangodb/provider.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,33 @@ func NewProvider() (*provider, error) {
107107
}
108108
}
109109

110+
webhookCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.Webhook)
111+
if !webhookCollectionExists {
112+
_, err = arangodb.CreateCollection(ctx, models.Collections.Webhook, nil)
113+
if err != nil {
114+
return nil, err
115+
}
116+
}
117+
118+
webhookCollection, _ := arangodb.Collection(nil, models.Collections.Webhook)
119+
webhookCollection.EnsureHashIndex(ctx, []string{"event_name"}, &arangoDriver.EnsureHashIndexOptions{
120+
Unique: true,
121+
Sparse: true,
122+
})
123+
124+
webhookLogCollectionExists, err := arangodb.CollectionExists(ctx, models.Collections.WebhookLog)
125+
if !webhookLogCollectionExists {
126+
_, err = arangodb.CreateCollection(ctx, models.Collections.WebhookLog, nil)
127+
if err != nil {
128+
return nil, err
129+
}
130+
}
131+
132+
webhookLogCollection, _ := arangodb.Collection(nil, models.Collections.WebhookLog)
133+
webhookLogCollection.EnsureHashIndex(ctx, []string{"webhook_id"}, &arangoDriver.EnsureHashIndexOptions{
134+
Sparse: true,
135+
})
136+
110137
return &provider{
111138
db: arangodb,
112139
}, err

server/db/providers/arangodb/session.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package arangodb
22

33
import (
4+
"context"
45
"fmt"
56
"time"
67

@@ -9,28 +10,28 @@ import (
910
)
1011

1112
// AddSession to save session information in database
12-
func (p *provider) AddSession(session models.Session) error {
13+
func (p *provider) AddSession(ctx context.Context, session models.Session) error {
1314
if session.ID == "" {
1415
session.ID = uuid.New().String()
1516
}
1617

1718
session.CreatedAt = time.Now().Unix()
1819
session.UpdatedAt = time.Now().Unix()
19-
sessionCollection, _ := p.db.Collection(nil, models.Collections.Session)
20-
_, err := sessionCollection.CreateDocument(nil, session)
20+
sessionCollection, _ := p.db.Collection(ctx, models.Collections.Session)
21+
_, err := sessionCollection.CreateDocument(ctx, session)
2122
if err != nil {
2223
return err
2324
}
2425
return nil
2526
}
2627

2728
// DeleteSession to delete session information from database
28-
func (p *provider) DeleteSession(userId string) error {
29+
func (p *provider) DeleteSession(ctx context.Context, userId string) error {
2930
query := fmt.Sprintf(`FOR d IN %s FILTER d.user_id == @userId REMOVE { _key: d._key } IN %s`, models.Collections.Session, models.Collections.Session)
3031
bindVars := map[string]interface{}{
3132
"userId": userId,
3233
}
33-
cursor, err := p.db.Query(nil, query, bindVars)
34+
cursor, err := p.db.Query(ctx, query, bindVars)
3435
if err != nil {
3536
return err
3637
}

server/db/providers/arangodb/user.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
)
1616

1717
// AddUser to save user information in database
18-
func (p *provider) AddUser(user models.User) (models.User, error) {
18+
func (p *provider) AddUser(ctx context.Context, user models.User) (models.User, error) {
1919
if user.ID == "" {
2020
user.ID = uuid.New().String()
2121
}
@@ -30,8 +30,8 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
3030

3131
user.CreatedAt = time.Now().Unix()
3232
user.UpdatedAt = time.Now().Unix()
33-
userCollection, _ := p.db.Collection(nil, models.Collections.User)
34-
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(nil), user)
33+
userCollection, _ := p.db.Collection(ctx, models.Collections.User)
34+
meta, err := userCollection.CreateDocument(arangoDriver.WithOverwrite(ctx), user)
3535
if err != nil {
3636
return user, err
3737
}
@@ -42,10 +42,10 @@ func (p *provider) AddUser(user models.User) (models.User, error) {
4242
}
4343

4444
// UpdateUser to update user information in database
45-
func (p *provider) UpdateUser(user models.User) (models.User, error) {
45+
func (p *provider) UpdateUser(ctx context.Context, user models.User) (models.User, error) {
4646
user.UpdatedAt = time.Now().Unix()
47-
collection, _ := p.db.Collection(nil, models.Collections.User)
48-
meta, err := collection.UpdateDocument(nil, user.Key, user)
47+
collection, _ := p.db.Collection(ctx, models.Collections.User)
48+
meta, err := collection.UpdateDocument(ctx, user.Key, user)
4949
if err != nil {
5050
return user, err
5151
}
@@ -56,9 +56,9 @@ func (p *provider) UpdateUser(user models.User) (models.User, error) {
5656
}
5757

5858
// DeleteUser to delete user information from database
59-
func (p *provider) DeleteUser(user models.User) error {
60-
collection, _ := p.db.Collection(nil, models.Collections.User)
61-
_, err := collection.RemoveDocument(nil, user.Key)
59+
func (p *provider) DeleteUser(ctx context.Context, user models.User) error {
60+
collection, _ := p.db.Collection(ctx, models.Collections.User)
61+
_, err := collection.RemoveDocument(ctx, user.Key)
6262
if err != nil {
6363
return err
6464
}
@@ -67,13 +67,13 @@ func (p *provider) DeleteUser(user models.User) error {
6767
}
6868

6969
// ListUsers to get list of users from database
70-
func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) {
70+
func (p *provider) ListUsers(ctx context.Context, pagination model.Pagination) (*model.Users, error) {
7171
var users []*model.User
72-
ctx := driver.WithQueryFullCount(context.Background())
72+
sctx := driver.WithQueryFullCount(ctx)
7373

7474
query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.User, pagination.Offset, pagination.Limit)
7575

76-
cursor, err := p.db.Query(ctx, query, nil)
76+
cursor, err := p.db.Query(sctx, query, nil)
7777
if err != nil {
7878
return nil, err
7979
}
@@ -84,7 +84,7 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
8484

8585
for {
8686
var user models.User
87-
meta, err := cursor.ReadDocument(nil, &user)
87+
meta, err := cursor.ReadDocument(ctx, &user)
8888

8989
if arangoDriver.IsNoMoreDocuments(err) {
9090
break
@@ -104,15 +104,15 @@ func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error)
104104
}
105105

106106
// GetUserByEmail to get user information from database using email address
107-
func (p *provider) GetUserByEmail(email string) (models.User, error) {
107+
func (p *provider) GetUserByEmail(ctx context.Context, email string) (models.User, error) {
108108
var user models.User
109109

110110
query := fmt.Sprintf("FOR d in %s FILTER d.email == @email RETURN d", models.Collections.User)
111111
bindVars := map[string]interface{}{
112112
"email": email,
113113
}
114114

115-
cursor, err := p.db.Query(nil, query, bindVars)
115+
cursor, err := p.db.Query(ctx, query, bindVars)
116116
if err != nil {
117117
return user, err
118118
}
@@ -125,7 +125,7 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
125125
}
126126
break
127127
}
128-
_, err := cursor.ReadDocument(nil, &user)
128+
_, err := cursor.ReadDocument(ctx, &user)
129129
if err != nil {
130130
return user, err
131131
}
@@ -135,15 +135,15 @@ func (p *provider) GetUserByEmail(email string) (models.User, error) {
135135
}
136136

137137
// GetUserByID to get user information from database using user ID
138-
func (p *provider) GetUserByID(id string) (models.User, error) {
138+
func (p *provider) GetUserByID(ctx context.Context, id string) (models.User, error) {
139139
var user models.User
140140

141141
query := fmt.Sprintf("FOR d in %s FILTER d._id == @id LIMIT 1 RETURN d", models.Collections.User)
142142
bindVars := map[string]interface{}{
143143
"id": id,
144144
}
145145

146-
cursor, err := p.db.Query(nil, query, bindVars)
146+
cursor, err := p.db.Query(ctx, query, bindVars)
147147
if err != nil {
148148
return user, err
149149
}
@@ -156,7 +156,7 @@ func (p *provider) GetUserByID(id string) (models.User, error) {
156156
}
157157
break
158158
}
159-
_, err := cursor.ReadDocument(nil, &user)
159+
_, err := cursor.ReadDocument(ctx, &user)
160160
if err != nil {
161161
return user, err
162162
}

0 commit comments

Comments
 (0)