trocla-ruby2 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +4 -0
- data/.rspec +1 -0
- data/.travis.yml +10 -0
- data/CHANGELOG.md +71 -0
- data/Gemfile +51 -0
- data/LICENSE.txt +15 -0
- data/README.md +351 -0
- data/Rakefile +53 -0
- data/bin/trocla +148 -0
- data/ext/redhat/rubygem-trocla.spec +120 -0
- data/lib/VERSION +4 -0
- data/lib/trocla.rb +162 -0
- data/lib/trocla/default_config.yaml +47 -0
- data/lib/trocla/encryptions.rb +54 -0
- data/lib/trocla/encryptions/none.rb +10 -0
- data/lib/trocla/encryptions/ssl.rb +51 -0
- data/lib/trocla/formats.rb +54 -0
- data/lib/trocla/formats/bcrypt.rb +7 -0
- data/lib/trocla/formats/md5crypt.rb +6 -0
- data/lib/trocla/formats/mysql.rb +6 -0
- data/lib/trocla/formats/pgsql.rb +7 -0
- data/lib/trocla/formats/plain.rb +7 -0
- data/lib/trocla/formats/sha1.rb +7 -0
- data/lib/trocla/formats/sha256crypt.rb +6 -0
- data/lib/trocla/formats/sha512crypt.rb +6 -0
- data/lib/trocla/formats/ssha.rb +9 -0
- data/lib/trocla/formats/sshkey.rb +46 -0
- data/lib/trocla/formats/x509.rb +197 -0
- data/lib/trocla/store.rb +80 -0
- data/lib/trocla/stores.rb +39 -0
- data/lib/trocla/stores/memory.rb +56 -0
- data/lib/trocla/stores/moneta.rb +58 -0
- data/lib/trocla/util.rb +71 -0
- data/lib/trocla/version.rb +22 -0
- data/spec/data/.keep +0 -0
- data/spec/spec_helper.rb +290 -0
- data/spec/trocla/encryptions/none_spec.rb +22 -0
- data/spec/trocla/encryptions/ssl_spec.rb +26 -0
- data/spec/trocla/formats/x509_spec.rb +375 -0
- data/spec/trocla/store/memory_spec.rb +6 -0
- data/spec/trocla/store/moneta_spec.rb +6 -0
- data/spec/trocla/util_spec.rb +54 -0
- data/spec/trocla_spec.rb +248 -0
- data/trocla-ruby2.gemspec +104 -0
- metadata +202 -0
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
|
15
|
+
require 'jeweler'
|
16
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
17
|
+
require 'trocla'
|
18
|
+
Jeweler::Tasks.new do |gem|
|
19
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
20
|
+
gem.name = "trocla"
|
21
|
+
gem.homepage = "https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/"
|
22
|
+
gem.license = "GPLv3"
|
23
|
+
gem.summary = "Trocla a simple password generator and storage"
|
24
|
+
gem.description = "Trocla helps you to generate random passwords and to store them in various formats (plain, MD5, bcrypt) for later retrival."
|
25
|
+
gem.email = "mh+trocla@immerda.ch"
|
26
|
+
gem.authors = ["mh"]
|
27
|
+
gem.version = Trocla::VERSION::STRING
|
28
|
+
# dependencies defined in Gemfile
|
29
|
+
end
|
30
|
+
Jeweler::RubygemsDotOrgTasks.new
|
31
|
+
|
32
|
+
require 'rspec/core'
|
33
|
+
require 'rspec/core/rake_task'
|
34
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
35
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
36
|
+
end
|
37
|
+
|
38
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
39
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
40
|
+
spec.rcov = true
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :spec
|
44
|
+
|
45
|
+
gem 'rdoc'
|
46
|
+
require 'rdoc/task'
|
47
|
+
RDoc::Task.new do |rdoc|
|
48
|
+
version = Trocla::VERSION::STRING
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "trocla #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/bin/trocla
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# CLI client for Trocla.
|
3
|
+
#
|
4
|
+
require 'rubygems'
|
5
|
+
require 'trocla'
|
6
|
+
require 'optparse'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
options = { :config_file => nil, :ask_password => true, :trace => false }
|
10
|
+
|
11
|
+
OptionParser.new do |opts|
|
12
|
+
opts.on('--version', '-V', 'Version information') do
|
13
|
+
puts Trocla::VERSION::STRING
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on('--config CONFIG', '-c', 'Configuration file') do |v|
|
18
|
+
if File.exist?(v)
|
19
|
+
options[:config_file] = v
|
20
|
+
else
|
21
|
+
STDERR.puts "Cannot find config file: #{v}"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on('--trace', 'Show stack trace on failure') do
|
27
|
+
options[:trace] = true
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on('--no-random', 'Do not generate a random password if there is no plain text password available') do
|
31
|
+
options['random'] = false
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on('--no-format', 'Do not format a password when setting it using `set`') do
|
35
|
+
options['no_format'] = true
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on('--length LENGTH', 'Length for a randomly created password') do |v|
|
39
|
+
options['length'] = v.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on('--password [PASSWORD]', '-p', 'Provide password at command line or STDIN') do |pass|
|
43
|
+
options[:ask_password] = false
|
44
|
+
options[:password] = pass
|
45
|
+
end
|
46
|
+
|
47
|
+
end.parse!
|
48
|
+
|
49
|
+
def create(options)
|
50
|
+
[ Trocla.new(options.delete(:config_file)).password(
|
51
|
+
options.delete(:trocla_key),
|
52
|
+
options.delete(:trocla_format),
|
53
|
+
options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
|
54
|
+
) , 0 ]
|
55
|
+
end
|
56
|
+
|
57
|
+
def get(options)
|
58
|
+
res = Trocla.new(options.delete(:config_file)).get_password(
|
59
|
+
options.delete(:trocla_key),
|
60
|
+
options.delete(:trocla_format),
|
61
|
+
options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
|
62
|
+
)
|
63
|
+
[ res, res.nil? ? 1 : 0 ]
|
64
|
+
end
|
65
|
+
def set(options)
|
66
|
+
if options.delete(:ask_password)
|
67
|
+
require 'highline/import'
|
68
|
+
password = ask('Enter your password: ') { |q| q.echo = 'x' }.to_s
|
69
|
+
pwd2 = ask('Repeat password: ') { |q| q.echo = 'x' }.to_s
|
70
|
+
unless password == pwd2
|
71
|
+
STDERR.puts 'Passwords did not match, exiting!'
|
72
|
+
return [ nil, 1 ]
|
73
|
+
end
|
74
|
+
else
|
75
|
+
password = options.delete(:password) || STDIN.read.chomp
|
76
|
+
end
|
77
|
+
format = options.delete(:trocla_format)
|
78
|
+
no_format = options.delete('no_format')
|
79
|
+
trocla = Trocla.new(options.delete(:config_file))
|
80
|
+
value = if no_format
|
81
|
+
password
|
82
|
+
else
|
83
|
+
trocla.formats(format).format(password, (YAML.load(options.delete(:other_options).shift.to_s)||{}))
|
84
|
+
end
|
85
|
+
trocla.set_password(
|
86
|
+
options.delete(:trocla_key),
|
87
|
+
format,
|
88
|
+
value
|
89
|
+
)
|
90
|
+
[ '', 0 ]
|
91
|
+
end
|
92
|
+
|
93
|
+
def reset(options)
|
94
|
+
[ Trocla.new(options.delete(:config_file)).reset_password(
|
95
|
+
options.delete(:trocla_key),
|
96
|
+
options.delete(:trocla_format),
|
97
|
+
options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
|
98
|
+
), 0 ]
|
99
|
+
end
|
100
|
+
|
101
|
+
def delete(options)
|
102
|
+
[ Trocla.new(options.delete(:config_file)).delete_password(
|
103
|
+
options.delete(:trocla_key),
|
104
|
+
options.delete(:trocla_format)
|
105
|
+
), 0 ]
|
106
|
+
end
|
107
|
+
|
108
|
+
def formats(options)
|
109
|
+
"Available formats: #{Trocla::Formats.all.join(', ')}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def check_format(format_name)
|
113
|
+
if format_name.nil?
|
114
|
+
STDERR.puts 'Missing format, exiting...'
|
115
|
+
exit 1
|
116
|
+
elsif !Trocla::Formats.available?(format_name)
|
117
|
+
STDERR.puts "Error: The format #{format_name} is not available"
|
118
|
+
exit 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
actions=['create','get','set','reset','delete', 'formats' ]
|
123
|
+
|
124
|
+
if (action=ARGV.shift) && actions.include?(action)
|
125
|
+
options[:trocla_key] = ARGV.shift
|
126
|
+
options[:trocla_format] = ARGV.shift
|
127
|
+
options[:other_options] = ARGV
|
128
|
+
check_format(options[:trocla_format]) unless ['delete','formats'].include?(action)
|
129
|
+
begin
|
130
|
+
result, excode = send(action,options)
|
131
|
+
if result
|
132
|
+
puts result.is_a?(String) ? result : result.inspect
|
133
|
+
end
|
134
|
+
rescue Exception => e
|
135
|
+
unless e.message == 'exit'
|
136
|
+
STDERR.puts "Action failed with the following message: #{e.message}"
|
137
|
+
STDERR.puts '(See full trace by running task with --trace)'
|
138
|
+
end
|
139
|
+
raise e if options[:trace]
|
140
|
+
exit 1
|
141
|
+
end
|
142
|
+
exit excode.nil? ? 0 : excode
|
143
|
+
else
|
144
|
+
STDERR.puts "Please supply one of the following actions: #{actions.join(', ')}"
|
145
|
+
STDERR.puts "Use #{$0} --help to get a list of options for these actions"
|
146
|
+
exit 1
|
147
|
+
end
|
148
|
+
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# Generated from trocla-0.1.2.gem by gem2rpm -*- rpm-spec -*-
|
2
|
+
%global gem_name trocla
|
3
|
+
|
4
|
+
Name: rubygem-%{gem_name}
|
5
|
+
Version: 0.3.0
|
6
|
+
Release: 1%{?dist}
|
7
|
+
Summary: Trocla a simple password generator and storage
|
8
|
+
Group: Development/Languages
|
9
|
+
License: GPLv3
|
10
|
+
URL: https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/
|
11
|
+
Source0: https://rubygems.org/gems/%{gem_name}-%{version}.gem
|
12
|
+
Requires: rubygem-moneta
|
13
|
+
Requires: rubygem-bcrypt
|
14
|
+
Requires: rubygem-highline
|
15
|
+
BuildRequires: rubygem-moneta = 0.7.20
|
16
|
+
BuildRequires: rubygem-bcrypt
|
17
|
+
BuildRequires: rubygem-highline
|
18
|
+
%if 0%{?rhel} >= 7
|
19
|
+
BuildRequires: ruby(release)
|
20
|
+
%endif
|
21
|
+
BuildRequires: rubygems-devel
|
22
|
+
BuildRequires: ruby
|
23
|
+
# BuildRequires: rubygem(mocha)
|
24
|
+
# BuildRequires: rubygem(rspec) => 2.4
|
25
|
+
# BuildRequires: rubygem(rspec) < 3
|
26
|
+
# BuildRequires: rubygem(jeweler) => 1.6
|
27
|
+
# BuildRequires: rubygem(jeweler) < 2
|
28
|
+
BuildArch: noarch
|
29
|
+
|
30
|
+
%description
|
31
|
+
Trocla helps you to generate random passwords and to store them in various
|
32
|
+
formats (plain, MD5, bcrypt) for later retrival.
|
33
|
+
|
34
|
+
|
35
|
+
%package doc
|
36
|
+
Summary: Documentation for %{name}
|
37
|
+
Group: Documentation
|
38
|
+
Requires: %{name} = %{version}-%{release}
|
39
|
+
BuildArch: noarch
|
40
|
+
|
41
|
+
%description doc
|
42
|
+
Documentation for %{name}.
|
43
|
+
|
44
|
+
%prep
|
45
|
+
gem unpack %{SOURCE0}
|
46
|
+
|
47
|
+
%setup -q -D -T -n %{gem_name}-%{version}
|
48
|
+
|
49
|
+
gem spec %{SOURCE0} -l --ruby > %{gem_name}.gemspec
|
50
|
+
|
51
|
+
%build
|
52
|
+
# Create the gem as gem install only works on a gem file
|
53
|
+
gem build %{gem_name}.gemspec
|
54
|
+
|
55
|
+
# %%gem_install compiles any C extensions and installs the gem into ./%%gem_dir
|
56
|
+
# by default, so that we can move it into the buildroot in %%install
|
57
|
+
%gem_install
|
58
|
+
|
59
|
+
%install
|
60
|
+
mkdir -p %{buildroot}%{gem_dir}
|
61
|
+
cp -a .%{gem_dir}/* \
|
62
|
+
%{buildroot}%{gem_dir}/
|
63
|
+
|
64
|
+
|
65
|
+
mkdir -p %{buildroot}%{_bindir}
|
66
|
+
mkdir -p %{buildroot}%{_sysconfdir}
|
67
|
+
mkdir -p %{buildroot}/%{_sharedstatedir}/%{gem_name}
|
68
|
+
touch %{buildroot}/%{_sharedstatedir}/%{gem_name}/%{gem_name}_data.yaml
|
69
|
+
|
70
|
+
cp -pa .%{_bindir}/* \
|
71
|
+
%{buildroot}%{_bindir}/
|
72
|
+
|
73
|
+
chmod a+x %{buildroot}%{gem_instdir}/bin/%{gem_name}
|
74
|
+
|
75
|
+
cat <<EOF > %{buildroot}/%{_sysconfdir}/%{gem_name}rc.yaml
|
76
|
+
---
|
77
|
+
store: :moneta
|
78
|
+
store_options:
|
79
|
+
adapter: :YAML
|
80
|
+
adapter_options:
|
81
|
+
:file: '%{_sharedstatedir}/%{gem_name}/%{gem_name}_data.yaml'
|
82
|
+
EOF
|
83
|
+
|
84
|
+
# Run the test suite
|
85
|
+
%check
|
86
|
+
pushd .%{gem_instdir}
|
87
|
+
|
88
|
+
popd
|
89
|
+
|
90
|
+
%files
|
91
|
+
%dir %{gem_instdir}
|
92
|
+
%{_bindir}/trocla
|
93
|
+
%{gem_instdir}/.rspec
|
94
|
+
%exclude %{gem_instdir}/.travis.yml
|
95
|
+
%exclude %{gem_instdir}/.rspec
|
96
|
+
%exclude %{gem_instdir}/ext/redhat/%{name}.spec
|
97
|
+
%license %{gem_instdir}/LICENSE.txt
|
98
|
+
%{gem_instdir}/bin
|
99
|
+
%{gem_libdir}
|
100
|
+
%exclude %{gem_cache}
|
101
|
+
%{gem_spec}
|
102
|
+
%config(noreplace) %{_sysconfdir}/%{gem_name}rc.yaml
|
103
|
+
%dir %attr(-, -, -) %{_sharedstatedir}/%{gem_name}
|
104
|
+
%config(noreplace) %attr(660, root, root) %{_sharedstatedir}/%{gem_name}/%{gem_name}_data.yaml
|
105
|
+
|
106
|
+
%files doc
|
107
|
+
%doc %{gem_docdir}
|
108
|
+
%doc %{gem_instdir}/.document
|
109
|
+
%{gem_instdir}/Gemfile
|
110
|
+
%doc %{gem_instdir}/README.md
|
111
|
+
%doc %{gem_instdir}/CHANGELOG.md
|
112
|
+
%{gem_instdir}/Rakefile
|
113
|
+
%{gem_instdir}/spec
|
114
|
+
%{gem_instdir}/trocla.gemspec
|
115
|
+
|
116
|
+
%changelog
|
117
|
+
* Mon Dec 21 2015 mh - 0.2.0-1
|
118
|
+
- Release of v0.2.0
|
119
|
+
* Sun Jun 21 2015 mh - 0.1.2-1
|
120
|
+
- Initial package
|
data/lib/VERSION
ADDED
data/lib/trocla.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'trocla/version'
|
2
|
+
require 'trocla/util'
|
3
|
+
require 'trocla/formats'
|
4
|
+
require 'trocla/encryptions'
|
5
|
+
require 'trocla/stores'
|
6
|
+
|
7
|
+
class Trocla
|
8
|
+
def initialize(config_file=nil)
|
9
|
+
if config_file
|
10
|
+
@config_file = File.expand_path(config_file)
|
11
|
+
elsif File.exists?(def_config_file=File.expand_path('~/.troclarc.yaml')) || File.exists?(def_config_file=File.expand_path('/etc/troclarc.yaml'))
|
12
|
+
@config_file = def_config_file
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.open(config_file=nil)
|
17
|
+
trocla = Trocla.new(config_file)
|
18
|
+
|
19
|
+
if block_given?
|
20
|
+
yield trocla
|
21
|
+
trocla.close
|
22
|
+
else
|
23
|
+
trocla
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def password(key,format,options={})
|
28
|
+
# respect a default profile, but let the
|
29
|
+
# profiles win over the default options
|
30
|
+
options['profiles'] ||= config['options']['profiles']
|
31
|
+
if options['profiles']
|
32
|
+
options = merge_profiles(options['profiles']).merge(options)
|
33
|
+
end
|
34
|
+
options = config['options'].merge(options)
|
35
|
+
|
36
|
+
raise "Format #{format} is not supported! Supported formats: #{Trocla::Formats.all.join(', ')}" unless Trocla::Formats::available?(format)
|
37
|
+
|
38
|
+
unless (password=get_password(key,format,options)).nil?
|
39
|
+
return password
|
40
|
+
end
|
41
|
+
|
42
|
+
plain_pwd = get_password(key,'plain',options)
|
43
|
+
if options['random'] && plain_pwd.nil?
|
44
|
+
plain_pwd = Trocla::Util.random_str(options['length'].to_i,options['charset'])
|
45
|
+
set_password(key,'plain',plain_pwd,options) unless format == 'plain'
|
46
|
+
elsif !options['random'] && plain_pwd.nil?
|
47
|
+
raise "Password must be present as plaintext if you don't want a random password"
|
48
|
+
end
|
49
|
+
pwd = self.formats(format).format(plain_pwd,options)
|
50
|
+
# it's possible that meanwhile another thread/process was faster in
|
51
|
+
# formating the password. But we want todo that second lookup
|
52
|
+
# only for expensive formats
|
53
|
+
if self.formats(format).expensive?
|
54
|
+
get_password(key,format,options) || set_password(key, format, pwd, options)
|
55
|
+
else
|
56
|
+
set_password(key, format, pwd, options)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_password(key, format, options={})
|
61
|
+
render(format,decrypt(store.get(key,format)),options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def reset_password(key,format,options={})
|
65
|
+
set_password(key,format,nil,options)
|
66
|
+
password(key,format,options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete_password(key,format=nil,options={})
|
70
|
+
v = store.delete(key,format)
|
71
|
+
if v.is_a?(Hash)
|
72
|
+
Hash[*v.map do |f,encrypted_value|
|
73
|
+
[f,render(format,decrypt(encrypted_value),options)]
|
74
|
+
end.flatten]
|
75
|
+
else
|
76
|
+
render(format,decrypt(v),options)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_password(key,format,password,options={})
|
81
|
+
store.set(key,format,encrypt(password),options)
|
82
|
+
render(format,password,options)
|
83
|
+
end
|
84
|
+
|
85
|
+
def formats(format)
|
86
|
+
(@format_cache||={})[format] ||= Trocla::Formats[format].new(self)
|
87
|
+
end
|
88
|
+
|
89
|
+
def encryption
|
90
|
+
@encryption ||= Trocla::Encryptions[config['encryption']].new(config['encryption_options'],self)
|
91
|
+
end
|
92
|
+
|
93
|
+
def config
|
94
|
+
@config ||= read_config
|
95
|
+
end
|
96
|
+
|
97
|
+
def close
|
98
|
+
store.close
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
def store
|
103
|
+
@store ||= build_store
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_store
|
107
|
+
s = config['store']
|
108
|
+
clazz = if s.is_a?(Symbol)
|
109
|
+
Trocla::Stores[s]
|
110
|
+
else
|
111
|
+
require config['store_require'] if config['store_require']
|
112
|
+
eval(s)
|
113
|
+
end
|
114
|
+
clazz.new(config['store_options'],self)
|
115
|
+
end
|
116
|
+
|
117
|
+
def read_config
|
118
|
+
if @config_file.nil?
|
119
|
+
default_config
|
120
|
+
else
|
121
|
+
raise "Configfile #{@config_file} does not exist!" unless File.exists?(@config_file)
|
122
|
+
c = default_config.merge(YAML.load(File.read(@config_file)))
|
123
|
+
c['profiles'] = default_config['profiles'].merge(c['profiles'])
|
124
|
+
# migrate all options to new store options
|
125
|
+
# TODO: remove workaround in 0.3.0
|
126
|
+
c['store_options']['adapter'] = c['adapter'] if c['adapter']
|
127
|
+
c['store_options']['adapter_options'] = c['adapter_options'] if c['adapter_options']
|
128
|
+
c['encryption_options'] = c['ssl_options'] if c['ssl_options']
|
129
|
+
c
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def encrypt(value)
|
134
|
+
encryption.encrypt(value)
|
135
|
+
end
|
136
|
+
|
137
|
+
def decrypt(value)
|
138
|
+
return nil if value.nil?
|
139
|
+
encryption.decrypt(value)
|
140
|
+
end
|
141
|
+
|
142
|
+
def render(format,output,options={})
|
143
|
+
if format && output && f=self.formats(format)
|
144
|
+
f.render(output,options['render']||{})
|
145
|
+
else
|
146
|
+
output
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def default_config
|
151
|
+
require 'yaml'
|
152
|
+
YAML.load(File.read(File.expand_path(File.join(File.dirname(__FILE__),'trocla','default_config.yaml'))))
|
153
|
+
end
|
154
|
+
|
155
|
+
def merge_profiles(profiles)
|
156
|
+
Array(profiles).inject({}) do |res,profile|
|
157
|
+
raise "No such profile #{profile} defined" unless profile_hash = config['profiles'][profile]
|
158
|
+
profile_hash.merge(res)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|