package main import ( "github.com/kataras/iris" "github.com/kataras/go-template/html" "fmt" "git.mmnx.de/Moe/databaseutils" "git.mmnx.de/Moe/usermanager" "git.mmnx.de/Moe/configutils" "golang.org/x/crypto/bcrypt" "errors" ) type pageUserParams struct{ HasError string Error string ReqDir string Username string Email string Admin string } // {Error: ""} func main() { conf := configutils.ReadConfig("config.json") // read config configutils.Conf = &conf // store conf globally accessible databaseutils.DBUtil = &databaseutils.DBUtils{configutils.Conf.DBUser, configutils.Conf.DBPass, configutils.Conf.DBHost, configutils.Conf.DBName, nil} // init dbutils databaseutils.DBUtil.Connect() // connect to db users := make([]usermanager.User, 0) // users list usermanager.Users = &users // store globally accessible fmt.Print("") // for not needing to remove fmt ... iris.Config.IsDevelopment = true //iris.Config.Render.Template.Gzip = true /** HELPER FUNCTION EXAMPLE **/ /*config := html.DefaultConfig() config.Layout = "layouts/main.html" config.Helpers["boldme"] = func(input string) raymond.SafeString { return raymond.SafeString(" " + input + "") }*/ /** ROUTING **/ iris.Static("/js", "./static/js", 1) iris.Static("/css", "./static/css", 1) iris.Static("/img", "./static/img", 1) iris.Static("/static", "./static/static", 1) iris.Post("/login", loginHandler) // login form handler iris.Post("/account", usermanager.AuthHandler, accountUpdateHandler) // Account update handler TODO implement iris.Post("/admin", usermanager.AuthHandler, adminPostHandler) // TODO register with token // TODO reset pw with token iris.Get("/", usermanager.AuthHandler, func(ctx *iris.Context) { params := usermanager.PageParams{"0", "", "", "0"} if err := ctx.Render("home_boxes.html", params); err != nil { println(err.Error()) } }) iris.Get("/account", usermanager.AuthHandler, func(ctx *iris.Context) { // todo outsource all those err := errors.New(""); err = nil // TODO: OUTSOURCE THIS IN FUNCTION userID := ctx.GetString("userID") usersArrayID := usermanager.SearchUser(userID) if usersArrayID == -1 { // TODO check if unneccessary (AuthHandler) err = errors.New("User not logged in WTF") ctx.Render("account_box.html", pageUserParams{"1", err.Error(), "account", "", "", "0"}) return } user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list params := usermanager.PageUserParams{"0", "", "account", user.Username, "", user.Admin} if err := ctx.Render("account_box.html", params); err != nil { println(err.Error()) } }) iris.Get("/help", usermanager.AuthHandler, func(ctx *iris.Context) { // todo outsource all those err := errors.New(""); err = nil // TODO: OUTSOURCE THIS IN FUNCTION userID := ctx.GetString("userID") usersArrayID := usermanager.SearchUser(userID) if usersArrayID == -1 { // TODO check if unneccessary (AuthHandler) err = errors.New("User not logged in WTF") ctx.Render("account_box.html", pageUserParams{"1", err.Error(), "account", "", "", "0"}) return } user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list params := usermanager.PageUserParams{"0", "", "help", user.Username, "", user.Admin} if err := ctx.Render("help_box.html", params); err != nil { println(err.Error()) } }) iris.Get("/admin", usermanager.AuthHandler, func(ctx *iris.Context) { // todo outsource all those err := errors.New(""); err = nil // TODO: OUTSOURCE THIS IN FUNCTION userID := ctx.GetString("userID") usersArrayID := usermanager.SearchUser(userID) if usersArrayID == -1 { // TODO check if unneccessary (AuthHandler) err = errors.New("User not logged in WTF") //ctx.Render("account_box.html", pageUserParams{"1", err.Error(), "account", "", "", "0"}) fmt.Println("Errors: ", err.Error()) ctx.Redirect("/") return } user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list if user.Admin != "1" { // check if user is admin // TODO check if useless / add adminAreaHandler err = errors.New("User no Admin") ctx.Redirect("/") return } tokens, err := databaseutils.DBUtil.GetRows("*", "tokens", "used", "0") // get unused tokens message := "" // string for textarea output in /admin for i, _ := range tokens { message += tokens[i][1] + "\n" } if err != nil { fmt.Println(err.Error()) // TODO: nice } params := usermanager.PageUserParamsMessage{"0", "", "admin", user.Username, "", user.Admin, message} if err := ctx.Render("admin_box.html", params); err != nil { println(err.Error()) } }) iris.Get("/login", func(ctx *iris.Context) { params := usermanager.PageParams{"0", "", "login", "0"} if err := ctx.Render("login.html", params); err != nil { // no error for normal login screen, struct{ Error string }{Error: ""} println(err.Error()) } }) iris.Get("/test", usermanager.AuthHandler, testHandler) // remove the layout for a specific route iris.Get("/nolayout", func(ctx *iris.Context) { if err := ctx.Render("page1.html", nil, iris.RenderOptions{"layout": iris.NoLayout}); err != nil { println(err.Error()) } }) iris.UseTemplate(html.New(html.Config{ Layout: "layouts/main.html", })) /** OTHER **/ iris.Listen(":8080") } func loginHandler(ctx *iris.Context) { username := ctx.FormValueString("username") // POST values from login form password := ctx.FormValueString("password") user := usermanager.User{} // new user tokenString, err := user.Login(username, password) // try to login if err != nil { ctx.Render("login.html", usermanager.PageParams{"1", err.Error(), "login", "0"}) } else { ctx.SetCookieKV("token", tokenString) ctx.Redirect("/") //ctx.Render("home.html", nil) // TODO: error-alternative success (main.html) } } func accountUpdateHandler(ctx *iris.Context) { err := errors.New(""); err = nil username := ctx.FormValueString("username") // POST values password := ctx.FormValueString("password") userID := ctx.GetString("userID") usersArrayID := usermanager.SearchUser(userID) if usersArrayID == -1 { // TODO check if this can never happen (routing ...) err = errors.New("User not logged in WTF") ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", "", "", "0"}) return } user := (*usermanager.Users)[usersArrayID] // user must be logged in to do this -> get from users list 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 ctx.Render("account_box.html", usermanager.PageUserParams{"1", errors.New("Username already taken").Error(), "account", user.Username, user.Mail, user.Admin}) return } needQuery := false if username != "" { // if not left empty (-> change) needQuery = true } else { username = user.Username // keep } hashedPassword := user.Password // we assumpt the user's not changing his password if password != "" { // if not left empty we change it needQuery = true hashedPassword, err = func (hashedPassword []byte, err error) (string, error) { // hash password, we use an anonymous function to convert it to string if err != nil { // should never happen ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Mail, user.Admin}) return "", err } return string(hashedPassword), nil }(bcrypt.GenerateFromPassword([]byte(password), 15)) // this is the actual hashing call if err != nil { // should never happen ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Mail, user.Admin}) return } } if !needQuery { // we don't need to update anything ctx.Render("account_box.html", usermanager.PageUserParams{"1", errors.New("nothing to update").Error(), "account", user.Username, user.Mail, user.Admin}) return } (*usermanager.Users)[usermanager.SearchUser(userID)].Username = username // update values in runtime users list (*usermanager.Users)[usermanager.SearchUser(userID)].Password = hashedPassword err = (*usermanager.Users)[usermanager.SearchUser(userID)].Update() // try to update in db if err != nil { // failed to update ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Mail, user.Admin}) return } // TODO success notifications if err != nil { // TODO: template compatible error handling ctx.Render("account_box.html", usermanager.PageUserParams{"1", err.Error(), "account", user.Username, user.Mail, user.Admin}) // TODO dynamic } else { ctx.Render("account_box.html", usermanager.PageUserParams{"0", "", "account", user.Username, user.Mail, user.Admin}) // TODO dynamic } } func adminPostHandler(ctx *iris.Context) { err := errors.New(""); err = nil userID := ctx.GetString("userID") usersArrayID := usermanager.SearchUser(userID) if usersArrayID == -1 { // TODO check if this can never happen (routing ...) err = errors.New("User not logged in WTF") fmt.Println(err.Error()) ctx.Redirect("/") return } _ = usermanager.GenerateTokens(5) // tokens ctx.Redirect("/admin") // just redirect so that we see old+new tokens // TODO success notifications } func testHandler(ctx *iris.Context) { userID := ctx.GetString("userID") ctx.Write("Test %d", userID); }