dragons_keep 0.5.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.
data/Gemfile ADDED
@@ -0,0 +1,29 @@
1
+ source "http://rubygems.org"
2
+
3
+ # ruby gems needed for Dragon's Keep
4
+ gem 'ezcrypto'
5
+ gem 'uuid'
6
+ # using datamapper instead of activerecord
7
+ # Active record Gems
8
+ #gem 'activerecord', "3.0.0.beta3"
9
+ #gem 'sqlite3-ruby'
10
+ #
11
+ # Data Mapper gems 0.10.2
12
+ gem 'dm-core', "0.10.2"
13
+ gem 'do_sqlite3', '0.10.2'
14
+
15
+ # Data Mapper gems 1.0.0
16
+ #gem 'data_mapper', "1.0.0"
17
+ #gem 'dm-sqlite-adapter', "1.0.0"
18
+
19
+ # Wxruby renames gem for 1.9.1 support
20
+ if (RUBY_PLATFORM =~ /linux$/) == nil
21
+ #Decide which gem to load based on version of ruby installed
22
+ if (RUBY_VERSION =~/^1.9/) != nil
23
+ gem 'wxruby-ruby19'
24
+ else
25
+ gem 'wxruby'
26
+ end
27
+ else
28
+ gem 'wxruby', "2.0.1"
29
+ end
data/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ == dragons_keep
2
+
3
+ Put appropriate LICENSE for your project here.
data/README ADDED
@@ -0,0 +1,3 @@
1
+ == dragons_keep
2
+
3
+ You should document your project here.
@@ -0,0 +1,59 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+
6
+ require 'rubygems'
7
+ require 'rake'
8
+ require 'rake/clean'
9
+ require 'rake/gempackagetask'
10
+ require 'rake/rdoctask'
11
+ require 'rake/testtask'
12
+ require 'bundler'
13
+
14
+
15
+ spec = Gem::Specification.new do |s|
16
+ s.name = 'dragons_keep'
17
+ s.version = '0.5.0'
18
+ s.has_rdoc = true
19
+ s.extra_rdoc_files = ['README', 'LICENSE']
20
+ s.summary = 'Secure Password Keeper Application'
21
+ s.description = s.summary
22
+ s.author = 'Allan Davis'
23
+ s.email = 'javaalley@gmail.com'
24
+ s.homepage = 'http://github.com/javaalley/dragons_keep'
25
+ s.executables = ['dragons_keep']
26
+ s.files = %w(LICENSE README Rakefile Gemfile) + Dir.glob("{bin,lib,spec,db}/**/*")
27
+ s.require_path = "lib"
28
+ s.bindir = "bin"
29
+ s.add_bundler_dependencies
30
+ end
31
+
32
+ Rake::GemPackageTask.new(spec) do |p|
33
+ p.gem_spec = spec
34
+ p.need_tar = true
35
+ p.need_zip = true
36
+ end
37
+
38
+ Rake::RDocTask.new do |rdoc|
39
+ files =['README', 'LICENSE', 'lib/**/*.rb']
40
+ rdoc.rdoc_files.add(files)
41
+ rdoc.main = "README" # page to start on
42
+ rdoc.title = "dragons_keep Docs"
43
+ rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
44
+ rdoc.options << '--line-numbers'
45
+ end
46
+
47
+ Rake::TestTask.new do |t|
48
+ t.test_files = FileList['test/**/*.rb']
49
+ end
50
+
51
+ #desc "Migrate the database through migrations scripts"
52
+ #task :migrate => :enviroment do
53
+ # ActiveRecord::Migrator.migrate('db/migrations', ENV["VERSION"]? ENV["VERSION"].to_i : nil)
54
+ #end
55
+ #
56
+ #task :enviroment do
57
+ # ActiveRecord::Base.establish_connection(YAML::load(File.open('config/database.yml')))
58
+ # ActiveRecord::Base.logger = Logger.new(File.open('database.log', 'a'))
59
+ #end
@@ -0,0 +1,17 @@
1
+ #! /usr/bin/env ruby
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+ require 'rubygems'
5
+ begin
6
+ require 'bundler'
7
+ Bundler.setup
8
+ rescue
9
+ end
10
+
11
+ # Set the path to load from the lib and main directory
12
+ path = File.expand_path(File.dirname(__FILE__))
13
+ $: << path
14
+ $: << File.join(path, "..", "lib")
15
+
16
+ load "dragons_keep.rb"
17
+
@@ -0,0 +1 @@
1
+ @"ruby.exe" "%~dpn0" %*
@@ -0,0 +1,19 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ class CreateAccounts < ActiveRecord::Migration
5
+ def self.up
6
+ create_table :accounts do |t|
7
+ t.string :name
8
+ t.string :password
9
+ t.string :salt
10
+ t.string :url
11
+ t.string :user_name
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+ def self.down
17
+ drop_table :accounts
18
+ end
19
+ end
@@ -0,0 +1,33 @@
1
+ #! /usr/etc ruby
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+ require 'rubygems'
5
+ #require 'bundler'
6
+ #Bundler.setup
7
+
8
+ # Set the path to load from the lib and main directory
9
+ path = File.expand_path(File.dirname(__FILE__))
10
+ $LOAD_PATH.insert 0, path
11
+ #puts "LOAD_PATH"
12
+ #puts $LOAD_PATH
13
+ #$: << File.join(path, "..", "lib")
14
+
15
+ require 'wx'
16
+ require 'dragons_keep/keeps_main'
17
+ require 'ezcrypto'
18
+ require 'uuid'
19
+
20
+ module DragonsKeep
21
+
22
+ class DragonsKeepApp < Wx::App
23
+ def on_init()
24
+ self.app_name = "Dragon's Keep"
25
+ @frame = KeepsMain.new "Dragon's Keep"
26
+ @frame.center_on_screen(Wx::BOTH)
27
+ @frame.show
28
+ end
29
+ end
30
+ end
31
+
32
+ dk = DragonsKeep::DragonsKeepApp.new
33
+ dk.main_loop
@@ -0,0 +1,99 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+ require 'dm-core'
4
+ require 'ezcrypto'
5
+ module DragonsKeep
6
+ # Account class to store accounts and passwords into a keeper system
7
+ class Account
8
+ include DataMapper::Resource
9
+ #Data Mapper properties
10
+ property :id, Serial
11
+ property :name, String, :length => 100
12
+ property :password, String, :length => 100
13
+ property :salt, String, :length => 100
14
+ property :user_name, String, :length => 100
15
+ property :url, String, :length => 100
16
+
17
+ #register callbacks
18
+ before :save, :before_create
19
+
20
+
21
+ # Transient storage of unencrypted password and confirmation field
22
+ attr_accessor :unencrypted_password
23
+ attr_reader :password_confirmation
24
+
25
+ # create writer for password confirmation
26
+ def password_confirmation=(value)
27
+ @password_confirmation = value
28
+ @unencrypted = true
29
+ end
30
+
31
+ # loading data validate password filed and check status
32
+ def after_initialize
33
+ @unencrypted = self.password.nil?
34
+ end
35
+
36
+ # Before create data set salt and encrypt password
37
+ def before_create
38
+ raise PasswordException, "Password is not Encrypted" if self.new_password? && self.unencrypted?
39
+ end
40
+
41
+ # are we re defining the account password
42
+ def new_password?()
43
+ return !(self.unencrypted_password.blank? and self.password_confirmation.blank?)
44
+ end
45
+
46
+ # Encrypt the password
47
+ # encrypt_pass = Given password when user created the account information
48
+ def encrypt_password(encrypt_pass)
49
+ if self.unencrypted? && self.unencrypted_password == self.password_confirmation
50
+ self.create_salt
51
+ self.password = Base64.encode64(EzCrypto::Key.encrypt_with_password(encrypt_pass, self.salt, self.unencrypted_password))
52
+ @unencrypted = false
53
+ end
54
+ end
55
+
56
+ # Decrypt the password
57
+ # encrypt_pass = Given password when user created the account information
58
+ def decrpyt_password(encrypt_pass)
59
+ if !(self.unencrypted?)
60
+ self.unencrypted_password = EzCrypto::Key.decrypt_with_password(encrypt_pass, self.salt, Base64.decode64( self.password))
61
+ @unencrypted = true
62
+ self.password_confirmation=""
63
+ end
64
+ end
65
+
66
+ # Is the password encrypted?
67
+ def unencrypted?
68
+ return (@unencrypted.nil?)? self.password.nil?: @unencrypted
69
+ end
70
+
71
+ # Generate a random password
72
+ # length_of_password = Length of the password to generate
73
+ # special_char = Can this password need to contain Special Characters
74
+ def generate_password( length_of_pass, special_char )
75
+ chars = []
76
+ ("a".."z").each {|ele| chars << ele}
77
+ ("A".."Z").each {|ele| chars << ele}
78
+ ("0".."9").each {|ele| chars << ele}
79
+ if(special_char)
80
+ ["@", "!", "_",].each {|ele| chars << ele}
81
+ end
82
+ newpass = ""
83
+ 1.upto(length_of_pass) { |i| newpass << chars[rand(chars.size-1)] }
84
+ #self.password
85
+ self.unencrypted_password = newpass
86
+ self.password_confirmation = newpass
87
+ @unencrypted = true
88
+ end
89
+
90
+ # Create the salt
91
+ def create_salt
92
+ self.salt = UUID.generate(:compact)
93
+ end
94
+ end
95
+
96
+ # Error on Passwords Encryption or validation
97
+ class PasswordException < RuntimeError
98
+ end
99
+ end
@@ -0,0 +1,85 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+ require 'dragons_keep/account'
4
+ require 'dm-core'
5
+ require 'ezcrypto'
6
+ require 'uuid'
7
+ require 'digest/sha1'
8
+
9
+ module DragonsKeep
10
+ class AccountController
11
+ attr_reader :encrypt_pass
12
+ attr_accessor :database
13
+
14
+ def encrypt_pass=(pass)
15
+ @encrypt_pass = Digest::SHA1.hexdigest(pass)
16
+ end
17
+
18
+ def establish_connection
19
+ migrate = false
20
+ if !(File.exist?(self.database))
21
+ migrate = true
22
+ end
23
+
24
+ #DataMapper::Logger.new $stdout, :debug
25
+
26
+ DataMapper.setup :default, "sqlite3://#{self.database}"
27
+ if migrate
28
+ DataMapper.auto_migrate!
29
+ else
30
+ validate_connection
31
+ end
32
+ @connection = true
33
+ end
34
+ # Check the first record in the database and decrypt the password to see if the password is valid
35
+ def validate_connection
36
+ account = Account.first
37
+ if ! account.nil?
38
+ self.decrypt!(account)
39
+ end
40
+ end
41
+
42
+ def initialize(database=nil, password=nil)
43
+ @connection = false
44
+ if(!(database.nil?))
45
+ self.database = File.expand_path database
46
+ end
47
+ if (!(password.nil?))
48
+ self.encrypt_pass = password
49
+ end
50
+ end
51
+
52
+ def list()
53
+ if @connection
54
+ return Account.all
55
+ end
56
+
57
+ end
58
+ def save!(account)
59
+ if @connection
60
+ if account.unencrypted?
61
+ account.encrypt_password(self.encrypt_pass)
62
+ end
63
+ return account.save()
64
+ end
65
+ end
66
+
67
+ def get(id)
68
+ if @connection
69
+ return Account.get id
70
+ end
71
+ end
72
+
73
+ def decrypt!(account)
74
+ begin
75
+ account.decrpyt_password self.encrypt_pass
76
+ rescue OpenSSL::Cipher::CipherError
77
+ raise PasswordException, "Password is invalid"
78
+ end
79
+ end
80
+
81
+ def delete(account)
82
+ account.destroy
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,103 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+ require 'wx'
4
+ require 'dragons_keep/generate_password_dialog'
5
+
6
+ module DragonsKeep
7
+ class AccountDialog < Wx::Dialog
8
+ ID_USER_NAME = 103
9
+ ID_ACCOUNT_NAME = 101
10
+ ID_URL = 102
11
+ ID_PASSWORD = 104
12
+ ID_GENERATE_PASSWORD = 105
13
+ ID_SAVE = 106
14
+ ID_COPY_CLIP = 107
15
+ ID_CANCEL = 108
16
+
17
+ def initialize parent, id, title
18
+ super parent, id, title
19
+ self.set_size(Wx::Size.new(400, 300))
20
+ main_sizer = Wx::BoxSizer.new(Wx::VERTICAL)
21
+ grid_sizer = Wx::FlexGridSizer.new(4,2,5,5)
22
+
23
+ # Create name entry
24
+ label = Wx::StaticText.new(self, :label=>"Name:")
25
+ grid_sizer.add label, 0, Wx::ALL |Wx::ALIGN_RIGHT
26
+ @name = Wx::TextCtrl.new self, ID_ACCOUNT_NAME
27
+ grid_sizer.add @name, 1, Wx::EXPAND
28
+
29
+ # Create url entry
30
+ label = Wx::StaticText.new(self, :label=>"URL:")
31
+ grid_sizer.add label, 0,Wx::ALL |Wx::ALIGN_RIGHT
32
+ @url = Wx::TextCtrl.new self, ID_URL
33
+ grid_sizer.add @url, 1, Wx::EXPAND
34
+
35
+ # Create User_name entry
36
+ label = Wx::StaticText.new(self, :label=>"User Name:")
37
+ grid_sizer.add label, 0, Wx::ALL |Wx::ALIGN_RIGHT
38
+ @user = Wx::TextCtrl.new self, ID_USER_NAME
39
+ grid_sizer.add @user, 1, Wx::EXPAND
40
+
41
+ # Create password entry
42
+ label = Wx::StaticText.new(self, :label=>"Password:")
43
+ grid_sizer.add label, 0, Wx::ALL |Wx::ALIGN_RIGHT
44
+ @pass = Wx::TextCtrl.new self, ID_PASSWORD, :style=> Wx::TE_PASSWORD
45
+ grid_sizer.add @pass, 1, Wx::EXPAND
46
+ main_sizer.add grid_sizer, 0, Wx::GROW|Wx::ALIGN_CENTER_VERTICAL|Wx::ALL, 5
47
+ grid_sizer.add_growable_col(1)
48
+ # add spacer to grid
49
+ grid_sizer.add(25, 25)
50
+ # Add generate password button
51
+ @gen_button = Wx::Button.new self, ID_GENERATE_PASSWORD, "Generate Password..."
52
+ grid_sizer.add @gen_button, 1, Wx::EXPAND
53
+ evt_button(ID_GENERATE_PASSWORD){|evt| self.gen_pass_click(evt)}
54
+ main_sizer.add self.create_separated_button_sizer(Wx::OK|Wx::CANCEL), 1, Wx::ALIGN_RIGHT
55
+ self.set_sizer main_sizer
56
+
57
+ end
58
+
59
+ def gen_pass_click(event)
60
+ # display generate pass dialog
61
+ gen_dialog = GeneratePasswordDialog.new self, -1, "Generate Password"
62
+ if gen_dialog.show_modal() == Wx::ID_OK
63
+ @account.generate_password gen_dialog.password_length, gen_dialog.use_special_chars?
64
+ @pass.value = @account.unencrypted_password
65
+ end
66
+ end
67
+
68
+ def account
69
+ save_account
70
+ @account
71
+ end
72
+
73
+ def account=(account)
74
+ @account = account
75
+ load_account
76
+ end
77
+
78
+ private
79
+ def save_account
80
+ if not @account.blank?
81
+ if @account.unencrypted_password != @pass.value && @account.password_confirmation.blank?
82
+ password_dialog = Wx::PasswordEntryDialog.new(self, "Please confirm the password")
83
+ if password_dialog.show_modal == Wx::ID_OK
84
+ @account.password_confirmation = password_dialog.get_value
85
+ @account.unencrypted_password = @pass.value
86
+ end
87
+ end
88
+ @account.name = @name.value
89
+ @account.user_name = @user.value
90
+ @account.url = @url.value
91
+ end
92
+ end
93
+ def load_account
94
+ if not @account.name.blank?
95
+ @name.value = @account.name
96
+ @url.value = @account.url
97
+ @user.value = @account.user_name
98
+ @pass.value = @account.unencrypted_password.blank? ? @account.password : @account.unencrypted_password
99
+ end
100
+ end
101
+
102
+ end
103
+ end