aboutsummaryrefslogtreecommitdiff
path: root/internal/db/redis/auth.go
blob: 0c5246cf8d74cbda56d9728d740f22b77950e41c (plain)
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
}