aboutsummaryrefslogtreecommitdiff
path: root/indentalUserDB/indentalUserDB.go
diff options
context:
space:
mode:
Diffstat (limited to 'indentalUserDB/indentalUserDB.go')
-rw-r--r--indentalUserDB/indentalUserDB.go189
1 files changed, 189 insertions, 0 deletions
diff --git a/indentalUserDB/indentalUserDB.go b/indentalUserDB/indentalUserDB.go
new file mode 100644
index 0000000..588eded
--- /dev/null
+++ b/indentalUserDB/indentalUserDB.go
@@ -0,0 +1,189 @@
+package indentalUserDB
+
+import (
+ "time"
+ "nilfm.cc/git/goldbug/cookie"
+ "nilfm.cc/git/goldbug/auth"
+ "golang.org/x/crypto/bcrypt"
+ //"io"
+ "os"
+ "strings"
+ "fmt"
+ "errors"
+)
+
+type IndentalUserDB struct {
+ Users map[string]*auth.User
+ Basis string
+}
+
+func CreateIndentalUserDB(filePath string) *IndentalUserDB {
+ u, err := readDB(filePath)
+ if err == nil {
+ uMap := map[string]*auth.User{}
+ for _, usr := range u {
+ uMap[usr.Name] = usr
+ }
+ return &IndentalUserDB{
+ Users: uMap,
+ Basis: filePath,
+ }
+ } else {
+ return &IndentalUserDB{
+ Users: map[string]*auth.User{},
+ Basis: filePath,
+ }
+ }
+}
+
+func (self *IndentalUserDB) InitiateSession(user string, password string) (string, error) {
+ if _, exists := self.Users[user]; !exists {
+ return "", errors.New("User not in DB")
+ }
+ if bcrypt.CompareHashAndPassword([]byte(self.Users[user].Pass), []byte(password)) != nil {
+ return "", errors.New("Incorrect password")
+ }
+ sessionId := cookie.GenToken(64)
+ self.Users[user].Session = sessionId
+ writeDB(self.Basis, self.Users)
+ return sessionId, nil
+}
+
+func (self *IndentalUserDB) ValidateUser(user string, sessionId string) (bool, error) {
+ if _, exists := self.Users[user]; !exists {
+ return false, errors.New("User not in DB")
+ }
+
+ validated := self.Users[user].Session == sessionId
+ if validated {
+ self.Users[user].LastSeen = time.Now()
+ writeDB(self.Basis, self.Users)
+ }
+
+ return validated, nil
+}
+
+func (self *IndentalUserDB) EndSession(user string) error {
+ if _, exists := self.Users[user]; !exists {
+ return errors.New("User not in DB")
+ }
+
+ self.Users[user].Session = ""
+ self.Users[user].LastSeen = time.Now()
+ writeDB(self.Basis, self.Users)
+ return nil
+}
+
+func (self *IndentalUserDB) DeleteUser(user string) error {
+ if _, exists := self.Users[user]; !exists {
+ return errors.New("User not in DB")
+ }
+
+ delete(self.Users, user)
+ writeDB(self.Basis, self.Users)
+ return nil
+}
+
+func (self *IndentalUserDB) ChangePassword(user string, password string, oldPassword string) error {
+ if _, exists := self.Users[user]; !exists {
+ return errors.New("User not in DB")
+ }
+ if bcrypt.CompareHashAndPassword([]byte(self.Users[user].Pass), []byte(oldPassword)) != nil {
+ return errors.New("Incorrect password")
+ }
+
+ hash, _ := bcrypt.GenerateFromPassword([]byte(password), 10)
+ self.Users[user].Pass = string(hash[:])
+ writeDB(self.Basis, self.Users)
+ return nil
+}
+
+func (self *IndentalUserDB) AddUser(user string, password string) error{
+ if _, exists := self.Users[user]; exists {
+ return errors.New("User already in DB")
+ }
+
+ hash, _ := bcrypt.GenerateFromPassword([]byte(password), 10)
+
+ self.Users[user] = &auth.User{
+ Name: user,
+ Pass: string(hash[:]),
+ LastSeen: time.UnixMicro(0),
+ LoginTime: time.UnixMicro(0),
+ Session: "",
+ }
+ writeDB(self.Basis, self.Users)
+ return nil;
+}
+
+const timeFmt = "2006-01-02T15:04Z"
+
+func readDB(filePath string) (map[string]*auth.User, error) {
+ f, err := os.ReadFile(filePath)
+ if err != nil {
+ return nil, err
+ }
+
+ data := string(f[:])
+ users := map[string]*auth.User{}
+
+ lines := strings.Split(data, "\n")
+ var name string
+ var pass string
+ var session string
+ var loginTime time.Time
+ var lastSeen time.Time
+ procFields := 0
+ for _, l := range lines {
+ if !strings.HasPrefix(l, " ") {
+ name = l
+ procFields++
+ } else {
+ kvp := strings.Split(l, ":")
+ k := strings.TrimSpace(kvp[0])
+ v := strings.TrimSpace(kvp[1])
+ switch k {
+ case "pass":
+ pass = v
+ case "session":
+ session = v
+ case "loginTime":
+ loginTime, _ = time.Parse(timeFmt, v)
+ case "lastSeen":
+ lastSeen, _ = time.Parse(timeFmt, v)
+ }
+ procFields++
+ if procFields == 5 {
+ users[name] = &auth.User{
+ Name: name,
+ Pass: pass,
+ Session: session,
+ LoginTime: loginTime,
+ LastSeen: lastSeen,
+ }
+ procFields = 0
+ }
+ }
+ }
+ return users, nil
+}
+
+func writeDB(filePath string, users map[string]*auth.User) error {
+ f, err := os.Create(filePath)
+ if err != nil {
+ return err
+ }
+
+ defer f.Close()
+
+ for _, user := range users {
+ f.WriteString(fmt.Sprintf("%s:\n pass: %s\n session: %s\n loginTime: %s\n lastSeen: %s\n",
+ user.Name,
+ user.Pass,
+ user.Session,
+ user.LoginTime,
+ user.LastSeen));
+ }
+ f.Sync()
+ return nil
+}