add nested template support in renderer and IndentalUserDB UserStore implementation
This commit is contained in:
parent
b17fa798b7
commit
8179aee263
5 changed files with 220 additions and 12 deletions
18
auth/auth.go
18
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) {
|
||||
|
|
189
indentalUserDB/indentalUserDB.go
Normal file
189
indentalUserDB/indentalUserDB.go
Normal file
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
5
userDB.ndtl
Normal file
5
userDB.ndtl
Normal file
|
@ -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
|
Loading…
Reference in a new issue