gowebframework/file-session-provider.go

158 lines
3.9 KiB
Go
Raw Permalink Normal View History

2018-07-17 22:00:51 +00:00
/*
* @Author: Bartuccio Antoine
* @Date: 2018-07-16 15:37:29
* @Last Modified by: klmp200
* @Last Modified time: 2018-07-17 23:47:56
*/
package gowebframework
import (
"encoding/json"
"io/ioutil"
"log"
"os"
"path/filepath"
"time"
)
var session_folder_path string = ".session"
var folder_perm os.FileMode = 0770
type FileSessionProvider struct{}
// Used to hide FileSession variables and still be able to write inside json with json.Marshal
type unexportedFileSession struct {
UUID string
LastUse time.Time
Data map[string]interface{}
}
type FileSession struct {
uuid string
lastUse time.Time
data map[string]interface{}
}
// Convert a unexportedFileSession to a FileSession
func (session unexportedFileSession) fileSession() FileSession {
return FileSession{
uuid: session.UUID,
lastUse: session.LastUse,
data: session.Data,
}
}
func (provider FileSessionProvider) checkOrCreateFolder() {
folder, err := os.Open(session_folder_path)
if err != nil {
// Auto create folder if doesn't exist
log.Println("No session folder found, creating " + session_folder_path)
err = os.Mkdir(session_folder_path, folder_perm)
if err != nil {
log.Fatal("Could not create session directory, exiting")
}
return
}
folder_infos, err := folder.Stat()
if err != nil {
log.Fatal(err)
}
if !folder_infos.IsDir() {
log.Fatal(session_folder_path + " is not a directory, exiting")
}
if !isWritable(session_folder_path) {
log.Fatal(session_folder_path + " directory is not writable, exiting")
}
}
func (provider FileSessionProvider) SessionInit(uuid string) (Session, error) {
provider.checkOrCreateFolder()
provider.SessionDestroy(uuid)
session := FileSession{}
session.uuid = uuid
session.data = make(map[string]interface{})
session.lastUse = time.Now()
return session, session.writeSession()
}
func (provider FileSessionProvider) SessionRead(uuid string) (Session, error) {
provider.checkOrCreateFolder()
data, err := ioutil.ReadFile(filepath.Join(session_folder_path, uuid+".json"))
if err != nil {
return provider.SessionInit(uuid)
}
unexported_session := unexportedFileSession{}
err = json.Unmarshal(data, &unexported_session)
if err != nil {
return nil, err
}
session := unexported_session.fileSession()
return session, session.writeSession()
}
func (provider FileSessionProvider) SessionDestroy(uuid string) error {
provider.checkOrCreateFolder()
return os.Remove(filepath.Join(session_folder_path, uuid+".json"))
}
func (provider FileSessionProvider) SessionClearExpired(maxLifetime time.Duration) {
provider.checkOrCreateFolder()
directory, _ := ioutil.ReadDir(session_folder_path)
for _, file := range directory {
session := unexportedFileSession{}
data, err := ioutil.ReadFile(filepath.Join(session_folder_path, file.Name()))
if err != nil {
log.Println(err)
} else {
err = json.Unmarshal(data, &session)
if err != nil {
log.Println(err)
} else {
if session.LastUse.Add(maxLifetime).Sub(time.Now()) <= 0 {
// Session expired
provider.SessionDestroy(session.UUID)
}
}
}
}
}
func (session FileSession) unexportedFileSession() unexportedFileSession {
return unexportedFileSession{
UUID: session.uuid,
LastUse: session.lastUse,
Data: session.data,
}
}
// Write a session on the disk
func (session FileSession) writeSession() error {
session.lastUse = time.Now()
data, _ := json.Marshal(session.unexportedFileSession())
err := ioutil.WriteFile(filepath.Join(session_folder_path, session.uuid+".json"), data, folder_perm)
return err
}
func (session FileSession) Set(key string, value interface{}) error {
session.data[key] = value
return session.writeSession()
}
func (session FileSession) Get(key string) interface{} {
value, ok := session.data[key]
if !ok {
return nil
}
return value
}
func (session FileSession) Delete(key string) error {
delete(session.data, key)
return session.writeSession()
}
func (session FileSession) SessionUUID() string {
return session.uuid
}