Feat/multiple session (#64)

* fix: disable windows build

* feat: add ability to handle multiple sessions
This commit is contained in:
Lakhan Samani 2021-10-27 23:15:38 +05:30 committed by GitHub
parent 4649391169
commit b69d0b8e23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 301 additions and 53 deletions

View File

@ -36,12 +36,12 @@ jobs:
run: echo VERSION=$(basename ${GITHUB_REF}) >> ${GITHUB_ENV} run: echo VERSION=$(basename ${GITHUB_REF}) >> ${GITHUB_ENV}
- name: Copy .env file - name: Copy .env file
run: mv .env.sample .env run: mv .env.sample .env
- name: Package files for windows # - name: Package files for windows
run: | # run: |
make clean && \ # make clean && \
CGO_ENABLED=1 GOOS=windows CC=/usr/bin/x86_64-w64-mingw32-gcc make && \ # CGO_ENABLED=1 GOOS=windows CC=/usr/bin/x86_64-w64-mingw32-gcc make && \
mv build/server build/server.exe && \ # mv build/server build/server.exe && \
zip -vr authorizer-${VERSION}-windows-amd64.zip .env app/build build templates # zip -vr authorizer-${VERSION}-windows-amd64.zip .env app/build build templates
- name: Package files for linux - name: Package files for linux
run: | run: |
make clean && \ make clean && \
@ -49,7 +49,6 @@ jobs:
tar cvfz authorizer-${VERSION}-linux-amd64.tar.gz .env app/build build templates tar cvfz authorizer-${VERSION}-linux-amd64.tar.gz .env app/build build templates
- name: Upload assets - name: Upload assets
run: | run: |
github-assets-uploader -f authorizer-${VERSION}-windows-amd64.zip -mediatype application/zip -repo authorizerdev/authorizer -token ${{secrets.RELEASE_TOKEN}} -tag ${VERSION} && \
github-assets-uploader -f authorizer-${VERSION}-linux-amd64.tar.gz -mediatype application/gzip -repo authorizerdev/authorizer -token ${{secrets.RELEASE_TOKEN}} -tag ${VERSION} github-assets-uploader -f authorizer-${VERSION}-linux-amd64.tar.gz -mediatype application/gzip -repo authorizerdev/authorizer -token ${{secrets.RELEASE_TOKEN}} -tag ${VERSION}
- name: Log in to Docker Hub - name: Log in to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v1

View File

@ -1,5 +1,11 @@
# Task List # Task List
## Feature Multiple sessions
- Multiple sessions for users to login use hMset from redis for this
user_id access_token1 long_live_token1
user_id access_token2 long_live_token2
# Feature roles # Feature roles
For the first version we will only support setting roles master list via env For the first version we will only support setting roles master list via env

View File

@ -27,6 +27,7 @@ type Manager interface {
GetVerificationByEmail(email string) (VerificationRequest, error) GetVerificationByEmail(email string) (VerificationRequest, error)
DeleteUser(email string) error DeleteUser(email string) error
SaveRoles(roles []Role) error SaveRoles(roles []Role) error
SaveSession(session Session) error
} }
type manager struct { type manager struct {
@ -56,7 +57,7 @@ func InitDB() {
if err != nil { if err != nil {
log.Fatal("Failed to init db:", err) log.Fatal("Failed to init db:", err)
} else { } else {
db.AutoMigrate(&User{}, &VerificationRequest{}, &Role{}) db.AutoMigrate(&User{}, &VerificationRequest{}, &Role{}, &Session{})
} }
Mgr = &manager{db: db} Mgr = &manager{db: db}

39
server/db/session.go Normal file
View File

@ -0,0 +1,39 @@
package db
import (
"log"
"github.com/google/uuid"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Session struct {
ID uuid.UUID `gorm:"type:uuid;"`
UserID uuid.UUID `gorm:"type:uuid;"`
User User
UserAgent string
IP string
CreatedAt int64 `gorm:"autoCreateTime"`
UpdatedAt int64 `gorm:"autoUpdateTime"`
}
func (r *Session) BeforeCreate(tx *gorm.DB) (err error) {
r.ID = uuid.New()
return
}
// SaveSession function to save user sessiosn
func (mgr *manager) SaveSession(session Session) error {
res := mgr.db.Clauses(
clause.OnConflict{
DoNothing: true,
}).Create(&session)
if res.Error != nil {
log.Println(`Error saving session`, res.Error)
return res.Error
}
return nil
}

View File

@ -30,6 +30,7 @@ func (mgr *manager) AddVerification(verification VerificationRequest) (Verificat
Columns: []clause.Column{{Name: "email"}}, Columns: []clause.Column{{Name: "email"}},
DoUpdates: clause.AssignmentColumns([]string{"token", "identifier", "expires_at"}), DoUpdates: clause.AssignmentColumns([]string{"token", "identifier", "expires_at"}),
}).Create(&verification) }).Create(&verification)
if result.Error != nil { if result.Error != nil {
log.Println(`Error saving verification record`, result.Error) log.Println(`Error saving verification record`, result.Error)
return verification, result.Error return verification, result.Error

View File

@ -147,11 +147,11 @@ func OAuthCallbackHandler() gin.HandlerFunc {
provider := c.Param("oauth_provider") provider := c.Param("oauth_provider")
state := c.Request.FormValue("state") state := c.Request.FormValue("state")
sessionState := session.GetToken(state) sessionState := session.GetSocailLoginState(state)
if sessionState == "" { if sessionState == "" {
c.JSON(400, gin.H{"error": "invalid oauth state"}) c.JSON(400, gin.H{"error": "invalid oauth state"})
} }
session.DeleteToken(sessionState) session.RemoveSocialLoginState(state)
// contains random token, redirect url, role // contains random token, redirect url, role
sessionSplit := strings.Split(state, "___") sessionSplit := strings.Split(state, "___")
@ -254,7 +254,16 @@ func OAuthCallbackHandler() gin.HandlerFunc {
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, inputRoles) accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, inputRoles)
utils.SetCookie(c, accessToken) utils.SetCookie(c, accessToken)
session.SetToken(userIdStr, refreshToken) session.SetToken(userIdStr, accessToken, refreshToken)
go func() {
sessionData := db.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(c.Request),
IP: utils.GetIP(c.Request),
}
db.Mgr.SaveSession(sessionData)
}()
c.Redirect(http.StatusTemporaryRedirect, redirectURL) c.Redirect(http.StatusTemporaryRedirect, redirectURL)
} }

View File

@ -51,18 +51,18 @@ func OAuthLoginHandler() gin.HandlerFunc {
switch provider { switch provider {
case enum.Google.String(): case enum.Google.String():
session.SetToken(oauthStateString, enum.Google.String()) session.SetSocailLoginState(oauthStateString, enum.Google.String())
// during the init of OAuthProvider authorizer url might be empty // during the init of OAuthProvider authorizer url might be empty
oauth.OAuthProvider.GoogleConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/google" oauth.OAuthProvider.GoogleConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/google"
url := oauth.OAuthProvider.GoogleConfig.AuthCodeURL(oauthStateString) url := oauth.OAuthProvider.GoogleConfig.AuthCodeURL(oauthStateString)
c.Redirect(http.StatusTemporaryRedirect, url) c.Redirect(http.StatusTemporaryRedirect, url)
case enum.Github.String(): case enum.Github.String():
session.SetToken(oauthStateString, enum.Github.String()) session.SetSocailLoginState(oauthStateString, enum.Github.String())
oauth.OAuthProvider.GithubConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/github" oauth.OAuthProvider.GithubConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/github"
url := oauth.OAuthProvider.GithubConfig.AuthCodeURL(oauthStateString) url := oauth.OAuthProvider.GithubConfig.AuthCodeURL(oauthStateString)
c.Redirect(http.StatusTemporaryRedirect, url) c.Redirect(http.StatusTemporaryRedirect, url)
case enum.Facebook.String(): case enum.Facebook.String():
session.SetToken(oauthStateString, enum.Github.String()) session.SetSocailLoginState(oauthStateString, enum.Facebook.String())
oauth.OAuthProvider.FacebookConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/facebook" oauth.OAuthProvider.FacebookConfig.RedirectURL = constants.AUTHORIZER_URL + "/oauth_callback/facebook"
url := oauth.OAuthProvider.FacebookConfig.AuthCodeURL(oauthStateString) url := oauth.OAuthProvider.FacebookConfig.AuthCodeURL(oauthStateString)
c.Redirect(http.StatusTemporaryRedirect, url) c.Redirect(http.StatusTemporaryRedirect, url)

View File

@ -56,7 +56,16 @@ func VerifyEmailHandler() gin.HandlerFunc {
accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, roles) accessToken, _, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
session.SetToken(userIdStr, refreshToken) session.SetToken(userIdStr, accessToken, refreshToken)
go func() {
sessionData := db.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(c.Request),
IP: utils.GetIP(c.Request),
}
db.Mgr.SaveSession(sessionData)
}()
utils.SetCookie(c, accessToken) utils.SetCookie(c, accessToken)
c.Redirect(http.StatusTemporaryRedirect, claim.Host) c.Redirect(http.StatusTemporaryRedirect, claim.Host)
} }

View File

@ -60,7 +60,7 @@ func AdminUpdateUser(ctx context.Context, params model.AdminUpdateUserInput) (*m
return res, fmt.Errorf("user with this email address already exists") return res, fmt.Errorf("user with this email address already exists")
} }
session.DeleteToken(fmt.Sprintf("%v", user.ID)) session.DeleteUserSession(fmt.Sprintf("%v", user.ID))
utils.DeleteCookie(gc) utils.DeleteCookie(gc)
user.Email = newEmail user.Email = newEmail
@ -100,7 +100,7 @@ func AdminUpdateUser(ctx context.Context, params model.AdminUpdateUserInput) (*m
rolesToSave = strings.Join(inputRoles, ",") rolesToSave = strings.Join(inputRoles, ",")
} }
session.DeleteToken(fmt.Sprintf("%v", user.ID)) session.DeleteUserSession(fmt.Sprintf("%v", user.ID))
utils.DeleteCookie(gc) utils.DeleteCookie(gc)
} }

View File

@ -27,7 +27,7 @@ func DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Respo
return res, err return res, err
} }
session.DeleteToken(fmt.Sprintf("%x", user.ID)) session.DeleteUserSession(fmt.Sprintf("%x", user.ID))
err = db.Mgr.DeleteUser(params.Email) err = db.Mgr.DeleteUser(params.Email)
if err != nil { if err != nil {

View File

@ -60,7 +60,16 @@ func Login(ctx context.Context, params model.LoginInput) (*model.AuthResponse, e
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles) accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
session.SetToken(userIdStr, refreshToken) session.SetToken(userIdStr, accessToken, refreshToken)
go func() {
sessionData := db.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request),
IP: utils.GetIP(gc.Request),
}
db.Mgr.SaveSession(sessionData)
}()
res = &model.AuthResponse{ res = &model.AuthResponse{
Message: `Logged in successfully`, Message: `Logged in successfully`,

View File

@ -27,7 +27,7 @@ func Logout(ctx context.Context) (*model.Response, error) {
} }
userId := fmt.Sprintf("%v", claim["id"]) userId := fmt.Sprintf("%v", claim["id"])
session.DeleteToken(userId) session.DeleteToken(userId, token)
res = &model.Response{ res = &model.Response{
Message: "Logged out successfully", Message: "Logged out successfully",
} }

View File

@ -30,7 +30,7 @@ func Profile(ctx context.Context) (*model.User, error) {
userID := fmt.Sprintf("%v", claim["id"]) userID := fmt.Sprintf("%v", claim["id"])
email := fmt.Sprintf("%v", claim["email"]) email := fmt.Sprintf("%v", claim["email"])
sessionToken := session.GetToken(userID) sessionToken := session.GetToken(userID, token)
if sessionToken == "" { if sessionToken == "" {
return res, fmt.Errorf(`unauthorized`) return res, fmt.Errorf(`unauthorized`)

View File

@ -127,7 +127,16 @@ func Signup(ctx context.Context, params model.SignUpInput) (*model.AuthResponse,
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles) accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
session.SetToken(userIdStr, refreshToken) session.SetToken(userIdStr, accessToken, refreshToken)
go func() {
sessionData := db.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request),
IP: utils.GetIP(gc.Request),
}
db.Mgr.SaveSession(sessionData)
}()
res = &model.AuthResponse{ res = &model.AuthResponse{
Message: `Signed up successfully.`, Message: `Signed up successfully.`,
AccessToken: &accessToken, AccessToken: &accessToken,

View File

@ -37,7 +37,7 @@ func Token(ctx context.Context, roles []string) (*model.AuthResponse, error) {
userIdStr := fmt.Sprintf("%v", user.ID) userIdStr := fmt.Sprintf("%v", user.ID)
sessionToken := session.GetToken(userIdStr) sessionToken := session.GetToken(userIdStr, token)
if sessionToken == "" { if sessionToken == "" {
return res, fmt.Errorf(`unauthorized`) return res, fmt.Errorf(`unauthorized`)
@ -63,7 +63,19 @@ func Token(ctx context.Context, roles []string) (*model.AuthResponse, error) {
if accessTokenErr != nil || expiresTimeObj.Sub(currentTimeObj).Minutes() <= 5 { if accessTokenErr != nil || expiresTimeObj.Sub(currentTimeObj).Minutes() <= 5 {
// if access token has expired and refresh/session token is valid // if access token has expired and refresh/session token is valid
// generate new accessToken // generate new accessToken
currentRefreshToken := session.GetToken(userIdStr, token)
session.DeleteToken(userIdStr, token)
token, expiresAt, _ = utils.CreateAuthToken(user, enum.AccessToken, claimRoles) token, expiresAt, _ = utils.CreateAuthToken(user, enum.AccessToken, claimRoles)
session.SetToken(userIdStr, token, currentRefreshToken)
go func() {
sessionData := db.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request),
IP: utils.GetIP(gc.Request),
}
db.Mgr.SaveSession(sessionData)
}()
} }
utils.SetCookie(gc, token) utils.SetCookie(gc, token)

View File

@ -33,7 +33,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
} }
id := fmt.Sprintf("%v", claim["id"]) id := fmt.Sprintf("%v", claim["id"])
sessionToken := session.GetToken(id) sessionToken := session.GetToken(id, token)
if sessionToken == "" { if sessionToken == "" {
return res, fmt.Errorf(`unauthorized`) return res, fmt.Errorf(`unauthorized`)
@ -99,7 +99,7 @@ func UpdateProfile(ctx context.Context, params model.UpdateProfileInput) (*model
return res, fmt.Errorf("user with this email address already exists") return res, fmt.Errorf("user with this email address already exists")
} }
session.DeleteToken(fmt.Sprintf("%v", user.ID)) session.DeleteUserSession(fmt.Sprintf("%v", user.ID))
utils.DeleteCookie(gc) utils.DeleteCookie(gc)
user.Email = newEmail user.Email = newEmail

View File

@ -47,7 +47,16 @@ func VerifyEmail(ctx context.Context, params model.VerifyEmailInput) (*model.Aut
accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles) accessToken, expiresAt, _ := utils.CreateAuthToken(user, enum.AccessToken, roles)
session.SetToken(userIdStr, refreshToken) session.SetToken(userIdStr, accessToken, refreshToken)
go func() {
sessionData := db.Session{
UserID: user.ID,
UserAgent: utils.GetUserAgent(gc.Request),
IP: utils.GetIP(gc.Request),
}
db.Mgr.SaveSession(sessionData)
}()
res = &model.AuthResponse{ res = &model.AuthResponse{
Message: `Email verified successfully.`, Message: `Email verified successfully.`,

View File

@ -1,41 +1,88 @@
package session package session
import "sync" import (
"log"
"sync"
)
type InMemoryStore struct { type InMemoryStore struct {
mu sync.Mutex mu sync.Mutex
store map[string]string store map[string]map[string]string
socialLoginState map[string]string
} }
func (c *InMemoryStore) AddToken(userId, token string) { func (c *InMemoryStore) AddToken(userId, accessToken, refreshToken string) {
c.mu.Lock() c.mu.Lock()
// delete sessions > 500 // not recommended for production // delete sessions > 500 // not recommended for production
if len(c.store) >= 500 { if len(c.store) >= 500 {
c.store = make(map[string]string) c.store = map[string]map[string]string{}
} }
c.store[userId] = token // check if entry exists in map
_, exists := c.store[userId]
if exists {
tempMap := c.store[userId]
tempMap[accessToken] = refreshToken
c.store[userId] = tempMap
} else {
tempMap := map[string]string{
accessToken: refreshToken,
}
c.store[userId] = tempMap
}
log.Println(c.store)
c.mu.Unlock() c.mu.Unlock()
} }
func (c *InMemoryStore) DeleteToken(userId string) { func (c *InMemoryStore) DeleteUserSession(userId string) {
c.mu.Lock() c.mu.Lock()
delete(c.store, userId) delete(c.store, userId)
c.mu.Unlock() c.mu.Unlock()
} }
func (c *InMemoryStore) ClearStore() { func (c *InMemoryStore) DeleteToken(userId, accessToken string) {
c.mu.Lock() c.mu.Lock()
c.store = make(map[string]string) delete(c.store[userId], accessToken)
c.mu.Unlock() c.mu.Unlock()
} }
func (c *InMemoryStore) GetToken(userId string) string { func (c *InMemoryStore) ClearStore() {
c.mu.Lock()
c.store = map[string]map[string]string{}
c.mu.Unlock()
}
func (c *InMemoryStore) GetToken(userId, accessToken string) string {
token := "" token := ""
c.mu.Lock() c.mu.Lock()
if val, ok := c.store[userId]; ok { if sessionMap, ok := c.store[userId]; ok {
token = val if val, ok := sessionMap[accessToken]; ok {
token = val
}
} }
c.mu.Unlock() c.mu.Unlock()
return token return token
} }
func (c *InMemoryStore) SetSocialLoginState(key, state string) {
c.mu.Lock()
c.socialLoginState[key] = state
c.mu.Unlock()
}
func (c *InMemoryStore) GetSocialLoginState(key string) string {
state := ""
if stateVal, ok := c.socialLoginState[key]; ok {
state = stateVal
}
return state
}
func (c *InMemoryStore) RemoveSocialLoginState(key string) {
c.mu.Lock()
delete(c.socialLoginState, key)
c.mu.Unlock()
}

View File

@ -2,6 +2,7 @@ package session
import ( import (
"context" "context"
"fmt"
"log" "log"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
@ -12,20 +13,29 @@ type RedisStore struct {
store *redis.Client store *redis.Client
} }
func (c *RedisStore) AddToken(userId, token string) { func (c *RedisStore) AddToken(userId, accessToken, refreshToken string) {
err := c.store.Set(c.ctx, "authorizer_"+userId, token, 0).Err() err := c.store.HMSet(c.ctx, "authorizer_"+userId, map[string]string{
accessToken: refreshToken,
}).Err()
if err != nil { if err != nil {
log.Fatalln("Error saving redis token:", err) log.Fatalln("Error saving redis token:", err)
} }
} }
func (c *RedisStore) DeleteToken(userId string) { func (c *RedisStore) DeleteUserSession(userId string) {
err := c.store.Del(c.ctx, "authorizer_"+userId).Err() err := c.store.Del(c.ctx, "authorizer_"+userId).Err()
if err != nil { if err != nil {
log.Fatalln("Error deleting redis token:", err) log.Fatalln("Error deleting redis token:", err)
} }
} }
func (c *RedisStore) DeleteToken(userId, accessToken string) {
err := c.store.HDel(c.ctx, "authorizer_"+userId, accessToken).Err()
if err != nil {
log.Fatalln("Error deleting redis token:", err)
}
}
func (c *RedisStore) ClearStore() { func (c *RedisStore) ClearStore() {
err := c.store.Del(c.ctx, "authorizer_*").Err() err := c.store.Del(c.ctx, "authorizer_*").Err()
if err != nil { if err != nil {
@ -33,11 +43,38 @@ func (c *RedisStore) ClearStore() {
} }
} }
func (c *RedisStore) GetToken(userId string) string { func (c *RedisStore) GetToken(userId, accessToken string) string {
token := "" token := ""
token, err := c.store.Get(c.ctx, "authorizer_"+userId).Result() res, err := c.store.HMGet(c.ctx, "authorizer_"+userId, accessToken).Result()
if err != nil { if err != nil {
log.Println("Error getting token from redis store:", err) log.Println("Error getting token from redis store:", err)
} }
if len(res) > 0 && res[0] != nil {
token = fmt.Sprintf("%v", res[0])
}
return token return token
} }
func (c *RedisStore) SetSocialLoginState(key, state string) {
err := c.store.Set(c.ctx, key, state, 0).Err()
if err != nil {
log.Fatalln("Error saving redis token:", err)
}
}
func (c *RedisStore) GetSocialLoginState(key string) string {
state := ""
state, err := c.store.Get(c.ctx, key).Result()
if err != nil {
log.Println("Error getting token from redis store:", err)
}
return state
}
func (c *RedisStore) RemoveSocialLoginState(key string) {
err := c.store.Del(c.ctx, key).Err()
if err != nil {
log.Fatalln("Error deleting redis token:", err)
}
}

View File

@ -15,30 +15,42 @@ type SessionStore struct {
var SessionStoreObj SessionStore var SessionStoreObj SessionStore
func SetToken(userId, token string) { func SetToken(userId, accessToken, refreshToken string) {
// TODO: Set session information in db for all the sessions that gets generated
// it should async go function
if SessionStoreObj.RedisMemoryStoreObj != nil { if SessionStoreObj.RedisMemoryStoreObj != nil {
SessionStoreObj.RedisMemoryStoreObj.AddToken(userId, token) SessionStoreObj.RedisMemoryStoreObj.AddToken(userId, accessToken, refreshToken)
} }
if SessionStoreObj.InMemoryStoreObj != nil { if SessionStoreObj.InMemoryStoreObj != nil {
SessionStoreObj.InMemoryStoreObj.AddToken(userId, token) SessionStoreObj.InMemoryStoreObj.AddToken(userId, accessToken, refreshToken)
} }
} }
func DeleteToken(userId string) { func DeleteToken(userId, accessToken string) {
if SessionStoreObj.RedisMemoryStoreObj != nil { if SessionStoreObj.RedisMemoryStoreObj != nil {
SessionStoreObj.RedisMemoryStoreObj.DeleteToken(userId) SessionStoreObj.RedisMemoryStoreObj.DeleteToken(userId, accessToken)
} }
if SessionStoreObj.InMemoryStoreObj != nil { if SessionStoreObj.InMemoryStoreObj != nil {
SessionStoreObj.InMemoryStoreObj.DeleteToken(userId) SessionStoreObj.InMemoryStoreObj.DeleteToken(userId, accessToken)
} }
} }
func GetToken(userId string) string { func DeleteUserSession(userId string) {
if SessionStoreObj.RedisMemoryStoreObj != nil { if SessionStoreObj.RedisMemoryStoreObj != nil {
return SessionStoreObj.RedisMemoryStoreObj.GetToken(userId) SessionStoreObj.RedisMemoryStoreObj.DeleteUserSession(userId)
} }
if SessionStoreObj.InMemoryStoreObj != nil { if SessionStoreObj.InMemoryStoreObj != nil {
return SessionStoreObj.InMemoryStoreObj.GetToken(userId) SessionStoreObj.InMemoryStoreObj.DeleteUserSession(userId)
}
}
func GetToken(userId, accessToken string) string {
if SessionStoreObj.RedisMemoryStoreObj != nil {
return SessionStoreObj.RedisMemoryStoreObj.GetToken(userId, accessToken)
}
if SessionStoreObj.InMemoryStoreObj != nil {
return SessionStoreObj.InMemoryStoreObj.GetToken(userId, accessToken)
} }
return "" return ""
@ -53,6 +65,35 @@ func ClearStore() {
} }
} }
func SetSocailLoginState(key, state string) {
if SessionStoreObj.RedisMemoryStoreObj != nil {
SessionStoreObj.RedisMemoryStoreObj.SetSocialLoginState(key, state)
}
if SessionStoreObj.InMemoryStoreObj != nil {
SessionStoreObj.InMemoryStoreObj.SetSocialLoginState(key, state)
}
}
func GetSocailLoginState(key string) string {
if SessionStoreObj.RedisMemoryStoreObj != nil {
return SessionStoreObj.RedisMemoryStoreObj.GetSocialLoginState(key)
}
if SessionStoreObj.InMemoryStoreObj != nil {
return SessionStoreObj.InMemoryStoreObj.GetSocialLoginState(key)
}
return ""
}
func RemoveSocialLoginState(key string) {
if SessionStoreObj.RedisMemoryStoreObj != nil {
SessionStoreObj.RedisMemoryStoreObj.RemoveSocialLoginState(key)
}
if SessionStoreObj.InMemoryStoreObj != nil {
SessionStoreObj.InMemoryStoreObj.RemoveSocialLoginState(key)
}
}
func InitSession() { func InitSession() {
if constants.REDIS_URL != "" { if constants.REDIS_URL != "" {
log.Println("Using redis store to save sessions") log.Println("Using redis store to save sessions")
@ -75,7 +116,8 @@ func InitSession() {
} else { } else {
log.Println("Using in memory store to save sessions") log.Println("Using in memory store to save sessions")
SessionStoreObj.InMemoryStoreObj = &InMemoryStore{ SessionStoreObj.InMemoryStoreObj = &InMemoryStore{
store: make(map[string]string), store: map[string]map[string]string{},
socialLoginState: map[string]string{},
} }
} }
} }

View File

@ -0,0 +1,19 @@
package utils
import "net/http"
func GetIP(r *http.Request) string {
IPAddress := r.Header.Get("X-Real-Ip")
if IPAddress == "" {
IPAddress = r.Header.Get("X-Forwarded-For")
}
if IPAddress == "" {
IPAddress = r.RemoteAddr
}
return IPAddress
}
func GetUserAgent(r *http.Request) string {
return r.UserAgent()
}