• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MarkUsProject / Markus / 21737220433

06 Feb 2026 03:08AM UTC coverage: 91.707% (-0.01%) from 91.717%
21737220433

Pull #7815

github

web-flow
Merge 66ea8905e into 20f52eeb8
Pull Request #7815: build(deps): bump rails from 8.0.3 to 8.1.2

935 of 1829 branches covered (51.12%)

Branch coverage included in aggregate %.

6 of 7 new or added lines in 3 files covered. (85.71%)

5 existing lines in 2 files now uncovered.

44722 of 47957 relevant lines covered (93.25%)

123.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.65
/app/controllers/api/roles_controller.rb
1
module Api
1✔
2
  # API controller for Roles
3
  class RolesController < MainApiController
1✔
4
    # Define default fields to display for index and show methods
5
    USER_FIELDS = [:user_name, :email, :id_number, :first_name, :last_name].freeze
1✔
6
    ROLE_FIELDS = [:type, :grace_credits, :hidden].freeze
1✔
7
    DEFAULT_FIELDS = [:id, *USER_FIELDS, *ROLE_FIELDS].freeze
1✔
8

9
    # Returns users and their attributes
10
    # Optional: filter, fields
11
    def index
1✔
12
      roles = filtered_roles || return
16✔
13
      respond_to do |format|
16✔
14
        format.xml do
16✔
15
          render xml: roles.to_xml(methods: DEFAULT_FIELDS,
8✔
16
                                   only: DEFAULT_FIELDS,
17
                                   root: :roles,
18
                                   skip_types: true)
19
        end
20
        format.json { render json: roles.to_json(only: DEFAULT_FIELDS, methods: DEFAULT_FIELDS) }
24✔
21
      end
22
    end
23

24
    # Creates a new role and user if it does not exist
25
    # Requires: user_name, type, first_name, last_name
26
    # Optional: section_name, grace_credits
27
    def create
1✔
28
      create_role
25✔
29
    end
30

31
    # Returns a user and its attributes
32
    # Requires: id
33
    # Optional: filter, fields
34
    def show
1✔
35
      role = Role.find_by(id: params[:id])
16✔
36
      if role.nil?
16✔
37
        # No user with that id
38
        render 'shared/http_status', locals: { code: '404', message: 'No user exists with that id' }, status: :not_found
×
39
      elsif role.admin_role? && !@real_user.admin_user?
16✔
40
        render 'shared/http_status',
2✔
41
               locals: { code: '403', message: 'You are not allowed to view information about this user' },
42
               status: :forbidden
43
      else
44
        respond_to do |format|
14✔
45
          format.xml do
14✔
46
            render xml: role.to_xml(methods: DEFAULT_FIELDS,
8✔
47
                                    only: DEFAULT_FIELDS,
48
                                    root: :role,
49
                                    skip_types: true)
50
          end
51
          format.json { render json: role.to_json(only: DEFAULT_FIELDS, methods: DEFAULT_FIELDS) }
20✔
52
        end
53
      end
54
    end
55

56
    # Requires: id
57
    # Optional: first_name, last_name, user_name, section_name, grace_credits
58
    def update
1✔
59
      role = Role.find_by(id: params[:id])
22✔
60
      if role.nil?
22✔
61
        render 'shared/http_status', locals: { code: '404', message: 'User was not found' }, status: :not_found
×
62
      elsif role.admin_role? && !@real_user.admin_user?
22✔
63
        render 'shared/http_status',
2✔
64
               locals: { code: '403', message: 'You are not allowed to update the role of this user' },
65
               status: :forbidden
66
      else
67
        update_role(role)
20✔
68
      end
69
    end
70

71
    # Update a user's attributes based on their user_name as opposed
72
    # to their id (use the regular update method instead)
73
    # Requires: user_name
74
    def update_by_username
1✔
75
      role = find_role_by_username
×
76
      if role.nil?
×
77
        render 'shared/http_status', locals: { code: '404', message: 'Role was not found' }, status: :not_found
×
78
        return
×
79
      elsif role.admin_role? && !@real_user.admin_user?
×
80
        render 'shared/http_status',
×
81
               locals: { code: '403', message: 'You are not allowed to update the role of this user' },
82
               status: :forbidden
83
        return
×
84
      end
85
      update_role(role) unless role.nil?
×
86
    end
87

88
    # Creates a new user or unhides a user if they already exist
89
    # Requires: user_name, type, first_name, last_name
90
    # Optional: section_name, grace_credits
91
    def create_or_unhide
1✔
92
      role = find_role_by_username
29✔
93
      if role.nil?
29✔
94
        create_role
23✔
95
      elsif role.admin_role? && !@real_user.admin_user?
6✔
96
        render 'shared/http_status',
2✔
97
               locals: { code: '403', message: 'You are not allowed to update the role of this user' },
98
               status: :forbidden
99
      else
100
        role.update!(hidden: false)
4✔
101
        render 'shared/http_status', locals: { code: '200', message:
4✔
102
            HttpStatusHelper::ERROR_CODE['message']['200'] }, status: :ok
103
      end
104
    end
105

106
    private
1✔
107

108
    def create_role
1✔
109
      unless role_params[:type] != AdminRole.name || @real_user.admin_user?
48✔
110
        render 'shared/http_status',
2✔
111
               locals: { code: '403', message: 'You are not allowed to create admin roles' },
112
               status: :forbidden
113
        return
2✔
114
      end
115
      ApplicationRecord.transaction do
46✔
116
        user = User.find_by(user_name: params[:user_name])
46✔
117
        role = Role.new(**role_params, user: user, course: @current_course)
46✔
118
        if params[:section_name]
40✔
119
          if params[:section_name].empty?
16✔
UNCOV
120
            role.section = nil
×
121
          else
122
            role.section = @current_course.sections.find_by!(name: params[:section_name])
16✔
123
          end
124
        end
125
        role.grace_credits = params[:grace_credits] if params[:grace_credits]
36✔
126
        role.hidden = params[:hidden].to_s.casecmp('true').zero? if params[:hidden]
36✔
127
        role.save!
36✔
128
        render 'shared/http_status', locals: { code: '201', message:
32✔
129
            HttpStatusHelper::ERROR_CODE['message']['201'] }, status: :created
130
      end
131
    rescue ActiveRecord::SubclassNotFound, ActiveRecord::RecordInvalid, ActiveRecord::RecordNotFound => e
132
      render 'shared/http_status', locals: { code: '422', message: e.to_s }, status: :unprocessable_content
14✔
133
    rescue StandardError
134
      render 'shared/http_status', locals: { code: '500', message:
×
135
          HttpStatusHelper::ERROR_CODE['message']['500'] }, status: :internal_server_error
136
    end
137

138
    def update_role(role)
1✔
139
      ApplicationRecord.transaction do
20✔
140
        if params.key?(:section_name)
20✔
141
          if params[:section_name].blank?
8✔
142
            role.section = nil
4✔
143
          else
144
            role.section = @current_course.sections.find_by!(name: params[:section_name])
4✔
145
          end
146
        end
147
        role.grace_credits = params[:grace_credits] if params.key?(:grace_credits)
18✔
148
        role.hidden = params[:hidden].to_s.casecmp('true').zero? if params.key?(:hidden)
18✔
149
        role.save!
18✔
150
      end
151
      render 'shared/http_status', locals: { code: '200', message:
18✔
152
          HttpStatusHelper::ERROR_CODE['message']['200'] }, status: :ok
153
    rescue ActiveRecord::SubclassNotFound, ActiveRecord::RecordInvalid, ActiveRecord::RecordNotFound => e
154
      render 'shared/http_status', locals: { code: '422', message: e.to_s }, status: :unprocessable_content
2✔
155
    rescue StandardError
156
      render 'shared/http_status', locals: { code: '500', message:
×
157
          HttpStatusHelper::ERROR_CODE['message']['500'] }, status: :internal_server_error
158
    end
159

160
    def find_role_by_username
1✔
161
      if has_missing_params?([:user_name])
29✔
162
        # incomplete/invalid HTTP params
163
        render 'shared/http_status', locals: { code: '422', message:
×
164
            HttpStatusHelper::ERROR_CODE['message']['422'] }, status: :unprocessable_content
165
        return
×
166
      end
167

168
      # Check if that user_name is taken
169
      user = User.find_by(user_name: params[:user_name])
29✔
170
      Role.find_by(user: user, course: @current_course)
29✔
171
    end
172

173
    def filtered_roles
1✔
174
      course_id = params[:course_id]
16✔
175
      collection = Role.includes(:user).where(course_id: course_id).order(:id)
16✔
176
      collection = collection.where.not(type: AdminRole.name) unless @real_user.admin_user?
16✔
177
      if params[:filter].present?
16✔
178
        role_filter = params[:filter].permit(*ROLE_FIELDS).to_h
4✔
179
        user_filter = params[:filter].permit(*USER_FIELDS).to_h.transform_keys { |k| "users.#{k}" }
8✔
180
        filter_params = { **role_filter, **user_filter }
4✔
181
        if filter_params.empty?
4✔
182
          render 'shared/http_status',
×
183
                 locals: { code: '422', message: 'Invalid or malformed parameter values' },
184
                 status: :unprocessable_content
185
          return false
×
186
        else
187
          return collection.where(**filter_params)
4✔
188
        end
189
      end
190
      collection
12✔
191
    end
192

193
    def role_params
1✔
194
      params.permit(:type, :grace_credits, :hidden)
94✔
195
    end
196
  end
197
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc