summaryrefslogtreecommitdiff
path: root/app/models/ci/user.rb
blob: 7456bd1a77b2d201c7aecd42ae6d04c99d41e6ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# User object is stored in session
module Ci
  class User
    DEVELOPER_ACCESS = 30

    attr_reader :attributes

    def initialize(hash)
      @attributes = hash
    end

    def gitlab_projects(search = nil, page = 1, per_page = 100)
      Rails.cache.fetch(cache_key(page, per_page, search)) do
        Ci::Project.from_gitlab(self, :authorized, { page: page, per_page: per_page, search: search, ci_enabled_first: true })
      end
    end

    def method_missing(meth, *args, &block)
      if attributes.has_key?(meth.to_s)
        attributes[meth.to_s]
      else
        super
      end
    end

    def avatar_url
      attributes['avatar_url']
    end

    def cache_key(*args)
      "#{self.id}:#{args.join(":")}:#{sync_at.to_s}"
    end

    def sync_at
      @sync_at ||= Time.now
    end

    def reset_cache
      @sync_at = Time.now
    end

    def can_access_project?(project_gitlab_id)
      !!project_info(project_gitlab_id)
    end

    # Indicate if user has developer access or higher
    def has_developer_access?(project_gitlab_id)
      data = project_info(project_gitlab_id)

      return false unless data && data["permissions"]

      permissions = data["permissions"]

      if permissions["project_access"] && permissions["project_access"]["access_level"] >= DEVELOPER_ACCESS
        return true
      end

      if permissions["group_access"] && permissions["group_access"]["access_level"] >= DEVELOPER_ACCESS
        return true
      end
    end

    def can_manage_project?(project_gitlab_id)
      Rails.cache.fetch(cache_key('manage', project_gitlab_id, sync_at)) do
        !!Ci::Network.new.project_hooks(authenticate_options, project_gitlab_id)
      end
    end

    def authorized_runners
      Ci::Runner.specific.includes(:runner_projects).
        where(runner_projects: { project_id: authorized_projects } )
    end

    def authorized_projects
      Ci::Project.where(gitlab_id: gitlab_projects.map(&:id)).select do |project|
        # This is slow: it makes request to GitLab for each project to verify manage permission
        can_manage_project?(project.gitlab_id)
      end
    end

    def authenticate_options
      if attributes['access_token']
        { access_token: attributes['access_token'] }
      else
        { private_token: attributes['private_token'] }
      end
    end

    private

    def project_info(project_gitlab_id)
      Rails.cache.fetch(cache_key("project_info", project_gitlab_id, sync_at)) do
        Ci::Network.new.project(authenticate_options, project_gitlab_id)
      end
    end
  end
end