diff options
| author | Max Resnick <max@ofmax.li> | 2020-08-14 23:13:41 -0700 |
|---|---|---|
| committer | Max Resnick <max@ofmax.li> | 2020-11-08 07:57:13 -0800 |
| commit | 689a57ec4a444f8233fe2e5ec7ceb0903218218d (patch) | |
| tree | 1bcfe6786c38b4ae11997d5d97dc3c5fba747b97 /internal/db/redis | |
| parent | 77c2e6aca2dc0f851f55e30a0f49c9ee7c2c952e (diff) | |
| download | iserv-689a57ec4a444f8233fe2e5ec7ceb0903218218d.tar.gz | |
Diffstat (limited to '')
| -rw-r--r-- | internal/db/redis/auth.go | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/internal/db/redis/auth.go b/internal/db/redis/auth.go new file mode 100644 index 0000000..0c5246c --- /dev/null +++ b/internal/db/redis/auth.go @@ -0,0 +1,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 +} |