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 }