logux_rails 0.1.0
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 +7 -0
- data/.gitignore +20 -0
- data/.pryrc +8 -0
- data/.rspec +3 -0
- data/.rubocop.yml +33 -0
- data/.rubocop_todo.yml +17 -0
- data/.travis.yml +11 -0
- data/Appraisals +13 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +68 -0
- data/Rakefile +10 -0
- data/app/controllers/logux_controller.rb +41 -0
- data/app/helpers/logux_helper.rb +4 -0
- data/app/logux/actions.rb +3 -0
- data/app/logux/policies.rb +3 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/config/routes.rb +5 -0
- data/docker-compose.yml +29 -0
- data/lib/generators/logux/model/USAGE +11 -0
- data/lib/generators/logux/model/model_generator.rb +28 -0
- data/lib/generators/logux/model/templates/migration.rb.erb +14 -0
- data/lib/logux.rb +107 -0
- data/lib/logux/action_caller.rb +42 -0
- data/lib/logux/action_controller.rb +6 -0
- data/lib/logux/actions.rb +29 -0
- data/lib/logux/add.rb +37 -0
- data/lib/logux/auth.rb +6 -0
- data/lib/logux/base_controller.rb +37 -0
- data/lib/logux/channel_controller.rb +24 -0
- data/lib/logux/class_finder.rb +61 -0
- data/lib/logux/client.rb +21 -0
- data/lib/logux/engine.rb +6 -0
- data/lib/logux/error_renderer.rb +40 -0
- data/lib/logux/meta.rb +36 -0
- data/lib/logux/model.rb +39 -0
- data/lib/logux/model/dsl.rb +15 -0
- data/lib/logux/model/proxy.rb +24 -0
- data/lib/logux/model/updater.rb +39 -0
- data/lib/logux/model/updates_deprecator.rb +54 -0
- data/lib/logux/node.rb +37 -0
- data/lib/logux/policy.rb +14 -0
- data/lib/logux/policy_caller.rb +34 -0
- data/lib/logux/process.rb +9 -0
- data/lib/logux/process/action.rb +60 -0
- data/lib/logux/process/auth.rb +27 -0
- data/lib/logux/process/batch.rb +59 -0
- data/lib/logux/response.rb +18 -0
- data/lib/logux/stream.rb +25 -0
- data/lib/logux/test.rb +35 -0
- data/lib/logux/test/helpers.rb +75 -0
- data/lib/logux/test/matchers.rb +10 -0
- data/lib/logux/test/matchers/base.rb +25 -0
- data/lib/logux/test/matchers/response_chunks.rb +48 -0
- data/lib/logux/test/matchers/send_to_logux.rb +51 -0
- data/lib/logux/test/store.rb +21 -0
- data/lib/logux/version.rb +5 -0
- data/lib/logux_rails.rb +3 -0
- data/lib/tasks/logux_tasks.rake +46 -0
- data/logux_rails.gemspec +46 -0
- metadata +398 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e2ddee267525e7f6503a6a64b42b4b18322dd7a597c1f535f5c3341921bad354
|
4
|
+
data.tar.gz: b7f32ba3524a11d9a81872064231cc939773cc68a22029a3cf52e48253fafeb6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a82d8cf1df3c2c228b4e6a371cf027d146cb59bc67f338cbef4103745132047f56224024fa9b24347d5b3734ead07afe4d0ca744b0b7d8eef07fe3a246d8e38
|
7
|
+
data.tar.gz: 7d9efeb074215bb2ac5c3d601ded5425f2c927efe5f6ed7c4f749c6f49b9f1fb33b4b40abdd0b9145912f1ecc17c08b3bca99580cd9f8a49fecbe2997a1869c3
|
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
|
+
.DS_Store
|
14
|
+
|
15
|
+
**/*.log
|
16
|
+
.*.swp
|
17
|
+
coverage
|
18
|
+
Gemfile.lock
|
19
|
+
spec/dummy/db/*.sqlite3
|
20
|
+
/gemfiles/*
|
data/.pryrc
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
require: rubocop-rspec
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
Exclude:
|
7
|
+
- 'spec/dummy/db/**/*.rb'
|
8
|
+
- 'vendor/**/*'
|
9
|
+
- 'gemfiles/*'
|
10
|
+
TargetRubyVersion: 2.4
|
11
|
+
|
12
|
+
Metrics/BlockLength:
|
13
|
+
Exclude:
|
14
|
+
- 'spec/**/*.rb'
|
15
|
+
- 'logux_rails.gemspec'
|
16
|
+
- 'lib/logux/test/helpers.rb'
|
17
|
+
|
18
|
+
RSpec/DescribeClass:
|
19
|
+
Exclude:
|
20
|
+
- 'spec/logux/tasks/*.rb'
|
21
|
+
- 'spec/requests/*.rb'
|
22
|
+
|
23
|
+
FactoryBot/StaticAttributeDefinedDynamically:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
RSpec/ExpectChange:
|
27
|
+
EnforcedStyle: block
|
28
|
+
|
29
|
+
Style/RescueStandardError:
|
30
|
+
EnforcedStyle: implicit
|
31
|
+
|
32
|
+
Style/DateTime:
|
33
|
+
Enabled: false
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2018-07-26 13:29:22 +0300 using RuboCop version 0.57.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 17
|
10
|
+
Style/Documentation:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
# Offense count: 2
|
14
|
+
Style/MixinUsage:
|
15
|
+
Exclude:
|
16
|
+
- 'spec/dummy/bin/setup'
|
17
|
+
- 'spec/dummy/bin/update'
|
data/.travis.yml
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
sudo: require
|
2
|
+
services:
|
3
|
+
- docker
|
4
|
+
|
5
|
+
before_script:
|
6
|
+
- unset BUNDLE_GEMFILE
|
7
|
+
- docker-compose run app bundle install
|
8
|
+
- docker-compose run app bundle exec appraisal install
|
9
|
+
script:
|
10
|
+
- docker-compose run app bundle exec appraisal rspec
|
11
|
+
- docker-compose run app bundle exec rubocop
|
data/Appraisals
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 WildDima
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Logux Rails
|
2
|
+
|
3
|
+
[](https://travis-ci.org/logux/logux_rails) [](https://coveralls.io/github/logux/logux_rails?branch=master)
|
4
|
+
|
5
|
+
Add WebSockets, live-updates and offline-first to Ruby on Rails with [Logux](https://github.com/logux/logux/). This gem will add [Logux Back-end Protocol](https://github.com/logux/logux/blob/master/backend-protocol/spec.md) to Ruby on Rails and then you can use Logux Server as a proxy between WebSocket and your Rails application.
|
6
|
+
|
7
|
+
Read [Creating Logux Proxy](https://github.com/logux/logux/blob/master/2-starting/2-creating-proxy.md) guide.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'logux_rails'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
```bash
|
20
|
+
bundle
|
21
|
+
```
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
First of all, you have to configure Logux, by defining server address in, for example, `config/initializers/logux.rb`:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
Logux.configuration do |config|
|
29
|
+
config.logux_host = 'http://localhost:31338'
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Mount logux in routes:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
mount Logux::Engine => '/'
|
37
|
+
```
|
38
|
+
|
39
|
+
After this, POST requests to `/logux` will be processed by `LoguxController`. You can redefine it or inherit from, if it necessary, for example, for implementing custom authorization flow.
|
40
|
+
|
41
|
+
Logux Rails will try to find Action for the specific message from Logux Server. For example, for `project/rename` action, you should define `Action::Project` class, inherited from `Logux::Action` base class, and implement `rename` method.
|
42
|
+
|
43
|
+
You can execute `rake logux:actions` to get the list of available action types, or `rake logux:channels` to get the list of available channels.
|
44
|
+
|
45
|
+
## Development with Docker
|
46
|
+
|
47
|
+
After checking out the repo, run:
|
48
|
+
|
49
|
+
```bash
|
50
|
+
docker-compose run app bundle install
|
51
|
+
docker-compose run app bundle exec appraisal install
|
52
|
+
```
|
53
|
+
|
54
|
+
Run tests with:
|
55
|
+
|
56
|
+
```bash
|
57
|
+
docker-compose run app bundle exec appraisal rspec
|
58
|
+
```
|
59
|
+
|
60
|
+
Run RuboCop with:
|
61
|
+
|
62
|
+
```bash
|
63
|
+
docker-compose run app bundle exec rubocop
|
64
|
+
```
|
65
|
+
|
66
|
+
## License
|
67
|
+
|
68
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class LoguxController < ActionController::Base
|
4
|
+
include ActionController::Live
|
5
|
+
|
6
|
+
def create
|
7
|
+
logux_stream.write('[')
|
8
|
+
Logux.verify_request_meta_data(meta_params)
|
9
|
+
Logux.process_batch(stream: logux_stream, batch: command_params)
|
10
|
+
rescue => ex
|
11
|
+
handle_processing_errors(ex)
|
12
|
+
ensure
|
13
|
+
logux_stream.write(']')
|
14
|
+
logux_stream.close
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def unsafe_params
|
20
|
+
params.to_unsafe_h
|
21
|
+
end
|
22
|
+
|
23
|
+
def command_params
|
24
|
+
unsafe_params.dig('commands')
|
25
|
+
end
|
26
|
+
|
27
|
+
def meta_params
|
28
|
+
unsafe_params&.slice(:version, :password)
|
29
|
+
end
|
30
|
+
|
31
|
+
def logux_stream
|
32
|
+
@logux_stream ||= Logux::Stream.new(response.stream)
|
33
|
+
end
|
34
|
+
|
35
|
+
def handle_processing_errors(exception)
|
36
|
+
Logux.configuration.on_error.call(exception)
|
37
|
+
Logux.logger.error("#{exception}\n#{exception.backtrace.join("\n")}")
|
38
|
+
ensure
|
39
|
+
logux_stream.write(Logux::ErrorRenderer.new(exception).message)
|
40
|
+
end
|
41
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'logux_rails'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/config/routes.rb
ADDED
data/docker-compose.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
version: '3.4'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
image: ruby:2.5.1
|
6
|
+
environment:
|
7
|
+
- BUNDLE_PATH=/bundle
|
8
|
+
- BUNDLE_CONFIG=/app/.bundle/config
|
9
|
+
|
10
|
+
- DB_HOST=db
|
11
|
+
- DB_NAME=logux_rails
|
12
|
+
- DB_USERNAME=postgres
|
13
|
+
command: bash
|
14
|
+
working_dir: /app
|
15
|
+
volumes:
|
16
|
+
- .:/app:cached
|
17
|
+
- bundler_data:/bundle
|
18
|
+
tmpfs:
|
19
|
+
- /tmp
|
20
|
+
depends_on:
|
21
|
+
- db
|
22
|
+
|
23
|
+
db:
|
24
|
+
image: postgres:10
|
25
|
+
environment:
|
26
|
+
- POSTGRES_DB=logux_rails
|
27
|
+
|
28
|
+
volumes:
|
29
|
+
bundler_data:
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Description:
|
2
|
+
Generates the necessary migration to enable field tracking for logux updates
|
3
|
+
|
4
|
+
Examples:
|
5
|
+
rails generate logux:model User
|
6
|
+
|
7
|
+
This will generate the migration to add a column with update time data.
|
8
|
+
|
9
|
+
rails generate logux:model User --nullable
|
10
|
+
|
11
|
+
This will generate the migration to add a column with update time data and add `null: false` constraint. Be careful, adding the constraint to the table with a big number of rows can cause lots of locks.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators'
|
4
|
+
require 'rails/generators/active_record/migration/migration_generator'
|
5
|
+
|
6
|
+
module Logux
|
7
|
+
module Generators
|
8
|
+
class ModelGenerator < ::ActiveRecord::Generators::Base # :nodoc:
|
9
|
+
source_root File.expand_path('templates', __dir__)
|
10
|
+
|
11
|
+
class_option :nullable,
|
12
|
+
type: :boolean,
|
13
|
+
optional: true,
|
14
|
+
desc: 'Define whether field should have not-null constraint'
|
15
|
+
|
16
|
+
def generate_migration
|
17
|
+
migration_template(
|
18
|
+
'migration.rb.erb',
|
19
|
+
"db/migrate/add_logux_fields_updated_at_to_#{plural_table_name}.rb"
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def nullable?
|
24
|
+
options.fetch(:nullable, false)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class <%= @migration_class_name %> < ActiveRecord::Migration<%= ActiveRecord::VERSION::MAJOR < 5 ? '' : '[5.0]' %>
|
2
|
+
def up
|
3
|
+
<% if nullable? %>
|
4
|
+
add_column :<%= plural_table_name %>, :logux_fields_updated_at, :jsonb, null: false, default: {}
|
5
|
+
<% else %>
|
6
|
+
add_column :<%= plural_table_name %>, :logux_fields_updated_at, :jsonb, null: true
|
7
|
+
change_column_default :<%= plural_table_name %>, :logux_fields_updated_at, {}
|
8
|
+
<% end %>
|
9
|
+
end
|
10
|
+
|
11
|
+
def down
|
12
|
+
remove_column :<%= plural_table_name %>, :logux_fields_updated_at
|
13
|
+
end
|
14
|
+
end
|
data/lib/logux.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'configurations'
|
4
|
+
require 'rest-client'
|
5
|
+
require 'rails/engine'
|
6
|
+
require 'active_support'
|
7
|
+
require 'action_controller'
|
8
|
+
require 'logux/engine'
|
9
|
+
require 'nanoid'
|
10
|
+
require 'colorize'
|
11
|
+
|
12
|
+
module Logux
|
13
|
+
extend ActiveSupport::Autoload
|
14
|
+
include Configurations
|
15
|
+
|
16
|
+
PROTOCOL_VERSION = 1
|
17
|
+
|
18
|
+
class WithMetaError < StandardError
|
19
|
+
attr_reader :meta
|
20
|
+
|
21
|
+
def initialize(msg, meta: nil)
|
22
|
+
@meta = meta
|
23
|
+
super(msg)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
UnknownActionError = Class.new(WithMetaError)
|
28
|
+
UnknownChannelError = Class.new(WithMetaError)
|
29
|
+
UnauthorizedError = Class.new(StandardError)
|
30
|
+
|
31
|
+
autoload :Client, 'logux/client'
|
32
|
+
autoload :Meta, 'logux/meta'
|
33
|
+
autoload :Actions, 'logux/actions'
|
34
|
+
autoload :Auth, 'logux/auth'
|
35
|
+
autoload :BaseController, 'logux/base_controller'
|
36
|
+
autoload :ActionController, 'logux/action_controller'
|
37
|
+
autoload :ChannelController, 'logux/channel_controller'
|
38
|
+
autoload :ClassFinder, 'logux/class_finder'
|
39
|
+
autoload :ActionCaller, 'logux/action_caller'
|
40
|
+
autoload :PolicyCaller, 'logux/policy_caller'
|
41
|
+
autoload :Policy, 'logux/policy'
|
42
|
+
autoload :Add, 'logux/add'
|
43
|
+
autoload :Node, 'logux/node'
|
44
|
+
autoload :Response, 'logux/response'
|
45
|
+
autoload :Stream, 'logux/stream'
|
46
|
+
autoload :Process, 'logux/process'
|
47
|
+
autoload :Logger, 'logux/logger'
|
48
|
+
autoload :Version, 'logux/version'
|
49
|
+
autoload :Test, 'logux/test'
|
50
|
+
autoload :ErrorRenderer, 'logux/error_renderer'
|
51
|
+
autoload :Model, 'logux/model'
|
52
|
+
|
53
|
+
configurable :logux_host, :verify_authorized,
|
54
|
+
:password, :logger,
|
55
|
+
:on_error, :auth_rule,
|
56
|
+
:render_backtrace_on_error
|
57
|
+
|
58
|
+
configuration_defaults do |config|
|
59
|
+
config.logux_host = 'localhost:1338'
|
60
|
+
config.verify_authorized = true
|
61
|
+
config.logger = ActiveSupport::Logger.new(STDOUT)
|
62
|
+
if defined?(Rails) && Rails.respond_to?(:logger)
|
63
|
+
config.logger = Rails.logger
|
64
|
+
end
|
65
|
+
config.on_error = proc {}
|
66
|
+
config.auth_rule = proc { false }
|
67
|
+
config.render_backtrace_on_error = true
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.add(action, meta = Meta.new)
|
71
|
+
Logux::Add.new.call([[action, meta]])
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.add_batch(commands)
|
75
|
+
Logux::Add.new.call(commands)
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.undo(meta, reason: nil, data: {})
|
79
|
+
add(
|
80
|
+
data.merge(type: 'logux/undo', id: meta.id, reason: reason),
|
81
|
+
Logux::Meta.new(clients: [meta.client_id])
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.verify_request_meta_data(meta_params)
|
86
|
+
if Logux.configuration.password.nil?
|
87
|
+
logger.warn(%(Please, add password for logux server:
|
88
|
+
Logux.configure do |c|
|
89
|
+
c.password = 'your-password'
|
90
|
+
end))
|
91
|
+
end
|
92
|
+
auth = Logux.configuration.password == meta_params&.dig(:password)
|
93
|
+
raise Logux::UnauthorizedError, 'Incorrect password' unless auth
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.process_batch(stream:, batch:)
|
97
|
+
Logux::Process::Batch.new(stream: stream, batch: batch).call
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.generate_action_id
|
101
|
+
Logux::Node.instance.generate_action_id
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.logger
|
105
|
+
configuration.logger
|
106
|
+
end
|
107
|
+
end
|