/* * @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 }