aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auth/auth.go18
-rw-r--r--indentalUserDB/indentalUserDB.go189
-rw-r--r--renderer/renderer.go4
-rw-r--r--router/router.go16
-rw-r--r--userDB.ndtl5
5 files changed, 220 insertions, 12 deletions
diff --git a/auth/auth.go b/auth/auth.go
index 17b6ad3..b8ce571 100644
--- a/auth/auth.go
+++ b/auth/auth.go
@@ -2,12 +2,26 @@ package auth
import (
//nilfm.cc/git/goldbug/cookie
+ "time"
)
+type User struct {
+ Name string
+ Pass string
+ Session string
+ LoginTime time.Time
+ LastSeen time.Time
+
+ Data map[string]interface{}
+}
+
type UserStore interface {
- InitiateSession(user string, sessionId string) error
- ValidateUser(user string, password string, sessionId string) (bool, error)
+ InitiateSession(user string, password string) (string, error)
+ ValidateUser(user string, sessionId string) (bool, error)
EndSession(user string) error
+ AddUser(user string, password string) error
+ DeleteUser(user string) error
+ ChangePassword(user string, oldPassword string, newPassword string) error
}
func Login(user string, password string, userStore UserStore) (string, error) {
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
+}
diff --git a/renderer/renderer.go b/renderer/renderer.go
index 79860cc..031986e 100644
--- a/renderer/renderer.go
+++ b/renderer/renderer.go
@@ -7,8 +7,8 @@ import (
"encoding/xml"
)
-func Template(t string) http.Handler {
- tmpl := template.Must(template.ParseFiles(t))
+func Template(t ...string) http.Handler {
+ tmpl := template.Must(template.ParseFiles(t...))
handlerFunc := func(w http.ResponseWriter, req *http.Request) {
tmpl.Execute(w, req)
diff --git a/router/router.go b/router/router.go
index d984ad0..f0ba53b 100644
--- a/router/router.go
+++ b/router/router.go
@@ -10,6 +10,7 @@ import (
"path"
"os"
"errors"
+ "context"
)
type Router struct {
@@ -24,7 +25,6 @@ type Router struct {
StaticPaths map[string]string
}
-
type Route struct {
path *regexp.Regexp
handlerMap map[string]http.Handler
@@ -125,7 +125,7 @@ func (self *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
for method, handler := range r.handlerMap {
if method == req.Method {
- /* Parse the form and add the params to it */
+ /* Parse the form and add the params to the context */
req.ParseForm()
ProcessParams(req, params)
/* handle the request! */
@@ -142,9 +142,7 @@ func (self *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
*******************/
func ProcessParams(req *http.Request, params map[string]string) {
- for key, value := range params {
- req.Form.Add(key, value)
- }
+ *req = *req.WithContext(context.WithValue(req.Context(), "params", params))
}
func (self *Route) Match(r *http.Request) map[string]string {
@@ -165,8 +163,10 @@ func (self *Route) Match(r *http.Request) map[string]string {
func (self *Router) ErrorPage(w http.ResponseWriter, req *http.Request, code int, errMsg string) {
w.WriteHeader(code)
- req.ParseForm()
- req.Form.Add("ErrorCode", strconv.Itoa(code))
- req.Form.Add("ErrorMessage", errMsg)
+ params := map[string]string{
+ "ErrorCode": strconv.Itoa(code),
+ "ErrorMessage": errMsg,
+ }
+ ProcessParams(req, params)
self.Fallback.Execute(w, req)
}
diff --git a/userDB.ndtl b/userDB.ndtl
new file mode 100644
index 0000000..0bf3576
--- /dev/null
+++ b/userDB.ndtl
@@ -0,0 +1,5 @@
+nilix:
+ pass: $2a$10$.Y59TRn/.qBjT8KwleyrBePsC34EuPzrRlQr014bjEKuLoUCWDMtO
+ session: eMOrLtCvjo_DTV_NqDLicJOugUALtiCIjdvPuzY@O!TOAAzunOs!jnCvCv#sQFxR
+ loginTime: 1969-12-31 17:00:00 -0700 MST
+ lastSeen: 1969-12-31 17:00:00 -0700 MST