admincredible 0.0.1

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.
Files changed (55) hide show
  1. data/Gemfile +12 -0
  2. data/Gemfile.lock +86 -0
  3. data/Rakefile +24 -0
  4. data/Readme.md +121 -0
  5. data/TODOS +1 -0
  6. data/admincredible.gemspec +35 -0
  7. data/developer_notes/README.md +2 -0
  8. data/developer_notes/TODOS.md +0 -0
  9. data/lib/admincredible.rb +1 -0
  10. data/lib/admincredible/client.rb +60 -0
  11. data/lib/admincredible/configuration.rb +125 -0
  12. data/lib/admincredible/connection.rb +30 -0
  13. data/lib/admincredible/core_ext/string.rb +16 -0
  14. data/lib/admincredible/joomla_request.rb +22 -0
  15. data/lib/admincredible/middleware/logger.rb +51 -0
  16. data/lib/admincredible/middleware/step.rb +44 -0
  17. data/lib/admincredible/request.rb +47 -0
  18. data/lib/admincredible/resource.rb +20 -0
  19. data/lib/admincredible/resources/Backup.rb +34 -0
  20. data/lib/admincredible/resources/Compatibility.rb +13 -0
  21. data/lib/admincredible/resources/Extension.rb +37 -0
  22. data/lib/admincredible/resources/Oauth.rb +53 -0
  23. data/lib/admincredible/resources/Setting.rb +21 -0
  24. data/lib/admincredible/resources/Site.rb +9 -0
  25. data/lib/admincredible/resources/Upgrade.rb +64 -0
  26. data/spec/core/client_spec.rb +24 -0
  27. data/spec/core/resource_spec.rb +13 -0
  28. data/spec/fixtures/cassettes/backups/create.yml +73 -0
  29. data/spec/fixtures/cassettes/backups/start.yml +38 -0
  30. data/spec/fixtures/cassettes/backups/step.yml +38 -0
  31. data/spec/fixtures/cassettes/compatibility/added_exceptions.yml +38 -0
  32. data/spec/fixtures/cassettes/compatibility/status.yml +38 -0
  33. data/spec/fixtures/cassettes/extensions/all.yml +38 -0
  34. data/spec/fixtures/cassettes/extensions/update.yml +38 -0
  35. data/spec/fixtures/cassettes/settings/all.yml +38 -0
  36. data/spec/fixtures/cassettes/settings/created.yml +39 -0
  37. data/spec/fixtures/cassettes/settings/first.yml +38 -0
  38. data/spec/fixtures/cassettes/settings/updated.yml +39 -0
  39. data/spec/fixtures/cassettes/site/configuration.yml +41 -0
  40. data/spec/fixtures/cassettes/upgrade/cleanup.yml +38 -0
  41. data/spec/fixtures/cassettes/upgrade/create.yml +249 -0
  42. data/spec/fixtures/cassettes/upgrade/create_restoration_file.yml +38 -0
  43. data/spec/fixtures/cassettes/upgrade/download.yml +38 -0
  44. data/spec/fixtures/cassettes/upgrade/finalize.yml +38 -0
  45. data/spec/fixtures/cassettes/upgrade/info.yml +38 -0
  46. data/spec/fixtures/cassettes/upgrade/start.yml +39 -0
  47. data/spec/fixtures/cassettes/upgrade/step.yml +38 -0
  48. data/spec/resources/backups_spec.rb +36 -0
  49. data/spec/resources/compatibility_spec.rb +25 -0
  50. data/spec/resources/extensions_spec.rb +25 -0
  51. data/spec/resources/setting_spec.rb +47 -0
  52. data/spec/resources/site_spec.rb +14 -0
  53. data/spec/resources/upgrade_spec.rb +91 -0
  54. data/spec/spec_helper.rb +38 -0
  55. metadata +353 -0
@@ -0,0 +1,30 @@
1
+ module Admincredible
2
+ module Connection
3
+ def connection
4
+ @connection ||= build_connection
5
+ return @connection
6
+ end
7
+
8
+ def rebuild_connection
9
+ @connection = build_connection
10
+ end
11
+
12
+ def build_connection
13
+ Faraday.new(config.connection_options) do |builder|
14
+ # Response
15
+ builder.use Faraday::Response::RaiseError
16
+ builder.use Admincredible::Middleware::Response::Logger, config.logger if config.logger
17
+ builder.response :json, :content_type => 'application/json'
18
+
19
+ # Request
20
+ builder.use Faraday::Request::OAuth, config.oauth_options if config.oauth?
21
+ builder.request :multipart
22
+ builder.request :json
23
+ builder.request :retry, 2 unless config.oauth?
24
+ builder.request :step unless config.oauth?
25
+
26
+ builder.adapter config.adapter || Faraday.default_adapter
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,16 @@
1
+ class String
2
+ ##
3
+ # Transforms a string into a module name.
4
+ #
5
+ # We at String Transforming Enterprise, Inc, TM, LLC, Corp, believe in three things;
6
+ # 1. All strings should be allowed to be whatever string they like.
7
+ # 2. ??
8
+ # 3. Profit
9
+ #
10
+ def modulize
11
+ self.gsub(/__(.?)/){ "::#{$1.upcase}" }.
12
+ gsub(/\/(.?)/){ "::#{$1.upcase}" }.
13
+ gsub(/(?:_+|-+)([a-z])/){ $1.upcase }.
14
+ gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase }
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ # Due to the fact Joomla cant handle decent URLs (at least not out of the box)
2
+ # we abstract the requests further. all these methods take a resource + task and then any other
3
+ # has GET request vars, finally it takes normal options.
4
+ module Admincredible
5
+ module JoomlaRequest
6
+ def jget(resource, task, options={})
7
+ get('', {:resource => resource, :task => task}.merge(options))
8
+ end
9
+
10
+ def jpost(resource, task, options={})
11
+ post('', options, {:resource => resource, :task => task})
12
+ end
13
+
14
+ def jput(resource, task, options={})
15
+ put('', options, {:resource => resource, :task => task})
16
+ end
17
+
18
+ def jdelete(resource, task, options={})
19
+ delete('', {:resource => resource, :task => task}.merge(options))
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,51 @@
1
+ require 'faraday_middleware/response_middleware'
2
+
3
+ module Admincredible
4
+ module Middleware
5
+ module Response
6
+ ##
7
+ # So you're sitting there and you're staring off into the abyss of your terminal,
8
+ # the solarized green color scheme begins to sink into your retinas and the anger begins to build.
9
+ # This class prevents hulk moments from occurring and automagically logs requests in when enable via config.
10
+ #
11
+ class Logger < Faraday::Response::Middleware
12
+ def initialize(app, logger = nil)
13
+ super(app)
14
+ @logger = logger || begin
15
+ require 'logger'
16
+ ::Logger.new(STDOUT)
17
+ end
18
+ end
19
+
20
+ def call(env)
21
+ @logger.info "#{env[:method]} #{env[:url].to_s}"
22
+ @logger.debug dump_debug(env, :request_headers)
23
+ super
24
+ end
25
+
26
+ def on_complete(env)
27
+ @logger.info("Status #{env[:status].to_s}")
28
+ @logger.debug dump_debug(env, :response_headers)
29
+ end
30
+
31
+ private
32
+
33
+ ##
34
+ # Dumps things, but safely, like a cat diligently using the litter box.
35
+ # It won't dump things that are nil and will make sure to inspect the objects first,
36
+ # if they are found to be carrying in countraband they'll be mapped and joined; which is probably code for
37
+ # something rather sinister.
38
+ # Remember cats, sand irst (safety), dump second,
39
+ #
40
+ def dump_debug(env, headers_key)
41
+ info = env[headers_key].map { |k, v| " #{k}: #{v.inspect}" }.join("\n")
42
+ unless env[:body].nil?
43
+ info.concat("\n")
44
+ info.concat(env[:body].inspect)
45
+ end
46
+ info
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,44 @@
1
+ require 'faraday/middleware'
2
+
3
+ module Admincredible
4
+ module Middleware
5
+ module Request
6
+ ##
7
+ # Akeeba powered restoration scripts use a step/ping methodology that avoids timing out servers.
8
+ # This will automatically send more requests when a step response is received.
9
+ #
10
+ # It sadly doesn't work with OAuth yet because the re-signing requests problem was too difficult for this dev too
11
+ # solve at the time of this writing.
12
+ #
13
+ # @todo Fix this for OAuth
14
+ #
15
+ # If many months pass before this is resolved you can blame the developer's intense devotion to getting other things
16
+ # done. You can probably motivate him to fix it for oauth by bribing him with books.
17
+ #
18
+ class Step < Faraday::Middleware
19
+ DEFAULT_RETRY_AFTER = 1
20
+
21
+ def initialize(app, options={})
22
+ super(app)
23
+ end
24
+
25
+ def call(env)
26
+ response = @app.call(env)
27
+
28
+ if response.env[:status] == 202
29
+ seconds_left = DEFAULT_RETRY_AFTER
30
+
31
+ seconds_left.times do |i|
32
+ sleep 1
33
+ end
34
+
35
+ call(env)
36
+ else
37
+ response
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ Faraday.register_middleware :request, :step => Admincredible::Middleware::Request::Step
@@ -0,0 +1,47 @@
1
+ module Admincredible
2
+ module Request
3
+ # Perform an HTTP GET request
4
+ def get(path, options={})
5
+ request(:get, path, options)
6
+ end
7
+
8
+ # Perform an HTTP POST request
9
+ def post(path, options={}, path_options={})
10
+ request(:post, path, options, path_options)
11
+ end
12
+
13
+ # Perform an HTTP PUT request
14
+ def put(path, options={}, path_options={})
15
+ request(:put, path, options, path_options)
16
+ end
17
+
18
+ # Perform an HTTP DELETE request
19
+ def delete(path, options={})
20
+ request(:delete, path, options)
21
+ end
22
+
23
+ private
24
+
25
+ def request(method, path, options={}, path_options={})
26
+ response = false
27
+ begin
28
+ response = connection.send(method) do |request|
29
+ case method
30
+ when :get, :delete
31
+ request.url(path, options)
32
+ when :post, :put
33
+ request.path = path
34
+ request.params = path_options
35
+ request.body = options unless options.empty?
36
+ end
37
+ end
38
+ rescue Faraday::Error::ClientError => e
39
+ response = e.response
40
+ end
41
+
42
+ return response.body if response.respond_to?(:body)
43
+ return response[:body] if response.is_a?(Hash)
44
+ return response
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,20 @@
1
+ module Admincredible
2
+ class Resource
3
+ attr_reader :client
4
+
5
+ ##
6
+ # Initializes with a client. You can use resource classes directly by passing and instance of Admincredible::Client
7
+ #
8
+ def initialize(client, options={})
9
+ @client = client
10
+ end
11
+
12
+ def connection
13
+ return client.connection
14
+ end
15
+
16
+ def config
17
+ return client.config
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ module Admincredible
2
+ module Resources
3
+ class Backup < Resource
4
+ def start
5
+ client.jget('backups', 'start')
6
+ end
7
+
8
+ def step(repeat_until_done=true)
9
+ response = client.jget('backups', 'step')
10
+
11
+ if response['status'] == 'working' && repeat_until_done
12
+ seconds_left = config.step_after_seconds
13
+
14
+ seconds_left.times do |i|
15
+ sleep 1
16
+ end
17
+
18
+ return step
19
+ end
20
+
21
+ response
22
+ end
23
+
24
+ def create
25
+ response = start
26
+ if response['status'] == 302
27
+ return step
28
+ else
29
+ return response
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,13 @@
1
+ module Admincredible
2
+ module Resources
3
+ class Compatibility < Resource
4
+ def status
5
+ client.jget('compatibility', 'status')['data']
6
+ end
7
+
8
+ def add_exceptions
9
+ client.jget('compatibility', 'add_exceptions', {:accept_terms => true})
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ module Admincredible
2
+ module Resources
3
+ class Extension < Resource
4
+ def all
5
+ client.jget('extensions', 'index')['data']['extensions']
6
+ end
7
+ alias :index :all
8
+
9
+ def update(extension_ids=[], repeat_until_response=true)
10
+ unless config.oauth?
11
+ client.rebuild_connection
12
+ connection.builder.request :retry, 18
13
+ end
14
+
15
+ response = nil
16
+ begin
17
+ response = client.jget('extensions', 'update', :extension_ids => extension_ids)
18
+ rescue Faraday::Error::TimeoutError => e
19
+ if repeat_until_response && config.oauth?
20
+ seconds_left = config.step_after_seconds
21
+
22
+ seconds_left.times do |i|
23
+ sleep 1
24
+ end
25
+
26
+ return update(extension_ids)
27
+ else
28
+ response = false
29
+ end
30
+ end
31
+
32
+ client.rebuild_connection unless config.oauth?
33
+ response
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,53 @@
1
+ module Admincredible
2
+ module Resources
3
+ class Oauth < Resource
4
+ def register
5
+ response = client.jget('oauth', 'register')
6
+ return response unless response['status'] == 200
7
+
8
+ config.consumer_key = response['data']['osr_consumer_key']
9
+ config.consumer_secret = response['data']['osr_consumer_secret']
10
+
11
+ client.rebuild_connection
12
+ return response['data']
13
+ end
14
+
15
+ def request_token
16
+ response = client.jget('oauth', 'request_token')
17
+ return response unless response['status'] == 200
18
+
19
+ config.token = response['data']['request_token']['oauth_token']
20
+ config.token_secret = response['data']['request_token']['oauth_token_secret']
21
+
22
+ client.rebuild_connection
23
+ return response['data']['request_token']
24
+ end
25
+
26
+ def authorization_url
27
+ url = config.url.gsub(config.direct_endpoint, config.main_endpoint)
28
+ url = URI.parse(url)
29
+ params = CGI.parse(url.query)
30
+
31
+ return ROAuth.sign_url(config.oauth_options, url.scheme + '://' + url.host + url.path, params.merge({:oauth_callback => config.oauth_callback}))
32
+ end
33
+
34
+ def access_token(oauth_verifier)
35
+ params = {
36
+ :resource => 'oauth',
37
+ :task => 'access_token',
38
+ :oauth_token => config.token,
39
+ :oauth_verifier => oauth_verifier
40
+ }
41
+ oauth_header = ROAuth.header(config.oauth_options, config.url, params)
42
+ response = JSON.parse(Nestful.get(config.url, :params => params, :headers => {'Accept' => 'application/json', 'Authorization' => oauth_header}))
43
+ return response unless response['status'] == 200
44
+
45
+ config.token = response['data']['access_token']['oauth_token']
46
+ config.token_secret = response['data']['access_token']['oauth_token_secret']
47
+
48
+ client.rebuild_connection
49
+ return response['data']['access_token']
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ module Admincredible
2
+ module Resources
3
+ class Setting < Resource
4
+ def all
5
+ client.jget('settings', 'index')['data']
6
+ end
7
+
8
+ def first
9
+ client.jget('settings', 'read')['data']
10
+ end
11
+
12
+ def create(*args)
13
+ client.jpost('settings', 'create', args.extract_options!)['data']
14
+ end
15
+
16
+ def update(*args)
17
+ client.jpost('settings', 'update', args.extract_options!)['data']
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ module Admincredible
2
+ module Resources
3
+ class Site < Resource
4
+ def configuration
5
+ client.jget('site', 'configuration')['data']
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,64 @@
1
+ module Admincredible
2
+ module Resources
3
+ class Upgrade < Resource
4
+ def info
5
+ client.jget('upgrade', 'info')['data']
6
+ end
7
+
8
+ def download
9
+ client.jget('upgrade', 'download')
10
+ end
11
+
12
+ def create_restoration_file
13
+ client.jget('upgrade', 'create_restoration_file')
14
+ end
15
+
16
+ def start
17
+ client.jget('upgrade', 'start')
18
+ end
19
+
20
+ def step(repeat_until_done=true)
21
+ response = client.jget('upgrade', 'step')
22
+
23
+ if response['status'] == 'working' && repeat_until_done
24
+ seconds_left = config.step_after_seconds
25
+
26
+ seconds_left.times do |i|
27
+ sleep 1
28
+ end
29
+
30
+ return step
31
+ end
32
+
33
+ response
34
+ end
35
+
36
+ def finalize
37
+ client.jget('upgrade', 'finalize')
38
+ end
39
+
40
+ def cleanup
41
+ client.jget('upgrade', 'cleanup')
42
+ end
43
+
44
+ def create
45
+ response = download
46
+ return response unless response['status'] == 200
47
+
48
+ response = create_restoration_file
49
+ return response unless response['status'] == 200
50
+
51
+ response = start
52
+ return response unless response['status'] == 302
53
+
54
+ response = step
55
+ return response unless response['status'] == 200
56
+
57
+ response = finalize
58
+ return response unless response['status'] == 200
59
+
60
+ return cleanup
61
+ end
62
+ end
63
+ end
64
+ end