plone_rest_api 0.8.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c5aeaf06c586ef2e3f935276a3a2fe99f9f0963bed0acd22b8e27a81f33e77b6
4
+ data.tar.gz: 27706b04dd799999109705e55086ac3e8fb2eda390a5b7094b86d8795ab9d9ec
5
+ SHA512:
6
+ metadata.gz: 318503f0ee4d4ff7a5e00b709ee0cc651a7489b12438d95a36f05dfb1464972bf567872704131caec03f3f2316a3b1d90d6beffd2d8721a4417fc7bf96ecf8cb
7
+ data.tar.gz: 359b4ce1b4f59edabd87b6ee1fdfae24fc1fe48bd99049dc09006231b24baefae5b855f9069e1e362cb58024352b8ba39fa298d21f549856ab4868f96c96cd44
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+
13
+ # Ignore auto-generated main file
14
+ /main
15
+
16
+ # Ignore Gemfile.lock. See https://stackoverflow.com/questions/4151495/should-gemfile-lock-be-included-in-gitignore
17
+ /Gemfile.lock
18
+
19
+ # Put your personal ignore files in /home/clr/.config/git/ignore
20
+ .*.swp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.6.5
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.0
7
+ before_install: gem install bundler -v 1.17.2
data/ABOUT.md ADDED
@@ -0,0 +1,3 @@
1
+
2
+ Wrapper around the Plone REST api for Ruby
3
+
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in plone_rest_api.gemspec
6
+ gemspec
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # PloneRestApi
2
+
3
+ Plone REST API. Can both be used as a library by requiring 'plone_rest_api' or as a command: plone-rest
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'plone_rest_api'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install plone_rest_api
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Development
26
+
27
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
28
+
29
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
30
+
31
+ ## Contributing
32
+
33
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/plone_rest_api.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "plone_rest_api"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/plone-rest ADDED
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'plone_rest_api.rb'
4
+
5
+ require 'shellopts'
6
+
7
+ USAGE = "u,user=ADMIN-USER p,password=ADMIN-PASSWORD s,site=SITE_URL version h,help create-user! read-user! update-user-password! delete-user! exist-user! list-users! create-group! read-group! update-group-add-user! update-group-remove-user! delete-group! exist-group! list-groups!"
8
+
9
+ user=nil
10
+ password=nil
11
+ site = nil
12
+ cmd = nil
13
+
14
+ cmds = [
15
+ [ "create-user", :create_user, "USERNAME PASSWORD FULLNAME EMAIL" ],
16
+ [ "read-user", :read_user, "USERNAME" ],
17
+ [ "update-user-password", :update_user_password, "USERNAME OLD_PASSWORD NEW_PASSWORD" ],
18
+ [ "delete-user", :delete_user, "USERNAME" ],
19
+ [ "exist-user", :exist_user, "USERNAME" ],
20
+ [ "list-users", :list_users, "" ],
21
+
22
+ [ "create-group", :create_group, "GROUPNAME TITLE" ],
23
+ [ "read-group", :read_group, "GROUPNAME" ],
24
+ [ "update-group-add-user", :update_group_add_user, "GROUPNAME USERNAME" ],
25
+ [ "update-group-remove-user", :update_group_remove_user, "GROUPNAME USERNAME" ],
26
+ [ "delete-group", :delete_group, "GROUPNAME" ],
27
+ [ "exist-group", :exist_group, "GROUPNAME" ],
28
+ [ "list-groups", :list_groups, "" ]
29
+ ].map { |name, method, msg| [name, [method, msg]] }.to_h
30
+
31
+ args = ShellOpts::process(USAGE, ARGV) { |opt, arg|
32
+ case opt
33
+ when "-u", "--user"; user = arg
34
+ when "-p", "--password"; password = arg
35
+ when "-s", "--site"; site = arg
36
+ when "--version"; puts PloneRestApi::VERSION; exit
37
+ when "-h", "--help"
38
+ puts "Usage:"
39
+ puts " #{PROGRAM} --user=ADMIN-USER --password=ADMIN-PASSWORD --site=URL --version --help COMMAND"
40
+ puts "Commands:"
41
+ cmds.each { |cmd,v|
42
+ puts " #{cmd} #{v.last}"
43
+ }
44
+ exit
45
+ when /[^-].*/; cmd = opt
46
+ else
47
+ raise "Oops: #{opt}"
48
+ end
49
+ }
50
+
51
+ # FIXME
52
+ #user = "ras"
53
+ #password = "tre109"
54
+ #site = "http://portal.vbox.veda.lan"
55
+ #site = "http://localhost:8080"
56
+
57
+ !cmd.nil? or ShellOpts::error "Missing command"
58
+ cmds.key?(cmd) or ShellOpts::error "Illegal command: #{cmd}"
59
+ !site.nil? or ShellOpts::error "Missing site URL"
60
+ if cmd != "update-user-password"
61
+ !user.nil? or ShellOpts::error "Missing administrative user name"
62
+ !password.nil? or ShellOpts::error "Missing administrative password"
63
+ end
64
+
65
+ api = PloneRestApi::Site.new(site, user, password)
66
+
67
+ method, msg, size = cmds[cmd]
68
+ size ||= msg.split.size
69
+ if args.size != size
70
+ $stderr.puts "#{PROGRAM}: Illegal number of arguments"
71
+ $stderr.puts "Usage: #{PROGRAM} #{cmd} #{msg}"
72
+ exit(1)
73
+ end
74
+
75
+ begin
76
+ puts api.send(method, *args)
77
+ rescue PloneRestApi::SubmitError => ex
78
+ $stderr.puts ex.long_message
79
+ exit 1
80
+ end
81
+
@@ -0,0 +1,3 @@
1
+ module PloneRestApi
2
+ VERSION = "0.8.4"
3
+ end
@@ -0,0 +1,191 @@
1
+ require "plone_rest_api/version"
2
+
3
+ require 'json'
4
+ require 'faraday'
5
+ require 'rack/utils'
6
+
7
+ module PloneRestApi
8
+ class Site
9
+ Credentials = Struct.new(:login, :password)
10
+
11
+ DEFAULT_RETRIES = 0
12
+ BATCH_SIZE = 100
13
+
14
+ attr_reader :url
15
+
16
+ # Create a Plone REST API handle. The url is the base-url of the Plone
17
+ # site. The login should have Manager rights to be able to use all methods.
18
+ # The :retries option is the number of times to retry in case of timeouts
19
+ # (default: 0)
20
+ def initialize(url, login, password, retries: DEFAULT_RETRIES)
21
+ @url = url
22
+ @credentials = Credentials.new(login, password)
23
+ @retries = retries
24
+ @conn = Faraday.new(
25
+ url: @url,
26
+ headers: {
27
+ 'Content-Type': 'application/json',
28
+ 'Accept': 'application/json',
29
+ 'User-Agent': 'Plone REST API'
30
+ }
31
+ )
32
+ end
33
+
34
+ # Create a new group. Returns the user hash
35
+ def create_user(username, password, fullname, email)
36
+ data = { username: username, password: password, fullname: fullname, email: email }
37
+ submit(:post, "@users", 201, data: data)
38
+ end
39
+
40
+ # Return the user hash for the given username or nil if the user doesn't
41
+ # exist and :ignore_not_found is true
42
+ def read_user(username, ignore_not_found: false)
43
+ begin
44
+ submit(:get, "@users/#{username}", 200)
45
+ rescue SubmitError => ex
46
+ return nil if ex.status == 404 && ignore_not_found
47
+ raise
48
+ end
49
+ end
50
+
51
+ # Return array of user hashes
52
+ def list_users
53
+ submit(:get, "@users", 200)
54
+ end
55
+
56
+ # Return true if user exists
57
+ def exist_user(username)
58
+ !read_user(username, ignore_not_found: true).nil?
59
+ end
60
+
61
+ # Update user and return true if successful
62
+ def update_user(username, update)
63
+ data = update
64
+ submit(:patch, "@users/#{username}", 204, data: data)
65
+ end
66
+
67
+ # Update user's password. Returns true
68
+ def update_user_password(username, old_password, new_password)
69
+ credentials = Credentials.new(username, old_password)
70
+ data = { old_password: old_password, new_password: new_password }
71
+ submit(:post, "@users/#{username}/reset-password", 200, data: data, credentials: credentials)
72
+ end
73
+
74
+ # Delete a user. Returns true if successful, but nil if the user doesn't
75
+ # exist and :ignore_not_found is true
76
+ def delete_user(username, ignore_not_found: false)
77
+ begin
78
+ submit(:delete, "@users/#{username}", 204)
79
+ rescue SubmitError => ex
80
+ return true if ex.status == 404 && ignore_not_found
81
+ raise
82
+ end
83
+ end
84
+
85
+ # Create a new group. Returns the group hash
86
+ def create_group(groupname, title)
87
+ data = { groupname: groupname, title: title }
88
+ submit(:post, "@groups", 201, data: data)
89
+ end
90
+
91
+ # Return the group hash for the given groupname or nil if the group doesn't
92
+ # exist and :ignore_not_found is true
93
+ def read_group(groupname, ignore_not_found: false)
94
+ items = []
95
+ begin
96
+ reply = submit(:get, "@groups/#{groupname}?b_size=#{BATCH_SIZE}", 200)
97
+ items = reply["users"]["items"]
98
+ if reply["users"]["batching"]
99
+ while next_url = reply["users"]["batching"]["next"]
100
+ reply = submit(:get, "#{next_url}&b_size=#{BATCH_SIZE}", 200)
101
+ items += reply["users"]["items"]
102
+ end
103
+ items.size == reply["users"]["items_total"] or raise Error.new "Failed batch-fetching items"
104
+ reply["users"]["batching"] = {} # Helps testing to leave the key instead of removing it
105
+ reply["users"]["items"] = items
106
+ end
107
+ reply
108
+ rescue SubmitError => ex
109
+ return nil if ex.status == 404 && ignore_not_found
110
+ raise
111
+ end
112
+ end
113
+
114
+ # Return array of group hashes
115
+ def list_groups
116
+ submit(:get, "@groups", 200)
117
+ end
118
+
119
+ # Return true if group exists
120
+ def exist_group(groupname)
121
+ !read_group(groupname, ignore_not_found: true).nil?
122
+ end
123
+
124
+ # Add a user to a group. Returns true
125
+ def update_group_add_user(groupname, username)
126
+ data = { "users": { username => true } }
127
+ submit(:patch, "@groups/#{groupname}", 204, data: data)
128
+ end
129
+
130
+ # Remove a user from a group. Returns true
131
+ def update_group_remove_user(groupname, username)
132
+ data = { "users": { username => false } }
133
+ submit(:patch, "@groups/#{groupname}", 204, data: data)
134
+ end
135
+
136
+ # Delete a group. Returns true or nil if the group doesn't exist and
137
+ # :ignore_not_found is true
138
+ def delete_group(groupname, ignore_not_found: false)
139
+ begin
140
+ submit(:delete, "@groups/#{groupname}", 204)
141
+ rescue SubmitError => ex
142
+ return true if ex.status == 404 && ignore_not_found
143
+ raise
144
+ end
145
+ end
146
+
147
+ private
148
+ def submit(verb, resource, expected_status, data: nil, credentials: @credentials)
149
+ begin
150
+ attempts ||= @retries + 1
151
+ resp = @conn.send(verb, resource) { |req|
152
+ req.headers["Authorization"] =
153
+ Faraday::Request::BasicAuthentication.header(credentials.login, credentials.password)
154
+ req.body = data.to_json if data
155
+ }
156
+ rescue Faraday::TimeoutError => ex
157
+ retry if (attempts -= 1) > 0
158
+ raise TimeoutError.new(ex.message)
159
+ end
160
+
161
+ resp.status == expected_status or begin
162
+ if resp.body && !resp.body.empty?
163
+ json = JSON.load(resp.body)
164
+ message = json.is_a?(Hash) ? json["message"] : nil
165
+ else
166
+ message = nil
167
+ end
168
+ raise SubmitError.new(resp.status, message)
169
+ end
170
+ resp.body && !resp.body.empty? && JSON.load(resp.body) || true
171
+ end
172
+ end
173
+
174
+ class Error < StandardError
175
+ def short_message() message end
176
+ def long_message() message end
177
+ end
178
+
179
+ class TimeoutError < Error; end
180
+
181
+ class SubmitError < Error
182
+ attr_accessor :status, :short_message, :long_message
183
+ def initialize(status, message = nil)
184
+ @status = status
185
+ @short_message = "#{@status} #{Rack::Utils::HTTP_STATUS_CODES[status]}"
186
+ @long_message = @short_message + (message && message != "" ? " - #{message}" : "")
187
+ super(message || @short_message)
188
+ end
189
+ end
190
+ end
191
+
@@ -0,0 +1,44 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "plone_rest_api/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "plone_rest_api"
8
+ spec.version = PloneRestApi::VERSION
9
+ spec.authors = ["Claus Rasmussen"]
10
+ spec.email = ["ras@danak.dk"]
11
+
12
+ spec.summary = %q{Plone REST api library and command}
13
+ spec.description = %q{Plone REST api library and command}
14
+ spec.homepage = "http://www.nowhere.com/"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ # if spec.respond_to?(:metadata)
19
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
20
+ #
21
+ # spec.metadata["homepage_uri"] = spec.homepage
22
+ # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
23
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
24
+ # else
25
+ # raise "RubyGems 2.0 or newer is required to protect against " \
26
+ # "public gem pushes."
27
+ # end
28
+
29
+ # Specify which files should be added to the gem when it is released.
30
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
31
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
32
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
33
+ end
34
+ spec.bindir = "exe"
35
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ["lib"]
37
+
38
+ spec.add_development_dependency "webmock"
39
+
40
+ spec.add_dependency "shellopts", "= 0.9.5"
41
+ spec.add_dependency "faraday"
42
+ spec.add_dependency "rack"
43
+ spec.add_dependency "pg"
44
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: plone_rest_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.4
5
+ platform: ruby
6
+ authors:
7
+ - Claus Rasmussen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-04-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: webmock
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: shellopts
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.9.5
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pg
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Plone REST api library and command
84
+ email:
85
+ - ras@danak.dk
86
+ executables:
87
+ - plone-rest
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".ruby-version"
94
+ - ".travis.yml"
95
+ - ABOUT.md
96
+ - Gemfile
97
+ - README.md
98
+ - Rakefile
99
+ - bin/console
100
+ - bin/setup
101
+ - exe/plone-rest
102
+ - lib/plone_rest_api.rb
103
+ - lib/plone_rest_api/version.rb
104
+ - plone_rest_api.gemspec
105
+ homepage: http://www.nowhere.com/
106
+ licenses: []
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.0.8
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Plone REST api library and command
127
+ test_files: []