From ec736aecd9eb1599472dae1ee9d3b16243143b35 Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Wed, 3 Apr 2019 15:05:23 +0200 Subject: [PATCH] fix(messaging): fix stutters, Init(), errors --- messaging/internal/service/attachment.go | 20 ++- messaging/internal/service/channel.go | 157 +++++++++++----------- messaging/internal/service/error.go | 10 +- messaging/internal/service/events.go | 6 +- messaging/internal/service/message.go | 122 +++++++++-------- messaging/internal/service/permissions.go | 56 ++++---- messaging/internal/service/service.go | 39 +++--- 7 files changed, 216 insertions(+), 194 deletions(-) diff --git a/messaging/internal/service/attachment.go b/messaging/internal/service/attachment.go index 3d136274c..608adb2d4 100644 --- a/messaging/internal/service/attachment.go +++ b/messaging/internal/service/attachment.go @@ -33,8 +33,8 @@ type ( ctx context.Context store store.Store - usr systemService.UserService - evl EventService + user systemService.UserService + event EventService attachment repository.AttachmentRepository message repository.MessageRepository @@ -50,12 +50,10 @@ type ( } ) -func Attachment(store store.Store) AttachmentService { +func Attachment(ctx context.Context, store store.Store) AttachmentService { return (&attachment{ store: store, - usr: systemService.DefaultUser, - evl: DefaultEvent, - }).With(context.Background()) + }).With(ctx) } func (svc *attachment) With(ctx context.Context) AttachmentService { @@ -65,8 +63,8 @@ func (svc *attachment) With(ctx context.Context) AttachmentService { ctx: ctx, store: svc.store, - usr: systemService.User(ctx), - evl: svc.evl.With(ctx), + user: systemService.User(ctx), + event: Event(ctx), attachment: repository.Attachment(ctx, db), message: repository.Message(ctx, db), @@ -154,7 +152,7 @@ func (svc *attachment) Create(name string, size int64, fh io.ReadSeeker, channel // Create the first message, doing this directly with repository to circumvent // message service constraints - if msg, err = svc.message.CreateMessage(msg); err != nil { + if msg, err = svc.message.Create(msg); err != nil { return } @@ -291,12 +289,12 @@ func (svc *attachment) processImage(original io.ReadSeeker, att *types.Attachmen func (svc *attachment) sendEvent(msg *types.Message) (err error) { if msg.User == nil { // @todo pull user from cache - if msg.User, err = svc.usr.FindByID(msg.UserID); err != nil { + if msg.User, err = svc.user.FindByID(msg.UserID); err != nil { return } } - return svc.evl.Message(msg) + return svc.event.Message(msg) } var _ AttachmentService = &attachment{} diff --git a/messaging/internal/service/channel.go b/messaging/internal/service/channel.go index 7afd10e08..a4d129cc9 100644 --- a/messaging/internal/service/channel.go +++ b/messaging/internal/service/channel.go @@ -19,10 +19,10 @@ type ( db db ctx context.Context - usr systemService.UserService + user systemService.UserService - evl EventService - prm PermissionsService + event EventService + perms PermissionsService channel repository.ChannelRepository cmember repository.ChannelMemberRepository @@ -67,12 +67,8 @@ const ( settingsChannelTopicLength = 200 ) -func Channel() ChannelService { - return (&channel{ - usr: systemService.DefaultUser, - evl: DefaultEvent, - prm: DefaultPermissions, - }).With(context.Background()) +func Channel(ctx context.Context) ChannelService { + return (&channel{}).With(ctx) } func (svc *channel) With(ctx context.Context) ChannelService { @@ -81,9 +77,9 @@ func (svc *channel) With(ctx context.Context) ChannelService { db: db, ctx: ctx, - usr: systemService.User(ctx), - evl: svc.evl.With(ctx), - prm: svc.prm.With(ctx), + user: systemService.User(ctx), + event: Event(ctx), + perms: Permissions(ctx), channel: repository.Channel(ctx, db), cmember: repository.ChannelMember(ctx, db), @@ -96,15 +92,15 @@ func (svc *channel) With(ctx context.Context) ChannelService { } func (svc *channel) FindByID(ID uint64) (ch *types.Channel, err error) { - ch, err = svc.channel.FindChannelByID(ID) + ch, err = svc.channel.FindByID(ID) if err != nil { return } else if err = svc.preloadExtras(types.ChannelSet{ch}); err != nil { return } - if !svc.prm.CanReadChannel(ch) { - return nil, errors.New("not allowed to access channel") + if !svc.perms.CanReadChannel(ch) { + return nil, errors.WithStack(ErrNoPermissions) } return @@ -114,14 +110,14 @@ func (svc *channel) Find(filter *types.ChannelFilter) (cc types.ChannelSet, err filter.CurrentUserID = auth.GetIdentityFromContext(svc.ctx).Identity() return cc, svc.db.Transaction(func() (err error) { - if cc, err = svc.channel.FindChannels(filter); err != nil { + if cc, err = svc.channel.Find(filter); err != nil { return } else if err = svc.preloadExtras(cc); err != nil { return } cc, err = cc.Filter(func(c *types.Channel) (b bool, e error) { - return svc.prm.CanReadChannel(c), nil + return svc.perms.CanReadChannel(c), nil }) return @@ -191,7 +187,7 @@ func (svc *channel) FindMembers(channelID uint64) (out types.ChannelMemberSet, e return err } - if uu, err := svc.usr.Find(nil); err != nil { + if uu, err := svc.user.Find(nil); err != nil { return err } else { return out.Walk(func(member *types.ChannelMember) error { @@ -219,20 +215,20 @@ func (svc *channel) Create(in *types.Channel) (out *types.Channel, err error) { // Group already exists so let's just return it return nil } else if out != nil && !out.CanObserve { - return errors.New("not allowed to create this channel due to permission settings") + return errors.WithStack(ErrNoPermissions) } } - if in.Type == types.ChannelTypePublic && !svc.prm.CanCreatePublicChannel() { - return errors.New("not allowed to create public channels") + if in.Type == types.ChannelTypePublic && !svc.perms.CanCreatePublicChannel() { + return errors.WithStack(ErrNoPermissions) } - if in.Type == types.ChannelTypePrivate && !svc.prm.CanCreatePrivateChannel() { - return errors.New("not allowed to create private channels") + if in.Type == types.ChannelTypePrivate && !svc.perms.CanCreatePrivateChannel() { + return errors.WithStack(ErrNoPermissions) } - if in.Type == types.ChannelTypeGroup && !svc.prm.CanCreateGroupChannel() { - return errors.New("not allowed to create group channels") + if in.Type == types.ChannelTypeGroup && !svc.perms.CanCreateGroupChannel() { + return errors.WithStack(ErrNoPermissions) } if len(in.Name) == 0 && in.Type != types.ChannelTypeGroup { @@ -257,7 +253,7 @@ func (svc *channel) Create(in *types.Channel) (out *types.Channel, err error) { } // Save the channel - if out, err = svc.channel.CreateChannel(out); err != nil { + if out, err = svc.channel.Create(out); err != nil { return } @@ -271,7 +267,7 @@ func (svc *channel) Create(in *types.Channel) (out *types.Channel, err error) { } // Subscribe all members - return svc.evl.Join(m.UserID, out.ID) + return svc.event.Join(m.UserID, out.ID) }) if err != nil { @@ -325,7 +321,7 @@ func (svc *channel) buildMemberSet(owner uint64, members ...uint64) (mm types.Ch } func (svc *channel) checkGroupExistance(mm types.ChannelMemberSet) (out *types.Channel, err error) { - if out, err = svc.channel.FindChannelByMemberSet(mm.AllMemberIDs()...); err == repository.ErrChannelNotFound { + if out, err = svc.channel.FindByMemberSet(mm.AllMemberIDs()...); err == repository.ErrChannelNotFound { return nil, nil } else if out != nil && err == nil { err = svc.preloadExtras(types.ChannelSet{out}) @@ -342,21 +338,21 @@ func (svc *channel) Update(in *types.Channel) (ch *types.Channel, err error) { return } - if !svc.prm.CanUpdateChannel(ch) { - return errors.New("not allowed to update this channel") + if !svc.perms.CanUpdateChannel(ch) { + return errors.WithStack(ErrNoPermissions) } if in.Type.IsValid() && ch.Type != in.Type { - if in.Type == types.ChannelTypePublic && !svc.prm.CanCreatePublicChannel() { - return errors.New("not allowed to change type of this channel to **public**") + if in.Type == types.ChannelTypePublic && !svc.perms.CanCreatePublicChannel() { + return errors.WithStack(ErrNoPermissions) } - if in.Type == types.ChannelTypePrivate && !svc.prm.CanCreatePrivateChannel() { - return errors.New("not allowed to change type of this channel to **private**") + if in.Type == types.ChannelTypePrivate && !svc.perms.CanCreatePrivateChannel() { + return errors.WithStack(ErrNoPermissions) } - if in.Type == types.ChannelTypeGroup && !svc.prm.CanCreateGroupChannel() { - return errors.New("not allowed to change type of this channel to **group**") + if in.Type == types.ChannelTypeGroup && !svc.perms.CanCreateGroupChannel() { + return errors.WithStack(ErrNoPermissions) } changed = true @@ -394,7 +390,7 @@ func (svc *channel) Update(in *types.Channel) (ch *types.Channel, err error) { return nil } // Save the updated channel - if ch, err = svc.channel.UpdateChannel(in); err != nil { + if ch, err = svc.channel.Update(in); err != nil { return } @@ -412,8 +408,8 @@ func (svc *channel) Delete(ID uint64) (ch *types.Channel, err error) { return } - if !svc.prm.CanDeleteChannel(ch) { - return errors.New("not allowed to delete this channel") + if !svc.perms.CanDeleteChannel(ch) { + return errors.WithStack(ErrNoPermissions) } if ch.DeletedAt != nil { @@ -425,7 +421,7 @@ func (svc *channel) Delete(ID uint64) (ch *types.Channel, err error) { svc.scheduleSystemMessage(ch, "<@%d> deleted this channel", userID) - if err = svc.channel.DeleteChannelByID(ID); err != nil { + if err = svc.channel.DeleteByID(ID); err != nil { return } else { // Set deletedAt timestamp so that our clients can react properly... @@ -446,8 +442,8 @@ func (svc *channel) Undelete(ID uint64) (ch *types.Channel, err error) { return } - if !svc.prm.CanUndeleteChannel(ch) { - return errors.New("not allowed to undelete this channel") + if !svc.perms.CanUndeleteChannel(ch) { + return errors.WithStack(ErrNoPermissions) } if ch.DeletedAt == nil { @@ -456,7 +452,7 @@ func (svc *channel) Undelete(ID uint64) (ch *types.Channel, err error) { svc.scheduleSystemMessage(ch, "<@%d> undeleted this channel", userID) - if err = svc.channel.UndeleteChannelByID(ID); err != nil { + if err = svc.channel.UndeleteByID(ID); err != nil { return } else { // Remove deletedAt timestamp so that our clients can react properly... @@ -505,8 +501,8 @@ func (svc *channel) Archive(ID uint64) (ch *types.Channel, err error) { return } - if !svc.prm.CanArchiveChannel(ch) { - return errors.New("not allowed to archive this channel") + if !svc.perms.CanArchiveChannel(ch) { + return errors.WithStack(ErrNoPermissions) } if ch.ArchivedAt != nil { @@ -515,7 +511,7 @@ func (svc *channel) Archive(ID uint64) (ch *types.Channel, err error) { svc.scheduleSystemMessage(ch, "<@%d> archived this channel", userID) - if err = svc.channel.ArchiveChannelByID(ID); err != nil { + if err = svc.channel.ArchiveByID(ID); err != nil { return } else { // Set archivedAt timestamp so that our clients can react properly... @@ -535,15 +531,15 @@ func (svc *channel) Unarchive(ID uint64) (ch *types.Channel, err error) { return } - if !svc.prm.CanUnarchiveChannel(ch) { - return errors.New("not allowed to unarchive this channel") + if !svc.perms.CanUnarchiveChannel(ch) { + return errors.WithStack(ErrNoPermissions) } if ch.ArchivedAt == nil { return errors.New("channel not archived") } - if err = svc.channel.UnarchiveChannelByID(ID); err != nil { + if err = svc.channel.UnarchiveByID(ID); err != nil { return } else { // Unset archivedAt timestamp so that our clients can react properly... @@ -574,8 +570,8 @@ func (svc *channel) InviteUser(channelID uint64, memberIDs ...uint64) (out types return nil, errors.New("adding members to a group is not currently supported") } - if !svc.prm.CanManageChannelMembers(ch) { - return nil, errors.New("not allowed to invite members") + if !svc.perms.CanManageChannelMembers(ch) { + return nil, errors.WithStack(ErrNoPermissions) } return out, svc.db.Transaction(func() (err error) { @@ -583,7 +579,7 @@ func (svc *channel) InviteUser(channelID uint64, memberIDs ...uint64) (out types return } - users, err := svc.usr.Find(nil) + users, err := svc.user.Find(nil) if err != nil { return err } @@ -642,7 +638,7 @@ func (svc *channel) AddMember(channelID uint64, memberIDs ...uint64) (out types. return } - users, err := svc.usr.Find(nil) + users, err := svc.user.Find(nil) if err != nil { return err } @@ -665,10 +661,10 @@ func (svc *channel) AddMember(channelID uint64, memberIDs ...uint64) (out types. } } - if memberID == userID && !svc.prm.CanJoinChannel(ch) { - return errors.New("not allowed to join") - } else if memberID != userID && !svc.prm.CanManageChannelMembers(ch) { - return errors.New("not allowed to add channel members") + if memberID == userID && !svc.perms.CanJoinChannel(ch) { + return errors.WithStack(ErrNoPermissions) + } else if memberID != userID && !svc.perms.CanManageChannelMembers(ch) { + return errors.WithStack(ErrNoPermissions) } if !exists { @@ -692,7 +688,7 @@ func (svc *channel) AddMember(channelID uint64, memberIDs ...uint64) (out types. member, err = svc.cmember.Create(member) } - svc.evl.Join(memberID, channelID) + svc.event.Join(memberID, channelID) if err != nil { return err @@ -736,10 +732,11 @@ func (svc *channel) DeleteMember(channelID uint64, memberIDs ...uint64) (err err continue } - if memberID == userID && !svc.prm.CanJoinChannel(ch) { - return errors.New("not allowed to leave") - } else if !svc.prm.CanManageChannelMembers(ch) { - return errors.New("not allowed to remove channel members") + if memberID == userID && !svc.perms.CanJoinChannel(ch) { + return errors.WithStack(ErrNoPermissions) + } + if !svc.perms.CanManageChannelMembers(ch) { + return errors.WithStack(ErrNoPermissions) } if userID == memberID { @@ -752,7 +749,7 @@ func (svc *channel) DeleteMember(channelID uint64, memberIDs ...uint64) (err err return err } - svc.evl.Part(memberID, channelID) + svc.event.Part(memberID, channelID) } return svc.flushSystemMessages() @@ -782,10 +779,10 @@ func (svc *channel) flushSystemMessages() (err error) { }() return svc.sysmsgs.Walk(func(msg *types.Message) error { - if msg, err = svc.message.CreateMessage(msg); err != nil { + if msg, err = svc.message.Create(msg); err != nil { return err } else { - return svc.evl.Message(msg) + return svc.event.Message(msg) } }) } @@ -810,7 +807,7 @@ func (svc *channel) sendChannelEvent(ch *types.Channel) (err error) { return } - if err = svc.evl.Channel(ch); err != nil { + if err = svc.event.Channel(ch); err != nil { return } @@ -818,22 +815,22 @@ func (svc *channel) sendChannelEvent(ch *types.Channel) (err error) { } func (svc *channel) setPermissionFlags(ch *types.Channel) (err error) { - ch.CanJoin = svc.prm.CanJoinChannel(ch) - ch.CanPart = svc.prm.CanLeaveChannel(ch) - ch.CanObserve = svc.prm.CanReadChannel(ch) - ch.CanSendMessages = svc.prm.CanSendMessage(ch) + ch.CanJoin = svc.perms.CanJoinChannel(ch) + ch.CanPart = svc.perms.CanLeaveChannel(ch) + ch.CanObserve = svc.perms.CanReadChannel(ch) + ch.CanSendMessages = svc.perms.CanSendMessage(ch) - ch.CanDeleteMessages = svc.prm.CanDeleteMessages(ch) - ch.CanDeleteOwnMessages = svc.prm.CanDeleteOwnMessages(ch) - ch.CanUpdateMessages = svc.prm.CanUpdateMessages(ch) - ch.CanUpdateOwnMessages = svc.prm.CanUpdateOwnMessages(ch) - ch.CanChangeMembers = svc.prm.CanManageChannelMembers(ch) + ch.CanDeleteMessages = svc.perms.CanDeleteMessages(ch) + ch.CanDeleteOwnMessages = svc.perms.CanDeleteOwnMessages(ch) + ch.CanUpdateMessages = svc.perms.CanUpdateMessages(ch) + ch.CanUpdateOwnMessages = svc.perms.CanUpdateOwnMessages(ch) + ch.CanChangeMembers = svc.perms.CanManageChannelMembers(ch) - ch.CanUpdate = svc.prm.CanUpdateChannel(ch) - ch.CanArchive = svc.prm.CanArchiveChannel(ch) - ch.CanUnarchive = svc.prm.CanUnarchiveChannel(ch) - ch.CanDelete = svc.prm.CanDeleteChannel(ch) - ch.CanUndelete = svc.prm.CanUndeleteChannel(ch) + ch.CanUpdate = svc.perms.CanUpdateChannel(ch) + ch.CanArchive = svc.perms.CanArchiveChannel(ch) + ch.CanUnarchive = svc.perms.CanUnarchiveChannel(ch) + ch.CanDelete = svc.perms.CanDeleteChannel(ch) + ch.CanUndelete = svc.perms.CanUndeleteChannel(ch) return nil } diff --git a/messaging/internal/service/error.go b/messaging/internal/service/error.go index bae0374e6..c4385ef95 100644 --- a/messaging/internal/service/error.go +++ b/messaging/internal/service/error.go @@ -1,9 +1,13 @@ package service type ( - serviceError string + readableError string ) -func (e serviceError) Error() string { - return "crust.messaging.service." + string(e) +func (e readableError) Error() string { + return string(e) } + +const ( + ErrNoPermissions readableError = "You don't have permissions for this operation" +) diff --git a/messaging/internal/service/events.go b/messaging/internal/service/events.go index 38b203322..199b41924 100644 --- a/messaging/internal/service/events.go +++ b/messaging/internal/service/events.go @@ -27,14 +27,14 @@ type ( ) // Event sends sends events back to all (or specific) subscribers -func Event() EventService { - return (&event{events: repository.Events()}).With(context.Background()) +func Event(ctx context.Context) EventService { + return (&event{}).With(ctx) } func (svc *event) With(ctx context.Context) EventService { return &event{ ctx: ctx, - events: svc.events, + events: repository.Events(), } } diff --git a/messaging/internal/service/message.go b/messaging/internal/service/message.go index 608e334a1..6bfc3fdc2 100644 --- a/messaging/internal/service/message.go +++ b/messaging/internal/service/message.go @@ -28,9 +28,9 @@ type ( mflag repository.MessageFlagRepository mentions repository.MentionRepository - usr systemService.UserService - evl EventService - prm PermissionsService + usr systemService.UserService + event EventService + prm PermissionsService } MessageService interface { @@ -40,6 +40,7 @@ type ( FindThreads(filter *types.MessageFilter) (types.MessageSet, error) Create(messages *types.Message) (*types.Message, error) + Update(messages *types.Message) (*types.Message, error) React(messageID uint64, reaction string) error @@ -53,7 +54,7 @@ type ( Bookmark(messageID uint64) error RemoveBookmark(messageID uint64) error - Delete(ID uint64) error + Delete(messageID uint64) error } ) @@ -66,12 +67,8 @@ var ( mentionsFinder = regexp.MustCompile(mentionRE) ) -func Message() MessageService { - return &message{ - usr: systemService.DefaultUser, - evl: DefaultEvent, - prm: DefaultPermissions, - } +func Message(ctx context.Context) MessageService { + return (&message{}).With(ctx) } func (svc *message) With(ctx context.Context) MessageService { @@ -80,9 +77,9 @@ func (svc *message) With(ctx context.Context) MessageService { db: db, ctx: ctx, - usr: systemService.User(ctx), - evl: svc.evl.With(ctx), - prm: svc.prm.With(ctx), + usr: systemService.User(ctx), + event: Event(ctx), + prm: Permissions(ctx), attachment: repository.Attachment(ctx, db), channel: repository.Channel(ctx, db), @@ -101,11 +98,11 @@ func (svc *message) Find(filter *types.MessageFilter) (mm types.MessageSet, err if ch, err := svc.findChannelByID(filter.ChannelID); err != nil { return nil, err } else if !svc.prm.CanReadChannel(ch) { - return nil, errors.New("not allowed to access channel") + return nil, errors.WithStack(ErrNoPermissions) } } - mm, err = svc.message.FindMessages(filter) + mm, err = svc.message.Find(filter) if err != nil { return nil, err } @@ -120,7 +117,7 @@ func (svc *message) FindThreads(filter *types.MessageFilter) (mm types.MessageSe if ch, err := svc.findChannelByID(filter.ChannelID); err != nil { return nil, err } else if !svc.prm.CanReadChannel(ch) { - return nil, errors.New("not allowed to access channel") + return nil, errors.WithStack(ErrNoPermissions) } } @@ -146,9 +143,10 @@ func (svc *message) Create(in *types.Message) (message *types.Message, err error return nil, errors.Errorf("message length (%d characters) too long (max: %d)", mlen, settingsMessageBodyLength) } - var currentUserID = auth.GetIdentityFromContext(svc.ctx).Identity() - - in.UserID = currentUserID + // keep pre-existing user id set + if in.UserID == 0 { + in.UserID = auth.GetIdentityFromContext(svc.ctx).Identity() + } return message, svc.db.Transaction(func() (err error) { // Broadcast queue @@ -161,7 +159,7 @@ func (svc *message) Create(in *types.Message) (message *types.Message, err error for replyTo > 0 { // Find original message - original, err = svc.message.FindMessageByID(in.ReplyTo) + original, err = svc.message.FindByID(in.ReplyTo) if err != nil { return } @@ -193,13 +191,16 @@ func (svc *message) Create(in *types.Message) (message *types.Message, err error return errors.New("channelID missing") } else if ch, err = svc.findChannelByID(in.ChannelID); err != nil { return - } else if in.ReplyTo > 0 && !svc.prm.CanReplyMessage(ch) { - return errors.New("not allowed to reply in this channel") - } else if !svc.prm.CanSendMessage(ch) { - return errors.New("not allowed to send messages in this channel") } - if message, err = svc.message.CreateMessage(in); err != nil { + if in.ReplyTo > 0 && !svc.prm.CanReplyMessage(ch) { + return errors.WithStack(ErrNoPermissions) + } + if !svc.prm.CanSendMessage(ch) { + return errors.WithStack(ErrNoPermissions) + } + + if message, err = svc.message.Create(in); err != nil { return } @@ -225,7 +226,8 @@ func (svc *message) Update(in *types.Message) (message *types.Message, err error if mlen == 0 { return nil, errors.Errorf("refusing to update message without contents") - } else if settingsMessageBodyLength > 0 && mlen > settingsMessageBodyLength { + } + if settingsMessageBodyLength > 0 && mlen > settingsMessageBodyLength { return nil, errors.Errorf("message length (%d characters) too long (max: %d)", mlen, settingsMessageBodyLength) } @@ -237,10 +239,11 @@ func (svc *message) Update(in *types.Message) (message *types.Message, err error if ch, err = svc.findChannelByID(in.ChannelID); err != nil { return err } else if !svc.prm.CanReadChannel(ch) { - return errors.New("not allowed to access channel") + return errors.WithStack(ErrNoPermissions) } - message, err = svc.message.FindMessageByID(in.ID) + message, err = svc.message.FindByID(in.ID) + if err != nil { return errors.Wrap(err, "could not load message for editing") } @@ -251,15 +254,15 @@ func (svc *message) Update(in *types.Message) (message *types.Message, err error } if message.UserID == currentUserID && !svc.prm.CanUpdateOwnMessages(ch) { - return errors.New("not allowed to edit your messages in this channel") + return errors.WithStack(ErrNoPermissions) } else if message.UserID != currentUserID && !svc.prm.CanUpdateMessages(ch) { - return errors.New("not allowed to edit messages in this channel") + return errors.WithStack(ErrNoPermissions) } // Allow message content to be changed message.Message = in.Message - if message, err = svc.message.UpdateMessage(message); err != nil { + if message, err = svc.message.Update(message); err != nil { return err } @@ -271,7 +274,7 @@ func (svc *message) Update(in *types.Message) (message *types.Message, err error }) } -func (svc *message) Delete(ID uint64) error { +func (svc *message) Delete(messageID uint64) error { var currentUserID = auth.GetIdentityFromContext(svc.ctx).Identity() _ = currentUserID @@ -282,7 +285,7 @@ func (svc *message) Delete(ID uint64) error { var deletedMsg, original *types.Message var ch *types.Channel - deletedMsg, err = svc.message.FindMessageByID(ID) + deletedMsg, err = svc.message.FindByID(messageID) if err != nil { return err } @@ -290,21 +293,23 @@ func (svc *message) Delete(ID uint64) error { if ch, err = svc.findChannelByID(deletedMsg.ChannelID); err != nil { return err } else if !svc.prm.CanReadChannel(ch) { - return errors.New("not allowed to access channel") + return errors.WithStack(ErrNoPermissions) } if deletedMsg.ReplyTo > 0 { - original, err = svc.message.FindMessageByID(deletedMsg.ReplyTo) + original, err = svc.message.FindByID(deletedMsg.ReplyTo) if err != nil { return err } - if ch, err = svc.channel.FindChannelByID(original.ChannelID); err != nil { + if ch, err = svc.channel.FindByID(original.ChannelID); err != nil { return - } else if original.UserID == currentUserID && !svc.prm.CanUpdateOwnMessages(ch) { - return errors.New("not allowed to delete your messages in this channel") - } else if !svc.prm.CanUpdateMessages(ch) { - return errors.New("not allowed to delete messages in this channel") + } + if original.UserID == currentUserID && !svc.prm.CanUpdateOwnMessages(ch) { + return errors.WithStack(ErrNoPermissions) + } + if !svc.prm.CanUpdateMessages(ch) { + return errors.WithStack(ErrNoPermissions) } // This is a reply to another message, decrease reply counter on the original, on struct and in the @@ -321,7 +326,7 @@ func (svc *message) Delete(ID uint64) error { bq = append(bq, original) } - if err = svc.message.DeleteMessageByID(ID); err != nil { + if err = svc.message.DeleteByID(messageID); err != nil { return } @@ -332,7 +337,7 @@ func (svc *message) Delete(ID uint64) error { deletedMsg.DeletedAt = timeNowPtr() } - if err = svc.updateMentions(ID, nil); err != nil { + if err = svc.updateMentions(messageID, nil); err != nil { return } @@ -352,14 +357,14 @@ func (svc *message) MarkAsRead(channelID, threadID, lastReadMessageID uint64) (c if ch, err = svc.findChannelByID(channelID); err != nil { return err } else if !svc.prm.CanReadChannel(ch) { - return errors.New("not allowed to access channel") + return errors.WithStack(ErrNoPermissions) } else if !ch.IsValid() { return errors.New("invalid channel") } if threadID > 0 { // Validate thread - if thread, err = svc.message.FindMessageByID(threadID); err != nil { + if thread, err = svc.message.FindByID(threadID); err != nil { return errors.Wrap(err, "unable to verify thread") } else if !thread.IsValid() { return errors.New("invalid thread") @@ -368,7 +373,7 @@ func (svc *message) MarkAsRead(channelID, threadID, lastReadMessageID uint64) (c if lastReadMessageID > 0 { // Validate thread - if lastMessage, err = svc.message.FindMessageByID(lastReadMessageID); err != nil { + if lastMessage, err = svc.message.FindByID(lastReadMessageID); err != nil { return errors.Wrap(err, "unable to verify last message") } else if !lastMessage.IsValid() { return errors.New("invalid message") @@ -445,22 +450,26 @@ func (svc *message) flag(messageID uint64, flag string, remove bool) error { if f.ID == 0 && remove { // Skip removing, flag does not exists return nil - } else if f.ID > 0 && !remove { + } + if f.ID > 0 && !remove { // Skip adding, flag already exists return nil - } else if err != nil && err != repository.ErrMessageFlagNotFound { + } + if err != nil && err != repository.ErrMessageFlagNotFound { // Other errors, exit return } - if msg, err = svc.message.FindMessageByID(messageID); err != nil { + if msg, err = svc.message.FindByID(messageID); err != nil { return } else if ch, err = svc.findChannelByID(msg.ChannelID); err != nil { return - } else if !svc.prm.CanReadChannel(ch) { - return errors.New("not allowed to access channel") - } else if f.IsReaction() && !svc.prm.CanReactMessage(ch) { - return errors.New("not allowed to react on channels") + } + if !svc.prm.CanReadChannel(ch) { + return errors.WithStack(ErrNoPermissions) + } + if f.IsReaction() && !svc.prm.CanReactMessage(ch) { + return errors.WithStack(ErrNoPermissions) } if remove { @@ -476,9 +485,10 @@ func (svc *message) flag(messageID uint64, flag string, remove bool) error { } if err != nil { - return err + return } + // @todo: log possible error svc.sendFlagEvent(f) return @@ -607,7 +617,7 @@ func (svc *message) sendEvent(mm ...*types.Message) (err error) { msg.User, _ = svc.usr.FindByID(msg.UserID) } - if err = svc.evl.Message(msg); err != nil { + if err = svc.event.Message(msg); err != nil { return } } @@ -618,7 +628,7 @@ func (svc *message) sendEvent(mm ...*types.Message) (err error) { // Sends message to event loop func (svc *message) sendFlagEvent(ff ...*types.MessageFlag) (err error) { for _, f := range ff { - if err = svc.evl.MessageFlag(f); err != nil { + if err = svc.event.MessageFlag(f); err != nil { return } } @@ -688,7 +698,7 @@ func (svc message) findChannelByID(channelID uint64) (ch *types.Channel, err err mm types.ChannelMemberSet ) - if ch, err = svc.channel.FindChannelByID(channelID); err != nil { + if ch, err = svc.channel.FindByID(channelID); err != nil { return nil, err } else if mm, err = svc.cmember.Find(&types.ChannelMemberFilter{ChannelID: ch.ID}); err != nil { return nil, err diff --git a/messaging/internal/service/permissions.go b/messaging/internal/service/permissions.go index 07e60dd76..062906280 100644 --- a/messaging/internal/service/permissions.go +++ b/messaging/internal/service/permissions.go @@ -33,28 +33,30 @@ type ( CanCreatePrivateChannel() bool CanCreateGroupChannel() bool - CanUpdateChannel(ch *types.Channel) bool - CanReadChannel(ch *types.Channel) bool - CanJoinChannel(ch *types.Channel) bool - CanLeaveChannel(ch *types.Channel) bool - CanDeleteChannel(ch *types.Channel) bool - CanUndeleteChannel(ch *types.Channel) bool - CanArchiveChannel(ch *types.Channel) bool - CanUnarchiveChannel(ch *types.Channel) bool + CanUpdateChannel(*types.Channel) bool + CanReadChannel(*types.Channel) bool + CanJoinChannel(*types.Channel) bool + CanLeaveChannel(*types.Channel) bool + CanDeleteChannel(*types.Channel) bool + CanUndeleteChannel(*types.Channel) bool + CanArchiveChannel(*types.Channel) bool + CanUnarchiveChannel(*types.Channel) bool - CanManageChannelMembers(ch *types.Channel) bool - CanManageChannelWebhooks(ch *types.Channel) bool - CanManageChannelAttachments(ch *types.Channel) bool + CanManageChannelMembers(*types.Channel) bool + CanManageChannelAttachments(*types.Channel) bool - CanSendMessage(ch *types.Channel) bool - CanReplyMessage(ch *types.Channel) bool - CanEmbedMessage(ch *types.Channel) bool - CanAttachMessage(ch *types.Channel) bool - CanUpdateOwnMessages(ch *types.Channel) bool - CanUpdateMessages(ch *types.Channel) bool - CanDeleteOwnMessages(ch *types.Channel) bool - CanDeleteMessages(ch *types.Channel) bool - CanReactMessage(ch *types.Channel) bool + CanManageWebhooks(*types.Webhook) bool + CanManageOwnWebhooks(*types.Webhook) bool + + CanSendMessage(*types.Channel) bool + CanReplyMessage(*types.Channel) bool + CanEmbedMessage(*types.Channel) bool + CanAttachMessage(*types.Channel) bool + CanUpdateOwnMessages(*types.Channel) bool + CanUpdateMessages(*types.Channel) bool + CanDeleteOwnMessages(*types.Channel) bool + CanDeleteMessages(*types.Channel) bool + CanReactMessage(*types.Channel) bool } effectivePermission struct { @@ -64,10 +66,8 @@ type ( } ) -func Permissions() PermissionsService { - return (&permissions{ - rules: systemService.DefaultRules, - }).With(context.Background()) +func Permissions(ctx context.Context) PermissionsService { + return (&permissions{}).With(ctx) } func (p *permissions) With(ctx context.Context) PermissionsService { @@ -154,8 +154,12 @@ func (p *permissions) CanManageChannelMembers(ch *types.Channel) bool { return p.checkAccess(ch, "members.manage", p.isChannelOwnerFallback(ch)) } -func (p *permissions) CanManageChannelWebhooks(ch *types.Channel) bool { - return p.checkAccess(ch, "webhooks.manage") +func (p *permissions) CanManageWebhooks(webhook *types.Webhook) bool { + return p.checkAccess(webhook, "webhook.manage.all") +} + +func (p *permissions) CanManageOwnWebhooks(webhook *types.Webhook) bool { + return p.checkAccess(webhook, "webhook.manage.own") } func (p *permissions) CanManageChannelAttachments(ch *types.Channel) bool { diff --git a/messaging/internal/service/service.go b/messaging/internal/service/service.go index e8d5c12ef..56ce46d6a 100644 --- a/messaging/internal/service/service.go +++ b/messaging/internal/service/service.go @@ -1,10 +1,11 @@ package service import ( - "log" - "sync" + "context" "time" + "github.com/crusttech/crust/internal/config" + "github.com/crusttech/crust/internal/http" "github.com/crusttech/crust/internal/store" ) @@ -15,7 +16,6 @@ type ( ) var ( - o sync.Once DefaultAttachment AttachmentService DefaultChannel ChannelService DefaultMessage MessageService @@ -24,20 +24,29 @@ var ( DefaultPermissions PermissionsService ) -func Init() { - o.Do(func() { - fs, err := store.New("var/store") - if err != nil { - log.Fatalf("Failed to initialize store: %v", err) - } +func Init() error { + fs, err := store.New("var/store") + if err != nil { + return err + } - DefaultPermissions = Permissions() - DefaultEvent = Event() - DefaultAttachment = Attachment(fs) - DefaultMessage = Message() - DefaultChannel = Channel() - DefaultPubSub = PubSub() + _, err := http.New(&config.HTTPClient{ + Timeout: 10, }) + if err != nil { + return err + } + + ctx := context.Background() + + DefaultPermissions = Permissions(ctx) + DefaultEvent = Event(ctx) + DefaultAttachment = Attachment(ctx, fs) + DefaultMessage = Message(ctx) + DefaultChannel = Channel(ctx) + DefaultPubSub = PubSub() + + return nil } func timeNowPtr() *time.Time {