main.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. package main
  2. import (
  3. "github.com/kataras/iris"
  4. "github.com/kataras/go-template/html"
  5. "fmt"
  6. "git.mmnx.de/Moe/databaseutils"
  7. "git.mmnx.de/Moe/usermanager"
  8. "git.mmnx.de/Moe/configutils"
  9. "golang.org/x/crypto/bcrypt"
  10. "errors"
  11. )
  12. type pageUserParams struct{
  13. HasError string
  14. Error string
  15. ReqDir string
  16. Username string
  17. Email string
  18. Admin string
  19. } // {Error: ""}
  20. func main() {
  21. conf := configutils.ReadConfig("config.json") // read config
  22. configutils.Conf = &conf // store conf globally accessible
  23. databaseutils.DBUtil = &databaseutils.DBUtils{configutils.Conf.DBUser, configutils.Conf.DBPass, configutils.Conf.DBHost, configutils.Conf.DBName, nil} // init dbutils
  24. databaseutils.DBUtil.Connect() // connect to db
  25. users := make([]usermanager.User, 0) // users list
  26. usermanager.Users = &users // store globally accessible
  27. fmt.Print("") // for not needing to remove fmt ...
  28. iris.Config.IsDevelopment = true
  29. //iris.Config.Render.Template.Gzip = true
  30. /** HELPER FUNCTION EXAMPLE **/
  31. /*config := html.DefaultConfig()
  32. config.Layout = "layouts/main.html"
  33. config.Helpers["boldme"] = func(input string) raymond.SafeString {
  34. return raymond.SafeString("<b> " + input + "</b>")
  35. }*/
  36. /** ROUTING **/
  37. iris.Static("/js", "./static/js", 1)
  38. iris.Static("/css", "./static/css", 1)
  39. iris.Static("/img", "./static/img", 1)
  40. iris.Static("/static", "./static/static", 1)
  41. iris.Post("/login", loginHandler) // login form handler
  42. iris.Post("/account", usermanager.AuthHandler, accountUpdateHandler) // Account update handler TODO implement
  43. iris.Post("/admin", usermanager.AuthHandler, adminPostHandler)
  44. // TODO register with token
  45. // TODO reset pw with token
  46. iris.Get("/", usermanager.AuthHandler, func(ctx *iris.Context) {
  47. params := usermanager.PageParams{"0", "", "", "0"}
  48. if err := ctx.Render("home_boxes.html", params); err != nil {
  49. println(err.Error())
  50. }
  51. })
  52. iris.Get("/account", usermanager.AuthHandler, func(ctx *iris.Context) { // todo outsource all those
  53. err := errors.New(""); err = nil
  54. // TODO: OUTSOURCE THIS IN FUNCTION
  55. userID := ctx.GetString("userID")
  56. usersArrayID := usermanager.SearchUser(userID)
  57. if usersArrayID == -1 { // TODO check if unneccessary (AuthHandler)
  58. err = errors.New("User not logged in WTF")
  59. ctx.Render("account_box.html", pageUserParams{"1", err.Error(), "account", "", "", "0"})
  60. return
  61. }
  62. user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list
  63. params := usermanager.PageUserParams{"0", "", "account", user.Username, "", user.Admin}
  64. if err := ctx.Render("account_box.html", params); err != nil {
  65. println(err.Error())
  66. }
  67. })
  68. iris.Get("/help", usermanager.AuthHandler, func(ctx *iris.Context) { // todo outsource all those
  69. err := errors.New(""); err = nil
  70. // TODO: OUTSOURCE THIS IN FUNCTION
  71. userID := ctx.GetString("userID")
  72. usersArrayID := usermanager.SearchUser(userID)
  73. if usersArrayID == -1 { // TODO check if unneccessary (AuthHandler)
  74. err = errors.New("User not logged in WTF")
  75. ctx.Render("account_box.html", pageUserParams{"1", err.Error(), "account", "", "", "0"})
  76. return
  77. }
  78. user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list
  79. params := usermanager.PageUserParams{"0", "", "help", user.Username, "", user.Admin}
  80. if err := ctx.Render("help_box.html", params); err != nil {
  81. println(err.Error())
  82. }
  83. })
  84. iris.Get("/admin", usermanager.AuthHandler, func(ctx *iris.Context) { // todo outsource all those
  85. err := errors.New(""); err = nil
  86. // TODO: OUTSOURCE THIS IN FUNCTION
  87. userID := ctx.GetString("userID")
  88. usersArrayID := usermanager.SearchUser(userID)
  89. if usersArrayID == -1 { // TODO check if unneccessary (AuthHandler)
  90. err = errors.New("User not logged in WTF")
  91. //ctx.Render("account_box.html", pageUserParams{"1", err.Error(), "account", "", "", "0"})
  92. fmt.Println("Errors: ", err.Error())
  93. ctx.Redirect("/")
  94. return
  95. }
  96. user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list
  97. if user.Admin != "1" { // check if user is admin // TODO check if useless / add adminAreaHandler
  98. err = errors.New("User no Admin")
  99. ctx.Redirect("/")
  100. return
  101. }
  102. tokens, err := databaseutils.DBUtil.GetRows("*", "tokens", "used", "0") // get unused tokens
  103. message := "" // string for textarea output in /admin
  104. for i, _ := range tokens {
  105. message += tokens[i][1] + "\n"
  106. }
  107. if err != nil {
  108. fmt.Println(err.Error()) // TODO: nice
  109. }
  110. params := usermanager.PageUserParamsMessage{"0", "", "admin", user.Username, "", user.Admin, message}
  111. if err := ctx.Render("admin_box.html", params); err != nil {
  112. println(err.Error())
  113. }
  114. })
  115. iris.Get("/login", func(ctx *iris.Context) {
  116. params := usermanager.PageParams{"0", "", "login", "0"}
  117. if err := ctx.Render("login.html", params); err != nil { // no error for normal login screen, struct{ Error string }{Error: ""}
  118. println(err.Error())
  119. }
  120. })
  121. iris.Get("/test", usermanager.AuthHandler, testHandler)
  122. // remove the layout for a specific route
  123. iris.Get("/nolayout", func(ctx *iris.Context) {
  124. if err := ctx.Render("page1.html", nil, iris.RenderOptions{"layout": iris.NoLayout}); err != nil {
  125. println(err.Error())
  126. }
  127. })
  128. iris.UseTemplate(html.New(html.Config{
  129. Layout: "layouts/main.html",
  130. }))
  131. /** OTHER **/
  132. iris.Listen(":8080")
  133. }
  134. func loginHandler(ctx *iris.Context) {
  135. username := ctx.FormValueString("username") // POST values from login form
  136. password := ctx.FormValueString("password")
  137. user := usermanager.User{} // new user
  138. tokenString, err := user.Login(username, password) // try to login
  139. if err != nil {
  140. ctx.Render("login.html", usermanager.PageParams{"1", err.Error(), "login", "0"})
  141. } else {
  142. ctx.SetCookieKV("token", tokenString)
  143. ctx.Redirect("/")
  144. //ctx.Render("home.html", nil) // TODO: error-alternative success (main.html)
  145. }
  146. }
  147. func accountUpdateHandler(ctx *iris.Context) {
  148. err := errors.New(""); err = nil
  149. username := ctx.FormValueString("username") // POST values
  150. password := ctx.FormValueString("password")
  151. userID := ctx.GetString("userID")
  152. usersArrayID := usermanager.SearchUser(userID)
  153. if usersArrayID == -1 { // TODO check if this can never happen (routing ...)
  154. err = errors.New("User not logged in WTF")
  155. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", "", "", "0"})
  156. return
  157. }
  158. user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list
  159. if username != "" && usermanager.SearchUserByUsername(username) != -1 && username != user.Username { // username can't be changed as there already exists a user with that name or it's the old name
  160. ctx.Render("account_box.html", usermanager.PageUserParams{"1", errors.New("Username already taken").Error(), "account", user.Username, user.Mail, user.Admin})
  161. return
  162. }
  163. needQuery := false
  164. if username != "" { // if not left empty (-> change)
  165. needQuery = true
  166. } else {
  167. username = user.Username // keep
  168. }
  169. hashedPassword := user.Password // we assumpt the user's not changing his password
  170. if password != "" { // if not left empty we change it
  171. needQuery = true
  172. hashedPassword, err = func (hashedPassword []byte, err error) (string, error) { // hash password, we use an anonymous function to convert it to string
  173. if err != nil { // should never happen
  174. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Mail, user.Admin})
  175. return "", err
  176. }
  177. return string(hashedPassword), nil
  178. }(bcrypt.GenerateFromPassword([]byte(password), 15)) // this is the actual hashing call
  179. if err != nil { // should never happen
  180. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Mail, user.Admin})
  181. return
  182. }
  183. }
  184. if !needQuery { // we don't need to update anything
  185. ctx.Render("account_box.html", usermanager.PageUserParams{"1", errors.New("nothing to update").Error(), "account", user.Username, user.Mail, user.Admin})
  186. return
  187. }
  188. (*usermanager.Users)[usermanager.SearchUser(userID)].Username = username // update values in runtime users list
  189. (*usermanager.Users)[usermanager.SearchUser(userID)].Password = hashedPassword
  190. err = (*usermanager.Users)[usermanager.SearchUser(userID)].Update() // try to update in db
  191. if err != nil { // failed to update
  192. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Mail, user.Admin})
  193. return
  194. }
  195. // TODO success notifications
  196. if err != nil { // TODO: template compatible error handling
  197. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Mail, user.Admin}) // TODO dynamic
  198. } else {
  199. ctx.Render("account_box.html", usermanager.PageUserParams{"0", "", "account", user.Username, user.Mail, user.Admin}) // TODO dynamic
  200. }
  201. }
  202. func adminPostHandler(ctx *iris.Context) {
  203. err := errors.New(""); err = nil
  204. userID := ctx.GetString("userID")
  205. usersArrayID := usermanager.SearchUser(userID)
  206. if usersArrayID == -1 { // TODO check if this can never happen (routing ...)
  207. err = errors.New("User not logged in WTF")
  208. fmt.Println(err.Error())
  209. ctx.Redirect("/")
  210. return
  211. }
  212. _ = usermanager.GenerateTokens(5) // tokens
  213. ctx.Redirect("/admin") // just redirect so that we see old+new tokens
  214. // TODO success notifications
  215. }
  216. func testHandler(ctx *iris.Context) {
  217. userID := ctx.GetString("userID")
  218. ctx.Write("Test %d", userID);
  219. }