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
|
package redis
import (
"log"
"github.com/gomodule/redigo/redis"
"golang.org/x/oauth2"
"git.ofmax.li/iserv/internal/auth"
)
var (
createAuthLua = redis.NewScript(2, `
if redis.call("SISMEMBER","invites",KEYS[1]) == 1 then
return redis.call("HMSET",KEYS[2],unpack(ARGV))
end
return nil
`)
)
// AuthRepo supporting auth
type AuthRepo struct {
db *redis.Pool
}
// NewRedisAuthRepo redis.Pool
// creates auth repo around redis pool
func NewRedisAuthRepo(conn *redis.Pool) *AuthRepo {
return &AuthRepo{
conn,
}
}
// IsAuthorized is member of invites
func (db *AuthRepo) IsAuthorized(gp *auth.GoogleAuthProfile) (bool, error) {
conn := db.db.Get()
defer conn.Close()
authProfileKey := "auth:goog:" + gp.Email
reply, err := redis.Bool(conn.Do("SISMEMBER", "invites", authProfileKey))
if err != nil {
return reply, err
}
return reply, err
}
// LookUpAuthProfileID get internal profileid
func (db *AuthRepo) LookUpAuthProfileID(gp *auth.GoogleAuthProfile) (string, error) {
conn := db.db.Get()
var id string
defer conn.Close()
authProfileKey := "auth:goog:" + gp.ProfileID
reply, err := redis.Values(conn.Do("HMGET", authProfileKey, "id"))
if err == redis.ErrNil {
// no profile
return "", nil
} else if err != nil {
// some other error
return "", err
}
if _, err := redis.Scan(reply, &id); err != nil {
return "", err
}
return id, nil
}
// SaveAuthProfile save profile, validate against invites
func (db *AuthRepo) SaveAuthProfile(ap *auth.Profile) error {
// TODO this will over-write refresh tokens
conn := db.db.Get()
defer conn.Close()
authProfileKey := "auth:goog:" + ap.ID
prof := redis.Args{}.Add(ap.Email).Add(authProfileKey).AddFlat(ap)
res, err := createAuthLua.Do(conn, prof...)
log.Printf("auth save response %+v", res)
conn.Flush()
return err
}
func (db *AuthRepo) getAuthProfile(id string) (*auth.Profile, error) {
conn := db.db.Get()
defer conn.Close()
authProfileKey := "auth:goog:" + id
authProfile := auth.Profile{}
res, err := redis.Values(conn.Do("HGETALL", authProfileKey))
if err != nil {
log.Fatal(err)
}
log.Printf("getAuthProfile: %+v", res)
redis.ScanStruct(res, &authProfile)
return &authProfile, err
}
// GetProfileToken token for profile
func (db *AuthRepo) GetProfileToken(id string) (*oauth2.Token, error) {
profile, err := db.getAuthProfile(id)
if err != nil {
return nil, err
}
tkn, err := profile.Token()
if err != nil {
return nil, err
}
refreshedToken, err := oauth2.ReuseTokenSource(tkn, profile).Token()
if err != nil {
return nil, err
}
return refreshedToken, nil
}
|