mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-08-12 18:10:43 +09:00
5c5c82b27a
Rooms::DirectsController relaxes ensure_can_administer to true, because every participant in a direct room may administer it. set_room was inherited unscoped, though, so that relaxation applied to any room the caller was merely a member of: DELETE /rooms/directs/<id> destroyed open and closed rooms and all their messages. The same unscoped lookup let a direct room be loaded by the opens and closeds controllers, where force_room_type promoted it. Promoting a DM to open grants every user on the account membership and republishes the whole conversation, including the other participant's messages; converting it to closed lets the initiator revise who is in it and lock the other participant out. Each controller now narrows room_scope to the types it may act on. Opens and closeds keep reach into each other, since converting between them is a feature. Neither can reach a direct room, and directs can only reach directs. Room also refuses to change type away from Rooms::Direct, so the invariant holds for any future caller of becomes! rather than only these two controllers.
42 lines
998 B
Ruby
42 lines
998 B
Ruby
class Rooms::DirectsController < RoomsController
|
|
before_action :set_room, only: %i[ edit destroy ]
|
|
def new
|
|
@room = Rooms::Direct.new
|
|
end
|
|
|
|
def create
|
|
room = Rooms::Direct.find_or_create_for(selected_users)
|
|
|
|
broadcast_create_room(room)
|
|
redirect_to room_url(room)
|
|
end
|
|
|
|
def edit
|
|
end
|
|
|
|
private
|
|
def selected_users
|
|
User.where(id: selected_users_ids.including(Current.user.id))
|
|
end
|
|
|
|
def selected_users_ids
|
|
params.fetch(:user_ids, [])
|
|
end
|
|
|
|
def broadcast_create_room(room)
|
|
room.memberships.each do |membership|
|
|
membership.broadcast_prepend_to membership.user, :rooms, target: :direct_rooms, partial: "users/sidebars/rooms/direct"
|
|
end
|
|
end
|
|
|
|
# All users in a direct room can administer it. Only direct rooms, though: this
|
|
# relaxation is why room_scope below has to keep every other type out of reach.
|
|
def ensure_can_administer
|
|
true
|
|
end
|
|
|
|
def room_scope
|
|
Current.user.rooms.directs
|
|
end
|
|
end
|