artifactory 2.1.3 → 2.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ccfaa5ca0cc4863850ec3838804360dbeab5680
4
- data.tar.gz: f1a22d50c6a7ebecedb5f2f6bd1d2b73778b2a0a
3
+ metadata.gz: b89a0d205ba82632c1f9b538a50b84f69b67ac0f
4
+ data.tar.gz: 1484191f4caf8502ca9ec7519d97c67fe5cc51f7
5
5
  SHA512:
6
- metadata.gz: 03c8645b02635c10d936e5b2f8b96dbd77355facda716164f1495efd3eb6955e3fd7f33338243518b4ac08ded41cc025cc0471ca0d54bfbcc392f8f9536b3c6f
7
- data.tar.gz: f87b952b9e0f0e282d8bcf9fcef3888a0fecf7d7c21dd341deb864bbf60783f1f6d0f7bc84c1163ac81cdeedd0857072ea8d7f574ce292b5cb87659ef99851a1
6
+ metadata.gz: 9d374065d88be5dc94f46fa9c4cf90694e8eb270ef1c92c6036a1e7941274735ca89e9ecc326d3d2d25d4a9170dd89217b0d6ee39cb2b616810817d756734249
7
+ data.tar.gz: dbe9986454583e5977d555d466a9163a535ae1a623b1d7916f258c1016315db1c32e09355f8e48303793a2c3189a3c9f5044b168217ecac6ca02d031aecbd042
@@ -3,6 +3,12 @@ Artifactory Client CHANGELOG
3
3
  This file is used to document the changes between releases of the Artifactory
4
4
  Ruby client.
5
5
 
6
+ v2.2.0 (11-20-2014)
7
+ -------------------
8
+ - Add artifact usage search
9
+ - Add artifact creation search
10
+ - Add support for configuring permission targets
11
+
6
12
  v2.1.3 (08-29-2014)
7
13
  -------------------
8
14
  - CGI escape matrix properties
data/README.md CHANGED
@@ -31,14 +31,14 @@ This will given you "Rails-like" access to the top-level Artifactory resources l
31
31
 
32
32
  ```ruby
33
33
  System.info
34
- Respository.all
34
+ Repository.all
35
35
  ```
36
36
 
37
37
  If you choose not to include the module (for namespacing reasons), you will need to specify the full module path to access resources:
38
38
 
39
39
  ```ruby
40
40
  Artifactory::Resource::System.info
41
- Artifactory::Resource::Respository.all
41
+ Artifactory::Resource::Repository.all
42
42
  ```
43
43
 
44
44
  ### Create a connection
@@ -30,19 +30,20 @@ module Artifactory
30
30
  end
31
31
 
32
32
  module Resource
33
- autoload :Artifact, 'artifactory/resources/artifact'
34
- autoload :Backup, 'artifactory/resources/backup'
35
- autoload :Base, 'artifactory/resources/base'
36
- autoload :Build, 'artifactory/resources/build'
37
- autoload :Group, 'artifactory/resources/group'
38
- autoload :Layout, 'artifactory/resources/layout'
39
- autoload :LDAPSetting, 'artifactory/resources/ldap_setting'
40
- autoload :MailServer, 'artifactory/resources/mail_server'
41
- autoload :Plugin, 'artifactory/resources/plugin'
42
- autoload :Repository, 'artifactory/resources/repository'
43
- autoload :System, 'artifactory/resources/system'
44
- autoload :URLBase, 'artifactory/resources/url_base'
45
- autoload :User, 'artifactory/resources/user'
33
+ autoload :Artifact, 'artifactory/resources/artifact'
34
+ autoload :Backup, 'artifactory/resources/backup'
35
+ autoload :Base, 'artifactory/resources/base'
36
+ autoload :Build, 'artifactory/resources/build'
37
+ autoload :Group, 'artifactory/resources/group'
38
+ autoload :Layout, 'artifactory/resources/layout'
39
+ autoload :LDAPSetting, 'artifactory/resources/ldap_setting'
40
+ autoload :MailServer, 'artifactory/resources/mail_server'
41
+ autoload :PermissionTarget, 'artifactory/resources/permission_target'
42
+ autoload :Plugin, 'artifactory/resources/plugin'
43
+ autoload :Repository, 'artifactory/resources/repository'
44
+ autoload :System, 'artifactory/resources/system'
45
+ autoload :URLBase, 'artifactory/resources/url_base'
46
+ autoload :User, 'artifactory/resources/user'
46
47
  end
47
48
 
48
49
  class << self
@@ -52,10 +52,11 @@ module Artifactory
52
52
  proxy Resource::Layout
53
53
  proxy Resource::LDAPSetting
54
54
  proxy Resource::MailServer
55
+ proxy Resource::PermissionTarget
55
56
  proxy Resource::Repository
57
+ proxy Resource::System
56
58
  proxy Resource::URLBase
57
59
  proxy Resource::User
58
- proxy Resource::System
59
60
 
60
61
  #
61
62
  # Create a new Artifactory Client with the given options. Any options
@@ -185,6 +185,88 @@ module Artifactory
185
185
  end
186
186
  end
187
187
 
188
+ #
189
+ # Search for an artifact by its usage
190
+ #
191
+ # @example Search for all repositories with the given usage statistics
192
+ # Artifact.usage_search(
193
+ # notUsedSince: 1388534400000,
194
+ # createdBefore: 1388534400000,
195
+ # )
196
+ #
197
+ # @example Search for all artifacts with the given usage statistics in a repo
198
+ # Artifact.usage_search(
199
+ # notUsedSince: 1388534400000,
200
+ # createdBefore: 1388534400000,
201
+ # repos: 'libs-release-local',
202
+ # )
203
+ #
204
+ # @param [Hash] options
205
+ # the list of options to search with
206
+ #
207
+ # @option options [Artifactory::Client] :client
208
+ # the client object to make the request with
209
+ # @option options [Long] :notUsedSince
210
+ # the last downloaded cutoff date of the artifact to search for (millis since epoch)
211
+ # @option options [Long] :createdBefore
212
+ # the creation cutoff date of the artifact to search for (millis since epoch)
213
+ # @option options [String, Array<String>] :repos
214
+ # the list of repos to search
215
+ #
216
+ # @return [Array<Resource::Artifact>]
217
+ # a list of artifacts that match the query
218
+ #
219
+ def usage_search(options = {})
220
+ client = extract_client!(options)
221
+ params = Util.slice(options, :notUsedSince, :createdBefore, :repos)
222
+ format_repos!(params)
223
+
224
+ client.get('/api/search/usage', params)['results'].map do |artifact|
225
+ from_url(artifact['uri'], client: client)
226
+ end
227
+ end
228
+
229
+ #
230
+ # Search for an artifact by its creation date
231
+ #
232
+ # @example Search for all repositories with the given creation date range
233
+ # Artifact.usage_search(
234
+ # from : 1414800000000,
235
+ # to : 1414871200000,
236
+ # )
237
+ #
238
+ # @example Search for all artifacts with the given creation date range in a repo
239
+ # Artifact.usage_search(
240
+ # from : 1414800000000,
241
+ # to : 1414871200000,
242
+ # repos: 'libs-release-local',
243
+ # )
244
+ #
245
+ # @param [Hash] options
246
+ # the list of options to search with
247
+ #
248
+ # @option options [Artifactory::Client] :client
249
+ # the client object to make the request with
250
+ # @option options [Long] :from
251
+ # the creation start date of the artifact to search for (millis since epoch)
252
+ # @option options [Long] :to
253
+ # the creation end date of the artifact to search for (millis since epoch)
254
+ # @option options [String, Array<String>] :repos
255
+ # the list of repos to search
256
+ #
257
+ # @return [Array<Resource::Artifact>]
258
+ # a list of artifacts that match the query
259
+ #
260
+ def creation_search(options = {})
261
+ client = extract_client!(options)
262
+ params = Util.slice(options, :from, :to, :repos)
263
+ format_repos!(params)
264
+
265
+ client.get('/api/search/creation', params)['results'].map do |artifact|
266
+ from_url(artifact['uri'], client: client)
267
+ end
268
+ end
269
+
188
270
  #
189
271
  # Get all versions of an artifact.
190
272
  #
@@ -0,0 +1,206 @@
1
+ module Artifactory
2
+ class Resource::PermissionTarget < Resource::Base
3
+ VERBOSE_PERMS = {
4
+ 'd' => 'delete',
5
+ 'm' => 'admin',
6
+ 'n' => 'annotate',
7
+ 'r' => 'read',
8
+ 'w' => 'deploy',
9
+ }
10
+ class << self
11
+ #
12
+ # Get a list of all PermissionTargets in the system.
13
+ #
14
+ # @param [Hash] options
15
+ # the list of options
16
+ #
17
+ # @option options [Artifactory::Client] :client
18
+ # the client object to make the request with
19
+ #
20
+ # @return [Array<Resource::PermissionTarget>]
21
+ # the list of PermissionTargets
22
+ #
23
+ def all(options = {})
24
+ client = extract_client!(options)
25
+ client.get('/api/security/permissions').map do |hash|
26
+ from_url(hash['uri'], client: client)
27
+ end
28
+ end
29
+
30
+ #
31
+ # Find (fetch) a permission target by its name.
32
+ #
33
+ # @example Find a permission target by its name
34
+ # PermissionTarget.find('readers') #=> #<PermissionTarget name: 'readers' ...>
35
+ #
36
+ # @param [String] name
37
+ # the name of the permission target to find
38
+ # @param [Hash] options
39
+ # the list of options
40
+ #
41
+ # @option options [Artifactory::Client] :client
42
+ # the client object to make the request with
43
+ #
44
+ # @return [Resource::PermissionTarget, nil]
45
+ # an instance of the permission target that matches the given name, or +nil+
46
+ # if one does not exist
47
+ #
48
+ def find(name, options = {})
49
+ client = extract_client!(options)
50
+
51
+ response = client.get("/api/security/permissions/#{url_safe(name)}")
52
+ from_hash(response, client: client)
53
+ rescue Error::HTTPError => e
54
+ raise unless e.code == 404
55
+ nil
56
+ end
57
+
58
+ #
59
+ # @see Resource::Base.from_hash
60
+ # Additionally use verbose names for permissions (e.g. 'read' for 'r')
61
+ #
62
+ def from_hash(hash, options = {})
63
+ super.tap do |instance|
64
+ %w(users groups).each do |key|
65
+ if instance.principals[key] && !instance.principals[key].nil?
66
+ instance.principals[key] = Hash[instance.principals[key].map { |k, v| [k, verbose(v)] } ]
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ #
75
+ # Replace an array of permissions with one using verbose permission names
76
+ #
77
+ def verbose(array)
78
+ array.map { |elt| VERBOSE_PERMS[elt] }.sort
79
+ end
80
+ end
81
+
82
+ class Principal
83
+ attr_accessor :users, :groups
84
+
85
+ def initialize(users = {}, groups = {})
86
+ @users = users
87
+ @groups = groups
88
+ end
89
+
90
+ #
91
+ # Converts the user-friendly form of the principals hash to one suitable
92
+ # for posting to Artifactory.
93
+ # @return [Hash]
94
+ #
95
+ def to_abbreviated
96
+ { 'users' => abbreviate_principal(@users), 'groups' => abbreviate_principal(@groups) }
97
+ end
98
+
99
+ private
100
+
101
+ #
102
+ # Replace an array of verbose permission names with an equivalent array of abbreviated permission names.
103
+ #
104
+ def abbreviate_permissions(array)
105
+ inverse = VERBOSE_PERMS.invert
106
+ if (inverse.keys & array).sort != array.sort then
107
+ raise "One of your principals contains an invalid permission. Valid permissions are #{inverse.keys.join(', ')}"
108
+ end
109
+ array.map { |elt| inverse[elt] }.sort
110
+ end
111
+
112
+ #
113
+ # Replace a principal with verbose permissions with an equivalent one with abbreviated permissions.
114
+ #
115
+ def abbreviate_principal(principal_hash)
116
+ Hash[principal_hash.map { |k, v| [k, abbreviate_permissions(v)] } ]
117
+ end
118
+ end
119
+
120
+ attribute :name, ->{ raise 'Name missing!' }
121
+ attribute :includes_pattern, '**'
122
+ attribute :excludes_pattern, ''
123
+ attribute :repositories
124
+ attribute :principals, { 'users' => {}, 'groups' => {} }
125
+
126
+ def client_principal
127
+ @client_principal ||= Principal.new(principals['users'], principals['groups'])
128
+ end
129
+
130
+ #
131
+ # Delete this PermissionTarget from artifactory, suppressing any +ResourceNotFound+
132
+ # exceptions might occur.
133
+ #
134
+ # @return [Boolean]
135
+ # true if the object was deleted successfully, false otherwise
136
+ #
137
+ def delete
138
+ client.delete(api_path)
139
+ true
140
+ rescue Error::HTTPError
141
+ false
142
+ end
143
+
144
+ #
145
+ # Save the PermissionTarget to the artifactory server.
146
+ # See http://bit.ly/1qMOw0L
147
+ #
148
+ # @return [Boolean]
149
+ #
150
+ def save
151
+ send("#{:principals}=", client_principal.to_abbreviated)
152
+ client.put(api_path, to_json, headers)
153
+ true
154
+ end
155
+
156
+ #
157
+ # Getter for groups
158
+ #
159
+ def groups
160
+ client_principal.groups
161
+ end
162
+
163
+ #
164
+ # Setter for groups (groups_hash expected to be friendly)
165
+ #
166
+ def groups=(groups_hash)
167
+ client_principal.groups = Hash[groups_hash.map { |k, v| [k, v.sort] } ]
168
+ end
169
+
170
+ #
171
+ # Getter for users
172
+ #
173
+ def users
174
+ client_principal.users
175
+ end
176
+
177
+ #
178
+ # Setter for users (expecting users_hash to be friendly)
179
+ #
180
+ def users=(users_hash)
181
+ client_principal.users = Hash[users_hash.map { |k, v| [k, v.sort] } ]
182
+ end
183
+
184
+ private
185
+
186
+ #
187
+ # The path to this PermissionTarget on the server.
188
+ #
189
+ # @return [String]
190
+ #
191
+ def api_path
192
+ @api_path ||= "/api/security/permissions/#{url_safe(name)}"
193
+ end
194
+
195
+ #
196
+ # The default headers for this object. This includes the +Content-Type+.
197
+ #
198
+ # @return [Hash]
199
+ #
200
+ def headers
201
+ @headers ||= {
202
+ 'Content-Type' => 'application/vnd.org.jfrog.artifactory.security.PermissionTarget+json'
203
+ }
204
+ end
205
+ end
206
+ end
@@ -39,7 +39,7 @@ module Artifactory
39
39
  #
40
40
  # Find (fetch) a repository by name.
41
41
  #
42
- # @example Find a respository by named key
42
+ # @example Find a repository by named key
43
43
  # Repository.find(name: 'libs-release-local') #=> #<Resource::Artifact>
44
44
  #
45
45
  # @param [Hash] options
@@ -15,5 +15,5 @@
15
15
  #
16
16
 
17
17
  module Artifactory
18
- VERSION = '2.1.3'
18
+ VERSION = '2.2.0'
19
19
  end
@@ -52,6 +52,14 @@ module Artifactory
52
52
  it_behaves_like 'an artifact search endpoint', :checksum_search, md5: 'abcd1234'
53
53
  end
54
54
 
55
+ describe '.usage_search' do
56
+ it_behaves_like 'an artifact search endpoint', :usage_search, notUsedSince: '1414800000'
57
+ end
58
+
59
+ describe '.creation_search' do
60
+ it_behaves_like 'an artifact search endpoint', :creation_search, from: '1414800000'
61
+ end
62
+
55
63
  describe '.versions' do
56
64
  it 'returns an array of versions' do
57
65
  response = described_class.versions
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ module Artifactory
4
+ describe Resource::PermissionTarget, :integration do
5
+ describe '.all' do
6
+ it 'returns an array of PermissionTarget objects' do
7
+ results = described_class.all
8
+ expect(results).to be_a(Array)
9
+ expect(results.first).to be_a(described_class)
10
+ end
11
+
12
+ it 'includes the information from the server' do
13
+ results = described_class.all
14
+ anything = results[0]
15
+ any_remote = results[1]
16
+
17
+ expect(anything.name).to eq('Anything')
18
+ expect(any_remote.name).to eq('Any Remote')
19
+ end
20
+ end
21
+
22
+ describe '.find' do
23
+ it 'finds a permission target by name' do
24
+ readers = described_class.find('Anything')
25
+
26
+ expect(readers).to be_a(described_class)
27
+ expect(readers.name).to eq('Anything')
28
+ end
29
+ end
30
+
31
+ describe '#delete' do
32
+ it 'deletes the permission target from the server' do
33
+ readers = described_class.find('Anything')
34
+ expect(readers.delete).to be_truthy
35
+ end
36
+ end
37
+
38
+ describe '#save' do
39
+ it 'saves the permission target to the server' do
40
+ target = described_class.new(name: 'testing')
41
+ expect(target.save).to be_truthy
42
+ end
43
+ end
44
+
45
+ describe '#users' do
46
+ it 'displays the users hash with sorted verbose permissions' do
47
+ target = described_class.find('Any Remote')
48
+ expect(target.users).to eq( { 'anonymous' => ['deploy', 'read'] } )
49
+ end
50
+ end
51
+
52
+ describe '#groups' do
53
+ it 'displays the groups hash with sorted verbose permissions' do
54
+ target = described_class.find('Anything')
55
+ expect(target.groups).to eq( { 'readers' => ['admin', 'read'] } )
56
+ end
57
+ end
58
+
59
+ describe '#users=' do
60
+ it 'sets the users hash' do
61
+ target = described_class.find('Any Remote')
62
+ target.users = { 'admins' => ['admin'] }
63
+ expect(target.users).to eq( { 'admins' => ['admin'] })
64
+ end
65
+ end
66
+
67
+ describe '#groups=' do
68
+ it 'sets the groups hash' do
69
+ target = described_class.find('Anything')
70
+ target.groups = { 'deployers' => ['deploy'] }
71
+ expect(target.groups).to eq( { 'deployers' => ['deploy'] })
72
+ end
73
+ end
74
+ end
75
+ end
@@ -10,6 +10,7 @@ module Artifactory
10
10
  require_relative 'api_server/build_endpoints'
11
11
  require_relative 'api_server/group_endpoints'
12
12
  require_relative 'api_server/repository_endpoints'
13
+ require_relative 'api_server/permission_target_endpoints'
13
14
  require_relative 'api_server/status_endpoints'
14
15
  require_relative 'api_server/system_endpoints'
15
16
  require_relative 'api_server/user_endpoints'
@@ -17,6 +18,7 @@ module Artifactory
17
18
  register APIServer::ArtifactEndpoints
18
19
  register APIServer::BuildEndpoints
19
20
  register APIServer::GroupEndpoints
21
+ register APIServer::PermissionTargetEndpoints
20
22
  register APIServer::RepositoryEndpoints
21
23
  register APIServer::StatusEndpoints
22
24
  register APIServer::SystemEndpoints
@@ -32,6 +32,20 @@ module Artifactory
32
32
  end
33
33
  end
34
34
 
35
+ app.get('/api/search/usage') do
36
+ content_type 'application/vnd.org.jfrog.artifactory.search.ArtifactUsageResult+json'
37
+ artifacts_for_conditions do
38
+ params['notUsedSince'] == '1414800000'
39
+ end
40
+ end
41
+
42
+ app.get('/api/search/creation') do
43
+ content_type 'application/vnd.org.jfrog.artifactory.search.ArtifactCreationResult+json'
44
+ artifacts_for_conditions do
45
+ params['from'] == '1414800000'
46
+ end
47
+ end
48
+
35
49
  app.get('/api/search/versions') do
36
50
  content_type 'application/vnd.org.jfrog.artifactory.search.ArtifactVersionsResult+json'
37
51
  JSON.fast_generate(
@@ -0,0 +1,53 @@
1
+ module Artifactory
2
+ module APIServer::PermissionTargetEndpoints
3
+ def self.registered(app)
4
+ app.get('/api/security/permissions') do
5
+ content_type 'application/vnd.org.jfrog.artifactory.security.PermissionTargets+json'
6
+ JSON.fast_generate([
7
+ {
8
+ 'name' => 'Anything',
9
+ 'uri' => server_url.join('/api/security/permissions/Anything'),
10
+ },
11
+ {
12
+ 'name' => 'Any Remote',
13
+ 'uri' => server_url.join('/api/security/permissions/Any%20Remote')
14
+ }
15
+ ])
16
+ end
17
+
18
+ app.get('/api/security/permissions/Any%20Remote') do
19
+ content_type 'application/vnd.org.jfrog.artifactory.security.PermissionTargets+json'
20
+ JSON.fast_generate(
21
+ 'name' => 'Any Remote',
22
+ 'includes_pattern' => nil,
23
+ 'excludes_pattern' => '',
24
+ 'repositories' => ["ANY REMOTE"],
25
+ 'principals' => { 'users' => { 'anonymous' => ['w', 'r'] }, 'groups' => nil }
26
+ )
27
+ end
28
+
29
+ app.get('/api/security/permissions/Anything') do
30
+ content_type 'application/vnd.org.jfrog.artifactory.security.PermissionTargets+json'
31
+ JSON.fast_generate(
32
+ 'name' => 'Anything',
33
+ 'includes_pattern' => nil,
34
+ 'excludes_pattern' => '',
35
+ 'repositories' => ["ANY"],
36
+ 'principals' => { 'users' => { 'anonymous' => ['r'] }, 'groups' => { 'readers' => ['r', 'm'] } }
37
+ )
38
+ end
39
+
40
+ app.put('/api/security/permissions/:name') do
41
+ return 415 unless request.content_type == 'application/vnd.org.jfrog.artifactory.security.PermissionTarget+json'
42
+
43
+ # Attempt to parse the response; if this succeeds, all is well...
44
+ JSON.parse(request.body.read)
45
+ nil
46
+ end
47
+
48
+ app.delete('/api/security/permissions/:name') do
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
@@ -207,6 +207,56 @@ module Artifactory
207
207
  end
208
208
  end
209
209
 
210
+ describe '.usage_search' do
211
+ let(:response) { { 'results' => [] } }
212
+
213
+ it 'calls /api/search/usage' do
214
+ expect(client).to receive(:get).with('/api/search/usage', {}).once
215
+ described_class.usage_search
216
+ end
217
+
218
+ it 'slices the correct parameters' do
219
+ expect(client).to receive(:get).with('/api/search/usage',
220
+ notUsedSince: 1414800000000,
221
+ createdBefore: 1414871200000,
222
+ ).once
223
+ described_class.usage_search(
224
+ notUsedSince: 1414800000000,
225
+ createdBefore: 1414871200000,
226
+ fizz: 'foo',
227
+ )
228
+ end
229
+
230
+ it 'returns an array of objects' do
231
+ expect(described_class.usage_search).to be_a(Array)
232
+ end
233
+ end
234
+
235
+ describe '.creation_search' do
236
+ let(:response) { { 'results' => [] } }
237
+
238
+ it 'calls /api/search/creation' do
239
+ expect(client).to receive(:get).with('/api/search/creation', {}).once
240
+ described_class.creation_search
241
+ end
242
+
243
+ it 'slices the correct parameters' do
244
+ expect(client).to receive(:get).with('/api/search/creation',
245
+ from: 1414800000000,
246
+ to: 1414871200000,
247
+ ).once
248
+ described_class.creation_search(
249
+ from: 1414800000000,
250
+ to: 1414871200000,
251
+ fizz: 'foo',
252
+ )
253
+ end
254
+
255
+ it 'returns an array of objects' do
256
+ expect(described_class.creation_search).to be_a(Array)
257
+ end
258
+ end
259
+
210
260
  describe '.versions' do
211
261
  let(:response) { { 'results' => [] } }
212
262
 
@@ -0,0 +1,186 @@
1
+ require 'spec_helper'
2
+
3
+ module Artifactory
4
+ describe Resource::PermissionTarget do
5
+ let(:client) { double(:client) }
6
+
7
+ before(:each) do
8
+ allow(Artifactory).to receive(:client).and_return(client)
9
+ allow(client).to receive(:get).and_return(response) if defined?(response)
10
+ end
11
+
12
+ describe '.all' do
13
+ let(:response) do
14
+ [
15
+ { 'uri' => 'a' },
16
+ { 'uri' => 'b' },
17
+ { 'uri' => 'c' },
18
+ ]
19
+ end
20
+ before do
21
+ allow(described_class).to receive(:from_url).with('a', client: client).and_return('a')
22
+ allow(described_class).to receive(:from_url).with('b', client: client).and_return('b')
23
+ allow(described_class).to receive(:from_url).with('c', client: client).and_return('c')
24
+ end
25
+
26
+ it 'gets /api/security/permissions' do
27
+ expect(client).to receive(:get).with('/api/security/permissions').once
28
+ described_class.all
29
+ end
30
+
31
+ it 'returns the permissions' do
32
+ expect(described_class.all).to eq(['a', 'b', 'c'])
33
+ end
34
+ end
35
+
36
+ describe '.find' do
37
+ let(:response) { {} }
38
+
39
+ it 'gets /api/security/permissions/#{name}' do
40
+ expect(client).to receive(:get).with('/api/security/permissions/Any%20Remote').once
41
+ described_class.find('Any Remote')
42
+ end
43
+ end
44
+
45
+ describe '.from_url' do
46
+ let(:response) { {} }
47
+
48
+ it 'constructs a new instance from the result' do
49
+ expect(described_class).to receive(:from_hash).once
50
+ described_class.from_url('/api/security/permissions/Any Remote')
51
+ end
52
+ end
53
+
54
+ describe '.from_hash' do
55
+ let(:hash) do
56
+ {
57
+ 'name' => 'Test Remote',
58
+ 'includes_pattern' => '**',
59
+ 'excludes_pattern' => '',
60
+ 'repositories' => ['ANY REMOTE'],
61
+ 'principals' => { 'users' => { 'anonymous' => ['w', 'r'] }, 'groups' => {} }
62
+ }
63
+ end
64
+
65
+ it 'creates a new instance' do
66
+ instance = described_class.from_hash(hash)
67
+ expect(instance.name).to eq('Test Remote')
68
+ expect(instance.includes_pattern).to eq('**')
69
+ expect(instance.excludes_pattern).to eq('')
70
+ expect(instance.repositories).to eq(['ANY REMOTE'])
71
+ expect(instance.principals).to eq({ 'users' => { 'anonymous' => ['deploy', 'read'] }, 'groups' => {} })
72
+ end
73
+ end
74
+
75
+ describe Artifactory::Resource::PermissionTarget::Principal do
76
+ context 'principal object' do
77
+ users = { 'anonymous_users' => ['admin', 'deploy', 'read'] }
78
+ groups = { 'anonymous_groups' => ['delete', 'read'] }
79
+ instance = described_class.new(users, groups)
80
+
81
+ it 'has unabbreviated users' do
82
+ expect(instance.users).to eq( { 'anonymous_users' => ['admin', 'deploy', 'read'] } )
83
+ end
84
+
85
+ it 'has unabbreviated groups' do
86
+ expect(instance.groups).to eq( { 'anonymous_groups' => ['delete', 'read'] } )
87
+ end
88
+
89
+ it 'abbreviates' do
90
+ expect(instance.to_abbreviated).to eq( { 'users' => { 'anonymous_users' => ['m', 'r', 'w'] }, 'groups' => { 'anonymous_groups' => ['d', 'r'] } } )
91
+ end
92
+ end
93
+ end
94
+
95
+ describe '#save' do
96
+ let(:client) { double }
97
+ before do
98
+ subject.client = client
99
+ subject.name = 'TestRemote'
100
+ subject.includes_pattern = nil
101
+ subject.excludes_pattern = ''
102
+ subject.repositories = ['ANY']
103
+ subject.principals = {
104
+ 'users' => {
105
+ 'anonymous_users' => ['read']
106
+ },
107
+ 'groups' => {
108
+ 'anonymous_readers' => ['read']
109
+ }
110
+ }
111
+ allow(described_class).to receive(:find).with(subject.name, client: client).and_return(nil)
112
+ end
113
+
114
+ it 'PUTS the permission target to the server' do
115
+ expect(client).to receive(:put).with("/api/security/permissions/TestRemote",
116
+ "{\"name\":\"TestRemote\",\"includesPattern\":null,\"excludesPattern\":\"\",\"repositories\":[\"ANY\"],\"principals\":{\"users\":{\"anonymous_users\":[\"r\"]},\"groups\":{\"anonymous_readers\":[\"r\"]}}}",
117
+ { "Content-Type" => "application/vnd.org.jfrog.artifactory.security.PermissionTarget+json"})
118
+ subject.save
119
+ end
120
+ end
121
+
122
+ describe '#delete' do
123
+ let(:client) { double }
124
+
125
+ it 'sends DELETE to the client' do
126
+ subject.client = client
127
+ subject.name = 'My Permissions'
128
+
129
+ expect(client).to receive(:delete).with('/api/security/permissions/My%20Permissions')
130
+ subject.delete
131
+ end
132
+ end
133
+
134
+ describe 'getters' do
135
+ let(:client) { double }
136
+ before do
137
+ subject.client = client
138
+ subject.name = 'TestGetters'
139
+ subject.principals = {
140
+ 'users' => {
141
+ 'anonymous' => ['read']
142
+ },
143
+ 'groups' => {
144
+ 'readers' => ['read']
145
+ }
146
+ }
147
+ allow(described_class).to receive(:find).with(subject.name, client: client).and_return(nil)
148
+ end
149
+
150
+ it '#users returns the users hash' do
151
+ expect(subject.users).to eq({ 'anonymous' => ['read'] })
152
+ end
153
+
154
+ it '#groups returns the groups hash' do
155
+ expect(subject.groups).to eq({ 'readers' => ['read'] })
156
+ end
157
+ end
158
+
159
+ describe 'setters' do
160
+ let(:client) { double }
161
+ before do
162
+ subject.client = client
163
+ subject.name = 'TestSetters'
164
+ subject.principals = {
165
+ 'users' => {
166
+ 'anonymous' => ['read']
167
+ },
168
+ 'groups' => {
169
+ 'readers' => ['read']
170
+ }
171
+ }
172
+ allow(described_class).to receive(:find).with(subject.name, client: client).and_return(nil)
173
+ end
174
+
175
+ it '#users= sets the users hash' do
176
+ subject.users = { 'spiders' => [ 'read', 'admin'] }
177
+ expect(subject.users).to eq({ 'spiders' => ['admin', 'read'] })
178
+ end
179
+
180
+ it '#groups= sets the groups hash' do
181
+ subject.groups = { 'beatles' => [ 'deploy', 'delete'] }
182
+ expect(subject.groups).to eq({ 'beatles' => ['delete', 'deploy'] })
183
+ end
184
+ end
185
+ end
186
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: artifactory
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seth Vargo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-29 00:00:00.000000000 Z
11
+ date: 2014-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,6 +67,7 @@ files:
67
67
  - lib/artifactory/resources/layout.rb
68
68
  - lib/artifactory/resources/ldap_setting.rb
69
69
  - lib/artifactory/resources/mail_server.rb
70
+ - lib/artifactory/resources/permission_target.rb
70
71
  - lib/artifactory/resources/plugin.rb
71
72
  - lib/artifactory/resources/repository.rb
72
73
  - lib/artifactory/resources/system.rb
@@ -81,6 +82,7 @@ files:
81
82
  - spec/integration/resources/layout_spec.rb
82
83
  - spec/integration/resources/ldap_setting_spec.rb
83
84
  - spec/integration/resources/mail_server_spec.rb
85
+ - spec/integration/resources/permission_target_spec.rb
84
86
  - spec/integration/resources/repository_spec.rb
85
87
  - spec/integration/resources/system_spec.rb
86
88
  - spec/integration/resources/url_base_spec.rb
@@ -90,6 +92,7 @@ files:
90
92
  - spec/support/api_server/artifact_endpoints.rb
91
93
  - spec/support/api_server/build_endpoints.rb
92
94
  - spec/support/api_server/group_endpoints.rb
95
+ - spec/support/api_server/permission_target_endpoints.rb
93
96
  - spec/support/api_server/repository_endpoints.rb
94
97
  - spec/support/api_server/status_endpoints.rb
95
98
  - spec/support/api_server/system_endpoints.rb
@@ -104,6 +107,7 @@ files:
104
107
  - spec/unit/resources/layout_spec.rb
105
108
  - spec/unit/resources/ldap_setting_spec.rb
106
109
  - spec/unit/resources/mail_server_spec.rb
110
+ - spec/unit/resources/permission_target_spec.rb
107
111
  - spec/unit/resources/plugin_spec.rb
108
112
  - spec/unit/resources/repository_spec.rb
109
113
  - spec/unit/resources/system_spec.rb
@@ -142,6 +146,7 @@ test_files:
142
146
  - spec/integration/resources/layout_spec.rb
143
147
  - spec/integration/resources/ldap_setting_spec.rb
144
148
  - spec/integration/resources/mail_server_spec.rb
149
+ - spec/integration/resources/permission_target_spec.rb
145
150
  - spec/integration/resources/repository_spec.rb
146
151
  - spec/integration/resources/system_spec.rb
147
152
  - spec/integration/resources/url_base_spec.rb
@@ -151,6 +156,7 @@ test_files:
151
156
  - spec/support/api_server/artifact_endpoints.rb
152
157
  - spec/support/api_server/build_endpoints.rb
153
158
  - spec/support/api_server/group_endpoints.rb
159
+ - spec/support/api_server/permission_target_endpoints.rb
154
160
  - spec/support/api_server/repository_endpoints.rb
155
161
  - spec/support/api_server/status_endpoints.rb
156
162
  - spec/support/api_server/system_endpoints.rb
@@ -165,6 +171,7 @@ test_files:
165
171
  - spec/unit/resources/layout_spec.rb
166
172
  - spec/unit/resources/ldap_setting_spec.rb
167
173
  - spec/unit/resources/mail_server_spec.rb
174
+ - spec/unit/resources/permission_target_spec.rb
168
175
  - spec/unit/resources/plugin_spec.rb
169
176
  - spec/unit/resources/repository_spec.rb
170
177
  - spec/unit/resources/system_spec.rb