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

MarkUsProject / Markus / 26985117764

04 Jun 2026 11:10PM UTC coverage: 84.913% (-5.3%) from 90.19%
26985117764

Pull #7972

github

web-flow
Merge c18340c77 into 9a5124c61
Pull Request #7972: Parallelize rspec tests

1023 of 2226 branches covered (45.96%)

Branch coverage included in aggregate %.

36935 of 42476 relevant lines covered (86.95%)

113.68 hits per line

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

91.84
/app/controllers/api/main_api_controller.rb
1
# Scripting API handlers for MarkUs
2
module Api
3✔
3
  # This is the parent class of all API controllers. Shared functionality of
4
  # all API controllers should go here.
5
  class MainApiController < ActionController::Base # rubocop:disable Rails/ApplicationController
3✔
6
    include SessionHandler
3✔
7
    include ActionPolicy::Controller
3✔
8

9
    before_action :check_format, :check_record, :authenticate
3✔
10
    skip_before_action :verify_authenticity_token
3✔
11

12
    authorize :real_user, through: :real_user
3✔
13
    authorize :real_role, through: :real_role
3✔
14
    authorize :role, through: :current_role
3✔
15
    verify_authorized
3✔
16
    rescue_from ActionPolicy::Unauthorized, with: :user_not_authorized
3✔
17
    before_action { authorize! }
416✔
18

19
    AUTHTYPE = 'MarkUsAuth'.freeze
3✔
20
    AUTH_TOKEN_REGEX = /#{AUTHTYPE} ([^\s,]+)/
3✔
21

22
    def page_not_found(message = HttpStatusHelper::ERROR_CODE['message']['404'])
3✔
23
      render 'shared/http_status',
43✔
24
             locals: { code: '404', message: message },
25
             status: :not_found,
26
             formats: request.format.symbol
27
    end
28

29
    private
3✔
30

31
    # Auth handler for the MarkUs API. It uses the Authorization HTTP header to
32
    # determine the user who issued the request. With the Authorization
33
    # HTTP header comes a Base 64 encoded MD5 digest of the user's private key.
34
    # Note that remote authentication is not supported. API key must be used.
35
    def authenticate
3✔
36
      api_key = parse_auth_token(request.headers['HTTP_AUTHORIZATION'])
453✔
37
      return user_not_authorized if api_key.nil?
453✔
38
      @real_user = User.find_by(api_key: parse_auth_token(request.headers['HTTP_AUTHORIZATION']))
413✔
39
      user_not_authorized if @real_user.nil?
413✔
40
    end
41

42
    # Make sure that the passed format is either xml or json
43
    # If no format is provided, default to XML
44
    def check_format
3✔
45
      # This allows us to support content negotiation
46
      if request.headers['HTTP_ACCEPT'].nil? || request.format == '*/*'
496✔
47
        request.format = 'xml'
240✔
48
      end
49

50
      request_format = request.format.symbol
496✔
51
      if request_format != :xml && request_format != :json
496✔
52
        # 406 is the default status code when the format is not support
53
        head :not_acceptable
×
54
      end
55
    end
56

57
    # Helper method for parsing the authentication token
58
    def parse_auth_token(token)
3✔
59
      return if token.nil?
866✔
60
      if token =~ AUTH_TOKEN_REGEX
866✔
61
        Regexp.last_match(1) # return matched part
826✔
62
      end
63
    end
64

65
    # Helper method for filtering
66
    # Ignores default_scope order, always order by id to be consistent
67
    #
68
    # Renders an error message and returns false if the filters are malformed
69
    def get_collection(collection)
3✔
70
      filter_params = params[:filter] ? params[:filter].permit(self.class::DEFAULT_FIELDS) : {}
91✔
71
      if params[:filter].present? && filter_params.empty?
91✔
72
        render 'shared/http_status', locals: { code: '422', message:
×
73
          'Invalid or malformed parameter values' }, status: :unprocessable_content
74
        false
×
75
      elsif filter_params.empty?
91✔
76
        collection.order(:id)
91✔
77
      else
78
        collection.order(:id).where(**filter_params)
×
79
      end
80
    end
81

82
    # Checks that the symbols provided in the array aren't blank in the params
83
    def has_missing_params?(required_params)
3✔
84
      required_params.each do |param|
112✔
85
        return true if params[param].blank?
186✔
86
      end
87
      false
104✔
88
    end
89

90
    def user_not_authorized
3✔
91
      render 'shared/http_status',
67✔
92
             locals: { code: '403', message: HttpStatusHelper::ERROR_CODE['message']['403'] },
93
             status: :forbidden,
94
             formats: request.format.symbol
95
    end
96

97
    protected
3✔
98

99
    def implicit_authorization_target
3✔
100
      OpenStruct.new policy_class: MainApiPolicy
247✔
101
    end
102
  end
103
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