Read about our upcoming Code of Conduct on this issue

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

Valery Sizov's avatar
Valery Sizov committed
3
class GroupsController < Groups::ApplicationController
4
  include API::Helpers::RelatedResourcesHelpers
5
  include IssuableCollectionsAction
6
  include ParamsBackwardCompatibility
7
  include PreviewMarkdown
8
  include RecordUserLastActivity
9

10
11
12
13
  before_action do
    push_frontend_feature_flag(:manual_sorting)
  end

randx's avatar
randx committed
14
  respond_to :html
15

16
17
18
  prepend_before_action(only: [:show, :issues]) { authenticate_sessionless_user!(:rss) }
  prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) }

Douwe Maan's avatar
Douwe Maan committed
19
  before_action :authenticate_user!, only: [:new, :create]
20
  before_action :group, except: [:index, :new, :create]
randx's avatar
randx committed
21

22
  # Authorize
23
  before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects, :transfer]
24
  before_action :authorize_create_group!, only: [:new]
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
25

26
  before_action :group_projects, only: [:projects, :activity, :issues, :merge_requests]
27
  before_action :event_filter, only: [:activity]
28

29
  before_action :user_actions, only: [:show]
30

31
32
33
34
35
36
  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? }

37
38
  layout :determine_layout

39
  def index
40
    redirect_to(current_user ? dashboard_groups_path : explore_groups_path)
41
42
  end

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
43
  def new
44
    @group = Group.new(params.permit(:parent_id))
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
45
46
47
  end

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

Felipe Artur's avatar
Felipe Artur committed
50
    if @group.persisted?
Z.J. van de Weg's avatar
Z.J. van de Weg committed
51
52
53
      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
54
                 "Group '#{@group.name}' was successfully created."
Z.J. van de Weg's avatar
Z.J. van de Weg committed
55
56
57
               end

      redirect_to @group, notice: notice
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
58
59
60
61
    else
      render action: "new"
    end
  end
62

randx's avatar
randx committed
63
64
  def show
    respond_to do |format|
65
66
67
      format.html do
        render_show_html
      end
68

69
      format.atom do
70
71
72
73
74
75
76
77
78
79
80
81
82
        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
83
      end
randx's avatar
randx committed
84
85
86
    end
  end

87
  def activity
88
    respond_to do |format|
89
90
      format.html

91
92
93
94
95
96
97
      format.json do
        load_events
        pager_json("events/_events", @events.count)
      end
    end
  end

98
  def edit
99
    @badge_api_endpoint = expose_url(api_v4_groups_badges_path(id: @group.id))
100
101
  end

Felipe Artur's avatar
Felipe Artur committed
102
  def projects
Markus Koller's avatar
Markus Koller committed
103
    @projects = @group.projects.with_statistics.page(params[:page])
Felipe Artur's avatar
Felipe Artur committed
104
105
  end

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

112
      render action: "edit"
113
114
115
116
    end
  end

  def destroy
117
    Groups::DestroyService.new(@group, current_user).async_execute
118

119
    redirect_to root_path, status: 302, alert: "Group '#{@group.name}' was scheduled for deletion."
120
121
  end

122
  # rubocop: disable CodeReuse/ActiveRecord
123
124
125
126
127
128
129
130
  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
131
132
      flash[:alert] = service.error
      redirect_to edit_group_path(@group)
133
134
    end
  end
135
  # rubocop: enable CodeReuse/ActiveRecord
136

randx's avatar
randx committed
137
138
  protected

139
140
141
142
143
144
145
146
147
148
149
150
151
  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

152
  # rubocop: disable CodeReuse/ActiveRecord
153
  def authorize_create_group!
154
155
156
157
158
159
160
161
    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
162
  end
163
  # rubocop: enable CodeReuse/ActiveRecord
164

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

175
  def group_params
176
    params.require(:group).permit(group_params_attributes)
177
178
  end

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

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

    options = {}
204
    options[:include_subgroups] = true
205
206
207
208
209

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

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

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

  def user_actions
    if current_user
      @notification_setting = current_user.notification_settings_for(group)
    end
  end
225
226
227

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

229
230
    params[:id] = group.to_param

blackst0ne's avatar
blackst0ne committed
231
    url_for(safe_params)
232
  end
randx's avatar
randx committed
233
end