groups_controller.rb 5.85 KB
Newer Older
1 2
# frozen_string_literal: true

3
class GroupsController < Groups::ApplicationController
4
  include API::Helpers::RelatedResourcesHelpers
5
  include IssuableCollectionsAction
6
  include ParamsBackwardCompatibility
7
  include PreviewMarkdown
8
  include RecordUserLastActivity
9

randx's avatar
randx committed
10
  respond_to :html
11

12 13 14
  prepend_before_action(only: [:show, :issues]) { authenticate_sessionless_user!(:rss) }
  prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) }

15
  before_action :authenticate_user!, only: [:new, :create]
16
  before_action :group, except: [:index, :new, :create]
randx's avatar
randx committed
17

18
  # Authorize
19
  before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects, :transfer]
20
  before_action :authorize_create_group!, only: [:new]
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
21

22
  before_action :group_projects, only: [:projects, :activity, :issues, :merge_requests]
23
  before_action :event_filter, only: [:activity]
24

25
  before_action :user_actions, only: [:show]
26

27 28 29 30 31 32
  skip_cross_project_access_check :index, :new, :create, :edit, :update,
                                  :destroy, :projects
  # When loading show as an atom feed, we render events that could leak cross
  # project information
  skip_cross_project_access_check :show, if: -> { request.format.html? }

33 34
  layout :determine_layout

35
  def index
36
    redirect_to(current_user ? dashboard_groups_path : explore_groups_path)
37 38
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
39
  def new
40
    @group = Group.new(params.permit(:parent_id))
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
41 42 43
  end

  def create
Felipe Artur's avatar
Felipe Artur committed
44
    @group = Groups::CreateService.new(current_user, group_params).execute
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
45

Felipe Artur's avatar
Felipe Artur committed
46
    if @group.persisted?
Z.J. van de Weg's avatar
Z.J. van de Weg committed
47 48 49
      notice = if @group.chat_team.present?
                 "Group '#{@group.name}' and its Mattermost team were successfully created."
               else
Z.J. van de Weg's avatar
Z.J. van de Weg committed
50
                 "Group '#{@group.name}' was successfully created."
Z.J. van de Weg's avatar
Z.J. van de Weg committed
51 52 53
               end

      redirect_to @group, notice: notice
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
54 55 56 57
    else
      render action: "new"
    end
  end
58

randx's avatar
randx committed
59 60
  def show
    respond_to do |format|
61 62 63
      format.html do
        render_show_html
      end
64

65
      format.atom do
66 67 68 69 70 71 72 73 74 75 76 77 78
        render_details_view_atom
      end
    end
  end

  def details
    respond_to do |format|
      format.html do
        render_details_html
      end

      format.atom do
        render_details_view_atom
79
      end
randx's avatar
randx committed
80 81 82
    end
  end

83
  def activity
84
    respond_to do |format|
85 86
      format.html

87 88 89 90 91 92 93
      format.json do
        load_events
        pager_json("events/_events", @events.count)
      end
    end
  end

94
  def edit
95
    @badge_api_endpoint = expose_url(api_v4_groups_badges_path(id: @group.id))
96 97
  end

98
  def projects
99
    @projects = @group.projects.with_statistics.page(params[:page])
100 101
  end

102
  def update
103
    if Groups::UpdateService.new(@group, current_user, group_params).execute
104
      redirect_to edit_group_path(@group, anchor: params[:update_section]), notice: "Group '#{@group.name}' was successfully updated."
105
    else
Heinrich Lee Yu's avatar
Heinrich Lee Yu committed
106
      @group.path = @group.path_before_last_save || @group.path_was
James Lopez's avatar
James Lopez committed
107

108
      render action: "edit"
109 110 111 112
    end
  end

  def destroy
113
    Groups::DestroyService.new(@group, current_user).async_execute
114

115
    redirect_to root_path, status: 302, alert: "Group '#{@group.name}' was scheduled for deletion."
116 117
  end

118
  # rubocop: disable CodeReuse/ActiveRecord
119 120 121 122 123 124 125 126
  def transfer
    parent_group = Group.find_by(id: params[:new_parent_group_id])
    service = ::Groups::TransferService.new(@group, current_user)

    if service.execute(parent_group)
      flash[:notice] = "Group '#{@group.name}' was successfully transferred."
      redirect_to group_path(@group)
    else
127 128
      flash[:alert] = service.error
      redirect_to edit_group_path(@group)
129 130
    end
  end
131
  # rubocop: enable CodeReuse/ActiveRecord
132

randx's avatar
randx committed
133 134
  protected

135 136 137 138 139 140 141 142 143 144 145 146 147
  def render_show_html
    render 'groups/show'
  end

  def render_details_html
    render 'groups/show'
  end

  def render_details_view_atom
    load_events
    render layout: 'xml.atom', template: 'groups/show'
  end

148
  # rubocop: disable CodeReuse/ActiveRecord
149
  def authorize_create_group!
150 151 152 153 154 155 156 157
    allowed = if params[:parent_id].present?
                parent = Group.find_by(id: params[:parent_id])
                can?(current_user, :create_subgroup, parent)
              else
                can?(current_user, :create_group)
              end

    render_404 unless allowed
158
  end
159
  # rubocop: enable CodeReuse/ActiveRecord
160

161
  def determine_layout
162
    if [:new, :create].include?(action_name.to_sym)
163
      'application'
164 165
    elsif [:edit, :update, :projects].include?(action_name.to_sym)
      'group_settings'
166
    else
167
      'group'
168 169
    end
  end
170

171
  def group_params
172
    params.require(:group).permit(group_params_attributes)
173 174
  end

175
  def group_params_attributes
176
    [
177
      :avatar,
178
      :description,
179
      :emails_disabled,
180 181
      :lfs_enabled,
      :name,
182 183 184
      :path,
      :public,
      :request_access_enabled,
185
      :share_with_group_lock,
186
      :visibility_level,
187
      :parent_id,
Z.J. van de Weg's avatar
Z.J. van de Weg committed
188
      :create_chat_team,
189 190
      :chat_team_name,
      :require_two_factor_authentication,
Gosia Ksionek's avatar
Gosia Ksionek committed
191
      :two_factor_grace_period,
192 193
      :project_creation_level,
      :subgroup_creation_level
194
    ]
195
  end
196

197
  # rubocop: disable CodeReuse/ActiveRecord
198
  def load_events
199 200 201
    params[:sort] ||= 'latest_activity_desc'

    options = {}
202
    options[:include_subgroups] = true
203 204 205 206 207

    @projects = GroupProjectsFinder.new(params: params, group: group, options: options, current_user: current_user)
                  .execute
                  .includes(:namespace)

208
    @events = EventCollection
209 210
                .new(@projects, offset: params[:offset].to_i, filter: event_filter)
                .to_a
211

212 213 214
    Events::RenderService
      .new(current_user)
      .execute(@events, atom_request: request.format.atom?)
215
  end
216
  # rubocop: enable CodeReuse/ActiveRecord
217 218 219 220 221 222

  def user_actions
    if current_user
      @notification_setting = current_user.notification_settings_for(group)
    end
  end
223 224 225

  def build_canonical_path(group)
    return group_path(group) if action_name == 'show' # root group path
226

227 228
    params[:id] = group.to_param

229
    url_for(safe_params)
230
  end
randx's avatar
randx committed
231
end