xing-backend 0.0.19 → 0.0.20

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/role.rb +24 -0
  3. data/config/locales/json.yml +29 -0
  4. data/config/routes.rb +3 -0
  5. data/db/migrate/20140828011806_initial.rb +45 -0
  6. data/db/migrate/20140914030703_devise_token_auth_add_token_info_to_users.rb +20 -0
  7. data/db/migrate/20140929192921_remove_login_from_users.rb +5 -0
  8. data/lib/xing-backend.rb +1 -0
  9. data/lib/xing/engine.rb +4 -0
  10. data/lib/xing/nominal/database_config_validator.rb +31 -0
  11. data/lib/xing/nominal/dependency_utils.rb +26 -0
  12. data/lib/xing/nominal/secrets_validator.rb +50 -0
  13. data/lib/xing/nominal/yaml_config_validator.rb +44 -0
  14. data/lib/xing/services.rb +0 -2
  15. data/lib/xing/services/class_registry.rb +31 -0
  16. data/lib/xing/services/{page_wrapper.rb → paged_wrapper.rb} +2 -2
  17. data/lib/xing/snapshot.rb +4 -0
  18. data/lib/xing/snapshot/domain_helpers.rb +24 -0
  19. data/lib/xing/snapshot/fetcher.rb +35 -0
  20. data/lib/xing/snapshot/local_site_snapshot.rb +37 -0
  21. data/lib/xing/snapshot/remote_site_snapshot.rb +16 -0
  22. data/lib/xing/snapshot/site_page_set.rb +29 -0
  23. data/lib/xing/snapshot/site_snapshot.rb +41 -0
  24. data/lib/xing/snapshot/sitemap.rb +68 -0
  25. data/lib/xing/snapshot/writer.rb +15 -0
  26. data/lib/xing/spec_helpers.rb +7 -0
  27. data/lib/xing/spec_helpers/api_response_matchers.rb +26 -0
  28. data/lib/xing/spec_helpers/ci_support.rb +6 -0
  29. data/lib/xing/spec_helpers/dom_equiv.rb +26 -0
  30. data/lib/xing/spec_helpers/json_requests.rb +58 -0
  31. data/lib/xing/spec_helpers/routing_spec_patch.rb +28 -0
  32. data/lib/xing/spec_helpers/split_servers.rb +15 -0
  33. data/lib/xing/spec_helpers/test_url_helpers.rb +5 -0
  34. data/lib/xing/static.rb +1 -0
  35. data/lib/xing/static/backend_url_cookie.rb +16 -0
  36. data/lib/xing/static/goto_param.rb +30 -0
  37. data/lib/xing/static/logger.rb +11 -0
  38. data/lib/xing/static/rack_app.rb +40 -0
  39. data/lib/xing/tasks/all.rake +4 -0
  40. data/lib/xing/tasks/db_recycle.rake +4 -0
  41. data/lib/xing/tasks/dependencies_common.rake +49 -0
  42. data/lib/xing/tasks/sample_data.rake +49 -0
  43. data/lib/xing/tasks/take_snapshot.rake +4 -0
  44. data/spec/xing/builders/list_builder_spec.rb +0 -2
  45. data/spec/xing/builders/ordered_list_builder_spec.rb +0 -2
  46. data/spec/xing/nominal/database_config_validator_spec.rb +98 -0
  47. data/spec/xing/nominal/secrets_validator_spec.rb +78 -0
  48. data/spec/xing/serializers/list_spec.rb +116 -0
  49. data/spec/xing/serializers/paged_index_spec.rb +2 -2
  50. data/spec/xing/serializers/paged_list_spec.rb +1 -1
  51. data/spec/xing/services/error_converter_spec.rb +1 -3
  52. data/spec/xing/services/paged_wrapper_spec.rb +30 -0
  53. data/spec/xing/snapshot/remote_snapshot_fetcher_spec.rb +81 -0
  54. data/spec/xing/{services → snapshot}/snapshot_fetcher_spec.rb +6 -4
  55. data/spec_help/dummy/db/test.sqlite3 +0 -0
  56. data/spec_help/dummy/log/test.log +143 -0
  57. data/spec_help/file-sandbox.rb +164 -0
  58. data/spec_help/spec_helper.rb +0 -2
  59. metadata +152 -12
  60. data/lib/xing/services/snapshot_fetcher.rb +0 -33
  61. data/lib/xing/services/snapshot_writer.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7bb90034c2383f0866fde062f849ea3aabace59
4
- data.tar.gz: a5823af9381a90361195f139eb80292cb085f738
3
+ metadata.gz: 06adc2c9335e9abd04144b3b77aa30b10ca66494
4
+ data.tar.gz: dab2b68d69fe03e1e510ccc4d3ae490f93065991
5
5
  SHA512:
6
- metadata.gz: 43fd7dd223af84a296b348e0731aaaf800ff4b41b61068df3069dd9dd8f934cb4bdd4ec5228a9af313a107442a0ae3192598951da13ef40943beffef481b5382
7
- data.tar.gz: d0b79eed9ed10eb308b65b0104c7fe6d93a36aa63853139157b98ade4445979fc05c65fbaa5f5fcc371d4d3d4c93245aae46837a31a80e8dc4f731117854195e
6
+ metadata.gz: db70e839274e8e2cd5f49583ec2435d6aef0fe25b10f3f7c4e5902922228d884a8dab7b11ed2cc7879718119234fc3e9ae60a546c29d51ed4e70a64baddc7559
7
+ data.tar.gz: 6e2e327f99f3fb411c0733d571d4cf5a3635c067b2eddf06eb40ada56643f7783947f34e66bc43ba912c041adf990df2f0d5ccc03bac0e8b13be1f5dd8b4df1a
@@ -0,0 +1,24 @@
1
+ require 'xing/services/class_registry'
2
+ class Role
3
+ include Xing::Services::ClassRegistry
4
+
5
+ #def self.registrar; Role; end
6
+
7
+ def self.for(user)
8
+ registry[user.role_name].new.tap do |role|
9
+ role.user = user
10
+ end
11
+ end
12
+
13
+ def self.users
14
+ User.where(:role_name => registrar.registry_key(self))
15
+ end
16
+
17
+ def role_name
18
+ user.role_name
19
+ end
20
+
21
+ attr_accessor :user
22
+
23
+ Dir[File.join(Rails.root, 'app/models/role/*.rb')].each { |file| require file }
24
+ end
@@ -0,0 +1,29 @@
1
+ json:
2
+ errors:
3
+ # The default format to use in full error messages.
4
+ format: "%{attribute} %{message}"
5
+
6
+ # The values :model, :attribute and :value are always available for interpolation
7
+ # The value :count is available when applicable. Can be used for pluralization.
8
+ messages:
9
+ inclusion: "inclusion"
10
+ exclusion: "exclusion"
11
+ invalid: "invalid"
12
+ confirmation: "confirmation"
13
+ accepted: "accepted"
14
+ empty: "empty"
15
+ blank: "required"
16
+ present: "must_be_blank"
17
+ too_long: "longer_than_%{count}"
18
+ too_short: "shorter_than_%{count}"
19
+ wrong_length: "wrong_length_%{count}"
20
+ not_a_number: "not_a_number"
21
+ not_an_integer: "not_an_integer"
22
+ greater_than: "greater_than_%{count}"
23
+ greater_than_or_equal_to: "greater_than_%{count}"
24
+ equal_to: "equal_to_%{count}"
25
+ less_than: "less_than_%{count}"
26
+ less_than_or_equal_to: "less_than_or_equal_to_%{count}"
27
+ other_than: "other_than_%{count}"
28
+ odd: "odd"
29
+ even: "even"
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ resources :resources, :only => [:index], :controller => 'xing/root_resources'
3
+ end
@@ -0,0 +1,45 @@
1
+ class Initial < ActiveRecord::Migration
2
+ def self.up
3
+
4
+ # These are extensions that must be enabled in order to support this database
5
+ enable_extension "plpgsql"
6
+ enable_extension "hstore"
7
+
8
+ create_table "users", force: true do |t|
9
+ t.string "login", limit: 20, null: false
10
+ t.string "email"
11
+ t.string "first_name", limit: 60
12
+ t.string "last_name", limit: 60
13
+ t.integer "sign_in_count", default: 0, null: false
14
+ t.integer "failed_attempts", default: 0, null: false
15
+ t.datetime "last_request_at"
16
+ t.datetime "current_sign_in_at"
17
+ t.datetime "last_sign_in_at"
18
+ t.string "current_sign_in_ip"
19
+ t.string "last_sign_in_ip"
20
+ t.string "role_name"
21
+ t.datetime "created_at"
22
+ t.datetime "updated_at"
23
+ t.string "encrypted_password"
24
+ t.string "confirmation_token"
25
+ t.datetime "confirmed_at"
26
+ t.datetime "confirmation_sent_at"
27
+ t.string "reset_password_token"
28
+ t.datetime "reset_password_sent_at"
29
+ t.string "remember_token"
30
+ t.datetime "remember_created_at"
31
+ t.string "unlock_token"
32
+ t.datetime "locked_at"
33
+ end
34
+
35
+ add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
36
+ add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
37
+ add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
38
+ add_index "users", ["unlock_token"], name: "index_users_on_unlock_token", unique: true, using: :btree
39
+
40
+ end
41
+
42
+ def self.down
43
+ raise ActiveRecord::IrreversibleMigration
44
+ end
45
+ end
@@ -0,0 +1,20 @@
1
+ class DeviseTokenAuthAddTokenInfoToUsers < ActiveRecord::Migration
2
+ def change
3
+ change_table(:users) do |t|
4
+ ## unique oauth id
5
+ t.string :provider
6
+ t.string :uid, :null => false, :default => ""
7
+
8
+ ## Tokens
9
+ t.text :tokens
10
+ end
11
+
12
+ add_index :users, :uid, :unique => true
13
+
14
+ User.reset_column_information
15
+ User.all.each do |user|
16
+ user.uid = user.login
17
+ user.save
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ class RemoveLoginFromUsers < ActiveRecord::Migration
2
+ def change
3
+ remove_column :users, :login
4
+ end
5
+ end
data/lib/xing-backend.rb CHANGED
@@ -2,6 +2,7 @@ require 'rails'
2
2
  require 'xing_backend_token_auth'
3
3
  require 'rails/rfc6570'
4
4
  require 'sidekiq'
5
+ require 'rack/cors'
5
6
 
6
7
  module Xing
7
8
  mattr_accessor :backend_subdomain
data/lib/xing/engine.rb CHANGED
@@ -3,6 +3,10 @@ module Xing
3
3
  class Engine < ::Rails::Engine
4
4
  isolate_namespace Xing
5
5
 
6
+ rake_tasks do
7
+ load "xing/tasks/all.rake"
8
+ end
9
+
6
10
  config.autoload_paths += Dir[File.join(__FILE__, '../controllers/**/')]
7
11
 
8
12
  config.generators do |g|
@@ -0,0 +1,31 @@
1
+ require 'xing/nominal/yaml_config_validator'
2
+
3
+ module Xing
4
+ module Nominal
5
+ class DatabaseConfigValidator < YamlConfigValidator
6
+ DATABASE_CONFIG_FILE = 'config/database.yml'
7
+ COMMON_DATABASE_RULES = {
8
+ 'adapter' => 'string',
9
+ 'database' => 'string'
10
+ }
11
+ PROD_DATABASE_RULES = COMMON_DATABASE_RULES.merge({
12
+ 'username' => 'string',
13
+ 'password' => 'string',
14
+ 'host' => 'string'
15
+ })
16
+
17
+ def rules(environment)
18
+ case environment
19
+ when 'production', 'staging'
20
+ PROD_DATABASE_RULES
21
+ else
22
+ COMMON_DATABASE_RULES
23
+ end
24
+ end
25
+
26
+ def file_under_test
27
+ DATABASE_CONFIG_FILE
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ module Xing
2
+ module Nominal
3
+ module DependencyUtils
4
+ require 'pp'
5
+ def sh_or_fail(command, fail_message)
6
+ sh command do |ok, result|
7
+ dep_fail fail_message unless ok
8
+ end
9
+ end
10
+
11
+ def dep_fail(fail_message, details = nil)
12
+ message = "Dependency Failed: " + fail_message
13
+ message += " (Details below):\n#{details.pretty_inspect}" if details
14
+ abort red(message)
15
+ end
16
+
17
+ def red(string)
18
+ "\e[1;31m#{string}\e[0m"
19
+ end
20
+
21
+ def dep_success(message)
22
+ puts message
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,50 @@
1
+ require 'xing/nominal/yaml_config_validator'
2
+
3
+ module Xing
4
+ module Nominal
5
+ class SecretsValidator < YamlConfigValidator
6
+ SECRETS_FILE = 'config/secrets.yml'
7
+ COMMON_SECRETS_VALIDATION = {
8
+ 'secret_key_base' => 'string',
9
+ 'smtp' => {
10
+ 'address' => 'string',
11
+ 'port' => 'integer',
12
+ 'domain' => 'string',
13
+ 'user_name' => 'string',
14
+ 'password' => 'string'
15
+ },
16
+ 'email' => {
17
+ 'from' => 'email',
18
+ 'reply_to' => 'email',
19
+ 'from_domain' => 'string'
20
+ },
21
+ 'snapshot_server' => {
22
+ 'url' => 'string',
23
+ 'user' => 'string',
24
+ 'password' => 'string'
25
+ },
26
+ 'sitemap_base_url' => 'string'
27
+ }
28
+
29
+ # Development needs the additional email key 'test'
30
+ DEV_SECRETS_VALIDATION = COMMON_SECRETS_VALIDATION.deep_merge(
31
+ 'email' => {
32
+ 'test' => 'email'
33
+ }
34
+ )
35
+
36
+ def rules(environment)
37
+ case environment
38
+ when 'development'
39
+ DEV_SECRETS_VALIDATION
40
+ else
41
+ COMMON_SECRETS_VALIDATION
42
+ end
43
+ end
44
+
45
+ def file_under_test
46
+ SECRETS_FILE
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,44 @@
1
+ require 'hash_validator'
2
+ require 'xing/nominal/dependency_utils'
3
+
4
+ module Xing
5
+ module Nominal
6
+ class YamlConfigValidator
7
+ include DependencyUtils
8
+
9
+ attr_accessor :yaml_hash, :results
10
+ def initialize
11
+ self.yaml_hash = YAML.load(File.open(file_under_test))
12
+ self.results = []
13
+ end
14
+
15
+ # Validate only with common secrets requirements
16
+ def validate(*envs)
17
+ envs << 'test' if envs.include?('development')
18
+ self.results.push(*envs.map{ |env|
19
+ HashValidator.validate(yaml_hash, { env => rules(env) })
20
+ })
21
+ end
22
+
23
+ def report!
24
+ if errors.blank?
25
+ dep_success("#{file_under_test} appears correctly formatted.")
26
+ else
27
+ dep_fail("#{file_under_test} didn't contain required values.", errors)
28
+ end
29
+ end
30
+
31
+ def errors
32
+ self.results.reduce({}) do |errs, validator|
33
+ errs.deep_merge!(validator.errors)
34
+ end
35
+ end
36
+
37
+ def assert_existence
38
+ unless File.exists?(file_under_test)
39
+ dep_fail("Please create #{file_under_test}, check the .example for format")
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
data/lib/xing/services.rb CHANGED
@@ -6,5 +6,3 @@ end
6
6
  require 'xing/services/json_tree_lister'
7
7
  require 'xing/services/error_converter'
8
8
  require 'xing/services/locator'
9
- require 'xing/services/snapshot_fetcher'
10
- require 'xing/services/snapshot_writer'
@@ -0,0 +1,31 @@
1
+ module Xing
2
+ module Services
3
+ module ClassRegistry
4
+ module ClassMethods
5
+ def registry
6
+ @registry ||= {}
7
+ end
8
+
9
+ def register(name, klass=self)
10
+ raise "Invalid registration: #{name} exists" if registrar.registry.has_key?(name) && registrar.registry[name] != klass
11
+ registrar.registry[name] = klass
12
+ end
13
+
14
+ def registry_key(klass)
15
+ registrar.registry.select{ |key, val| val == klass}.keys.first
16
+ end
17
+
18
+ def registry_get(name)
19
+ registrar.registry.fetch(name)
20
+ end
21
+ end
22
+
23
+ def self.included(base)
24
+ base.define_singleton_method(:registrar) do
25
+ base
26
+ end
27
+ base.extend(ClassMethods)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,8 +1,8 @@
1
1
  module Xing::Services
2
2
  # If you want to use the PagedList serializers, but are using resources that
3
3
  # aren't actually provided by Kaminari, you can instead feed them to
4
- # PageWrapper and you should get everything you need
5
- class PageWrapper
4
+ # PagedWrapper and you should get everything you need
5
+ class PagedWrapper
6
6
  include Enumerable
7
7
 
8
8
  def initialize(list, page_num, total_items, per_page)
@@ -0,0 +1,4 @@
1
+ require 'xing/snapshot/local_site_snapshot'
2
+ require 'xing/snapshot/remote_site_snapshot'
3
+ require 'xing/snapshot/fetcher'
4
+ require 'xing/snapshot/sitemap'
@@ -0,0 +1,24 @@
1
+ module Xing
2
+ module Snapshot
3
+ module DomainHelpers
4
+ def domain(url = nil)
5
+ if url
6
+ url
7
+ elsif defined? Rails.application.secrets.sitemap_base_url
8
+ Rails.application.secrets.sitemap_base_url
9
+ else
10
+ raise "No Domain is set for the sitemap. Please set it in secrets.yml."
11
+ end
12
+ end
13
+
14
+ def page_frontend_url(path)
15
+ if PAGES_FRONTEND_URL.present?
16
+ PAGES_FRONTEND_URL + "/" + path
17
+ else
18
+ path
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ require 'typhoeus'
2
+ require 'addressable/uri'
3
+ require 'xing/snapshot/writer'
4
+ require 'sidekiq/worker'
5
+
6
+ module Xing
7
+ module Snapshot
8
+ class Fetcher
9
+ include Sidekiq::Worker
10
+ include Writer
11
+
12
+ def perform(url, path)
13
+ admin_server = Rails.application.secrets.snapshot_server['url']
14
+ user_password = "#{Rails.application.secrets.snapshot_server['user']}:#{Rails.application.secrets.snapshot_server['password']}"
15
+ snapshot_url = Addressable::URI.join(url,path).to_s
16
+ request = Typhoeus::Request.new(admin_server, userpwd: user_password, params: { url: snapshot_url })
17
+
18
+ hydra = Typhoeus::Hydra.new
19
+ hydra.queue(request)
20
+ hydra.run
21
+
22
+ response = request.response
23
+
24
+ if response.success?
25
+ html = response.body
26
+ write(path, html)
27
+ else
28
+ logger.warn response.status_message
29
+ logger.warn response.body
30
+ raise "Query to #{admin_server} for #{path} failed!"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end