package main import ( "log" "net/http" "time" "golang.org/x/crypto/bcrypt" ) func isMethodAllowed(response *http.ResponseWriter, request *http.Request) bool { if request.Method != http.MethodPost { http.Error(*response, "POST only", http.StatusMethodNotAllowed) return false } return true } func RegisterHandler(response http.ResponseWriter, request *http.Request) { if !isMethodAllowed(&response, request) { return } ctx := request.Context() username := request.FormValue("username") password := request.FormValue("password") if len(username) < 2 { http.Error(response, "no or short username", http.StatusBadRequest) return } if username == "server" { http.Error(response, "only server can use such name", http.StatusBadRequest) } if len(password) < 8 { http.Error(response, "short or no password", http.StatusBadRequest) return } if _, err := GetUserDataByName(ctx, username); err == nil { http.Error(response, "user already exists", http.StatusBadRequest) return } if _, err := AddNewUser(ctx, &User{ Name: username, Password: password, IsPasswordHashed: false, }); err != nil { http.Error(response, "internal server error", http.StatusInternalServerError) log.Fatal(err) return } response.WriteHeader(http.StatusCreated) _, err := response.Write([]byte("registered")) if err != nil { http.Error(response, "internal server error", http.StatusInternalServerError) return } } func LoginHandler(response http.ResponseWriter, request *http.Request) { if !isMethodAllowed(&response, request) { return } ctx := request.Context() username := request.FormValue("username") password := request.FormValue("password") respondBadLogin := func() { http.Error(response, "bad login", http.StatusConflict) } if len(username) < 2 { respondBadLogin() return } user, err := GetUserDataByName(ctx, username) if err != nil { respondBadLogin() return } if bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) == nil { token, err := GetToken(&user) if err != nil { respondBadLogin() return } if _, err = response.Write([]byte(token)); err != nil { return } return } respondBadLogin() } func CreateGroupHandler(response http.ResponseWriter, request *http.Request) { if !isMethodAllowed(&response, request) { return } var anyAuthDone bool = false var user User ctx := request.Context() username := request.FormValue("username") password := request.FormValue("password") respondBadLogin := func() { http.Error(response, "bad login", http.StatusConflict) } if len(password) > 0 { if len(username) < 2 { http.Error(response, "no or too short nick", http.StatusBadRequest) return } tmp, err := GetUserDataByName(ctx, username) if err != nil { respondBadLogin() return } if bcrypt.CompareHashAndPassword([]byte(tmp.Password), []byte(password)) != nil { respondBadLogin() return } user = tmp anyAuthDone = true } else if token := request.FormValue("token"); len(token) > 0 { tmp, err := GetUserFromToken(token) if err != nil { respondBadLogin() return } user = tmp anyAuthDone = true } if !anyAuthDone { http.Error(response, "no login or token", http.StatusBadRequest) return } groupName := request.FormValue("name") if len(groupName) < 2 { http.Error(response, "no or too short group name", http.StatusBadRequest) return } _, err := CreateChatGroupWithoutMembers(ctx, &ChatGroup{ Name: groupName, CreatorId: user.Id, OwnerId: user.Id, CreatedAt: time.Now(), }) if err != nil { http.Error(response, "internal server error", http.StatusInternalServerError) log.Fatal(err) return } response.WriteHeader(http.StatusCreated) }