package main import ( "encoding/json" "flag" "fmt" "log" "net/http" "strconv" "github.com/boltdb/bolt" "github.com/gorilla/sessions" ) // Functions implemented: signup, login with username and password, logout, the user cannot login again if he/she is already logged in (except admin) // cannot signup for username already used, check how many users logged in (INDEX.html) // User for testing: username -> hello, password -> world // Admin user (hard-coded): admin var store = sessions.NewCookieStore([]byte("secret-key")) var db *bolt.DB var Online_users int = 0 type Status struct { NumberLoggedIn int } type LogoutCheck struct { LoggedOut bool } type SignupNewName struct { Success bool } type LoginCheck struct { Success bool Repeat bool } func loginHandler(rw http.ResponseWriter, req *http.Request) { if req.Method == "GET" { username := req.FormValue("username") password := req.FormValue("password") log.Println("The typed username is:" + username) log.Println("The typed password is:" + password) var typed LoginCheck db.Update(func(tx *bolt.Tx) error { users := tx.Bucket([]byte("Users")) password_database_byte := users.Get([]byte(username)) password_database := string(password_database_byte) if password_database_byte == nil { log.Println("Error: The username is not valid!") typed.Success = false typed.Repeat = false } else { if password == password_database { log.Println("Password is correct") session, err := store.Get(req, username) if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) return nil } if session.Values["auth"] == true && username != "admin" { typed.Success = false typed.Repeat = true log.Println("Alert: " + username + " has already loggged in, please logged in with a different account!") } else { session.Values["auth"] = true err = session.Save(req, rw) if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) return nil } Online_users = Online_users + 1 typed.Success = true typed.Repeat = false log.Println("Logged in") } } else { typed.Success = false typed.Repeat = false log.Println("WRONG password!!") } } send_message, _ := json.Marshal(typed) rw.Write(send_message) return nil }) } } func logoutHandler(rw http.ResponseWriter, req *http.Request) { log.Println("Logout button is clicked!") username := req.FormValue("username") log.Println(username + " wants to log out") session, err := store.Get(req, username) if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) return } session.Values["auth"] = nil err = session.Save(req, rw) if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) return } var result LogoutCheck result.LoggedOut = true send_message, _ := json.Marshal(result) rw.Write(send_message) log.Println("Pass log-out message to html") Online_users = Online_users - 1 log.Println("Logged out successfully") } func checkloginHandler(rw http.ResponseWriter, req *http.Request) { log.Println("Check button is clicked") log.Println("Logged in users: " + strconv.Itoa(Online_users)) var status Status status.NumberLoggedIn = Online_users send_message, _ := json.Marshal(status) rw.Write(send_message) } func signupHandler(rw http.ResponseWriter, req *http.Request) { username := req.FormValue("username") password := req.FormValue("password") log.Println("Create an account that username is:" + username) log.Println("Create an account that password is:" + password) db.Update(func(tx *bolt.Tx) error { users := tx.Bucket([]byte("Users")) exist_user := users.Get([]byte(username)) if exist_user != nil { log.Println("Error: The username has already been used!") rw.Write([]byte("fail")) } else { err := users.Put([]byte(username), []byte(password)) if err != nil { return fmt.Errorf("create user: %s", err) } rw.Write([]byte("success")) } return nil }) } func main() { portPointer := flag.String("port", "8000", "An integer") flag.Parse() log.Println("Port Number: " + *portPointer) httpFileServer := http.FileServer(http.Dir("./files")) http.Handle("/", httpFileServer) var err1 error db, err1 = bolt.Open("my.db", 0600, nil) if err1 != nil { log.Fatal(err1) } else { log.Println("database opened") } defer db.Close() db.Update(func(tx *bolt.Tx) error { users, err2 := tx.CreateBucketIfNotExists([]byte("Users")) if err2 != nil { return fmt.Errorf("create bucket: %s", err2) } err3 := users.Put([]byte("admin"), []byte("admin")) if err3 != nil { return fmt.Errorf("create admin: %s", err3) } return nil }) http.HandleFunc("/login", loginHandler) http.HandleFunc("/logout", logoutHandler) http.HandleFunc("/checklogin", checkloginHandler) http.HandleFunc("/signup", signupHandler) log.Printf("Listening http://localhost:%s\n", *portPointer) if error := http.ListenAndServe(":"+*portPointer, nil); error != nil { log.Printf("Error: %s\n", error) } }