Moritz Schmidt преди 9 години
родител
ревизия
77687188c3
променени са 1 файла, в които са добавени 96 реда и са изтрити 20 реда
  1. 96 20
      usermanager.go

+ 96 - 20
usermanager.go

@@ -3,11 +3,12 @@ package usermanager
 import (
   "errors"
   "time"
-  "strconv"
+  "math/rand"
   "git.mmnx.de/Moe/databaseutils"
   "git.mmnx.de/Moe/configutils"
   "github.com/dgrijalva/jwt-go"
   "github.com/kataras/iris"
+  "golang.org/x/crypto/bcrypt"
   "fmt"
 )
 
@@ -23,18 +24,38 @@ const ( // Error constants
 )
 
 type User struct { // User
-  ID int
+  ID string
   Username string
   Password string
   Mail string
-  Admin bool
+  Admin string
 }
 
-type pageParams struct{
+type PageParams struct{
   HasError string
   Error string
   ReqDir string
-  } // {Error: ""} // TODO: OUTSOURCE
+  Admin string
+  } // {Error: ""} // TODO: OUTSOURCE : is outsourced here now
+
+type PageUserParams struct{
+  HasError string
+  Error string
+  ReqDir string
+  Username string
+  Email string
+  Admin string
+  } // {Error: ""}
+
+type PageUserParamsMessage struct{
+  HasError string
+  Error string
+  ReqDir string
+  Username string
+  Email string
+  Admin string
+  Message string
+  } // {Error: ""}
 
 func (user *User) Login(username string, password string) (string, error) {
   hmacSampleSecret := []byte(configutils.Conf.CryptoKey) // crypto key for JWT encryption
@@ -48,7 +69,9 @@ func (user *User) Login(username string, password string) (string, error) {
     }
   }
 
-  if password == row[2] { // if sent pw == stored pw // TODO md5/crypto
+  err = bcrypt.CompareHashAndPassword([]byte(row[2]), []byte(password))
+
+  if err == nil { // if sent' pw hash == stored pw hash
     expire, _ := time.ParseDuration("168h") // 7 days
 
     token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
@@ -61,10 +84,11 @@ func (user *User) Login(username string, password string) (string, error) {
 
     tokenString, _ := token.SignedString(hmacSampleSecret)
 
-    user.ID, _ = strconv.Atoi(row[0])
+    user.ID = row[0]
     user.Username = row[1]
+    user.Password = string(row[2])
     user.Mail = row[3]
-    user.Admin, err = strconv.ParseBool(row[4])
+    user.Admin = string(row[4])
 
     if err != nil {
       fmt.Printf("Error: ", err.Error())
@@ -72,15 +96,27 @@ func (user *User) Login(username string, password string) (string, error) {
 
     *Users = append(*Users, *user) // store user in logged-in-users list
 
-    //fmt.Printf("%v\n", *Users) // DEBUG
-
     return tokenString, nil // return tokenString (Cookie)
   } else {
     return "", errors.New(ERR_PASSWORD_MISMATCH) // wrong password
   }
 }
 
-func searchUser(userID int) int {
+func (user *User) Update() error {
+  colsVals := make([][]string, 2)
+  colsVals[0] = []string{"username", user.Username}
+  colsVals[1] = []string{"password", user.Password}
+
+  err := databaseutils.DBUtil.UpdateRow("users", "id", string(user.ID), colsVals)
+
+  if err != nil {
+    fmt.Println("ERROOR UPDATING: " + err.Error())
+  }
+
+  return nil
+}
+
+func SearchUser(userID string) int {
     for i := range *Users {
         if (*Users)[i].ID == userID {
           return i
@@ -89,9 +125,18 @@ func searchUser(userID int) int {
     return -1
 }
 
-func VerifyUserLoggedIn(tokenString string) (bool, int, error) { // TODO renew JWT from time to time preventing expiry
+func SearchUserByUsername(username string) int {
+    for i := range *Users {
+        if (*Users)[i].Username == username {
+          return i
+        }
+    }
+    return -1
+}
+
+func VerifyUserLoggedIn(tokenString string) (bool, string, error) { // TODO renew JWT from time to time preventing expiry
   if tokenString == "" { // if no tokenString("Cookie") exists fail
-    return false, -1, errors.New(ERR_INVALID_TOKEN)
+    return false, "-1", errors.New(ERR_INVALID_TOKEN)
   }
 
   hmacSampleSecret := []byte(configutils.Conf.CryptoKey) // crypto key for JWT encryption
@@ -105,18 +150,17 @@ func VerifyUserLoggedIn(tokenString string) (bool, int, error) { // TODO renew J
 
   if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { // if token is valid
     if userID, ok := claims["userid"].(string); ok { // extract userID
-      intUserID, _ := strconv.Atoi(userID) // convert to int ... god i love scripting languages
-      sliceID := searchUser(intUserID) // verify that user has a session on the server
+      sliceID := SearchUser(userID) // verify that user has a session on the server
       if sliceID != -1 { // searchUser returns -1 if there's no such user
-        return true, intUserID, nil // logged in, TODO: "0" template comparision dynamic
+        return true, userID, nil // logged in, TODO: "0" template comparision dynamic
       } else {
-        return false, -1, errors.New(ERR_SESSION_TIMED_OUT) // Session probably expired - may also be faked? TODO more checks?
+        return false, "-1", errors.New(ERR_SESSION_TIMED_OUT) // Session probably expired - may also be faked? TODO more checks?
       }
     } else {
-        return false, -1, errors.New("Unknown error") // This should never happen, prolly can't convert something in claims then..
+        return false, "-1", errors.New("Unknown error") // This should never happen, prolly can't convert something in claims then..
     }
   } else {
-    return false, -1, errors.New(ERR_INVALID_TOKEN) // Token is invalid, expired or whatever, TODO switch with ERR_SESSION_TIMED_OUT when database based session system
+    return false, "-1", errors.New(ERR_INVALID_TOKEN) // Token is invalid, expired or whatever, TODO switch with ERR_SESSION_TIMED_OUT when database based session system
   }
 }
 
@@ -133,9 +177,41 @@ func AuthHandler(ctx *iris.Context) {
   if isAuthed {
     ctx.Next() // successfully authed, next handler
   } else {
-    if err := ctx.Render("login.html", pageParams{"1", err.Error(), "login"}); err != nil {
+    if err := ctx.Render("login.html", PageParams{"1", err.Error(), "login", "0"}); err != nil {
       println(err.Error())
       } // failed to auth
 
   }
+}
+
+func GenerateTokens(numTokens int) []string {
+  const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    tokens := make([]string, 0)
+    dbTokens := make([][]string, 0)
+
+    for i := 0; i < numTokens; i++ {
+      b := make([]byte, 16) // 16 char long tokens
+      for i := range b {
+          b[i] = letterBytes[rand.Intn(len(letterBytes))]
+      }
+      tokens = append(tokens, string(b))
+      //dbTokens = append(dbTokens, []string{string(b), "0"})
+      dbTokens = [][]string{[]string{"value", string(b)}, []string{"used", "0"}}
+      err := databaseutils.DBUtil.InsertRow("tokens", dbTokens)
+      if err != nil {
+        fmt.Println(err.Error())
+        return []string{""}
+      }
+      // dbTokens[i] :=
+    }
+
+    // err := databaseutils.DBUtil.InsertRow("tokens", dbTokens)
+
+    /*if err != nil {
+      fmt.Println(err.Error())
+      return []string{""}
+    }*/
+
+    return tokens
+
 }