package main import ( "log" "net/http" "strconv" "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) return } 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.StatusUnauthorized) } if len(username) < 2 { log.Printf("username<2") respondBadLogin() return } user, err := GetUserDataByName(ctx, username) if err != nil { log.Printf("could not get user: %v", err) 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 } log.Printf("bad hash") respondBadLogin() } func CreateGroupHandler(response http.ResponseWriter, request *http.Request) { if !isMethodAllowed(&response, request) { return } ctx := request.Context() user, err := GetUserFromToken(request.FormValue("token")) if err != nil { http.Error(response, "invalid token", http.StatusUnauthorized) 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) } func SendMessageToGroupHandler(response http.ResponseWriter, request *http.Request) { groupIdString := request.PathValue("groupid") if groupIdString == "" { http.Error(response, "no group id", http.StatusBadRequest) return } var user User var err error token := request.FormValue("token") if token == "" { http.Error(response, "no token", http.StatusBadRequest) return } if user, err = GetUserFromToken(token); err != nil { http.Error(response, "invalid token", http.StatusUnauthorized) return } content := request.FormValue("content") if content == "" { http.Error(response, "no content", http.StatusBadRequest) return } groupId, err := strconv.ParseUint(groupIdString, 10, 64) if err != nil { http.Error(response, "no such group", http.StatusBadRequest) return } groupIds, err := GetUserMemberGroupIds(request.Context(), user.Id) if err != nil { http.Error(response, "internal server error", http.StatusInternalServerError) return } isMember := false for _, id := range groupIds { if id == groupId { isMember = true break } } if isMember { var message = map[string]any{ "type": ServerResponseType.MessageFromUser, "content": content, "from": user, "time": time.Now().Unix(), } err := sendToGroup(groupId, user.Id, &message) if err != nil { http.Error(response, "internal server error", http.StatusInternalServerError) return } } }