Initial commit: Эфир мессенджер
This commit is contained in:
41
internal/api/handlers/admin.go
Normal file
41
internal/api/handlers/admin.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"messenger/internal/api/responses"
|
||||
"messenger/internal/service"
|
||||
"net/http"
|
||||
|
||||
//"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type AdminHandler struct {
|
||||
adminService *service.AdminService
|
||||
}
|
||||
|
||||
func NewAdminHandler(adminService *service.AdminService) *AdminHandler {
|
||||
return &AdminHandler{
|
||||
adminService: adminService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AdminHandler) DeleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
// userID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
// if err != nil {
|
||||
// responses.BadRequest(w, "invalid user id")
|
||||
// return
|
||||
// }
|
||||
|
||||
// TODO: Реализовать удаление пользователя
|
||||
responses.Success(w, http.StatusOK, map[string]string{"message": "user deleted"})
|
||||
}
|
||||
|
||||
func (h *AdminHandler) DeleteMessage(w http.ResponseWriter, r *http.Request) {
|
||||
// messageID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
// if err != nil {
|
||||
// responses.BadRequest(w, "invalid message id")
|
||||
// return
|
||||
// }
|
||||
|
||||
// TODO: Реализовать удаление сообщения
|
||||
responses.Success(w, http.StatusOK, map[string]string{"message": "message deleted"})
|
||||
}
|
||||
80
internal/api/handlers/auth.go
Normal file
80
internal/api/handlers/auth.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"messenger/internal/api/middleware"
|
||||
"messenger/internal/api/responses"
|
||||
"messenger/internal/service"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
authService *service.AuthService
|
||||
}
|
||||
|
||||
func NewAuthHandler(authService *service.AuthService) *AuthHandler {
|
||||
return &AuthHandler{authService: authService}
|
||||
}
|
||||
|
||||
type RegisterRequest struct {
|
||||
Login string `json:"login"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type LoginRequest struct {
|
||||
Login string `json:"login"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type AuthResponse struct {
|
||||
Token string `json:"token"`
|
||||
User interface{} `json:"user"`
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Register(w http.ResponseWriter, r *http.Request) {
|
||||
var req RegisterRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
responses.BadRequest(w, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
user, token, err := h.authService.Register(r.Context(), req.Login, req.Password)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusCreated, AuthResponse{
|
||||
Token: token,
|
||||
User: user.ToSafe(),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) {
|
||||
var req LoginRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
responses.BadRequest(w, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
user, token, err := h.authService.Login(r.Context(), req.Login, req.Password)
|
||||
if err != nil {
|
||||
responses.Unauthorized(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, AuthResponse{
|
||||
Token: token,
|
||||
User: user.ToSafe(),
|
||||
})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) GetMe(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, user.ToSafe())
|
||||
}
|
||||
228
internal/api/handlers/chats.go
Normal file
228
internal/api/handlers/chats.go
Normal file
@@ -0,0 +1,228 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"messenger/internal/api/middleware"
|
||||
"messenger/internal/api/responses"
|
||||
"messenger/internal/models"
|
||||
"messenger/internal/service"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type ChatHandler struct {
|
||||
chatService *service.ChatService
|
||||
userService *service.UserService
|
||||
}
|
||||
|
||||
func NewChatHandler(chatService *service.ChatService, userService *service.UserService) *ChatHandler {
|
||||
return &ChatHandler{
|
||||
chatService: chatService,
|
||||
userService: userService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ChatHandler) CreatePrivateChat(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
var req models.CreatePrivateChatRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
responses.BadRequest(w, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
if req.TargetLogin == "" {
|
||||
responses.BadRequest(w, "target_login is required")
|
||||
return
|
||||
}
|
||||
|
||||
// Находим целевого пользователя по логину
|
||||
targetUser, err := h.userService.GetUserByLogin(r.Context(), req.TargetLogin)
|
||||
if err != nil {
|
||||
responses.NotFound(w, "target user not found")
|
||||
return
|
||||
}
|
||||
|
||||
if targetUser == nil {
|
||||
responses.NotFound(w, "target user not found")
|
||||
return
|
||||
}
|
||||
|
||||
// Создаем приватный чат
|
||||
chat, err := h.chatService.CreatePrivateChat(r.Context(), user.ID, targetUser.ID)
|
||||
if err != nil {
|
||||
responses.InternalServerError(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusCreated, chat)
|
||||
}
|
||||
|
||||
func (h *ChatHandler) CreateGroupChat(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
var req models.CreateGroupChatRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
responses.BadRequest(w, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
chat, err := h.chatService.CreateGroupChat(r.Context(), user.ID, req.Title, req.MemberLogins)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusCreated, chat)
|
||||
}
|
||||
|
||||
func (h *ChatHandler) GetMyChats(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
chats, err := h.chatService.GetUserChatsWithDetails(r.Context(), user.ID)
|
||||
if err != nil {
|
||||
responses.InternalServerError(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, chats)
|
||||
}
|
||||
|
||||
func (h *ChatHandler) GetChatByID(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
chatID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid chat id")
|
||||
return
|
||||
}
|
||||
|
||||
chat, err := h.chatService.GetChatByID(r.Context(), chatID, user.ID)
|
||||
if err != nil {
|
||||
responses.NotFound(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, chat)
|
||||
}
|
||||
|
||||
func (h *ChatHandler) GetChatMembers(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
chatID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid chat id")
|
||||
return
|
||||
}
|
||||
|
||||
members, err := h.chatService.GetChatMembers(r.Context(), chatID, user.ID)
|
||||
if err != nil {
|
||||
responses.Forbidden(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, members)
|
||||
}
|
||||
|
||||
func (h *ChatHandler) AddMembers(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
chatID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid chat id")
|
||||
return
|
||||
}
|
||||
|
||||
var req models.AddMembersRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
responses.BadRequest(w, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.chatService.AddMembers(r.Context(), chatID, user.ID, req.UserLogins); err != nil {
|
||||
responses.BadRequest(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, map[string]string{"message": "members added"})
|
||||
}
|
||||
|
||||
func (h *ChatHandler) RemoveMember(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
chatID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid chat id")
|
||||
return
|
||||
}
|
||||
|
||||
memberID, err := strconv.ParseInt(chi.URLParam(r, "user_id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid member id")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.chatService.RemoveMember(r.Context(), chatID, user.ID, memberID); err != nil {
|
||||
responses.BadRequest(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, map[string]string{"message": "member removed"})
|
||||
}
|
||||
|
||||
func (h *ChatHandler) UpdateChatTitle(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
chatID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid chat id")
|
||||
return
|
||||
}
|
||||
|
||||
var req models.UpdateChatTitleRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
responses.BadRequest(w, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.chatService.UpdateChatTitle(r.Context(), chatID, user.ID, req.Title); err != nil {
|
||||
responses.BadRequest(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, map[string]string{"message": "chat title updated"})
|
||||
}
|
||||
82
internal/api/handlers/files.go
Normal file
82
internal/api/handlers/files.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"messenger/internal/api/middleware"
|
||||
"messenger/internal/api/responses"
|
||||
"messenger/internal/service"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type FileHandler struct {
|
||||
fileService *service.FileService
|
||||
}
|
||||
|
||||
func NewFileHandler(fileService *service.FileService) *FileHandler {
|
||||
return &FileHandler{
|
||||
fileService: fileService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *FileHandler) UploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
chatID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid chat id")
|
||||
return
|
||||
}
|
||||
|
||||
// Parse multipart form (20 MB max)
|
||||
if err := r.ParseMultipartForm(20 << 20); err != nil {
|
||||
responses.BadRequest(w, "failed to parse form")
|
||||
return
|
||||
}
|
||||
|
||||
file, header, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "file is required")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
attachment, err := h.fileService.UploadFile(r.Context(), chatID, user.ID, header)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, attachment)
|
||||
}
|
||||
|
||||
func (h *FileHandler) DownloadFile(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
attachmentID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid attachment id")
|
||||
return
|
||||
}
|
||||
|
||||
fileName, file, mimeType, err := h.fileService.DownloadFile(r.Context(), attachmentID, user.ID)
|
||||
if err != nil {
|
||||
responses.NotFound(w, err.Error())
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
w.Header().Set("Content-Type", mimeType)
|
||||
w.Header().Set("Content-Disposition", "attachment; filename="+strconv.Quote(fileName))
|
||||
http.ServeContent(w, r, fileName, time.Now(), file)
|
||||
}
|
||||
83
internal/api/handlers/messages.go
Normal file
83
internal/api/handlers/messages.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
//"encoding/json"
|
||||
"messenger/internal/api/middleware"
|
||||
"messenger/internal/api/responses"
|
||||
//"messenger/internal/models"
|
||||
"messenger/internal/service"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type MessageHandler struct {
|
||||
messageService *service.MessageService
|
||||
chatService *service.ChatService
|
||||
}
|
||||
|
||||
func NewMessageHandler(messageService *service.MessageService, chatService *service.ChatService) *MessageHandler {
|
||||
return &MessageHandler{
|
||||
messageService: messageService,
|
||||
chatService: chatService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *MessageHandler) GetMessages(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
chatID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid chat id")
|
||||
return
|
||||
}
|
||||
|
||||
limit := 50
|
||||
if l := r.URL.Query().Get("limit"); l != "" {
|
||||
if parsed, err := strconv.Atoi(l); err == nil && parsed > 0 && parsed <= 100 {
|
||||
limit = parsed
|
||||
}
|
||||
}
|
||||
|
||||
var before time.Time
|
||||
if b := r.URL.Query().Get("before"); b != "" {
|
||||
if parsed, err := time.Parse(time.RFC3339, b); err == nil {
|
||||
before = parsed
|
||||
}
|
||||
}
|
||||
|
||||
messages, err := h.messageService.GetChatHistory(r.Context(), chatID, user.ID, limit, before)
|
||||
if err != nil {
|
||||
responses.InternalServerError(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, messages)
|
||||
}
|
||||
|
||||
func (h *MessageHandler) MarkAsRead(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
messageID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
|
||||
if err != nil {
|
||||
responses.BadRequest(w, "invalid message id")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.messageService.MarkMessageAsRead(r.Context(), messageID, user.ID); err != nil {
|
||||
responses.InternalServerError(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, map[string]string{"message": "marked as read"})
|
||||
}
|
||||
103
internal/api/handlers/users.go
Normal file
103
internal/api/handlers/users.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"messenger/internal/api/middleware"
|
||||
"messenger/internal/api/responses"
|
||||
"messenger/internal/models"
|
||||
"messenger/internal/service"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type UserHandler struct {
|
||||
userService *service.UserService
|
||||
}
|
||||
|
||||
func NewUserHandler(userService *service.UserService) *UserHandler {
|
||||
return &UserHandler{userService: userService}
|
||||
}
|
||||
|
||||
type UpdateProfileRequest struct {
|
||||
DisplayName *string `json:"display_name,omitempty"`
|
||||
Bio *string `json:"bio,omitempty"`
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetProfile(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
profile, err := h.userService.GetProfile(r.Context(), user.ID)
|
||||
if err != nil {
|
||||
responses.NotFound(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, profile)
|
||||
}
|
||||
|
||||
func (h *UserHandler) UpdateProfile(w http.ResponseWriter, r *http.Request) {
|
||||
user := middleware.GetUserFromContext(r.Context())
|
||||
if user == nil {
|
||||
responses.Unauthorized(w, "user not found")
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateProfileRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
responses.BadRequest(w, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.userService.UpdateProfile(r.Context(), user.ID, req.DisplayName, req.Bio); err != nil {
|
||||
responses.BadRequest(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, map[string]string{"message": "profile updated"})
|
||||
}
|
||||
|
||||
func (h *UserHandler) SearchUsers(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query().Get("q")
|
||||
if query == "" {
|
||||
responses.BadRequest(w, "search query required")
|
||||
return
|
||||
}
|
||||
|
||||
limit := 20
|
||||
if l := r.URL.Query().Get("limit"); l != "" {
|
||||
if parsed, err := strconv.Atoi(l); err == nil && parsed > 0 && parsed <= 100 {
|
||||
limit = parsed
|
||||
}
|
||||
}
|
||||
|
||||
users, err := h.userService.SearchUsers(r.Context(), query, limit)
|
||||
if err != nil {
|
||||
responses.InternalServerError(w, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
responses.Success(w, http.StatusOK, users)
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetUserByID(w http.ResponseWriter, r *http.Request) {
|
||||
// Реализация с chi.URLParam будет в main.go
|
||||
// Пока заглушка
|
||||
responses.Success(w, http.StatusOK, nil)
|
||||
}
|
||||
|
||||
// GetUserByLoginFromContext - метод для получения пользователя по логину (используется в других хендлерах)
|
||||
func (h *UserHandler) GetUserByLogin(ctx context.Context, login string) (*models.SafeUser, error) {
|
||||
user, err := h.userService.GetUserByLogin(ctx, login)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return user.ToSafe(), nil
|
||||
}
|
||||
58
internal/api/handlers/websocket.go
Normal file
58
internal/api/handlers/websocket.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
gorillaWS "github.com/gorilla/websocket"
|
||||
|
||||
"messenger/internal/pkg/logger"
|
||||
"messenger/internal/service"
|
||||
ws "messenger/internal/websocket"
|
||||
)
|
||||
|
||||
var upgrader = gorillaWS.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
type WebSocketHandler struct {
|
||||
hub *ws.Hub
|
||||
authService *service.AuthService
|
||||
}
|
||||
|
||||
func NewWebSocketHandler(hub *ws.Hub, authService *service.AuthService) *WebSocketHandler {
|
||||
return &WebSocketHandler{
|
||||
hub: hub,
|
||||
authService: authService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *WebSocketHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request) {
|
||||
token := r.URL.Query().Get("token")
|
||||
if token == "" {
|
||||
http.Error(w, "missing token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := h.authService.ValidateToken(token)
|
||||
if err != nil {
|
||||
logger.Error("WebSocket auth failed", "error", err)
|
||||
http.Error(w, "invalid token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("WebSocket connecting", "user_id", user.ID, "login", user.Login)
|
||||
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
logger.Error("WebSocket upgrade failed", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
client := ws.NewClient(h.hub, conn, user)
|
||||
h.hub.GetRegisterChan() <- client
|
||||
|
||||
go client.WritePump()
|
||||
client.ReadPump()
|
||||
}
|
||||
Reference in New Issue
Block a user