-
-
Notifications
You must be signed in to change notification settings - Fork 146
/
authenticator.go
133 lines (111 loc) · 3.77 KB
/
authenticator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package cassandradb
import (
"context"
"encoding/json"
"fmt"
"reflect"
"strings"
"time"
"github.com/gocql/gocql"
"github.com/google/uuid"
"github.com/authorizerdev/authorizer/server/db/models"
)
func (p *provider) AddAuthenticator(ctx context.Context, authenticators *models.Authenticator) (*models.Authenticator, error) {
exists, _ := p.GetAuthenticatorDetailsByUserId(ctx, authenticators.UserID, authenticators.Method)
if exists != nil {
return authenticators, nil
}
if authenticators.ID == "" {
authenticators.ID = uuid.New().String()
}
authenticators.CreatedAt = time.Now().Unix()
authenticators.UpdatedAt = time.Now().Unix()
bytes, err := json.Marshal(authenticators)
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()
authenticatorsMap := map[string]interface{}{}
err = decoder.Decode(&authenticatorsMap)
if err != nil {
return nil, err
}
fields := "("
values := "("
for key, value := range authenticatorsMap {
if value != nil {
if key == "_id" {
fields += "id,"
} else {
fields += key + ","
}
valueType := reflect.TypeOf(value)
if valueType.Name() == "string" {
values += fmt.Sprintf("'%s',", value.(string))
} else {
values += fmt.Sprintf("%v,", value)
}
}
}
fields = fields[:len(fields)-1] + ")"
values = values[:len(values)-1] + ")"
query := fmt.Sprintf("INSERT INTO %s %s VALUES %s IF NOT EXISTS", KeySpace+"."+models.Collections.Authenticators, fields, values)
err = p.db.Query(query).Exec()
if err != nil {
return nil, err
}
return authenticators, nil
}
func (p *provider) UpdateAuthenticator(ctx context.Context, authenticators *models.Authenticator) (*models.Authenticator, error) {
authenticators.UpdatedAt = time.Now().Unix()
bytes, err := json.Marshal(authenticators)
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()
authenticatorsMap := map[string]interface{}{}
err = decoder.Decode(&authenticatorsMap)
if err != nil {
return nil, err
}
updateFields := ""
for key, value := range authenticatorsMap {
if key == "_id" {
continue
}
if key == "_key" {
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.Authenticators, updateFields, authenticators.ID)
err = p.db.Query(query).Exec()
if err != nil {
return nil, err
}
return authenticators, nil
}
func (p *provider) GetAuthenticatorDetailsByUserId(ctx context.Context, userId string, authenticatorType string) (*models.Authenticator, error) {
var authenticators models.Authenticator
query := fmt.Sprintf("SELECT id, user_id, method, secret, recovery_codes, verified_at, created_at, updated_at FROM %s WHERE user_id = '%s' AND method = '%s' LIMIT 1 ALLOW FILTERING", KeySpace+"."+models.Collections.Authenticators, userId, authenticatorType)
err := p.db.Query(query).Consistency(gocql.One).Scan(&authenticators.ID, &authenticators.UserID, &authenticators.Method, &authenticators.Secret, &authenticators.RecoveryCodes, &authenticators.VerifiedAt, &authenticators.CreatedAt, &authenticators.UpdatedAt)
if err != nil {
return nil, err
}
return &authenticators, nil
}