From d33df6d65a3c5df4ce9daddcf393f2c7cc7fe3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?BENEDEK=20L=C3=A1szl=C3=B3?= Date: Wed, 11 Jun 2025 19:27:51 +0200 Subject: [PATCH] check rights --- api/chat.go | 15 ++----- api/endpoints.go | 8 +++- controller/ChatController.go | 85 +++++++++++++++++++++++++++++++----- dao/postgres/ChannelDAO.go | 2 +- util/errors.go | 4 ++ 5 files changed, 89 insertions(+), 25 deletions(-) diff --git a/api/chat.go b/api/chat.go index 933e686..e76a055 100644 --- a/api/chat.go +++ b/api/chat.go @@ -23,9 +23,7 @@ var upgrader = websocket.Upgrader{ } func listAvailableChannels(c *gin.Context) { - token, _ := c.Get(SESSION_COOKIE) - - channels, err := chatController.ListAvailableChannels(token.(string)) + channels, err := chatController.ListAvailableChannels(c.GetInt(USER_ID)) if err != nil { sendError(c, err) return @@ -73,9 +71,7 @@ func getMessages(c *gin.Context) { } } - fmt.Println(from, limit) - - messages, msgErr := chatController.GetMessages(id, from, limit) + messages, msgErr := chatController.GetMessages(c.GetInt(USER_ID), id, from, limit) if msgErr != nil { sendError(c, msgErr) return @@ -88,8 +84,6 @@ func getMessages(c *gin.Context) { } func sendMessage(c *gin.Context) { - token, _ := c.Get(SESSION_COOKIE) - message := model.Message{} if err := c.Bind(&message); err != nil { c.JSON(http.StatusBadRequest, gin.H{ @@ -98,7 +92,7 @@ func sendMessage(c *gin.Context) { return } - err := chatController.SendMessage(token.(string), message.Channel, message.Content) + err := chatController.SendMessage(c.GetInt(USER_ID), message.Channel, message.Content) if err != nil { fmt.Println(err.Error()) @@ -112,7 +106,6 @@ func sendMessage(c *gin.Context) { } func subscribeToChannel(c *gin.Context) { - // TODO: check if the user has right to subscribe to the given channel id, err := strconv.Atoi(c.Param(CHANNEL_ID)) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ @@ -128,7 +121,7 @@ func subscribeToChannel(c *gin.Context) { } defer conn.Close() - messages, chanErr := chatController.SubscribeToChannel(c, id) + messages, chanErr := chatController.SubscribeToChannel(c, id, c.GetInt(USER_ID)) for { select { diff --git a/api/endpoints.go b/api/endpoints.go index bd64798..cebfb43 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -35,6 +35,11 @@ func initControlles() *util.ChatError { return err } + rightDAO, err := dao.GetRightDAO() + if err != nil { + return err + } + notifcationDAO, err := dao.GetNotificationDAO() if err != nil { return err @@ -47,7 +52,8 @@ func initControlles() *util.ChatError { sessionDAO, messageDAO, notifcationDAO, - userDAO) + userDAO, + rightDAO) return nil } diff --git a/controller/ChatController.go b/controller/ChatController.go index 982c132..f9cfcb4 100644 --- a/controller/ChatController.go +++ b/controller/ChatController.go @@ -15,33 +15,64 @@ type ChatController struct { messageDAO dao.IMessageDAO notifcationDAO dao.INotificationDAO userDAO dao.IUserDAO + rightDAO dao.IRightDAO } -func (c ChatController) ListAvailableChannels(token string) ([]model.Channel, *util.ChatError) { - userID, err := c.sessionDAO.Get(token) +func (c ChatController) ListAvailableChannels(userID int) ([]model.Channel, *util.ChatError) { + return c.channelDAO.ListAvailableChannels(userID) +} + +func (c ChatController) GetMessages(userID int, channel int, from time.Time, limit int) ([]model.Message, *util.ChatError) { + rights, err := c.rightDAO.ListUserRigths(model.User{ID: userID}) if err != nil { return nil, err } - return c.channelDAO.ListAvailableChannels(userID) -} + right, ok := rights[channel] + if !ok { + return nil, &util.ChatError{Message: "", Code: util.SEND_NOT_AUTHORIZED} + } + + switch right { + case model.RightWrite: + return nil, &util.ChatError{Message: "", Code: util.SEND_NOT_AUTHORIZED} + case model.RightReadWrite: + break + case model.RightAdmin: + break + case model.RightRead: + break + } -func (c ChatController) GetMessages(channel int, from time.Time, limit int) ([]model.Message, *util.ChatError) { return c.messageDAO.List(model.Channel{ID: channel}, from, limit) } -func (c ChatController) SendMessage(token string, channel int, content string) *util.ChatError { - sender_id, err := c.sessionDAO.Get(token) +func (c ChatController) SendMessage(userID int, channel int, content string) *util.ChatError { + user, err := c.userDAO.Read(model.User{ID: userID}) if err != nil { return err } - user, err := c.userDAO.Read(model.User{ID: sender_id}) + rights, err := c.rightDAO.ListUserRigths(user) if err != nil { return err } - // TODO: check if user has right to send message in the given channel + right, ok := rights[channel] + if !ok { + return &util.ChatError{Message: "", Code: util.SEND_NOT_AUTHORIZED} + } + + switch right { + case model.RightWrite: + break + case model.RightReadWrite: + break + case model.RightAdmin: + break + case model.RightRead: + return &util.ChatError{Message: "", Code: util.SEND_NOT_AUTHORIZED} + } message := model.Message{ SenderID: user.ID, @@ -59,8 +90,36 @@ func (c ChatController) SendMessage(token string, channel int, content string) * return c.notifcationDAO.SendMessage(message) } -func (c ChatController) SubscribeToChannel(ctx context.Context, id int) (<-chan model.Message, <-chan *util.ChatError) { - return c.notifcationDAO.SubscribeToChannel(ctx, id) +func (c ChatController) SubscribeToChannel(ctx context.Context, channel int, userID int) (<-chan model.Message, <-chan *util.ChatError) { + + rights, err := c.rightDAO.ListUserRigths(model.User{ID: userID}) + if err != nil { + errs := make(chan *util.ChatError, 1) + errs <- err + return nil, errs + } + + right, ok := rights[channel] + if !ok { + errs := make(chan *util.ChatError, 1) + errs <- &util.ChatError{Message: "", Code: util.SEND_NOT_AUTHORIZED} + return nil, errs + } + + switch right { + case model.RightWrite: + errs := make(chan *util.ChatError, 1) + errs <- &util.ChatError{Message: "", Code: util.SEND_NOT_AUTHORIZED} + return nil, errs + case model.RightReadWrite: + break + case model.RightAdmin: + break + case model.RightRead: + break + } + + return c.notifcationDAO.SubscribeToChannel(ctx, channel) } func MakeChatController( @@ -68,13 +127,15 @@ func MakeChatController( sessionDAO dao.ISessionDAO, messageDAO dao.IMessageDAO, notificationDAO dao.INotificationDAO, - userDAO dao.IUserDAO) ChatController { + userDAO dao.IUserDAO, + rightDAO dao.IRightDAO) ChatController { controller := ChatController{ channelDAO: channelDAO, sessionDAO: sessionDAO, messageDAO: messageDAO, notifcationDAO: notificationDAO, userDAO: userDAO, + rightDAO: rightDAO, } return controller } diff --git a/dao/postgres/ChannelDAO.go b/dao/postgres/ChannelDAO.go index dc3b397..0871270 100644 --- a/dao/postgres/ChannelDAO.go +++ b/dao/postgres/ChannelDAO.go @@ -60,7 +60,7 @@ func (d ChannelDAOPG) List() ([]model.Channel, *util.ChatError) { // ListAvailableChannels returns channels that the given user has access to func (d ChannelDAOPG) ListAvailableChannels(userID int) ([]model.Channel, *util.ChatError) { - rows, err := d.db.Queryx(`select "channel_id" as "id", "channel_name" as "name", "channel_description" as "description" from "user_rigths_per_channel" where "user_id" = $1 order by "id"`, userID) + rows, err := d.db.Queryx(`select "channel_id" as "id", "channel_name" as "name", "channel_description" as "description", "rights" from "user_rigths_per_channel" where "user_id" = $1 order by "id"`, userID) if err != nil { return nil, util.MakeError(err, util.DATABASE_QUERY_FAULT) } diff --git a/util/errors.go b/util/errors.go index baf9bf0..7411aa5 100644 --- a/util/errors.go +++ b/util/errors.go @@ -18,6 +18,8 @@ const ( USERNAME_TOO_SHORT PASSWORD_TOO_SHORT PASSWORDS_DONT_MATCH + SEND_NOT_AUTHORIZED + READ_NOT_AUTHORIZED NOT_LOGGED_IN ) @@ -31,6 +33,8 @@ var codeToMessage = map[ChatErrorCode]string{ USERNAME_TOO_SHORT: "username is too short", PASSWORD_TOO_SHORT: "password is too short", PASSWORDS_DONT_MATCH: "passwords do not match", + SEND_NOT_AUTHORIZED: "not authorized to send messages in this channel", + READ_NOT_AUTHORIZED: "not authorized to read messages in this channel", NOT_LOGGED_IN: "not logged in", }