Skip to content

Commit

Permalink
feat: introduce CommunityAdminSettings in CommunityDescription
Browse files Browse the repository at this point in the history
This allows to store community admin settings that are meant to be propagated
to community members (as opposed to the already existing
`CommunitySettings` which are considered local to every account).

The first setting introduced as part of this commit is one that enables
community admins to configure whether or not members of the community
are allowed to pin messages in community channels.

Prior to this commit, this was not restricted at all on the protocol
level and only enforced by clients via UI (e.g. members don't see an
option to pin messages, although they could).

This config setting now ensures that:

1. If turned off, members cannot send a pin message
2. If turned off, pin messages from members are not handled/processed

This is needed by status-im/status-desktop#5662
  • Loading branch information
0x-r4bbit committed May 11, 2022
1 parent d884749 commit 76c200e
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 121 deletions.
4 changes: 2 additions & 2 deletions appdatabase/migrations/bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 58 additions & 30 deletions protocol/communities/community.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ func New(config Config) (*Community, error) {
return community, nil
}

type CommunityAdminSettings struct {
PinMessageAllMembersEnabled bool `json:"pinMessageAllMembersEnabled"`
}

type CommunityChat struct {
ID string `json:"id"`
Name string `json:"name"`
Expand All @@ -84,17 +88,18 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
return nil, errors.New("member identity not set")
}
communityItem := struct {
ID types.HexBytes `json:"id"`
Verified bool `json:"verified"`
Chats map[string]CommunityChat `json:"chats"`
Categories map[string]CommunityCategory `json:"categories"`
Name string `json:"name"`
Description string `json:"description"`
Images map[string]images.IdentityImage `json:"images"`
Color string `json:"color"`
MembersCount int `json:"membersCount"`
EnsName string `json:"ensName"`
Link string `json:"link"`
ID types.HexBytes `json:"id"`
Verified bool `json:"verified"`
Chats map[string]CommunityChat `json:"chats"`
Categories map[string]CommunityCategory `json:"categories"`
Name string `json:"name"`
Description string `json:"description"`
Images map[string]images.IdentityImage `json:"images"`
Color string `json:"color"`
MembersCount int `json:"membersCount"`
EnsName string `json:"ensName"`
Link string `json:"link"`
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
}{
ID: o.ID(),
Verified: o.config.Verified,
Expand Down Expand Up @@ -144,6 +149,13 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
}
}

communityItem.CommunityAdminSettings = CommunityAdminSettings{
PinMessageAllMembersEnabled: false,
}

if o.config.CommunityDescription.AdminSettings != nil {
communityItem.CommunityAdminSettings.PinMessageAllMembersEnabled = o.config.CommunityDescription.AdminSettings.PinMessageAllMembersEnabled
}
}
return json.Marshal(communityItem)
}
Expand All @@ -153,25 +165,26 @@ func (o *Community) MarshalJSON() ([]byte, error) {
return nil, errors.New("member identity not set")
}
communityItem := struct {
ID types.HexBytes `json:"id"`
Admin bool `json:"admin"`
Verified bool `json:"verified"`
Joined bool `json:"joined"`
RequestedAccessAt int `json:"requestedAccessAt"`
Name string `json:"name"`
Description string `json:"description"`
Chats map[string]CommunityChat `json:"chats"`
Categories map[string]CommunityCategory `json:"categories"`
Images map[string]images.IdentityImage `json:"images"`
Permissions *protobuf.CommunityPermissions `json:"permissions"`
Members map[string]*protobuf.CommunityMember `json:"members"`
CanRequestAccess bool `json:"canRequestAccess"`
CanManageUsers bool `json:"canManageUsers"`
CanJoin bool `json:"canJoin"`
Color string `json:"color"`
RequestedToJoinAt uint64 `json:"requestedToJoinAt,omitempty"`
IsMember bool `json:"isMember"`
Muted bool `json:"muted"`
ID types.HexBytes `json:"id"`
Admin bool `json:"admin"`
Verified bool `json:"verified"`
Joined bool `json:"joined"`
RequestedAccessAt int `json:"requestedAccessAt"`
Name string `json:"name"`
Description string `json:"description"`
Chats map[string]CommunityChat `json:"chats"`
Categories map[string]CommunityCategory `json:"categories"`
Images map[string]images.IdentityImage `json:"images"`
Permissions *protobuf.CommunityPermissions `json:"permissions"`
Members map[string]*protobuf.CommunityMember `json:"members"`
CanRequestAccess bool `json:"canRequestAccess"`
CanManageUsers bool `json:"canManageUsers"`
CanJoin bool `json:"canJoin"`
Color string `json:"color"`
RequestedToJoinAt uint64 `json:"requestedToJoinAt,omitempty"`
IsMember bool `json:"isMember"`
Muted bool `json:"muted"`
CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"`
}{
ID: o.ID(),
Admin: o.IsAdmin(),
Expand Down Expand Up @@ -229,6 +242,13 @@ func (o *Community) MarshalJSON() ([]byte, error) {
}
}

communityItem.CommunityAdminSettings = CommunityAdminSettings{
PinMessageAllMembersEnabled: false,
}

if o.config.CommunityDescription.AdminSettings != nil {
communityItem.CommunityAdminSettings.PinMessageAllMembersEnabled = o.config.CommunityDescription.AdminSettings.PinMessageAllMembersEnabled
}
}
return json.Marshal(communityItem)
}
Expand Down Expand Up @@ -664,6 +684,10 @@ func (o *Community) Edit(description *protobuf.CommunityDescription) {
o.config.CommunityDescription.Identity.Color = description.Identity.Color
o.config.CommunityDescription.Identity.Emoji = description.Identity.Emoji
o.config.CommunityDescription.Identity.Images = description.Identity.Images
if o.config.CommunityDescription.AdminSettings == nil {
o.config.CommunityDescription.AdminSettings = &protobuf.CommunityAdminSettings{}
}
o.config.CommunityDescription.AdminSettings.PinMessageAllMembersEnabled = description.AdminSettings.PinMessageAllMembersEnabled
o.increaseClock()
}

Expand Down Expand Up @@ -1297,6 +1321,10 @@ func (o *Community) ChatIDs() (chatIDs []string) {
return chatIDs
}

func (o *Community) AllowsAllMembersToPinMessage() bool {
return o.config.CommunityDescription.AdminSettings != nil && o.config.CommunityDescription.AdminSettings.PinMessageAllMembersEnabled
}

func emptyCommunityChanges() *CommunityChanges {
return &CommunityChanges{
MembersAdded: make(map[string]*protobuf.CommunityMember),
Expand Down
14 changes: 13 additions & 1 deletion protocol/messenger_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1369,17 +1369,29 @@ func (m *Messenger) matchChatEntity(chatEntity common.ChatEntity) (*Chat, error)
}

var emojiReaction bool
var pinMessage bool
// We allow emoji reactions from anyone
switch chatEntity.(type) {
case *EmojiReaction:
emojiReaction = true
case *common.PinMessage:
pinMessage = true
}

canPost, err := m.communitiesManager.CanPost(chatEntity.GetSigPubKey(), chat.CommunityID, chat.CommunityChatID(), chatEntity.GetGrant())
if err != nil {
return nil, err
}
if !emojiReaction && !canPost {

community, err := m.communitiesManager.GetByIDString(chat.CommunityID)
if err != nil {
return nil, err
}

isMemberAdmin := community.IsMemberAdmin(chatEntity.GetSigPubKey())
pinMessageAllowed := community.AllowsAllMembersToPinMessage()

if (pinMessage && !isMemberAdmin && !pinMessageAllowed) || (!emojiReaction && !canPost) {
return nil, errors.New("user can't post")
}

Expand Down
13 changes: 12 additions & 1 deletion protocol/messenger_pin_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,18 @@ func (m *Messenger) sendPinMessage(ctx context.Context, message *common.PinMessa
return nil, errors.New("chat not found")
}

err := m.handleStandaloneChatIdentity(chat)
community, err := m.communitiesManager.GetByIDString(chat.CommunityID)
if err != nil {
return nil, err
}
isMemberAdmin := community.IsMemberAdmin(&m.identity.PublicKey)
pinMessageAllowed := community.AllowsAllMembersToPinMessage()

if !pinMessageAllowed && !isMemberAdmin {
return nil, errors.New("member can't pin message")
}

err = m.handleStandaloneChatIdentity(chat)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit 76c200e

Please sign in to comment.