Add canView to chat & fix admin role
This commit is contained in:
parent
ade85df3a5
commit
894eb5758e
|
@ -104,6 +104,7 @@ type CommunityChat struct {
|
||||||
Members map[string]*protobuf.CommunityMember `json:"members"`
|
Members map[string]*protobuf.CommunityMember `json:"members"`
|
||||||
Permissions *protobuf.CommunityPermissions `json:"permissions"`
|
Permissions *protobuf.CommunityPermissions `json:"permissions"`
|
||||||
CanPost bool `json:"canPost"`
|
CanPost bool `json:"canPost"`
|
||||||
|
CanView bool `json:"canView"`
|
||||||
ViewersCanPostReactions bool `json:"viewersCanPostReactions"`
|
ViewersCanPostReactions bool `json:"viewersCanPostReactions"`
|
||||||
Position int `json:"position"`
|
Position int `json:"position"`
|
||||||
CategoryID string `json:"categoryID"`
|
CategoryID string `json:"categoryID"`
|
||||||
|
@ -187,6 +188,8 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
canView := o.CanView(o.config.MemberIdentity, id)
|
||||||
|
|
||||||
chat := CommunityChat{
|
chat := CommunityChat{
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: c.Identity.DisplayName,
|
Name: c.Identity.DisplayName,
|
||||||
|
@ -196,6 +199,7 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
||||||
Permissions: c.Permissions,
|
Permissions: c.Permissions,
|
||||||
Members: c.Members,
|
Members: c.Members,
|
||||||
CanPost: canPost,
|
CanPost: canPost,
|
||||||
|
CanView: canView,
|
||||||
ViewersCanPostReactions: c.ViewersCanPostReactions,
|
ViewersCanPostReactions: c.ViewersCanPostReactions,
|
||||||
TokenGated: o.channelEncrypted(id),
|
TokenGated: o.channelEncrypted(id),
|
||||||
CategoryID: c.CategoryId,
|
CategoryID: c.CategoryId,
|
||||||
|
@ -328,6 +332,8 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
canView := o.CanView(o.config.MemberIdentity, id)
|
||||||
|
|
||||||
chat := CommunityChat{
|
chat := CommunityChat{
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: c.Identity.DisplayName,
|
Name: c.Identity.DisplayName,
|
||||||
|
@ -337,6 +343,7 @@ func (o *Community) MarshalJSON() ([]byte, error) {
|
||||||
Permissions: c.Permissions,
|
Permissions: c.Permissions,
|
||||||
Members: c.Members,
|
Members: c.Members,
|
||||||
CanPost: canPost,
|
CanPost: canPost,
|
||||||
|
CanView: canView,
|
||||||
ViewersCanPostReactions: c.ViewersCanPostReactions,
|
ViewersCanPostReactions: c.ViewersCanPostReactions,
|
||||||
TokenGated: o.channelEncrypted(id),
|
TokenGated: o.channelEncrypted(id),
|
||||||
CategoryID: c.CategoryId,
|
CategoryID: c.CategoryId,
|
||||||
|
@ -1877,63 +1884,70 @@ func (o *Community) VerifyGrantSignature(data []byte) (*protobuf.Grant, error) {
|
||||||
return grant, nil
|
return grant, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Community) CanPost(pk *ecdsa.PublicKey, chatID string, messageType protobuf.ApplicationMetadataMessage_Type) (bool, error) {
|
func (o *Community) CanView(pk *ecdsa.PublicKey, chatID string) bool {
|
||||||
if o.config.CommunityDescription.Chats == nil {
|
if o.config.CommunityDescription.Chats == nil {
|
||||||
o.config.Logger.Debug("Community.CanPost: no-chats")
|
o.config.Logger.Debug("Community.CanView: no-chats")
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
chat, ok := o.config.CommunityDescription.Chats[chatID]
|
chat, ok := o.config.CommunityDescription.Chats[chatID]
|
||||||
if !ok {
|
if !ok {
|
||||||
o.config.Logger.Debug("Community.CanPost: no chat with id", zap.String("chat-id", chatID))
|
o.config.Logger.Debug("Community.CanView: no chat with id", zap.String("chat-id", chatID))
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// community creator can always post, return immediately
|
// community creator can always post, return immediately
|
||||||
if common.IsPubKeyEqual(pk, o.ControlNode()) {
|
if common.IsPubKeyEqual(pk, o.ControlNode()) {
|
||||||
return true, nil
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.isBanned(pk) {
|
if o.isBanned(pk) {
|
||||||
o.config.Logger.Debug("Community.CanPost: user is banned", zap.String("chat-id", chatID))
|
o.config.Logger.Debug("Community.CanView: user is banned", zap.String("chat-id", chatID))
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.config.CommunityDescription.Members == nil {
|
if o.config.CommunityDescription.Members == nil {
|
||||||
o.config.Logger.Debug("Community.CanPost: no members in org", zap.String("chat-id", chatID))
|
o.config.Logger.Debug("Community.CanView: no members in org", zap.String("chat-id", chatID))
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// If community member, also check chat membership next
|
// If community member, also check chat membership next
|
||||||
_, ok = o.config.CommunityDescription.Members[common.PubkeyToHex(pk)]
|
_, ok = o.config.CommunityDescription.Members[common.PubkeyToHex(pk)]
|
||||||
if !ok {
|
if !ok {
|
||||||
o.config.Logger.Debug("Community.CanPost: not a community member", zap.String("chat-id", chatID))
|
o.config.Logger.Debug("Community.CanView: not a community member", zap.String("chat-id", chatID))
|
||||||
return false, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if chat.Members == nil {
|
if chat.Members == nil {
|
||||||
o.config.Logger.Debug("Community.CanPost: no members in chat", zap.String("chat-id", chatID))
|
o.config.Logger.Debug("Community.CanView: no members in chat", zap.String("chat-id", chatID))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
_, isChatMember := chat.Members[common.PubkeyToHex(pk)]
|
||||||
|
return isChatMember
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Community) CanPost(pk *ecdsa.PublicKey, chatID string, messageType protobuf.ApplicationMetadataMessage_Type) (bool, error) {
|
||||||
|
hasAccessToChat := o.CanView(pk, chatID)
|
||||||
|
if !hasAccessToChat {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
member, isChatMember := chat.Members[common.PubkeyToHex(pk)]
|
chat := o.config.CommunityDescription.Chats[chatID]
|
||||||
|
member := chat.Members[common.PubkeyToHex(pk)]
|
||||||
|
|
||||||
switch messageType {
|
switch messageType {
|
||||||
case protobuf.ApplicationMetadataMessage_PIN_MESSAGE:
|
case protobuf.ApplicationMetadataMessage_PIN_MESSAGE:
|
||||||
pinAllowed := o.IsPrivilegedMember(pk) || o.AllowsAllMembersToPinMessage()
|
pinAllowed := o.IsPrivilegedMember(pk) || o.AllowsAllMembersToPinMessage()
|
||||||
return isChatMember && pinAllowed, nil
|
return pinAllowed, nil
|
||||||
|
|
||||||
case protobuf.ApplicationMetadataMessage_EMOJI_REACTION:
|
case protobuf.ApplicationMetadataMessage_EMOJI_REACTION:
|
||||||
if !isChatMember {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
isPoster := member.GetChannelRole() == protobuf.CommunityMember_CHANNEL_ROLE_POSTER
|
isPoster := member.GetChannelRole() == protobuf.CommunityMember_CHANNEL_ROLE_POSTER
|
||||||
isViewer := member.GetChannelRole() == protobuf.CommunityMember_CHANNEL_ROLE_VIEWER
|
isViewer := member.GetChannelRole() == protobuf.CommunityMember_CHANNEL_ROLE_VIEWER
|
||||||
return isPoster || (isViewer && chat.ViewersCanPostReactions), nil
|
return isPoster || (isViewer && chat.ViewersCanPostReactions), nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return isChatMember, nil
|
return member.GetChannelRole() == protobuf.CommunityMember_CHANNEL_ROLE_POSTER, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -451,6 +451,44 @@ func (s *CommunitySuite) TestValidateRequestToJoin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *CommunitySuite) TestCanPostCanView() {
|
||||||
|
chatID := "chat-id"
|
||||||
|
memberKey := common.PubkeyToHex(&s.member1.PublicKey)
|
||||||
|
// Member has no channel role
|
||||||
|
description := &protobuf.CommunityDescription{
|
||||||
|
Members: map[string]*protobuf.CommunityMember{
|
||||||
|
memberKey: &protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
Chats: map[string]*protobuf.CommunityChat{
|
||||||
|
chatID: &protobuf.CommunityChat{
|
||||||
|
Members: map[string]*protobuf.CommunityMember{
|
||||||
|
memberKey: &protobuf.CommunityMember{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
community := &Community{config: &Config{ID: &s.member2.PublicKey}}
|
||||||
|
community.config.CommunityDescription = description
|
||||||
|
|
||||||
|
result, err := community.CanPost(&s.member1.PublicKey, chatID, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().True(result)
|
||||||
|
|
||||||
|
result = community.CanView(&s.member1.PublicKey, chatID)
|
||||||
|
s.Require().True(result)
|
||||||
|
|
||||||
|
// member has view channel permissions
|
||||||
|
description.Chats[chatID].Members[memberKey].ChannelRole = protobuf.CommunityMember_CHANNEL_ROLE_VIEWER
|
||||||
|
|
||||||
|
result, err = community.CanPost(&s.member1.PublicKey, chatID, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().False(result)
|
||||||
|
|
||||||
|
result = community.CanView(&s.member1.PublicKey, chatID)
|
||||||
|
s.Require().True(result)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *CommunitySuite) TestCanPost() {
|
func (s *CommunitySuite) TestCanPost() {
|
||||||
notMember := &s.member3.PublicKey
|
notMember := &s.member3.PublicKey
|
||||||
member := &s.member1.PublicKey
|
member := &s.member1.PublicKey
|
||||||
|
|
|
@ -1006,7 +1006,7 @@ func (m *Manager) ReevaluateMembers(community *Community) (map[protobuf.Communit
|
||||||
if isNewRoleAdmin {
|
if isNewRoleAdmin {
|
||||||
if !isCurrentRoleAdmin {
|
if !isCurrentRoleAdmin {
|
||||||
newPrivilegedRoles[protobuf.CommunityMember_ROLE_ADMIN] =
|
newPrivilegedRoles[protobuf.CommunityMember_ROLE_ADMIN] =
|
||||||
append(newPrivilegedRoles[protobuf.CommunityMember_ROLE_TOKEN_MASTER], memberPubKey)
|
append(newPrivilegedRoles[protobuf.CommunityMember_ROLE_ADMIN], memberPubKey)
|
||||||
}
|
}
|
||||||
// Skip further validation if user has Admin permissions
|
// Skip further validation if user has Admin permissions
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -1361,6 +1361,25 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestMemberRoleGetUpdatedWhen
|
||||||
err = <-waitOnChannelKeyToBeDistributedToBob
|
err = <-waitOnChannelKeyToBeDistributedToBob
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
// wait until bob permissions are upgraded
|
||||||
|
_, err = WaitOnMessengerResponse(
|
||||||
|
s.bob,
|
||||||
|
func(r *MessengerResponse) bool {
|
||||||
|
community, err = s.bob.communitiesManager.GetByID(community.ID())
|
||||||
|
s.Require().NoError(err)
|
||||||
|
chats := community.Chats()
|
||||||
|
if len(chats) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if chats[chat.ID] == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
members = chats[chat.ID].Members
|
||||||
|
return len(members) == 2 && members[s.bob.myHexIdentity()] != nil && members[s.bob.myHexIdentity()].ChannelRole == protobuf.CommunityMember_CHANNEL_ROLE_POSTER
|
||||||
|
},
|
||||||
|
"bob never got post permissions",
|
||||||
|
)
|
||||||
|
|
||||||
msg = s.sendChatMessage(s.bob, chat.ID, "hello on closed channel from Bob")
|
msg = s.sendChatMessage(s.bob, chat.ID, "hello on closed channel from Bob")
|
||||||
|
|
||||||
// owner can read the message
|
// owner can read the message
|
||||||
|
|
Loading…
Reference in New Issue