waylon-core 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 +11 -0
- data/.roxanne.yml +4 -0
- data/.rspec +3 -0
- data/.rubocop.yml +38 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +137 -0
- data/LICENSE.txt +21 -0
- data/README.md +57 -0
- data/Rakefile +23 -0
- data/bin/console +17 -0
- data/bin/setup +8 -0
- data/lib/waylon/base_component.rb +124 -0
- data/lib/waylon/condition.rb +64 -0
- data/lib/waylon/conditions/default.rb +34 -0
- data/lib/waylon/conditions/permission_denied.rb +34 -0
- data/lib/waylon/conditions/regex.rb +22 -0
- data/lib/waylon/config.rb +134 -0
- data/lib/waylon/core.rb +46 -0
- data/lib/waylon/exceptions/not_implemented_error.rb +9 -0
- data/lib/waylon/exceptions/validation_error.rb +9 -0
- data/lib/waylon/generic_exception.rb +7 -0
- data/lib/waylon/group.rb +70 -0
- data/lib/waylon/logger.rb +41 -0
- data/lib/waylon/message.rb +17 -0
- data/lib/waylon/route.rb +71 -0
- data/lib/waylon/routes/default.rb +17 -0
- data/lib/waylon/routes/permission_denied.rb +17 -0
- data/lib/waylon/rspec/matchers/route_matcher.rb +43 -0
- data/lib/waylon/rspec/skill.rb +71 -0
- data/lib/waylon/rspec/test_channel.rb +83 -0
- data/lib/waylon/rspec/test_message.rb +63 -0
- data/lib/waylon/rspec/test_sense.rb +110 -0
- data/lib/waylon/rspec/test_server.rb +120 -0
- data/lib/waylon/rspec/test_user.rb +165 -0
- data/lib/waylon/rspec/test_worker.rb +15 -0
- data/lib/waylon/rspec.rb +50 -0
- data/lib/waylon/sense.rb +74 -0
- data/lib/waylon/sense_registry.rb +30 -0
- data/lib/waylon/skill.rb +132 -0
- data/lib/waylon/skill_registry.rb +74 -0
- data/lib/waylon/skills/default.rb +48 -0
- data/lib/waylon/skills/fun.rb +26 -0
- data/lib/waylon/user.rb +61 -0
- data/lib/waylon/version.rb +12 -0
- data/lib/waylon/webhook.rb +73 -0
- data/lib/waylon.rb +5 -0
- data/scripts/test.sh +5 -0
- data/waylon-core.gemspec +50 -0
- metadata +312 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 01c6d89ed4d79dba9305c9c83fd597fed10ace104592f7d8ae6ed2f630bb9351
|
4
|
+
data.tar.gz: 83ac891dc983e61f76b5cd366062381b748dcc49c86d6177b4e245c8c29573e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd0fabfda6646c84cb17af27dd55bd8c70ad1c803a257e1e4ed992ce4298563a579705dff33b898519b82ed2123e59ab2259021bbdec320914914a7ee19291f0
|
7
|
+
data.tar.gz: 5b2c06fc2c55256014f35e953465f21c11c6de9390e55c0a504f7fcb08c2fcff1898e583dac97b546b1d1a7c00650014562c2e678aff6832353a3c24f08527b8
|
data/.gitignore
ADDED
data/.roxanne.yml
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 3.0
|
3
|
+
NewCops: enable
|
4
|
+
|
5
|
+
Style/MixinUsage:
|
6
|
+
Exclude:
|
7
|
+
- "bin/console"
|
8
|
+
|
9
|
+
Style/StringLiterals:
|
10
|
+
Enabled: true
|
11
|
+
EnforcedStyle: double_quotes
|
12
|
+
|
13
|
+
Style/StringLiteralsInInterpolation:
|
14
|
+
Enabled: true
|
15
|
+
EnforcedStyle: double_quotes
|
16
|
+
|
17
|
+
Layout/LineLength:
|
18
|
+
Max: 120
|
19
|
+
|
20
|
+
Gemspec/RequireMFA:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Metrics/AbcSize:
|
24
|
+
Max: 19
|
25
|
+
|
26
|
+
Metrics/CyclomaticComplexity:
|
27
|
+
Max: 9
|
28
|
+
|
29
|
+
Metrics/PerceivedComplexity:
|
30
|
+
Max: 9
|
31
|
+
|
32
|
+
Metrics/MethodLength:
|
33
|
+
Max: 20
|
34
|
+
|
35
|
+
Metrics/BlockLength:
|
36
|
+
Exclude:
|
37
|
+
- "**/*_spec.rb"
|
38
|
+
- "*.gemspec"
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.0.3
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
waylon-core (0.1.0)
|
5
|
+
addressable (~> 2.8)
|
6
|
+
faraday (~> 1.8)
|
7
|
+
i18n (~> 1.8)
|
8
|
+
json (~> 2.6)
|
9
|
+
moneta (~> 1.4)
|
10
|
+
puma (~> 5.5)
|
11
|
+
resque (~> 2.2)
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
addressable (2.8.0)
|
17
|
+
public_suffix (>= 2.0.2, < 5.0)
|
18
|
+
ast (2.4.2)
|
19
|
+
concurrent-ruby (1.1.9)
|
20
|
+
diff-lcs (1.4.4)
|
21
|
+
docile (1.4.0)
|
22
|
+
faraday (1.8.0)
|
23
|
+
faraday-em_http (~> 1.0)
|
24
|
+
faraday-em_synchrony (~> 1.0)
|
25
|
+
faraday-excon (~> 1.1)
|
26
|
+
faraday-httpclient (~> 1.0.1)
|
27
|
+
faraday-net_http (~> 1.0)
|
28
|
+
faraday-net_http_persistent (~> 1.1)
|
29
|
+
faraday-patron (~> 1.0)
|
30
|
+
faraday-rack (~> 1.0)
|
31
|
+
multipart-post (>= 1.2, < 3)
|
32
|
+
ruby2_keywords (>= 0.0.4)
|
33
|
+
faraday-em_http (1.0.0)
|
34
|
+
faraday-em_synchrony (1.0.0)
|
35
|
+
faraday-excon (1.1.0)
|
36
|
+
faraday-httpclient (1.0.1)
|
37
|
+
faraday-net_http (1.0.1)
|
38
|
+
faraday-net_http_persistent (1.2.0)
|
39
|
+
faraday-patron (1.0.0)
|
40
|
+
faraday-rack (1.0.0)
|
41
|
+
i18n (1.8.11)
|
42
|
+
concurrent-ruby (~> 1.0)
|
43
|
+
json (2.6.1)
|
44
|
+
moneta (1.4.2)
|
45
|
+
mono_logger (1.1.1)
|
46
|
+
multi_json (1.15.0)
|
47
|
+
multipart-post (2.1.1)
|
48
|
+
mustermann (1.1.1)
|
49
|
+
ruby2_keywords (~> 0.0.1)
|
50
|
+
nio4r (2.5.8)
|
51
|
+
parallel (1.21.0)
|
52
|
+
parser (3.0.3.2)
|
53
|
+
ast (~> 2.4.1)
|
54
|
+
public_suffix (4.0.6)
|
55
|
+
puma (5.5.2)
|
56
|
+
nio4r (~> 2.0)
|
57
|
+
rack (2.2.3)
|
58
|
+
rack-protection (2.1.0)
|
59
|
+
rack
|
60
|
+
rainbow (3.0.0)
|
61
|
+
rake (13.0.6)
|
62
|
+
redis (4.5.1)
|
63
|
+
redis-namespace (1.8.1)
|
64
|
+
redis (>= 3.0.4)
|
65
|
+
regexp_parser (2.2.0)
|
66
|
+
resque (2.2.0)
|
67
|
+
mono_logger (~> 1.0)
|
68
|
+
multi_json (~> 1.0)
|
69
|
+
redis-namespace (~> 1.6)
|
70
|
+
sinatra (>= 0.9.2)
|
71
|
+
vegas (~> 0.1.2)
|
72
|
+
rexml (3.2.5)
|
73
|
+
rspec (3.10.0)
|
74
|
+
rspec-core (~> 3.10.0)
|
75
|
+
rspec-expectations (~> 3.10.0)
|
76
|
+
rspec-mocks (~> 3.10.0)
|
77
|
+
rspec-core (3.10.1)
|
78
|
+
rspec-support (~> 3.10.0)
|
79
|
+
rspec-expectations (3.10.1)
|
80
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
81
|
+
rspec-support (~> 3.10.0)
|
82
|
+
rspec-mocks (3.10.2)
|
83
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
84
|
+
rspec-support (~> 3.10.0)
|
85
|
+
rspec-support (3.10.3)
|
86
|
+
rubocop (1.23.0)
|
87
|
+
parallel (~> 1.10)
|
88
|
+
parser (>= 3.0.0.0)
|
89
|
+
rainbow (>= 2.2.2, < 4.0)
|
90
|
+
regexp_parser (>= 1.8, < 3.0)
|
91
|
+
rexml
|
92
|
+
rubocop-ast (>= 1.12.0, < 2.0)
|
93
|
+
ruby-progressbar (~> 1.7)
|
94
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
95
|
+
rubocop-ast (1.15.0)
|
96
|
+
parser (>= 3.0.1.1)
|
97
|
+
rubocop-rake (0.6.0)
|
98
|
+
rubocop (~> 1.0)
|
99
|
+
rubocop-rspec (2.6.0)
|
100
|
+
rubocop (~> 1.19)
|
101
|
+
ruby-progressbar (1.11.0)
|
102
|
+
ruby2_keywords (0.0.5)
|
103
|
+
simplecov (0.21.2)
|
104
|
+
docile (~> 1.1)
|
105
|
+
simplecov-html (~> 0.11)
|
106
|
+
simplecov_json_formatter (~> 0.1)
|
107
|
+
simplecov-html (0.12.3)
|
108
|
+
simplecov_json_formatter (0.1.3)
|
109
|
+
sinatra (2.1.0)
|
110
|
+
mustermann (~> 1.0)
|
111
|
+
rack (~> 2.2)
|
112
|
+
rack-protection (= 2.1.0)
|
113
|
+
tilt (~> 2.0)
|
114
|
+
tilt (2.0.10)
|
115
|
+
unicode-display_width (2.1.0)
|
116
|
+
vegas (0.1.11)
|
117
|
+
rack (>= 1.0.0)
|
118
|
+
webrick (1.7.0)
|
119
|
+
yard (0.9.27)
|
120
|
+
webrick (~> 1.7.0)
|
121
|
+
|
122
|
+
PLATFORMS
|
123
|
+
arm64-darwin-21
|
124
|
+
|
125
|
+
DEPENDENCIES
|
126
|
+
bundler (~> 2.2)
|
127
|
+
rake (~> 13.0)
|
128
|
+
rspec (~> 3.10)
|
129
|
+
rubocop (~> 1.23)
|
130
|
+
rubocop-rake (~> 0.6)
|
131
|
+
rubocop-rspec (~> 2.6)
|
132
|
+
simplecov (~> 0.21)
|
133
|
+
waylon-core!
|
134
|
+
yard (~> 0.9, >= 0.9.27)
|
135
|
+
|
136
|
+
BUNDLED WITH
|
137
|
+
2.2.32
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Jonathan Gnagy
|
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,57 @@
|
|
1
|
+
# Waylon::Core
|
2
|
+
|
3
|
+
Waylon is a bot framework in the same vein as [Lita](https://www.lita.io/) built to make creating bots easy and fun. It supports swappable sensory inputs (chat platforms, web endpoints, and more), easy to build Skills, built-in and extensible permissions, and modern JSON logging.
|
4
|
+
|
5
|
+
This repo/library is the core of Waylon; it provides the essential pieces of the framework and some working examples.
|
6
|
+
|
7
|
+
## Why Waylon
|
8
|
+
|
9
|
+
Waylon is built to be scalable and to deliver features missing in other chat frameworks. For instance, it supports self-reporting and discovering plugin features (such as supporting HTML cards, reactions, etc.) to making Skills more powerful and dynamic. Waylon also supports a full, shared caching layer to make scaling simple. It also makes heavy use of Redis for queuing work, meaning zero-downtime upgrades and faster user responses.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'waylon-core'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle install
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install waylon-core
|
26
|
+
|
27
|
+
If you're building a plugin for Waylon, you'll only need to require the core:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require "waylon/core"
|
31
|
+
```
|
32
|
+
|
33
|
+
If you're launching your own bot, require the entire library and plus any additional plugins:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require "waylon"
|
37
|
+
```
|
38
|
+
|
39
|
+
## Usage
|
40
|
+
|
41
|
+
### Demo Mode
|
42
|
+
|
43
|
+
Alone, this library isn't super useful for running a bot, but it does include a "demo", local REPL mode for experimenting. To use it, run `rake demo`.
|
44
|
+
|
45
|
+
## Development
|
46
|
+
|
47
|
+
Waylon's development pipeline makes heavy use of [RSpec](https://rspec.info/) for testing (and [SimpleCov](https://github.com/simplecov-ruby/simplecov) for reporting on coverage), [Rubocop](https://rubocop.org/) for linting/format checking, [YARD](https://yardoc.org/) for documentation, and [Travis CI](https://www.travis-ci.com/) for CI. Most of this is built-in and will work out-of-the-box for GitHub PRs.
|
48
|
+
|
49
|
+
To get started locally, after checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake` to run the tests and linting. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
50
|
+
|
51
|
+
## Contributing
|
52
|
+
|
53
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jgnagy/waylon-core.
|
54
|
+
|
55
|
+
## License
|
56
|
+
|
57
|
+
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,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
require "rubocop/rake_task"
|
6
|
+
require "redis/errors"
|
7
|
+
require "resque/tasks"
|
8
|
+
require "yard"
|
9
|
+
require "waylon/core"
|
10
|
+
|
11
|
+
RSpec::Core::RakeTask.new(:spec)
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
YARD::Rake::YardocTask.new do |y|
|
14
|
+
y.options = [
|
15
|
+
"--markup", "markdown"
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
task default: %i[spec rubocop yard]
|
20
|
+
|
21
|
+
task :demo do
|
22
|
+
require "waylon/rspec/test_server"
|
23
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "waylon"
|
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
|
+
include Waylon
|
16
|
+
|
17
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
# The base mixin for all core Waylon components
|
5
|
+
# @abstract
|
6
|
+
module BaseComponent
|
7
|
+
def self.included(base)
|
8
|
+
base.send :include, InstanceLoggingMethods
|
9
|
+
base.send :include, InstanceUtilityMethods
|
10
|
+
base.extend ClassLoggingMethods
|
11
|
+
base.extend ClassUtilityMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
# Base class logging methods
|
15
|
+
module ClassLoggingMethods
|
16
|
+
# Simple pass-through for logging through the Waylon Logger
|
17
|
+
# @param message [String] The message to log
|
18
|
+
# @param level [String,Symbol] The log level for this message
|
19
|
+
def log(message, level = :info)
|
20
|
+
::Waylon::Logger.log(message, level)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Base Component utility methods
|
25
|
+
module ClassUtilityMethods
|
26
|
+
# The namespace used for this component's storage
|
27
|
+
# @param value [String,nil] Sets this namespace unless set (without setting, returns a sane default)
|
28
|
+
# @return [String] The namespace for this component
|
29
|
+
def component_namespace(value = nil)
|
30
|
+
@namespace ||= value
|
31
|
+
# Either returns the namespace or the stripped down class name
|
32
|
+
@namespace || name.to_s.split("::").last.downcase
|
33
|
+
end
|
34
|
+
|
35
|
+
# Creates namespaced configuration keys for Webhook subclasses
|
36
|
+
# @param (see Config#add_schema)
|
37
|
+
def config(key, default: nil, required: false, type: String)
|
38
|
+
conf = Config.instance
|
39
|
+
config_key = config_key_for(key)
|
40
|
+
conf.add_schema(config_key, default: default, required: required, type: type)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Provides the full Config key given a relative key
|
44
|
+
# @param key [String] The relative key to fully-qualify
|
45
|
+
# @return [String] The fully-qualified Config key
|
46
|
+
def config_key_for(key)
|
47
|
+
"#{config_namespace}.#{key}"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Determines if the current component is fully configured
|
51
|
+
# @return [Boolean]
|
52
|
+
def configured?
|
53
|
+
conf = Config.instance
|
54
|
+
req_confs = conf.schema.select do |k, v|
|
55
|
+
k.match?(/^#{config_namespace}\./) && v[:required]
|
56
|
+
end
|
57
|
+
missing_configs = req_confs.reject { |k, _v| conf.set?(k) }
|
58
|
+
if missing_configs.empty? && conf.valid?
|
59
|
+
true
|
60
|
+
elsif missing_configs.empty?
|
61
|
+
log("Configuration for #{component_namespace} failed validation!", :error)
|
62
|
+
false
|
63
|
+
else
|
64
|
+
missing_configs.each { |k, _v| log("Missing required configuration: #{k}", :error) }
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Describes features supported by a Sense
|
70
|
+
# @param list [String,Array<String,Symbol>] List of features supported by this BaseComponent
|
71
|
+
def features(list)
|
72
|
+
@features = [*list].map(&:to_sym)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Determine if a BaseComponent subclass supports a feature
|
76
|
+
# @param key [String,Symbol] The feature in question
|
77
|
+
def supports?(key)
|
78
|
+
@features ||= []
|
79
|
+
@features.include?(key.to_sym)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Base instance logging methods
|
84
|
+
module InstanceLoggingMethods
|
85
|
+
# Instance-level access to logging via the Class log method
|
86
|
+
# @param (see ClassLoggingMethods#log)
|
87
|
+
def log(message, level = :info)
|
88
|
+
self.class.log(message, level)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Base instance utility methods
|
93
|
+
module InstanceUtilityMethods
|
94
|
+
# Allows caching operations (or retrieving cached versions)
|
95
|
+
# @param [String] key How to store/retrieved the cached value
|
96
|
+
# @param [Integer] expires How long to cache the value
|
97
|
+
def cache(key, expires: 600)
|
98
|
+
cache_key = self.class.config_key_for(key)
|
99
|
+
if !Waylon::Cache.key?(cache_key) && block_given?
|
100
|
+
result = yield
|
101
|
+
Waylon::Cache.store(cache_key, result, expires: expires)
|
102
|
+
elsif !Waylon::Cache.key?(cache_key)
|
103
|
+
return nil
|
104
|
+
end
|
105
|
+
Waylon::Cache.load(cache_key, expires: expires)
|
106
|
+
end
|
107
|
+
|
108
|
+
# A wrapper for access to a namespaced Config key
|
109
|
+
# @param [String] key The key name to lookup
|
110
|
+
def config(key)
|
111
|
+
conf = Config.instance
|
112
|
+
conf[self.class.config_key_for(key)]
|
113
|
+
end
|
114
|
+
|
115
|
+
# A wrapper for accessing the persistent storage
|
116
|
+
# @return [Waylon::Storage] The Storage wrapper class
|
117
|
+
def storage
|
118
|
+
Waylon::Storage
|
119
|
+
end
|
120
|
+
|
121
|
+
alias db storage
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
# Abstract route condition superclass
|
5
|
+
# @abstract
|
6
|
+
class Condition
|
7
|
+
attr_reader :action, :help, :mechanism
|
8
|
+
|
9
|
+
# @param mechanism The meat of the condition used to decide if this condition applies
|
10
|
+
# @param action [Symbol] The method to call if the condition matches
|
11
|
+
# @param allowed_groups [Array<Symbol>] The group names allowed to use this action
|
12
|
+
# @param help [String] Optional help text to describe usage for this action
|
13
|
+
def initialize(mechanism, action, allowed_groups, help = nil)
|
14
|
+
@mechanism = mechanism
|
15
|
+
@action = action
|
16
|
+
@allowed_groups = allowed_groups
|
17
|
+
@help = help
|
18
|
+
end
|
19
|
+
|
20
|
+
# Placeholder for determining if this condition applies to the given input
|
21
|
+
# @param _input [Waylon::Message] The input message
|
22
|
+
def matches?(_input)
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
# Checks if a user is allowed based on this condition
|
27
|
+
# @param user [Waylon::User] abstract user
|
28
|
+
def permits?(user)
|
29
|
+
return true if allows?(:everyone)
|
30
|
+
|
31
|
+
Logger.log("Checking permissions for #{user.email}", :debug)
|
32
|
+
group_class = user.class.sense.group_class
|
33
|
+
# Check for global admins
|
34
|
+
return true if Config.instance.admins.include?(user.email)
|
35
|
+
# Check for managed admins
|
36
|
+
return true if group_class.new("admins").include?(user)
|
37
|
+
|
38
|
+
permitted = false
|
39
|
+
|
40
|
+
[*@allowed_groups].each do |group|
|
41
|
+
permitted = true if group_class.new(group).include?(user)
|
42
|
+
break if permitted
|
43
|
+
end
|
44
|
+
permitted
|
45
|
+
end
|
46
|
+
|
47
|
+
# Tokens is used to provide details about the message input to the action
|
48
|
+
# @param _input [String] The message content as text
|
49
|
+
# @return [Array<String>] The tokens extracted from the input message
|
50
|
+
def tokens(_input)
|
51
|
+
[]
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# Determines if a group name is among the list of allowed groups for this condition
|
57
|
+
# @note Does not involve determining user group membership, just allows access to the list of allowed groups
|
58
|
+
# @param group [Symbol] A group name to lookup
|
59
|
+
def allows?(group)
|
60
|
+
@allowed_groups ||= []
|
61
|
+
[*@allowed_groups].include?(group.to_sym)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
module Conditions
|
5
|
+
# A pre-made catch-all condition for denying access
|
6
|
+
class Default < Condition
|
7
|
+
# Overrides normal Condition initialization to force a specific action
|
8
|
+
def initialize(*_args) # rubocop:disable Lint/MissingSuper
|
9
|
+
@mechanism = nil
|
10
|
+
@action = :unknown
|
11
|
+
@allowed_groups = [:everyone]
|
12
|
+
@help = ""
|
13
|
+
end
|
14
|
+
|
15
|
+
# Matches any input (since the Default route, when used, should always function)
|
16
|
+
# @return [Boolean]
|
17
|
+
def matches?(_input)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Permits any user (since the Default route, when used, should always function)
|
22
|
+
# @return [Boolean]
|
23
|
+
def permits?(_user)
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
# Just provides back all input as a single token
|
28
|
+
# @return [Array<String>]
|
29
|
+
def tokens(input)
|
30
|
+
[input]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
module Conditions
|
5
|
+
# A pre-made catch-all condition for denying access
|
6
|
+
class PermissionDenied < Condition
|
7
|
+
# Overrides normal Condition initialization to force a specific action
|
8
|
+
def initialize(*_args) # rubocop:disable Lint/MissingSuper
|
9
|
+
@mechanism = nil
|
10
|
+
@action = :denied
|
11
|
+
@allowed_groups = [:everyone]
|
12
|
+
@help = "This action is not allowed"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Matches any input (since the PermissionDenied route, when used, should always function)
|
16
|
+
# @return [Boolean]
|
17
|
+
def matches?(_input)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Permits any user (since the PermissionDenied route, when used, should always function)
|
22
|
+
# @return [Boolean]
|
23
|
+
def permits?(_user)
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
# Just provides back all input as a single token
|
28
|
+
# @return [Array<String>]
|
29
|
+
def tokens(input)
|
30
|
+
[input]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
module Conditions
|
5
|
+
# Routing via Regular Expression
|
6
|
+
class Regex < Condition
|
7
|
+
# Checks if this condition matches the message
|
8
|
+
# @param message [String] The message text
|
9
|
+
# @return [Boolean]
|
10
|
+
def matches?(message)
|
11
|
+
@mechanism =~ message
|
12
|
+
end
|
13
|
+
|
14
|
+
# Provides the regular expression match groups as tokens
|
15
|
+
# @param input [String] The message text
|
16
|
+
# @return [Array<String>] The regular expression match groups
|
17
|
+
def tokens(input)
|
18
|
+
@mechanism.match(input).to_a[1..]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|