Builder.apply_impersonation()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
dl 0
loc 9
rs 9.6666
1
# frozen_string_literal: true
2
3
require 'set'
4
5
require_relative '../model/policy'
6
7
module AMA
8
  module Chef
9
    module User
10
      module State
11
        # Simple class that builds target state by applying partitions to
12
        # clients
13
        class Builder
14
          # @param [Hash{Symbol, AMA::Chef::User::Model::Client}] clients
15
          # @param [Hash{Symbol, AMA::Chef::User::Model::Partition}] partitions
16
          # @return [AMA::Chef::User::Model::State]
17
          def build(clients, partitions)
18
            state = Model::State.new
19
            partitions.values.each do |partition|
20
              process_partition(state, partition, clients)
21
            end
22
            clean_state(state)
23
            state
24
          end
25
26
          private
27
28
          # @param [AMA::Chef::User::Model::State] state
29
          # @param [AMA::Chef::User::Model::Partition] partition
30
          # @param [Hash<Symbol, AMA::Chef::User::Model::Client>] clients
31
          def process_partition(state, partition, clients)
32
            unless partition.policy.group == Model::Policy::NONE
33
              state.groups[partition.id] = extract_group(partition)
34
            end
35
            clients.values.each do |client|
36
              next unless partition.applies_to(client)
37
              apply_partition(state, client, partition)
38
            end
39
          end
40
41
          # @param [AMA::Chef::User::Model::State] state
42
          # @param [AMA::Chef::User::Model::Client] client
43
          # @param [AMA::Chef::User::Model::Partition] partition
44
          def apply_partition(state, client, partition)
45
            account = extract_account(client, partition)
46
            state.account!(client.id).merge(account)
47
            apply_impersonation(state, client, partition)
48
            return unless partition.policy.group != Model::Policy::NONE
49
            state.group(partition.id).members.add(account.id)
50
          end
51
52
          # @param [AMA::Chef::User::Model::State] state
53
          def clean_state(state)
54
            state.accounts.reject! do |_, account|
55
              account.policy == Model::Policy::NONE
56
            end
57
            state.groups.reject! do |_, group|
58
              group.policy == Model::Policy::NONE
59
            end
60
            state
61
          end
62
63
          def extract_group(partition)
64
            group = Model::Group.new(partition.id)
65
            group.policy = partition.policy.group
66
            group.privileges = partition.privileges.clone
67
            group
68
          end
69
70
          # rubocop:disable Metrics/AbcSize
71
          def extract_account(client, partition)
72
            account = Model::Account.new(client.id)
73
            account.policy = partition.policy.account
74
            unless client.public_keys.empty?
75
              account.public_keys!(client.id).merge!(client.public_keys)
76
            end
77
            unless client.private_keys.empty?
78
              account.private_keys!(client.id).merge!(client.private_keys)
79
            end
80
            if partition.policy.group.nothing? && !partition.privileges.empty?
81
              account.privileges = partition.privileges.clone
82
            end
83
            account
84
          end
85
          # rubocop:enable Metrics/AbcSize
86
87
          def apply_impersonation(state, client, partition)
88
            return if client.public_keys.empty?
89
            partition.impersonation.keys.each do |hijacked|
90
              package = Model::Account.new(hijacked)
91
              package.policy = :edit
92
              package.public_keys!(client.id).merge!(client.public_keys)
93
              state.account!(hijacked).merge(package)
94
            end
95
          end
96
        end
97
      end
98
    end
99
  end
100
end
101