main.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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. "git.mmnx.de/Moe/templatehelpers"
  10. "golang.org/x/crypto/bcrypt"
  11. "errors"
  12. )
  13. type pageUserParams struct{
  14. HasError string
  15. Error string
  16. ReqDir string
  17. Username string
  18. Email string
  19. Admin string
  20. } // {Error: ""}
  21. func main() {
  22. conf := configutils.ReadConfig("config.json") // read config
  23. configutils.Conf = &conf // store conf globally accessible
  24. databaseutils.DBUtil = &databaseutils.DBUtils{configutils.Conf.DBUser, configutils.Conf.DBPass, configutils.Conf.DBHost, configutils.Conf.DBName, nil} // init dbutils
  25. databaseutils.DBUtil.Connect() // connect to db
  26. users := make([]usermanager.User, 0) // users list
  27. usermanager.Users = &users // store globally accessible
  28. fmt.Print("") // for not needing to remove fmt ...
  29. iris.Config.IsDevelopment = true
  30. //iris.Config.Render.Template.Gzip = true
  31. /** HELPER FUNCTION EXAMPLE **/
  32. /*config := html.DefaultConfig()
  33. config.Layout = "layouts/main.html"
  34. config.Helpers["boldme"] = func(input string) raymond.SafeString {
  35. return raymond.SafeString("<b> " + input + "</b>")
  36. }*/
  37. /** ROUTING **/
  38. iris.UseTemplate(html.New(html.Config{
  39. Layout: "layouts/main.html",
  40. }))
  41. iris.Static("/js", "./static/js", 1)
  42. iris.Static("/css", "./static/css", 1)
  43. iris.Static("/img", "./static/img", 1)
  44. iris.Static("/static", "./static/static", 1)
  45. iris.Post("/login", loginHandler) // login form handler // TODO: outsource ?
  46. iris.Post("/register", registerHandler) // TODO outsource ?
  47. iris.Post("/account", usermanager.AuthHandler, accountUpdateHandler)
  48. iris.Post("/admin", usermanager.AuthHandler, usermanager.AdminHandler, adminPostHandler)
  49. iris.Get("/login", templateHandler) // TODO not when logged in
  50. iris.Get("/register", templateHandler) // TODO not when logged in
  51. iris.Get("/", usermanager.AuthHandler, templateHandler)
  52. iris.Get("/account", usermanager.AuthHandler, templateHandler)
  53. iris.Get("/help", usermanager.AuthHandler, templateHandler)
  54. iris.Get("/admin", usermanager.AuthHandler, usermanager.AdminHandler, templateHandler)
  55. /** OTHER **/
  56. iris.Listen(":8080")
  57. }
  58. func loginHandler(ctx *iris.Context) {
  59. username := ctx.FormValueString("username") // POST values from login form
  60. password := ctx.FormValueString("password")
  61. user := usermanager.User{} // new user
  62. tokenString, err := user.Login(username, password) // try to login
  63. if err != nil {
  64. ctx.Render("login_box.html", usermanager.PageParams{"1", err.Error(), "login", "0"})
  65. } else {
  66. ctx.SetCookieKV("token", tokenString)
  67. ctx.Redirect("/")
  68. // TODO: error-alternative success (main.html)
  69. }
  70. }
  71. func registerHandler(ctx *iris.Context) {
  72. token := ctx.FormValueString("token") // POST values from login form
  73. username := ctx.FormValueString("username")
  74. password := ctx.FormValueString("password")
  75. user := usermanager.User{} // new user
  76. tokens := usermanager.GetTokens(false) // get all unused tokens
  77. validToken := false
  78. for i, _ := range tokens {
  79. if token == tokens[i] {
  80. validToken = true
  81. break
  82. }
  83. }
  84. if !validToken { // token not valid
  85. templatehelpers.ShowError(usermanager.ERR_INVALID_TOKEN, ctx, "register")
  86. }
  87. userID := usermanager.SearchUserByUsernameInDB(username) // check if a user with that name already exists
  88. if userID != -1 {
  89. templatehelpers.ShowError(usermanager.ERR_USERNAME_TAKEN, ctx, "register")
  90. }
  91. passwordBin, _ := bcrypt.GenerateFromPassword([]byte(password), 15) // hash password
  92. err := usermanager.RegisterUserWithToken(username, string(passwordBin), token) // register user
  93. if err != nil {
  94. templatehelpers.ShowError(err.Error(), ctx, "register")
  95. return
  96. }
  97. tokenString, err := user.Login(username, password) // try to login
  98. if err != nil {
  99. templatehelpers.ShowError(err.Error(), ctx, "login")
  100. } else {
  101. ctx.SetCookieKV("token", tokenString)
  102. ctx.Redirect("/")
  103. // TODO: error-alternative success (main.html)
  104. }
  105. }
  106. func accountUpdateHandler(ctx *iris.Context) { // TODO tidy up?
  107. err := errors.New(""); err = nil
  108. username := ctx.FormValueString("username") // POST values
  109. password := ctx.FormValueString("password")
  110. userID := ctx.GetString("userID")
  111. usersArrayID := usermanager.SearchUser(userID)
  112. user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list
  113. 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
  114. ctx.Render("account_box.html", usermanager.PageUserParams{"1", errors.New("Username already taken").Error(), "account", user.Username, user.Admin, []string{"ayy", "lmao"}})
  115. return
  116. }
  117. needQuery := false
  118. if username != "" { // if not left empty (-> change)
  119. needQuery = true
  120. } else {
  121. username = user.Username // keep
  122. }
  123. hashedPassword := user.Password // we assumpt the user's not changing his password
  124. if password != "" { // if not left empty we change it
  125. needQuery = true
  126. hashedPassword, err = func (hashedPassword []byte, err error) (string, error) { // hash password, we use an anonymous function to convert it to string
  127. if err != nil { // should never happen
  128. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Admin, []string{"ayy", "lmao"}})
  129. return "", err
  130. }
  131. return string(hashedPassword), nil
  132. }(bcrypt.GenerateFromPassword([]byte(password), 15)) // this is the actual hashing call
  133. if err != nil { // should never happen
  134. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Admin, []string{"ayy", "lmao"}})
  135. return
  136. }
  137. }
  138. if !needQuery { // we don't need to update anything
  139. ctx.Render("account_box.html", usermanager.PageUserParams{"1", errors.New("nothing to update").Error(), "account", user.Username, user.Admin, []string{"ayy", "lmao"}})
  140. return
  141. }
  142. (*usermanager.Users)[usermanager.SearchUser(userID)].Username = username // update values in runtime users list
  143. (*usermanager.Users)[usermanager.SearchUser(userID)].Password = hashedPassword
  144. err = (*usermanager.Users)[usermanager.SearchUser(userID)].Update() // try to update in db
  145. if err != nil { // failed to update
  146. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Admin, []string{"ayy", "lmao"}})
  147. return
  148. }
  149. // TODO success notifications
  150. if err != nil {
  151. ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Admin, []string{"ayy", "lmao"}}) // TODO dynamic
  152. } else {
  153. ctx.Render("account_box.html", usermanager.PageUserParams{"0", "", "account", user.Username, user.Admin, []string{"ayy", "lmao"}}) // TODO dynamic
  154. }
  155. }
  156. func adminPostHandler(ctx *iris.Context) {
  157. _ = usermanager.GenerateTokens(5) // generate tokens and store in db, we don't need them now
  158. ctx.Redirect("/admin") // just redirect so that we see old+new tokens
  159. // TODO success notifications
  160. }
  161. func templateHandler(ctx *iris.Context) {
  162. var params usermanager.PageUserParams
  163. userID := ctx.GetString("userID")
  164. user, err := usermanager.GetUser(userID)
  165. if err != nil {
  166. if err.Error() != "User not logged in" {
  167. fmt.Println(err.Error())
  168. }
  169. }
  170. template := ""
  171. switch ctx.RequestPath(false) {
  172. default:
  173. template = "home"
  174. params = usermanager.PageUserParams{"0", "", template, user.Username, user.Admin, []string{}}
  175. case "/":
  176. template = "home"
  177. params = usermanager.PageUserParams{"0", "", template, user.Username, user.Admin, []string{}}
  178. case "/account":
  179. template = "account"
  180. params = usermanager.PageUserParams{"0", "", template, user.Username, user.Admin, []string{}}
  181. case "/help":
  182. template = "help"
  183. params = usermanager.PageUserParams{"0", "", template, user.Username, user.Admin, []string{}}
  184. case "/admin":
  185. template = "admin"
  186. tokens := usermanager.GetTokens(false)
  187. params = usermanager.PageUserParams{"0", "", template, user.Username, user.Admin, tokens}
  188. case "/login":
  189. template = "login"
  190. params = usermanager.PageUserParams{"0", "", template, "", "0", []string{"ayy", "lmao"}}
  191. case "/register":
  192. template = "register"
  193. params = usermanager.PageUserParams{"0", "", template, "", "0", []string{}}
  194. }
  195. // fmt.Println(ctx.RequestPath(false))
  196. // fmt.Println(template)
  197. ctx.MustRender(template + "_box.html", params);
  198. }