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.
- checksums.yaml +4 -4
- data/app/models/role.rb +24 -0
- data/config/locales/json.yml +29 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20140828011806_initial.rb +45 -0
- data/db/migrate/20140914030703_devise_token_auth_add_token_info_to_users.rb +20 -0
- data/db/migrate/20140929192921_remove_login_from_users.rb +5 -0
- data/lib/xing-backend.rb +1 -0
- data/lib/xing/engine.rb +4 -0
- data/lib/xing/nominal/database_config_validator.rb +31 -0
- data/lib/xing/nominal/dependency_utils.rb +26 -0
- data/lib/xing/nominal/secrets_validator.rb +50 -0
- data/lib/xing/nominal/yaml_config_validator.rb +44 -0
- data/lib/xing/services.rb +0 -2
- data/lib/xing/services/class_registry.rb +31 -0
- data/lib/xing/services/{page_wrapper.rb → paged_wrapper.rb} +2 -2
- data/lib/xing/snapshot.rb +4 -0
- data/lib/xing/snapshot/domain_helpers.rb +24 -0
- data/lib/xing/snapshot/fetcher.rb +35 -0
- data/lib/xing/snapshot/local_site_snapshot.rb +37 -0
- data/lib/xing/snapshot/remote_site_snapshot.rb +16 -0
- data/lib/xing/snapshot/site_page_set.rb +29 -0
- data/lib/xing/snapshot/site_snapshot.rb +41 -0
- data/lib/xing/snapshot/sitemap.rb +68 -0
- data/lib/xing/snapshot/writer.rb +15 -0
- data/lib/xing/spec_helpers.rb +7 -0
- data/lib/xing/spec_helpers/api_response_matchers.rb +26 -0
- data/lib/xing/spec_helpers/ci_support.rb +6 -0
- data/lib/xing/spec_helpers/dom_equiv.rb +26 -0
- data/lib/xing/spec_helpers/json_requests.rb +58 -0
- data/lib/xing/spec_helpers/routing_spec_patch.rb +28 -0
- data/lib/xing/spec_helpers/split_servers.rb +15 -0
- data/lib/xing/spec_helpers/test_url_helpers.rb +5 -0
- data/lib/xing/static.rb +1 -0
- data/lib/xing/static/backend_url_cookie.rb +16 -0
- data/lib/xing/static/goto_param.rb +30 -0
- data/lib/xing/static/logger.rb +11 -0
- data/lib/xing/static/rack_app.rb +40 -0
- data/lib/xing/tasks/all.rake +4 -0
- data/lib/xing/tasks/db_recycle.rake +4 -0
- data/lib/xing/tasks/dependencies_common.rake +49 -0
- data/lib/xing/tasks/sample_data.rake +49 -0
- data/lib/xing/tasks/take_snapshot.rake +4 -0
- data/spec/xing/builders/list_builder_spec.rb +0 -2
- data/spec/xing/builders/ordered_list_builder_spec.rb +0 -2
- data/spec/xing/nominal/database_config_validator_spec.rb +98 -0
- data/spec/xing/nominal/secrets_validator_spec.rb +78 -0
- data/spec/xing/serializers/list_spec.rb +116 -0
- data/spec/xing/serializers/paged_index_spec.rb +2 -2
- data/spec/xing/serializers/paged_list_spec.rb +1 -1
- data/spec/xing/services/error_converter_spec.rb +1 -3
- data/spec/xing/services/paged_wrapper_spec.rb +30 -0
- data/spec/xing/snapshot/remote_snapshot_fetcher_spec.rb +81 -0
- data/spec/xing/{services → snapshot}/snapshot_fetcher_spec.rb +6 -4
- data/spec_help/dummy/db/test.sqlite3 +0 -0
- data/spec_help/dummy/log/test.log +143 -0
- data/spec_help/file-sandbox.rb +164 -0
- data/spec_help/spec_helper.rb +0 -2
- metadata +152 -12
- data/lib/xing/services/snapshot_fetcher.rb +0 -33
- data/lib/xing/services/snapshot_writer.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06adc2c9335e9abd04144b3b77aa30b10ca66494
|
4
|
+
data.tar.gz: dab2b68d69fe03e1e510ccc4d3ae490f93065991
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db70e839274e8e2cd5f49583ec2435d6aef0fe25b10f3f7c4e5902922228d884a8dab7b11ed2cc7879718119234fc3e9ae60a546c29d51ed4e70a64baddc7559
|
7
|
+
data.tar.gz: 6e2e327f99f3fb411c0733d571d4cf5a3635c067b2eddf06eb40ada56643f7783947f34e66bc43ba912c041adf990df2f0d5ccc03bac0e8b13be1f5dd8b4df1a
|
data/app/models/role.rb
ADDED
@@ -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,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
|
data/lib/xing-backend.rb
CHANGED
data/lib/xing/engine.rb
CHANGED
@@ -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
@@ -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
|
-
#
|
5
|
-
class
|
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,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
|