Moritz Schmidt 9 years ago
parent
commit
b28fb1d28d
1 changed files with 127 additions and 12 deletions
  1. 127 12
      usermanager.go

+ 127 - 12
usermanager.go

@@ -7,6 +7,7 @@ import (
   "strconv"
   "strconv"
   "git.mmnx.de/Moe/databaseutils"
   "git.mmnx.de/Moe/databaseutils"
   "git.mmnx.de/Moe/configutils"
   "git.mmnx.de/Moe/configutils"
+  "git.mmnx.de/Moe/templatehelpers"
   "github.com/dgrijalva/jwt-go"
   "github.com/dgrijalva/jwt-go"
   "github.com/kataras/iris"
   "github.com/kataras/iris"
   "golang.org/x/crypto/bcrypt"
   "golang.org/x/crypto/bcrypt"
@@ -23,6 +24,8 @@ const ( // Error constants
   ERR_SESSION_TIMED_OUT = "ERR_SESSION_TIMED_OUT"
   ERR_SESSION_TIMED_OUT = "ERR_SESSION_TIMED_OUT"
   ERR_INVALID_TOKEN = "ERR_INVALID_TOKEN"
   ERR_INVALID_TOKEN = "ERR_INVALID_TOKEN"
   ERR_USERNAME_TAKEN = "ERR_USERNAME_TAKEN"
   ERR_USERNAME_TAKEN = "ERR_USERNAME_TAKEN"
+  ERR_INVALID_PARAM = "ERR_INVALID_PARAM"
+  ERR_NO_CHANGES = "ERR_NO_CHANGES"
 )
 )
 
 
 type User struct { // User
 type User struct { // User
@@ -104,6 +107,33 @@ func (user *User) Login(username string, password string) (string, error) {
   }
   }
 }
 }
 
 
+func (user *User) Logout(userID string) {
+  userArrayID := SearchUser(userID) // get logged in users list index
+
+  user.ID = "" // empty
+  user.Username = ""
+  user.Password = ""
+  user.Admin = ""
+  user.TokenUsed = ""
+
+  (*Users)[userArrayID] = *user
+  return
+}
+
+func LogoutHandler(ctx *iris.Context) {
+  userID := ctx.GetString("userID")
+
+  user, err := GetUserFromDB(userID)
+  if err != nil {
+    templatehelpers.ShowError(err.Error(), ctx, "account")
+    return
+  }
+
+  user.Logout(userID);
+  ctx.SetCookieKV("token", "")
+  ctx.Redirect("/")
+}
+
 func (user *User) Update() error {
 func (user *User) Update() error {
   colsVals := make([][]string, 2)
   colsVals := make([][]string, 2)
   colsVals[0] = []string{"username", user.Username}
   colsVals[0] = []string{"username", user.Username}
@@ -119,21 +149,21 @@ func (user *User) Update() error {
 }
 }
 
 
 func SearchUser(userID string) int {
 func SearchUser(userID string) int {
-    for i := range *Users {
-        if (*Users)[i].ID == userID {
-          return i
-        }
+  for i := range *Users {
+    if (*Users)[i].ID == userID {
+      return i
     }
     }
-    return -1
+  }
+  return -1
 }
 }
 
 
 func SearchUserByUsername(username string) int {
 func SearchUserByUsername(username string) int {
-    for i := range *Users {
-        if (*Users)[i].Username == username {
-          return i
-        }
+  for i := range *Users {
+    if (*Users)[i].Username == username {
+      return i
     }
     }
-    return -1
+  }
+  return -1
 }
 }
 
 
 func VerifyUserLoggedIn(tokenString string) (bool, string, error) { // TODO renew JWT from time to time preventing expiry
 func VerifyUserLoggedIn(tokenString string) (bool, string, error) { // TODO renew JWT from time to time preventing expiry
@@ -173,13 +203,13 @@ func AuthHandler(ctx *iris.Context) {
   ctx.Set("userID", userID) // save userID for in-context use
   ctx.Set("userID", userID) // save userID for in-context use
 
 
   if err != nil {
   if err != nil {
-    fmt.Println("Auth error: ", err.Error())
+    // fmt.Println("Auth error: ", err.Error())
   }
   }
 
 
   if isAuthed {
   if isAuthed {
     ctx.Next() // successfully authed, next handler
     ctx.Next() // successfully authed, next handler
   } else {
   } else {
-    if err := ctx.Render("login_box.html", PageParams{"1", err.Error(), "login", "0"}); err != nil {
+    if err := ctx.Render("login_box.html", PageUserParams{"1", err.Error(), "login", "", "0", []string{}}); err != nil {
       println(err.Error())
       println(err.Error())
     } // failed to auth
     } // failed to auth
 
 
@@ -252,6 +282,16 @@ func GetUser(userID string) (User, error) {
   return user, nil
   return user, nil
 }
 }
 
 
+func GetUserFromDB(userID string) (User, error) {
+  row, err := databaseutils.DBUtil.GetRow("*", "users", "id", userID) // get user from db
+
+  if err != nil {
+    return User{}, err
+  }
+
+  return User{row[0], row[1], string(row[2]), string(row[3]), string(row[4])}, nil
+}
+
 func SearchUserByUsernameInDB(username string) int {
 func SearchUserByUsernameInDB(username string) int {
   user, err := databaseutils.DBUtil.GetRow("*", "users", "username", username)
   user, err := databaseutils.DBUtil.GetRow("*", "users", "username", username)
   if err != nil {
   if err != nil {
@@ -269,6 +309,20 @@ func SearchUserByUsernameInDB(username string) int {
   return userID
   return userID
 }
 }
 
 
+func SearchUserByTokenInDB(token string) (int, error) {
+  user, err := databaseutils.DBUtil.GetRowsDoubleCond("users", "tokens", "`token-id` = `tokens`.`id`", "`tokens`.`value` = '" + token + "'")
+  if err != nil {
+    return -1, err
+  }
+
+  userID, err := strconv.Atoi(user[0][0])
+  if err != nil {
+    return -1, err
+  }
+
+  return userID, nil
+}
+
 func RegisterUserWithToken(username string, password string, token string) error {
 func RegisterUserWithToken(username string, password string, token string) error {
   tokenID := databaseutils.DBUtil.GetString("id", "tokens", "value", token)
   tokenID := databaseutils.DBUtil.GetString("id", "tokens", "value", token)
 
 
@@ -285,5 +339,66 @@ func RegisterUserWithToken(username string, password string, token string) error
     return err
     return err
   }
   }
 
 
+  return nil
+}
+
+func VerifyUserUpdate(username string, password string, userID string) error {
+  tmpUser, err := GetUserFromDB(userID)
+  if err != nil {
+    return err
+  }
+
+  if SearchUserByUsernameInDB(username) != -1 && username != tmpUser.Username { // username can't be changed as there already exists a user with that name or it's the old name
+    return errors.New(ERR_USERNAME_TAKEN)
+  }
+
+  if username == "" { // if not left empty change
+    return errors.New(ERR_INVALID_PARAM)
+  }
+
+  if password == "" { // if not left empty we change it
+    return errors.New(ERR_INVALID_PARAM)
+  }
+
+  return nil
+}
+
+// Processes the update of an user, username and password are the new "wanted" values, can also be empty string ("")
+func UserUpdateProcessor(username string, password string, userID string) error {
+  user, err := GetUserFromDB(userID)
+  hashedPassword := ""
+  if err != nil {
+    return err
+  }
+
+  if username == "" {
+    username = user.Username
+  }
+
+  if password == "" {
+    password = user.Password
+    hashedPassword = user.Password // we dont need to / _can't_ re-hash the hash
+  }
+
+  if err = VerifyUserUpdate(username, password, userID); err != nil {
+    return err
+  }
+
+  if hashedPassword == "" {
+    hashedPassword, err = func (hashedPassword []byte, err error) (string, error) { // hash password, we use an anonymous function to convert int to string
+        if err != nil { // should never happen
+          return "", err
+        }
+        return string(hashedPassword), nil
+      }(bcrypt.GenerateFromPassword([]byte(password), 15)) // this is the actual hashing call
+  }
+
+  user.Username = username
+  user.Password = hashedPassword
+
+  if err = user.Update(); err != nil {
+    return err
+  }
+
   return nil
   return nil
 }
 }