gprov 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,44 @@
1
+ # Generic representation of the various types of feeds available from the
2
+ # provisioning api
3
+ require 'gprov'
4
+ require 'nokogiri'
5
+
6
+ module GProv
7
+ module Provision
8
+ class Feed
9
+
10
+ attr_reader :results
11
+ def initialize(connection, path, xpath)
12
+ @connection = connection
13
+ @url = path
14
+ @xpath = xpath
15
+
16
+ @results = []
17
+ end
18
+
19
+ def fetch
20
+ retrieve_page
21
+ @results
22
+ end
23
+
24
+ private
25
+
26
+ def retrieve_page
27
+ response = @connection.get(@url)
28
+
29
+ if response.code == 200
30
+ document = Nokogiri::XML(response.body)
31
+ entries = document.xpath(@xpath)
32
+
33
+ @results.concat(entries.to_a)
34
+ end
35
+ end
36
+
37
+ def retrieve_all
38
+ raise NotImplementedError
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,147 @@
1
+ # = gprov/provision/group.rb: implementation of the gprov provisioning groupentry
2
+ #
3
+ # == Overview
4
+ #
5
+ # implementation of the gprov provisioning groupentry
6
+ #
7
+ # == Authors
8
+ #
9
+ # Adrien Thebo
10
+ #
11
+ # == Copyright
12
+ #
13
+ # 2011 Puppet Labs
14
+ #
15
+ require 'gprov'
16
+ require 'gprov/provision/entrybase'
17
+ require 'gprov/provision/member'
18
+ require 'gprov/provision/owner'
19
+ module GProv
20
+ module Provision
21
+ class Group < GProv::Provision::EntryBase
22
+
23
+ # TODO copy group_id on instantiation so that groups can change
24
+ # their IDs without exploding
25
+ xmlattr :group_id, :xpath => %Q{apps:property[@name = "groupId"]/@value}
26
+ xmlattr :group_name, :xpath => %Q{apps:property[@name = "groupName"]/@value}
27
+ xmlattr :email_permission, :xpath => %Q{apps:property[@name = "emailPermission"]/@value}
28
+ xmlattr :permission_preset, :xpath => %Q{apps:property[@name = "permissionPreset"]/@value}
29
+ xmlattr :description, :xpath => %Q{apps:property[@name = "description"]/@value}
30
+
31
+ # Retrieves all users within a domain
32
+ def self.all(connection, options={})
33
+
34
+ # TODO Fail if unrecognized options passed
35
+ url = "/group/2.0/:domain"
36
+ if member = options[:member]
37
+ url << "/?member=#{member}"
38
+
39
+ if direct_only = options[:direct_only]
40
+ url << "&directOnly=#{direct_only}"
41
+ end
42
+ end
43
+
44
+ feed = GProv::Provision::Feed.new(connection, url, "/xmlns:feed/xmlns:entry")
45
+ entries = feed.fetch
46
+ entries.map { |xml| new(:status => :clean, :connection => connection, :source => xml) }
47
+ end
48
+
49
+ def self.get(connection, group_id)
50
+ response = connection.get("/group/2.0/:domain/#{group_id}")
51
+ document = Nokogiri::XML(response.body)
52
+ xml = document.root
53
+
54
+ new(:status => :clean, :connection => connection, :source => xml)
55
+ end
56
+
57
+ def to_nokogiri
58
+ base_document = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
59
+ xml.entry('xmlns:atom' => 'http://www.w3.org/2005/Atom',
60
+ 'xmlns:apps' => 'http://schemas.google.com/apps/2006',
61
+ 'xmlns:gd' => "http://schemas.google.com/g/2005" ) {
62
+
63
+ # Namespaces cannot be used until they are declared, so we need to
64
+ # retroactively declare the namespace of the parent
65
+ xml.parent.namespace = xml.parent.namespace_definitions.select {|ns| ns.prefix == "atom"}.first
66
+ xml.category("scheme" => "http://schemas.google.com/g/2005#kind",
67
+ "term" =>"http://schemas.google.com/apps/2006#user")
68
+
69
+ xml['apps'].property("name" => "groupId", "value" => @group_id)
70
+ xml['apps'].property("name" => "groupName", "value" => @group_name)
71
+ xml['apps'].property("name" => "emailPermission", "value" => @email_permission)
72
+ xml['apps'].property("name" => "description", "value" => @description)
73
+ }
74
+ end
75
+
76
+ base_document
77
+ end
78
+
79
+ def create!
80
+ response = connection.post("/group/2.0/:domain", {:body => to_nokogiri.to_xml})
81
+ status = :clean
82
+ end
83
+
84
+ def update!
85
+ response = connection.put("/group/2.0/:domain", {:body => to_nokogiri.to_xml})
86
+ status = :clean
87
+ end
88
+
89
+ def delete!
90
+ response = connection.put("/group/2.0/:domain/#{group_id}")
91
+ status = :deleted
92
+ end
93
+
94
+ def add_member(membername)
95
+ member = GProv::Provision::Member.new(
96
+ :connection => @connection,
97
+ :source => {
98
+ :group_id => @group_id,
99
+ :member_id => membername,
100
+ }
101
+ )
102
+ member.create!
103
+ end
104
+
105
+ def del_member(membername)
106
+ member = GProv::Provision::Member.new(
107
+ :connection => @connection,
108
+ :source => {
109
+ :group_id => @group_id,
110
+ :member_id => membername,
111
+ }
112
+ )
113
+ member.delete!
114
+ end
115
+
116
+ def list_members
117
+ GProv::Provision::Member.all(@connection, @group_id)
118
+ end
119
+
120
+ def add_owner(ownername)
121
+ owner = GProv::Provision::Owner.new(
122
+ :connection => @connection,
123
+ :source => {
124
+ :group_id => @group_id,
125
+ :email => ownername,
126
+ }
127
+ )
128
+ owner.create!
129
+ end
130
+
131
+ def del_owner(ownername)
132
+ owner = GProv::Provision::Owner.new(
133
+ :connection => @connection,
134
+ :source => {
135
+ :group_id => @group_id,
136
+ :email => ownername,
137
+ }
138
+ )
139
+ owner.delete!
140
+ end
141
+
142
+ def list_owners
143
+ GProv::Provision::Owner.all(@connection, @group_id)
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,48 @@
1
+ # Representation of group members
2
+ require 'gprov'
3
+ require 'gprov/provision/entrybase'
4
+
5
+ module GProv
6
+ module Provision
7
+ class Member < GProv::Provision::EntryBase
8
+
9
+ xmlattr :member_id, :xpath => %Q{apps:property[@name = "memberId"]/@value}
10
+ xmlattr :member_type, :xpath => %Q{apps:property[@name = "memberType"]/@value}
11
+ xmlattr :direct_member, :xpath => %Q{apps:property[@name = "directMember"]/@value}
12
+ attr_accessor :group_id
13
+
14
+ def self.all(connection, group_id)
15
+ feed = GProv::Provision::Feed.new(connection, "/group/2.0/:domain/#{group_id}/member", "/xmlns:feed/xmlns:entry")
16
+ entries = feed.fetch
17
+ entries.map { |xml| new(:status => :clean, :connection => connection, :source => xml) }
18
+ end
19
+
20
+ def to_nokogiri
21
+ base_document = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
22
+ xml.entry('xmlns:atom' => 'http://www.w3.org/2005/Atom',
23
+ 'xmlns:apps' => 'http://schemas.google.com/apps/2006',
24
+ 'xmlns:gd' => "http://schemas.google.com/g/2005" ) {
25
+
26
+ # Namespaces cannot be used until they are declared, so we need to
27
+ # retroactively declare the namespace of the parent
28
+ xml.parent.namespace = xml.parent.namespace_definitions.select {|ns| ns.prefix == "atom"}.first
29
+
30
+ xml['apps'].property("name" => "memberId", "value" => @member_id)
31
+ }
32
+ end
33
+
34
+ base_document
35
+ end
36
+
37
+ def create!
38
+ response = connection.post("/group/2.0/:domain/#{@group_id}/member", {:body => to_nokogiri.to_xml})
39
+ status = :clean
40
+ end
41
+
42
+ def delete!
43
+ response = connection.delete("/group/2.0/:domain/#{@group_id}/member/#{@member_id}")
44
+ status = :clean
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,84 @@
1
+ # = gprov/provision/orgmember.rb
2
+ #
3
+ # == Overview
4
+ #
5
+ # Representation of the members of organizational units
6
+ #
7
+ # == Authors
8
+ #
9
+ # Adrien Thebo
10
+ #
11
+ # == Copyright
12
+ #
13
+ # 2011 Puppet Labs
14
+ #
15
+ require 'gprov'
16
+ require 'gprov/provision/feed'
17
+ require 'gprov/provision/entrybase'
18
+ module GProv
19
+ module Provision
20
+ class OrgMember < GProv::Provision::EntryBase
21
+
22
+ # This attribute will only be received and never sent
23
+ xmlattr :org_user_email, :xpath => %Q{apps:property[@name = "orgUserEmail"]/@value}
24
+ xmlattr :org_unit_path, :xpath => %Q{apps:property[@name = "orgUnitPath"]/@value}
25
+
26
+ # Retrieve all organization users in the domain.
27
+ def self.all(connection, options = {:target => :all})
28
+ id = GProv::Provision::CustomerID.get(connection)
29
+
30
+ case options[:target]
31
+ when :orgunit
32
+ # XXX validation
33
+ url = "/orguser/2.0/#{id.customer_id}?get=children&orgUnitPath=#{options[:orgunit]}"
34
+ when :all
35
+ url = "/orguser/2.0/#{id.customer_id}?get=all"
36
+ end
37
+
38
+ feed = GProv::Provision::Feed.new(connection, url, "/xmlns:feed/xmlns:entry")
39
+ entries = feed.fetch
40
+ entries.map { |xml| new(:status => :clean, :connection => connection, :source => xml) }
41
+ end
42
+
43
+ def self.get(connection, email)
44
+ id = GProv::Provision::CustomerID.get(connection)
45
+ response = connection.get("/orguser/2.0/#{id.customer_id}/#{email}")
46
+
47
+ document = Nokogiri::XML(response.body)
48
+ xml = document.root
49
+
50
+ new(:status => :clean, :connection => connection, :source => xml)
51
+ end
52
+
53
+ # This attribute will only be sent and never received
54
+ def initialize(opts={})
55
+ super
56
+ # Generate this variable in the case that the org_unit_path is updated
57
+ @old_org_unit_path = @org_unit_path
58
+ end
59
+
60
+ def to_nokogiri
61
+ base_document = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
62
+ xml.entry('xmlns:atom' => 'http://www.w3.org/2005/Atom',
63
+ 'xmlns:apps' => 'http://schemas.google.com/apps/2006',
64
+ 'xmlns:gd' => "http://schemas.google.com/g/2005" ) {
65
+
66
+ # Namespaces cannot be used until they are declared, so we need to
67
+ # retroactively declare the namespace of the parent
68
+ xml.parent.namespace = xml.parent.namespace_definitions.select {|ns| ns.prefix == "atom"}.first
69
+
70
+ xml['apps'].property("name" => "orgUnitPath", "value" => @org_unit_path)
71
+ xml['apps'].property("name" => "oldOrgUnitPath", "value" => @old_org_unit_path)
72
+ }
73
+ end
74
+ end
75
+
76
+ def update!
77
+ id = GProv::Provision::CustomerID.get(connection)
78
+ response = connection.put("/orguser/2.0/#{id.customer_id}/#{@org_user_email}", {:body => to_nokogiri.to_xml})
79
+ status = :clean
80
+ end
81
+ end
82
+ end
83
+ end
84
+
@@ -0,0 +1,89 @@
1
+ # = gprov/provision/orgunit.rb
2
+ #
3
+ # == Overview
4
+ #
5
+ # implementation of the gprov organizational unit
6
+ #
7
+ # == Authors
8
+ #
9
+ # Adrien Thebo
10
+ #
11
+ # == Copyright
12
+ #
13
+ # 2011 Puppet Labs
14
+ #
15
+ require 'gprov'
16
+ require 'gprov/provision/feed'
17
+ require 'gprov/provision/entrybase'
18
+ require 'gprov/provision/customerid'
19
+ require 'gprov/provision/orgmember'
20
+ module GProv
21
+ module Provision
22
+ class OrgUnit < GProv::Provision::EntryBase
23
+
24
+ xmlattr :name, :xpath => %Q{apps:property[@name = "name"]/@value}
25
+ xmlattr :description, :xpath => %Q{apps:property[@name = "description"]/@value}
26
+ xmlattr :org_unit_path, :xpath => %Q{apps:property[@name = "orgUnitPath"]/@value}
27
+ xmlattr :parent_org_unit_path, :xpath => %Q{apps:property[@name = "parentOrgUnitPath"]/@value}
28
+ xmlattr :block_inheritance, :xpath => %Q{apps:property[@name = "blockInheritance"]/@value}
29
+
30
+ def self.all(connection)
31
+ id = GProv::Provision::CustomerID.get(connection)
32
+ feed = GProv::Provision::Feed.new(connection, "/orgunit/2.0/#{id.customer_id}?get=all", "/xmlns:feed/xmlns:entry")
33
+ entries = feed.fetch
34
+ entries.map { |xml| new(:status => :clean, :connection => connection, :source => xml) }
35
+ end
36
+
37
+ def self.get(connection, org_path)
38
+ id = GProv::Provision::CustomerID.get(connection)
39
+ response = connection.get("/orgunit/2.0/#{id.customer_id}/#{org_path}")
40
+ document = Nokogiri::XML(response.body)
41
+ xml = document.root
42
+
43
+ new(:status => :clean, :connection => connection, :source => xml)
44
+ end
45
+
46
+ def to_nokogiri
47
+ base_document = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
48
+ xml.entry('xmlns:atom' => 'http://www.w3.org/2005/Atom',
49
+ 'xmlns:apps' => 'http://schemas.google.com/apps/2006',
50
+ 'xmlns:gd' => "http://schemas.google.com/g/2005" ) {
51
+
52
+ # Namespaces cannot be used until they are declared, so we need to
53
+ # retroactively declare the namespace of the parent
54
+ xml.parent.namespace = xml.parent.namespace_definitions.select {|ns| ns.prefix == "atom"}.first
55
+
56
+ xml['apps'].property("name" => "name", "value" => @name)
57
+ xml['apps'].property("name" => "description", "value" => @description)
58
+ xml['apps'].property("name" => "parentOrgUnitPath", "value" => @parent_org_unit_path)
59
+ xml['apps'].property("name" => "blockInheritance", "value" => @block_inheritance)
60
+ }
61
+ end
62
+ end
63
+
64
+ def create!
65
+ # xxx cache this?
66
+ id = GProv::Provision::CustomerID.get(connection)
67
+ response = connection.post("/orgunit/2.0/#{id.customer_id}")
68
+ status = :clean
69
+ end
70
+
71
+ def update!
72
+ # xxx cache this?
73
+ id = GProv::Provision::Customerid.get(connection)
74
+ response = connection.put("/orgunit/2.0/#{id.customer_id}/#{@org_unit_path}")
75
+ status = :clean
76
+ end
77
+
78
+ def delete!
79
+ id = GProv::Provision::Customerid.get(connection)
80
+ response = connection.delete("/orgunit/2.0/#{id.customer_id}/#{@org_unit_path}")
81
+ status = :deleted
82
+ end
83
+
84
+ def list_members
85
+ GProv::Provision::OrgMember.all(connection, :target => :orgunit, :orgunit => @org_unit_path)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,46 @@
1
+ # Representation of group owners
2
+ require 'gprov'
3
+ require 'gprov/provision/entrybase'
4
+
5
+ module GProv
6
+ module Provision
7
+ class Owner < GProv::Provision::EntryBase
8
+
9
+ xmlattr :email, :xpath => %Q{apps:property[@name = "email"]/@value}
10
+ attr_accessor :group_id
11
+
12
+ def self.all(connection, group_id)
13
+ feed = GProv::Provision::Feed.new(connection, "/group/2.0/:domain/#{group_id}/owner", "/xmlns:feed/xmlns:entry")
14
+ entries = feed.fetch
15
+ entries.map { |xml| new(:status => :clean, :connection => connection, :source => xml) }
16
+ end
17
+
18
+ def to_nokogiri
19
+ base_document = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
20
+ xml.entry('xmlns:atom' => 'http://www.w3.org/2005/Atom',
21
+ 'xmlns:apps' => 'http://schemas.google.com/apps/2006',
22
+ 'xmlns:gd' => "http://schemas.google.com/g/2005" ) {
23
+
24
+ # Namespaces cannot be used until they are declared, so we need to
25
+ # retroactively declare the namespace of the parent
26
+ xml.parent.namespace = xml.parent.namespace_definitions.select {|ns| ns.prefix == "atom"}.first
27
+
28
+ xml['apps'].property("name" => "email", "value" => @email)
29
+ }
30
+ end
31
+
32
+ base_document
33
+ end
34
+
35
+ def create!
36
+ response = connection.post("/group/2.0/:domain/#{@group_id}/owner", {:body => to_nokogiri.to_xml})
37
+ status = :clean
38
+ end
39
+
40
+ def delete!
41
+ response = connection.delete("/group/2.0/:domain/#{@group_id}/owner/#{@email}")
42
+ status = :clean
43
+ end
44
+ end
45
+ end
46
+ end