xing-backend 0.0.19 → 0.0.20

Sign up to get free protection for your applications and to get access to all the features.
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