Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add read only channels #3861

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/rocketchat-authorization/server/startup.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Meteor.startup ->
{ _id: 'manage-oauth-apps', roles : ['admin'] }
{ _id: 'mention-all', roles : ['admin', 'moderator', 'owner', 'user'] }
{ _id: 'mute-user', roles : ['admin', 'moderator', 'owner'] }
{ _id: 'post-read-only', roles : ['admin', 'moderator', 'owner'] }
{ _id: 'remove-user', roles : ['admin', 'moderator', 'owner'] }
{ _id: 'run-import', roles : ['admin'] }
{ _id: 'run-migration', roles : ['admin'] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ Template.channelSettings.helpers
return t('Room_archivation_state_true')
else
return t('Room_archivation_state_false')
readOnly: ->
return ChatRoom.findOne(@rid, { fields: { ro: 1 }})?.ro
systemMessages: ->
return ChatRoom.findOne(@rid, { fields: { sysMes: 1 }})?.sysMes isnt false

Template.channelSettings.events
'keydown input[type=text]': (e, t) ->
Expand Down Expand Up @@ -129,4 +133,12 @@ Template.channelSettings.onCreated ->
return handleError err if err
toastr.success TAPi18n.__ 'Room_unarchived'
RocketChat.callbacks.run 'unarchiveRoom', ChatRoom.findOne(room._id)
when 'readOnly'
Meteor.call 'saveRoomSettings', room._id, 'readOnly', @$('input[name=readOnly]:checked').val() is 'true', (err, result) ->
return handleError err if err
toastr.success TAPi18n.__ 'Read_only_changed_successfully'
when 'systemMessages'
Meteor.call 'saveRoomSettings', room._id, 'systemMessages', @$('input[name=systemMessages]:checked').val() is 'true', (err, result) ->
return handleError err if err
toastr.success TAPi18n.__ 'System_messages_setting_changed_successfully'
@editing.set()
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ <h2>{{_ "Room_Info"}}</h2>
{{/if}}
</div>
</li>
{{/if}}
{{#if notDirect}}
<li>
<label>{{_ "Type"}}</label>
<div>
Expand All @@ -54,8 +52,6 @@ <h2>{{_ "Room_Info"}}</h2>
{{/if}}
</div>
</li>
{{/if}}
{{#if notDirect}}
<li>
<label>{{_ "Room_archivation_state"}}</label>
<div>
Expand All @@ -69,6 +65,32 @@ <h2>{{_ "Room_Info"}}</h2>
{{/if}}
</div>
</li>
<li>
<label>{{_ "Read_only"}}</label>
<div>
{{#if editing 'readOnly'}}
<label><input type="radio" name="readOnly" class="editing" value="true" checked="{{$eq readOnly true}}" /> {{_ "True"}}</label>
<label><input type="radio" name="readOnly" value="false" checked="{{$neq readOnly true}}" /> {{_ "False"}}</label>
<button type="button" class="button secondary cancel">{{_ "Cancel"}}</button>
<button type="button" class="button primary save">{{_ "Save"}}</button>
{{else}}
<span>{{#if readOnly}}{{_ "True"}}{{else}}{{_ "False"}}{{/if}}{{#if canEdit}} <i class="icon-pencil" data-edit="readOnly"></i>{{/if}}</span>
{{/if}}
</div>
</li>
<li>
<label>{{_ "System_messages"}}</label>
<div>
{{#if editing 'systemMessages'}}
<label><input type="radio" name="systemMessages" class="editing" value="true" checked="{{$eq systemMessages true}}" /> {{_ "On"}}</label>
<label><input type="radio" name="systemMessages" value="false" checked="{{$neq systemMessages true}}" /> {{_ "Off"}}</label>
<button type="button" class="button secondary cancel">{{_ "Cancel"}}</button>
<button type="button" class="button primary save">{{_ "Save"}}</button>
{{else}}
<span>{{#if systemMessages}}{{_ "On"}}{{else}}{{_ "Off"}}{{/if}}{{#if canEdit}} <i class="icon-pencil" data-edit="systemMessages"></i>{{/if}}</span>
{{/if}}
</div>
</li>
{{/if}}
{{#each channelSettings}}
{{> Template.dynamic template=template data=data}}
Expand Down
2 changes: 2 additions & 0 deletions packages/rocketchat-channel-settings/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ Package.onUse(function(api) {
'server/functions/saveRoomType.coffee',
'server/functions/saveRoomTopic.coffee',
'server/functions/saveRoomName.coffee',
'server/functions/saveRoomReadOnly.coffee',
'server/functions/saveRoomDescription.coffee',
'server/functions/saveRoomSystemMessages.coffee',
'server/methods/saveRoomSettings.coffee',
'server/models/Messages.coffee',
'server/models/Rooms.coffee'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
RocketChat.saveRoomReadOnly = (rid, readOnly, user) ->
unless Match.test rid, String
throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomReadOnly' }

update = RocketChat.models.Rooms.setReadOnlyById rid, readOnly

return update
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
RocketChat.saveRoomSystemMessages = (rid, systemMessages, user) ->
unless Match.test rid, String
throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomSystemMessages' }

update = RocketChat.models.Rooms.setSystemMessagesById rid, systemMessages

return update
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Meteor.methods
unless Match.test rid, String
throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'saveRoomSettings' }

if setting not in ['roomName', 'roomTopic', 'roomDescription', 'roomType', 'default']
if setting not in ['roomName', 'roomTopic', 'roomDescription', 'roomType', 'readOnly', 'systemMessages', 'default']
throw new Meteor.Error 'error-invalid-settings', 'Invalid settings provided', { method: 'saveRoomSettings' }

unless RocketChat.authz.hasPermission(Meteor.userId(), 'edit-room', rid)
Expand Down Expand Up @@ -32,6 +32,12 @@ Meteor.methods
else
message = TAPi18n.__('Private_Group')
RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_privacy', rid, message, Meteor.user()
when 'readOnly'
if value isnt room.ro
RocketChat.saveRoomReadOnly rid, value, Meteor.user()
when 'systemMessages'
if value isnt room.sysMes
RocketChat.saveRoomSystemMessages rid, value, Meteor.user()
when 'default'
RocketChat.models.Rooms.saveDefaultById rid, value

Expand Down
25 changes: 25 additions & 0 deletions packages/rocketchat-channel-settings/server/models/Rooms.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,28 @@ RocketChat.models.Rooms.setDescriptionById = (_id, description) ->
description: description

return @update query, update

RocketChat.models.Rooms.setReadOnlyById = (_id, readOnly) ->
query =
_id: _id

update =
$set:
ro: readOnly

if readOnly
users = @findOne(query, { fields: { usernames: 1 }})?.usernames
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you doing this query?

else
update.$set.muted = []

return @update query, update

RocketChat.models.Rooms.setSystemMessagesById = (_id, systemMessages) ->
query =
_id: _id

update =
$set:
sysMes: systemMessages

return @update query, update
8 changes: 8 additions & 0 deletions packages/rocketchat-lib/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,7 @@
"OAuth_Application" : "OAuth Application",
"OAuth_Applications" : "OAuth Applications",
"Objects" : "Objects",
"Off" : "Off",
"Off_the_record_conversation" : "Off-the-record Conversation",
"Off_the_record_conversation_is_not_available_for_your_browser_or_device" : "Off-the-record conversation is not available for your browser or device.",
"Offline" : "Offline",
Expand All @@ -798,6 +799,7 @@
"Offline_message" : "Offline message",
"Offline_success_message" : "Offline success message",
"Offline_unavailable" : "Offline unavailable",
"On" : "On",
"Online" : "Online",
"Only_you_can_see_this_message" : "Only you can see this message",
"Oops!" : "Oops",
Expand Down Expand Up @@ -893,6 +895,10 @@
"Random" : "Random",
"Reacted_with" : "Reacted with",
"Reactions" : "Reactions",
"Read_only" : "Read Only",
"Read_only_channel" : "Read Only Channel",
"Read_only_changed_successfully" : "Read only changed successfully",
"Read_only_group" : "Read Only Group",
"Record" : "Record",
"Redirect_URI" : "Redirect URI",
"Refresh_keys" : "Refresh keys",
Expand Down Expand Up @@ -1067,6 +1073,7 @@
"Symbols" : "Symbols",
"Sync_success" : "Sync success",
"Sync_Users" : "Sync Users",
"System_messages" : "System Messages",
"Tag" : "Tag",
"Take_it" : "Take it!",
"Test_Connection" : "Test Connection",
Expand Down Expand Up @@ -1188,6 +1195,7 @@
"User_left_male" : "Has left the channel.",
"User_logged_out" : "User is logged out",
"User_management" : "User Management",
"User_muted" : "User Muted",
"User_muted_by" : "User <em>__user_muted__</em> muted by <em>__user_by__</em>.",
"User_not_found" : "User not found",
"User_not_found_or_incorrect_password" : "User not found or incorrect password",
Expand Down
3 changes: 3 additions & 0 deletions packages/rocketchat-lib/server/models/Messages.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base

# INSERT
createWithTypeRoomIdMessageAndUser: (type, roomId, message, user, extraData) ->
room = RocketChat.models.Rooms.findOneById roomId, { fields: { sysMes: 1 }}
if room?.sysMes is false
return
record =
t: type
rid: roomId
Expand Down
11 changes: 11 additions & 0 deletions packages/rocketchat-lib/server/models/Rooms.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,17 @@ RocketChat.models.Rooms = new class extends RocketChat.models._Base

return @update query, update

addUsernameByIdAndMute: (_id, username) ->
query =
_id: _id

update =
$addToSet:
usernames: username
muted: username

return @update query, update

addUsernamesById: (_id, usernames) ->
query =
_id: _id
Expand Down
5 changes: 5 additions & 0 deletions packages/rocketchat-theme/assets/stylesheets/base.less
Original file line number Diff line number Diff line change
Expand Up @@ -3555,6 +3555,11 @@ body:not(.is-cordova) {
padding-left: 10px;
.calc(width, ~"100% - 45px");
}
.icon-mute {
float: left;
color: #7f7f7f;
line-height: 20px;
}
}
button {
display: block;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ Template.membersList.helpers
roomUsers: ->
users = []
onlineUsers = RoomManager.onlineUsers.get()
roomUsernames = ChatRoom.findOne(this.rid)?.usernames or []
room = ChatRoom.findOne(this.rid)
roomUsernames = room?.usernames or []
roomMuted = room?.muted or []

for username in roomUsernames
if Template.instance().showAllUsers.get() or onlineUsers[username]?
Expand All @@ -31,6 +33,7 @@ Template.membersList.helpers
users.push
username: username
status: onlineUsers[username]?.status
muted: username in roomMuted
utcOffset: utcOffset

users = _.sortBy users, 'username'
Expand Down
3 changes: 3 additions & 0 deletions packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ <h2>{{_ "Members_List"}}</h2>
<button data-username="{{username}}" tabindex="0" title="{{username}}">
{{> avatar username=username}}
<p>{{username}} {{utcOffset}}</p>
{{#if muted}}
<i class="icon-mute" title="{{_ "User Muted"}}"></i>
{{/if}}
</button>
</li>
{{/each}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ Template.createChannelFlex.events
'click .save-channel': (e, instance) ->
err = SideNav.validate()
name = instance.find('#channel-name').value.toLowerCase().trim()
readOnly = instance.find('#channel-ro').checked
instance.roomName.set name
if not err
Meteor.call 'createChannel', name, instance.selectedUsers.get(), (err, result) ->
Meteor.call 'createChannel', name, instance.selectedUsers.get(), readOnly, (err, result) ->
if err
console.log err
if err.error is 'error-invalid-name'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ <h4>{{_ "Create_new" }}</h4>
<label for="channel-name">{{_ "Name"}}</label>
<input type="text" id="channel-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
</div>
<div class="input-line">
<label for="channel-ro">{{_ "Read_only_channel"}}</label>
<input type="checkbox" id="channel-ro">
</div>
<div class="input-line">
<label for="channel-members">{{_ "Select_users"}}</label>
{{> inputAutocomplete settings=autocompleteSettings id="channel-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,12 @@ Template.createCombinedFlex.events
err = SideNav.validate()
name = instance.find('#channel-name').value.toLowerCase().trim()
privateGroup = instance.find('#channel-type').checked
readOnly = instance.find('#channel-ro').checked
createRoute = if privateGroup then 'createPrivateGroup' else 'createChannel'
successRoute = if privateGroup then 'group' else 'channel'
instance.roomName.set name
if not err
Meteor.call createRoute, name, instance.selectedUsers.get(), (err, result) ->
Meteor.call createRoute, name, instance.selectedUsers.get(), readOnly, (err, result) ->
if err
console.log err
if err.error is 'error-invalid-name'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ <h4>{{_ "Create_new" }}</h4>
<input type="text" id="channel-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
</div>
<div class="input-line">
<label for="channel-type">Private Group</label>
<label for="channel-type">{{_ "Private_Group"}}</label>
<input type="checkbox" id="channel-type" {{privateSwitchDisabled}} {{privateSwitchChecked}}>
</div>
<div class="input-line">
<label for="channel-ro">{{_ "Read_only_channel"}}</label>
<input type="checkbox" id="channel-ro">
</div>
<div class="input-line">
<label for="channel-members">{{_ "Select_users"}}</label>
{{> inputAutocomplete settings=autocompleteSettings id="channel-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ Template.privateGroupsFlex.events
'click .save-pvt-group': (e, instance) ->
err = SideNav.validate()
name = instance.find('#pvt-group-name').value.toLowerCase().trim()
readOnly = instance.find('#channel-ro').checked
instance.groupName.set name
if not err
Meteor.call 'createPrivateGroup', name, instance.selectedUsers.get(), (err, result) ->
Meteor.call 'createPrivateGroup', name, instance.selectedUsers.get(), readOnly, (err, result) ->
if err
if err.error is 'error-invalid-name'
instance.error.set({ invalid: true })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ <h4>{{_ "Create_new"}}</h4>
<label for="pvt-group-name">{{_ "Name"}}</label>
<input type="text" id="pvt-group-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
</div>
<div class="input-line">
<label for="channel-ro">{{_ "Read_only_group"}}</label>
<input type="checkbox" id="channel-ro">
</div>
<div class="input-line">
<label for="pvt-group-members">{{_ "Select_users" }}</label>
{{> inputAutocomplete settings=autocompleteSettings id="pvt-group-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}
Expand Down
5 changes: 4 additions & 1 deletion server/methods/addUserToRoom.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ Meteor.methods

newUser = RocketChat.models.Users.findOneByUsername data.username

RocketChat.models.Rooms.addUsernameById data.rid, data.username
if room.ro and not RocketChat.authz.hasPermission(newUser._id, 'post-read-only')
RocketChat.models.Rooms.addUsernameByIdAndMute data.rid, data.username
else
RocketChat.models.Rooms.addUsernameById data.rid, data.username

now = new Date()

Expand Down
6 changes: 5 additions & 1 deletion server/methods/createChannel.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Meteor.methods
createChannel: (name, members) ->
createChannel: (name, members, readOnly) ->
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', "Invalid user", { method: 'createChannel' }

Expand Down Expand Up @@ -32,6 +32,8 @@ Meteor.methods
t: 'c'
name: name
ts: now
ro: readOnly is true
sysMes: readOnly isnt true
usernames: members
u:
_id: user._id
Expand All @@ -40,6 +42,8 @@ Meteor.methods
# create new room
room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames 'c', name, user, members,
ts: now
ro: readOnly is true
sysMes: readOnly isnt true

for username in members
member = RocketChat.models.Users.findOneByUsername username
Expand Down
4 changes: 3 additions & 1 deletion server/methods/createPrivateGroup.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Meteor.methods
createPrivateGroup: (name, members) ->
createPrivateGroup: (name, members, readOnly) ->
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', "Invalid user", { method: 'createPrivateGroup' }

Expand Down Expand Up @@ -32,6 +32,8 @@ Meteor.methods
# create new room
room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames 'p', name, me, members,
ts: now
ro: readOnly is true
sysMes: readOnly isnt true

for username in members
member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }})
Expand Down
Loading