doorkeeper
doorkeeper copied to clipboard
[WIP][PoC] Doorkeeper Plugins
PoC for Doorkeeper plugins system.
Allows to extend Doorkeeper without the need to patch internals or create PRs to main repository.
Something similar (but not inspired by) to official AWS Ruby SDK.
TODO
- [x] Implement plugins registry
- [x] Implement plugins invocation with context
- [ ] Collect namespaces & places where plugins can be used
- [ ] Extract some existing hooks (after/before auth) into plugins ?
- [ ] Add specs
- [ ] Add documentation for plugins
Example of usage:
class Plugin
def initialize(options = {})
@options = options
end
def run(**context)
puts "#{self.class.name} invoked"
end
end
TestPlugin1 = Class.new(Plugin)
TestPlugin2 = Class.new(Plugin)
TestPlugin3 = Class.new(Plugin)
TestPlugin4 = Class.new(Plugin)
PluginWithException = Class.new(Plugin) do
def run(**context)
raise StandardError, "test exception"
end
end
InvalidPlugin = Class.new
Doorkeeper::Plugin.register(TestPlugin1, namespace: "access_token")
Doorkeeper::Plugin.register(TestPlugin2, namespace: "access_token", options: { key: "123" })
Doorkeeper::Plugin.register(TestPlugin3, namespace: "access_token", after: TestPlugin2)
Doorkeeper::Plugin.register(TestPlugin4, namespace: "access_token", before: TestPlugin1)
Doorkeeper::Plugin.register(PluginWithException, namespace: "access_token", shallow_exceptions: false)
Doorkeeper::Plugin.run_for("access_token")
# => TestPlugin4
# TestPlugin1
# TestPlugin2
# TestPlugin3
Doorkeeper::Plugin.register(InvalidPlugin, namespace: "access_token")
# => ArgumentError ('InvalidPlugin' must respond to #run method!)
Doorkeeper::Plugin.register(TestPlugin2, namespace: "access_token")
# => ArgumentError ('TestPlugin3' already registered for access_a)
Doorkeeper::Plugin.register(TestPlugin3, namespace: "0123_access_token")
Doorkeeper::Plugin.register(TestPlugin3, namespace: "")
Doorkeeper::Plugin.register(TestPlugin3, namespace: "access-token")
Doorkeeper::Plugin.register(TestPlugin3, namespace: "access_token.")
Doorkeeper::Plugin.register(TestPlugin3, namespace: "access_token11")
# => ArgumentError (namespace must contain only letters, digits and underscore)
Real-life example
class FakeAccessToken
def destroy
puts "Token destroyed"
end
end
class AccessTokenPlugin
def initialize(options = {})
@options = options
end
def run(**context)
puts "#{self.class.name} invoked"
access_token = context.fetch(:token)
access_token.destroy
end
end
Doorkeeper::Plugin.register(AccessTokenPlugin, namespace: "access_token")
# app/controllers/tokens_controller.rb
token = FakeAccessToken.new
Doorkeeper::Plugin.run_for("access_token", token: token)
#=> AccessTokenPlugin invoked
#=> Token destroyed
1 Warning | |
---|---|
:warning: | Please squash all your commits to a single one |
Generated by :no_entry_sign: Danger
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.