Skip to content

Commit

Permalink
add support for hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
duritong committed Nov 26, 2024
1 parent 1045895 commit 24926fe
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 2 deletions.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,37 @@ encryption_options:
:public_key: '/var/lib/puppet/ssl/public_keys/trocla.pem'
```

## Hooks

You can specify hooks to be called whenever trocla sets or deletes a password. The idea is that this allows you to run custom code that can trigger further actions based on deleting or setting a password.

Enabling hooks is done through the following configuration:

```YAML
hooks:
set:
my_hook: /path/to/my_hook_file.rb
delete:
other_hook: /path/to/my_other_hook_file.rb
```

A hook must have the following implementation based on the above config:

```Ruby
class Trocla
module Hooks
def self.my_hook(trocla, key, format, options)
# [... your code ...]
end
end
end
```
You can specify only either one or both kinds of hooks.

Hooks must not raise any exceptions or interrupt the flow itself. They can also not change the value that was set or revert a deletion.

However, they have Trocla itself available (through `trocla`) and you must ensure to not create infinite loops.

## Update & Changes

See [Changelog](CHANGELOG.md)
Expand Down
9 changes: 9 additions & 0 deletions lib/trocla.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'trocla/formats'
require 'trocla/encryptions'
require 'trocla/stores'
require 'trocla/hooks'

# Trocla class
class Trocla
Expand Down Expand Up @@ -67,6 +68,7 @@ def reset_password(key, format, options = {})

def delete_password(key, format = nil, options = {})
v = store.delete(key, format)
hooks_runner.run('delete', key, format, options)
if v.is_a?(Hash)
Hash[*v.map do |f, encrypted_value|
[f, render(format, decrypt(encrypted_value), options)]
Expand All @@ -78,6 +80,7 @@ def delete_password(key, format = nil, options = {})

def set_password(key, format, password, options = {})
store.set(key, format, encrypt(password), options)
hooks_runner.run('set', key, format, options)
render(format, password, options)
end

Expand Down Expand Up @@ -122,6 +125,12 @@ def build_store
clazz.new(config['store_options'], self)
end

def hooks_runner
@hooks_runner ||= begin
Trocla::Hooks::Runner.new(self)
end
end

def read_config
if @config_file.nil?
default_config
Expand Down
32 changes: 32 additions & 0 deletions lib/trocla/hooks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class Trocla
module Hooks
class Runner
attr_reader :trocla
def initialize(trocla)
@trocla = trocla
end

def run(action, key, format, options)
hooks[action].each do |cmd|
Trocla::Hooks.send(cmd, trocla, key, format, options)
end
end

private

def hooks
@hooks ||= begin
res = {}
(trocla.config['hooks'] || {}).each do |action,action_hooks|
res[action] ||= []
action_hooks.each do |cmd,file|
require File.join(file)
res[action] << cmd
end
end
res
end
end
end
end
end
12 changes: 12 additions & 0 deletions spec/fixtures/delete_test_hook.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Trocla
module Hooks

def self.delete_test_hook(trocla, key, format, options)
self.delete_messages << "#{key}_#{format}"
end

def self.delete_messages
@delete_messages ||= []
end
end
end
12 changes: 12 additions & 0 deletions spec/fixtures/set_test_hook.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Trocla
module Hooks

def self.set_test_hook(trocla, key, format, options)
self.set_messages << "#{key}_#{format}"
end

def self.set_messages
@set_messages ||= []
end
end
end
17 changes: 15 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,13 @@ def default_config
end

def test_config
@config ||= default_config.merge({
@test_config ||= default_config.merge({
'store' => :memory,
})
end

def test_config_persistent
@config ||= default_config.merge({
@test_config_persistent ||= default_config.merge({
'store_options' => {
'adapter' => :YAML,
'adapter_options' => {
Expand All @@ -267,6 +267,19 @@ def ssl_test_config
})
end

def hooks_config
@hooks_config ||= test_config.merge({
'hooks' => {
'set' => {
'set_test_hook' => File.expand_path(File.join(base_dir,'spec/fixtures/set_test_hook.rb'))
},
'delete' => {
'delete_test_hook' => File.expand_path(File.join(base_dir,'spec/fixtures/delete_test_hook.rb'))
}
}
})
end

def base_dir
File.dirname(__FILE__)+'/../'
end
Expand Down
42 changes: 42 additions & 0 deletions spec/trocla/hooks_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe "Trocla::Hooks::Runner" do

before(:each) do
expect_any_instance_of(Trocla).to receive(:read_config).and_return(hooks_config)
@trocla = Trocla.new
end

after(:each) do
Trocla::Hooks.set_messages.clear
Trocla::Hooks.delete_messages.clear
end

describe 'running hooks' do
describe 'setting password' do
it "calls the set hook" do
@trocla.password('random1', 'plain')
expect(Trocla::Hooks.set_messages.length).to eql(1)
expect(Trocla::Hooks.delete_messages.length).to eql(0)
expect(Trocla::Hooks.set_messages.first).to eql("random1_plain")
end
end
describe 'deleting password' do
it "calls the delete hook" do
@trocla.delete_password('random1', 'plain')
expect(Trocla::Hooks.delete_messages.length).to eql(1)
expect(Trocla::Hooks.set_messages.length).to eql(0)
expect(Trocla::Hooks.delete_messages.first).to eql("random1_plain")
end
end
describe 'reset password' do
it "calls the delete and set hook" do
@trocla.reset_password('random1', 'plain')
expect(Trocla::Hooks.set_messages.length).to eql(1)
expect(Trocla::Hooks.set_messages.first).to eql("random1_plain")
expect(Trocla::Hooks.delete_messages.length).to eql(1)
expect(Trocla::Hooks.delete_messages.first).to eql("random1_plain")
end
end
end
end

0 comments on commit 24926fe

Please sign in to comment.