safedb 0.01.0001

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.yardopts +3 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE +21 -0
  6. data/README.md +793 -0
  7. data/Rakefile +16 -0
  8. data/bin/safe +5 -0
  9. data/lib/configs/README.md +58 -0
  10. data/lib/extension/array.rb +162 -0
  11. data/lib/extension/dir.rb +35 -0
  12. data/lib/extension/file.rb +123 -0
  13. data/lib/extension/hash.rb +33 -0
  14. data/lib/extension/string.rb +572 -0
  15. data/lib/factbase/facts.safedb.net.ini +38 -0
  16. data/lib/interprete.rb +462 -0
  17. data/lib/keytools/PRODUCE_RAND_SEQ_USING_DEV_URANDOM.txt +0 -0
  18. data/lib/keytools/kdf.api.rb +243 -0
  19. data/lib/keytools/kdf.bcrypt.rb +265 -0
  20. data/lib/keytools/kdf.pbkdf2.rb +262 -0
  21. data/lib/keytools/kdf.scrypt.rb +190 -0
  22. data/lib/keytools/key.64.rb +326 -0
  23. data/lib/keytools/key.algo.rb +109 -0
  24. data/lib/keytools/key.api.rb +1391 -0
  25. data/lib/keytools/key.db.rb +330 -0
  26. data/lib/keytools/key.docs.rb +195 -0
  27. data/lib/keytools/key.error.rb +110 -0
  28. data/lib/keytools/key.id.rb +271 -0
  29. data/lib/keytools/key.ident.rb +243 -0
  30. data/lib/keytools/key.iv.rb +107 -0
  31. data/lib/keytools/key.local.rb +259 -0
  32. data/lib/keytools/key.now.rb +402 -0
  33. data/lib/keytools/key.pair.rb +259 -0
  34. data/lib/keytools/key.pass.rb +120 -0
  35. data/lib/keytools/key.rb +585 -0
  36. data/lib/logging/gem.logging.rb +132 -0
  37. data/lib/modules/README.md +43 -0
  38. data/lib/modules/cryptology/aes-256.rb +154 -0
  39. data/lib/modules/cryptology/amalgam.rb +70 -0
  40. data/lib/modules/cryptology/blowfish.rb +130 -0
  41. data/lib/modules/cryptology/cipher.rb +207 -0
  42. data/lib/modules/cryptology/collect.rb +138 -0
  43. data/lib/modules/cryptology/crypt.io.rb +225 -0
  44. data/lib/modules/cryptology/engineer.rb +99 -0
  45. data/lib/modules/mappers/dictionary.rb +288 -0
  46. data/lib/modules/storage/coldstore.rb +186 -0
  47. data/lib/modules/storage/git.store.rb +399 -0
  48. data/lib/session/fact.finder.rb +334 -0
  49. data/lib/session/require.gem.rb +112 -0
  50. data/lib/session/time.stamp.rb +340 -0
  51. data/lib/session/user.home.rb +49 -0
  52. data/lib/usecase/cmd.rb +487 -0
  53. data/lib/usecase/config/README.md +57 -0
  54. data/lib/usecase/docker/README.md +146 -0
  55. data/lib/usecase/docker/docker.rb +49 -0
  56. data/lib/usecase/edit/README.md +43 -0
  57. data/lib/usecase/edit/delete.rb +46 -0
  58. data/lib/usecase/export.rb +40 -0
  59. data/lib/usecase/files/README.md +37 -0
  60. data/lib/usecase/files/eject.rb +56 -0
  61. data/lib/usecase/files/file_me.rb +78 -0
  62. data/lib/usecase/files/read.rb +169 -0
  63. data/lib/usecase/files/write.rb +89 -0
  64. data/lib/usecase/goto.rb +57 -0
  65. data/lib/usecase/id.rb +36 -0
  66. data/lib/usecase/import.rb +157 -0
  67. data/lib/usecase/init.rb +63 -0
  68. data/lib/usecase/jenkins/README.md +146 -0
  69. data/lib/usecase/jenkins/jenkins.rb +208 -0
  70. data/lib/usecase/login.rb +71 -0
  71. data/lib/usecase/logout.rb +28 -0
  72. data/lib/usecase/open.rb +71 -0
  73. data/lib/usecase/print.rb +40 -0
  74. data/lib/usecase/put.rb +81 -0
  75. data/lib/usecase/set.rb +44 -0
  76. data/lib/usecase/show.rb +138 -0
  77. data/lib/usecase/terraform/README.md +91 -0
  78. data/lib/usecase/terraform/terraform.rb +121 -0
  79. data/lib/usecase/token.rb +35 -0
  80. data/lib/usecase/update/README.md +55 -0
  81. data/lib/usecase/update/rename.rb +180 -0
  82. data/lib/usecase/use.rb +41 -0
  83. data/lib/usecase/verse.rb +20 -0
  84. data/lib/usecase/view.rb +71 -0
  85. data/lib/usecase/vpn/README.md +150 -0
  86. data/lib/usecase/vpn/vpn.ini +31 -0
  87. data/lib/usecase/vpn/vpn.rb +54 -0
  88. data/lib/version.rb +3 -0
  89. data/safedb.gemspec +34 -0
  90. metadata +193 -0
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # This docker use case handles the ...
6
+ #
7
+ # safe docker login
8
+ # safe docker logout
9
+
10
+ class Docker < UseCase
11
+
12
+ # The command which currently must be login, logout or
13
+ # an empty string.
14
+ attr_writer :command
15
+
16
+ def execute
17
+
18
+ return unless ops_key_exists?
19
+ master_db = get_master_database()
20
+ return if unopened_envelope?( master_db )
21
+
22
+ # Get the open chapter identifier (id).
23
+ # Decide whether chapter already exists.
24
+ # Then get (or instantiate) the chapter's hash data structure
25
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
26
+ verse_id = master_db[ KEY_PATH ]
27
+ chapter_exists = KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
28
+
29
+ # Unlock the chapter data structure by supplying
30
+ # key/value mini-dictionary breadcrumbs sitting
31
+ # within the master database at the section labelled
32
+ # envelope@<<actual_chapter_id>>.
33
+ chapter_data = KeyDb.from_json( KeyApi.content_unlock( master_db[ chapter_id ] ) )
34
+
35
+ key_value_dictionary = chapter_data[ verse_id ]
36
+ docker_username = key_value_dictionary[ "docker.username" ]
37
+ docker_password = key_value_dictionary[ "@docker.password" ]
38
+ docker_login_cmd = "docker login --username #{docker_username} --password #{docker_password} 2>/dev/null"
39
+ docker_logout_cmd = "docker logout"
40
+ docker_cmd = @command.eql?( "logout" ) ? docker_logout_cmd : docker_login_cmd
41
+ system docker_cmd
42
+
43
+ end
44
+
45
+
46
+ end
47
+
48
+
49
+ end
@@ -0,0 +1,43 @@
1
+
2
+ ### safe put | safe delete | safe copy | safe paste
3
+
4
+ # edit use cases | copy | paste | delete
5
+
6
+ The edit use cases create, delete and update the credentials and configuration inside your safe.
7
+
8
+ ## Common Usage
9
+
10
+ Typically you login to a book, open a chapter and verse, then you put **`key/value`** pairs, known as **lines**.
11
+
12
+ ```
13
+ safe login joe@home
14
+
15
+ # -- -------------------------------------------------- -- #
16
+ # -- Create chapter (email) and verse <<email-address>> -- #
17
+ # -- -------------------------------------------------- -- #
18
+ safe open email joebloggs@gmail.com
19
+
20
+ # -- ---------------------------- -- #
21
+ # -- Populate it with credentials -- #
22
+ # -- ---------------------------- -- #
23
+ safe put gmail.id joebloggs
24
+ safe put @password s3cr3et
25
+ safe put recovery.phone 07500875278
26
+
27
+ # -- ----------------------------------------------- -- #
28
+ # -- Now copy and then paste a line (key/value pair) -- #
29
+ # -- ----------------------------------------------- -- #
30
+ safe copy recovery.phone
31
+ safe open email joe@ywork.com
32
+ safe paste
33
+ ```
34
+
35
+ ## editing behaviour
36
+
37
+ **These use cases are intuitive and behave almost like what you would expect.** The safe ethos is for commands to behave according to which of the 5 levels you are at.
38
+
39
+
40
+ | Command | Verse | Chapter | Book |
41
+ |:---------------- |:----------------------------- |:-------------------------------- |:------------------------------- |
42
+ | safe copy <<id>> | Copy one of the verse's lines | Copy one of the chapter's verses | Copy one of the book's chapters |
43
+ | safe copy | Copy all of the verse's lines | Copy all of the chapter's verses | Copy all of the book's chapters |
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # The <b>delete use case</b> delete's one or more of the safe's entities.
6
+ #
7
+ # - at <tt>verse</tt> level - it can delete one or more lines
8
+ # - at <tt>chapter</tt> level - it can delete one or more verses
9
+ # - at <tt>book</tt> level - it can delete one or more chapters
10
+ # - at <tt>safe</tt> level - it can delete one book
11
+ #
12
+ class DeleteMe < UseCase
13
+
14
+ attr_writer :entity_id
15
+
16
+ # Deletion that currently expects an open chapter and verse and always
17
+ # wants to delete only one line (key/value pair).
18
+ def execute
19
+
20
+ return unless ops_key_exists?
21
+ master_db = KeyApi.read_master_db()
22
+ return if unopened_envelope?( master_db )
23
+
24
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
25
+ chapter_exists = KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
26
+ chapter_data = KeyDb.from_json( KeyApi.content_unlock( master_db[ chapter_id ] ) ) if chapter_exists
27
+ chapter_data = KeyDb.new() unless chapter_exists
28
+
29
+ content_hdr = create_header()
30
+ master_db[ chapter_id ] = {} unless chapter_exists
31
+ verse_id = master_db[ KEY_PATH ]
32
+
33
+ chapter_data.delete_entry( verse_id, @entity_id )
34
+ chapter_data.delete_entry( verse_id, "#{FILE_KEY_PREFIX}#{@entity_id}" )
35
+
36
+ KeyApi.content_lock( master_db[ chapter_id ], chapter_data.to_json, content_hdr )
37
+ KeyApi.write_master_db( content_hdr, master_db )
38
+ Show.new.flow_of_events
39
+
40
+ end
41
+
42
+
43
+ end
44
+
45
+
46
+ end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # Export the entire book if no chapter and verse is specified (achieved with a safe close),
6
+ # or the chapter if only the chapter is open (safe shut or safe open <<chapter>>, or the
7
+ # mini-dictionary at the verse if both chapter and verse are open.
8
+ class Export < UseCase
9
+
10
+ def get_chapter_data( chapter_key )
11
+ return KeyDb.from_json( KeyApi.content_unlock( chapter_key ) )
12
+ end
13
+
14
+ def execute
15
+
16
+ return unless ops_key_exists?
17
+ master_db = KeyApi.read_master_db()
18
+
19
+ return if unopened_envelope?( master_db )
20
+
21
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
22
+ has_chapter = KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
23
+
24
+ unless has_chapter
25
+ puts "{}"
26
+ return
27
+ end
28
+
29
+ chapter_data = get_chapter_data( master_db[ chapter_id ] )
30
+ puts JSON.pretty_generate( chapter_data )
31
+
32
+ return
33
+
34
+ end
35
+
36
+
37
+ end
38
+
39
+
40
+ end
@@ -0,0 +1,37 @@
1
+
2
+ # safe file | ingest and eject files
3
+
4
+ You ingest a file with **safe file** and then **safe eject** will output that file into the present working directory.
5
+
6
+ If safe detects during an eject, that a file already exists with the same name - it backs it up with a timestamp before ejecting and clobbering the existing file.
7
+
8
+ ```bash
9
+ safe open <<chapter-name>> <<verse-name>>
10
+ safe file <<keyname>> <</path/to/private-key.pem>>
11
+ safe eject <<keyname>>
12
+ safe show
13
+ ```
14
+
15
+ To pull in 3 certificate oriented files for Kubernetes one could use these commands.
16
+
17
+ ```bash
18
+ safe open production kubernetes
19
+ safe file kubernetes.cert ~/.kubectl/kube.prod.cert.pem
20
+ safe file kubernetes.ca.cert ~/.kubectl/kube.prod.ca.cert.pem
21
+ safe file kubernetes.key ~/.kubectl/kube.prod.key.pem
22
+ cd /tmp
23
+ safe eject
24
+ ```
25
+
26
+ The safe ingests the files and spits them out whenever you so desire.
27
+ **Binary files** are supported and can be safely pulled in with <tt>safe file</tt> and ejected at any point in the future.
28
+
29
+ ## remote (external) files
30
+
31
+ The **local filesystem** is the most common, but by no means the only file storage location. You can read from and write to
32
+
33
+ - a zip file **`zip://`**
34
+ - an S3 filesystem **`s3://`**
35
+ - SSH locations **`<<user>>@<<hostname>>:/path/to/file`**
36
+ - a git repository **`git@github.com`**
37
+ - a **google drive** store
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # The <b>eject use case</b> writes (or overwrites) a file or files.
6
+ # Files are always ejected into the present working directory. If an
7
+ # overwrite is detected a backup is taken of the about to be clobbered
8
+ # file.
9
+ #
10
+ # If a keyname is provided then only the file against that key is ejected.
11
+ # No keyname will eject every file in the opened chapter and verse.
12
+ class Eject < UseCase
13
+
14
+ attr_writer :file_key
15
+
16
+ # Files are always ejected into the present working directory and any
17
+ # about to be clobbered files are backed up with a timestamp.
18
+ #
19
+ # If a keyname is provided then only the file against that key is ejected.
20
+ # No keyname will eject every file in the opened chapter and verse.
21
+ def execute
22
+
23
+ return unless ops_key_exists?
24
+ master_db = get_master_database()
25
+ return if unopened_envelope?( master_db )
26
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
27
+ verse_id = master_db[ KEY_PATH ]
28
+ chapter_data = KeyDb.from_json( KeyApi.content_unlock( master_db[ chapter_id ] ) )
29
+
30
+ base64_content = chapter_data[ verse_id ][ "#{FILE_KEY_PREFIX}#{@file_key}" ][ FILE_CONTENT_KEY ]
31
+ simple_filename = chapter_data[ verse_id ][ "#{FILE_KEY_PREFIX}#{@file_key}" ][ FILE_NAME_KEY ]
32
+ file_full_path = File.join( Dir.pwd, simple_filename )
33
+ backup_filename = KeyNow.yyjjj_hhmm_sst() + "-" + simple_filename
34
+ backup_file_path = File.join( Dir.pwd, backup_filename )
35
+ will_clobber = File.file?( file_full_path )
36
+
37
+ File.write( backup_file_path, File.read( file_full_path ) ) if will_clobber
38
+ ::File.write( file_full_path, Base64.urlsafe_decode64( base64_content ) )
39
+
40
+ puts ""
41
+ puts "File successfully ejected from safe into current directory."
42
+ puts ""
43
+ puts "Clobbered File = #{backup_filename}" if will_clobber
44
+ puts "Current Directory = #{Dir.pwd}"
45
+ puts "Ejected Filename = #{simple_filename}"
46
+ puts "Chapter and Verse = #{master_db[ENV_PATH]}:#{verse_id}"
47
+ puts "Ejected File Key = #{@file_key}"
48
+ puts ""
49
+
50
+ end
51
+
52
+
53
+ end
54
+
55
+
56
+ end
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # The <b>file use case</b> pulls a file in from either an accessible filesystem
6
+ # or from a remote http, https, git, S3, GoogleDrive and/or ssh source.
7
+ #
8
+ # The @file_url is the most common parameter given to this use case.
9
+ class FileMe < UseCase
10
+
11
+ attr_writer :file_key, :file_url
12
+
13
+ # There are 3 maps involved in the implementation and they are all (or in part) retrieved and/or
14
+ # created as necessary. They are
15
+ #
16
+ # - the current chapter as a map
17
+ # - the current verse as a map
18
+ # - the file's keyname as a map
19
+ #
20
+ # Once the maps have been found and/or created if necessary the file's keyname map is either
21
+ # populated or amended with the following data.
22
+ #
23
+ # - filename | {UseCase::FILE_NAME_KEY} | the file's simple name
24
+ # - content64 | {UseCase::FILE_CONTENT_KEY} | the file's base64 content
25
+ def execute
26
+
27
+ return unless ops_key_exists?
28
+ master_db = KeyApi.read_master_db()
29
+ return if unopened_envelope?( master_db )
30
+
31
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
32
+ chapter_exists = KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
33
+ chapter_data = KeyDb.from_json( KeyApi.content_unlock( master_db[ chapter_id ] ) ) if chapter_exists
34
+ chapter_data = KeyDb.new() unless chapter_exists
35
+
36
+ content_hdr = create_header()
37
+ master_db[ chapter_id ] = {} unless chapter_exists
38
+ verse_id = master_db[ KEY_PATH ]
39
+
40
+ file_full_path = ::File.absolute_path( @file_url )
41
+ file_base_name = ::File.basename( file_full_path )
42
+ file_content64 = Base64.urlsafe_encode64( ::File.read( file_full_path ) )
43
+
44
+ log.info(x) { "Key name of the file to ingest => #{@file_key}" }
45
+ log.info(x) { "Ingesting file at path => #{file_full_path}" }
46
+ log.info(x) { "The name of the file to ingest is => #{file_base_name}" }
47
+ log.info(x) { "Size of base64 file content => [#{file_content64.length}]" }
48
+
49
+ chapter_data.create_map_entry( verse_id, "#{FILE_KEY_PREFIX}#{@file_key}", FILE_NAME_KEY, file_base_name )
50
+ chapter_data.create_map_entry( verse_id, "#{FILE_KEY_PREFIX}#{@file_key}", FILE_CONTENT_KEY, file_content64 )
51
+
52
+ KeyApi.content_lock( master_db[ chapter_id ], chapter_data.to_json, content_hdr )
53
+ KeyApi.write_master_db( content_hdr, master_db )
54
+
55
+ Show.new.flow_of_events
56
+
57
+ end
58
+
59
+
60
+ private
61
+
62
+
63
+ # Perform pre-conditional validations in preparation to executing the main flow
64
+ # of events for this use case. This method may throw the below exceptions.
65
+ #
66
+ # @raise [SafeDirNotConfigured] if the safe's url has not been configured
67
+ # @raise [EmailAddrNotConfigured] if the email address has not been configured
68
+ # @raise [StoreUrlNotConfigured] if the crypt store url is not configured
69
+ def pre_validation
70
+
71
+
72
+ end
73
+
74
+
75
+ end
76
+
77
+
78
+ end
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # The <b>read use case</b> pulls a file in from either an accessible filesystem
6
+ # or from a remote http, https, git, S3, GoogleDrive and/or ssh source.
7
+ #
8
+ # This use case expects a @file_url parameter. The actions it takes are to
9
+ #
10
+ # - register @in.url to mirror @file_url
11
+ # - register @out.url to mirror @file_url
12
+ # - check the location of @file_url
13
+ # - if no file exists it humbly finishes up
14
+ #
15
+ # If a file does exist at the @in.url this use case
16
+ #
17
+ # - handles HOME directory enabling portability
18
+ # - creates an encryption key and random iv
19
+ # - creates a file (name) id
20
+ # - stores the file byte and human readable size
21
+ # - stores the extension if it has one
22
+ # - stores the last created date
23
+ # - stores the last modified date
24
+ # - stores the (now) in date
25
+ #
26
+ # Once done it displays <b><em>key facts about the file</em></b>.
27
+ class Read < UseCase
28
+
29
+ # -- ---------------------- --#
30
+ # -- ---------------------- --#
31
+ # -- [SAFE] Name Changes --#
32
+ # -- ---------------------- --#
33
+ # -- Change env.path ~> open.chapter
34
+ # -- Change key.path ~> open.verse
35
+ # -- Change envelope@xxxx ~> chapter@xxxx
36
+ # --
37
+ # -- Change filenames to ~~~~~> book.db.breadcrumbs
38
+ # -- Change filenames to ~~~~~> chapter.cipher.file
39
+ # -- Change filenames to ~~~~~> safe.db.abc123xyzpq
40
+ # -- ---------------------- --#
41
+ # -- {
42
+ # -- "db.create.date": "Sat Aug 11 11:20:16 2018 ( 18223.1120.07.511467675 )",
43
+ # -- "db.domain.name": "ab.com",
44
+ # -- "db.domain.id": "uhow-ku9l",
45
+ # -- "env.path": "aa",
46
+ # -- "key.path": "aa",
47
+ # -- "envelope@aa": {
48
+ # -- "content.xid": "3uzk12dxity",
49
+ # -- "content.iv": "XTVe%qIGKVvWw@EKcgSa153nfVPaMVJH",
50
+ # -- "content.key": "1u3b2o6KLiAUmt11yYEDThJw1E5Mh4%1iHYOpJQjWiYLthUGgl8IZ5szus8Fz2Jt"
51
+ # -- }
52
+ # -- }
53
+ # -- ---------------------- --#
54
+ # -- ---------------------- --#
55
+
56
+ attr_writer :file_url
57
+
58
+ # The <b>read use case</b> pulls a file in from either an accessible filesystem
59
+ # or from a remote http, https, git, S3, GoogleDrive and/or ssh source.
60
+ def execute
61
+
62
+ return unless ops_key_exists?
63
+ master_db = KeyApi.read_master_db()
64
+ return if unopened_envelope?( master_db )
65
+
66
+ # -- Get the open chapter identifier (id).
67
+ # -- Decide whether chapter already exists.
68
+ # -- Then get (or instantiate) the chapter's hash data structure
69
+ # --
70
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
71
+ chapter_exists = KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
72
+ chapter_data = KeyDb.from_json( KeyApi.content_unlock( master_db[ chapter_id ] ) ) if chapter_exists
73
+ chapter_data = KeyDb.new() unless chapter_exists
74
+
75
+ content_hdr = create_header()
76
+
77
+ # -- If no content envelope exists we need to place
78
+ # -- an empty one inside the appdb content database.
79
+ # --
80
+ master_db[ chapter_id ] = {} unless chapter_exists
81
+
82
+ # -- We populate (PUT) file instance attributes into
83
+ # -- the mini-dictionary at the [VERSE] location.
84
+ # --
85
+ verse_id = master_db[ KEY_PATH ]
86
+ file_absolute_path = ::File.absolute_path( @file_url )
87
+ chapter_data.create_entry( verse_id, "@in.url", file_absolute_path )
88
+ chapter_data.create_entry( verse_id, "@out.url", file_absolute_path )
89
+
90
+ # -- Lock No.1
91
+ # --
92
+ # -- Lock the file content and leave the 3 breadcrumbs
93
+ # -- (content id, content iv and content key) inside
94
+ # -- the file attributes mini dictionary to facilitate
95
+ # -- decrypting and writing out the file again.
96
+ # --
97
+ KeyApi.content_lock( chapter_data[ verse_id ], ::File.read( @file_url ), content_hdr )
98
+
99
+ # -- Lock No.2
100
+ # --
101
+ # -- Lock the chapter's data which includes the new or
102
+ # -- updated mini-dictionary that holds the breadcrumbs
103
+ # -- (content id, content iv and content key) that will
104
+ # -- be used to decrypt and write out the file content.
105
+ # --
106
+ # -- Leave another set of breadcrumbs inside the master
107
+ # -- database (content id, content iv and content key)
108
+ # -- to facilitate decrypting the chapter's data.
109
+ # --
110
+ KeyApi.content_lock( master_db[ chapter_id ], chapter_data.to_json, content_hdr )
111
+
112
+ # -- Lock No.3
113
+ # --
114
+ # -- Re-lock the master database including the breadcrumbs
115
+ # -- (content id, content iv and content key) that will
116
+ # -- (in the future) decrypt this chapter's data.
117
+ # --
118
+ KeyApi.write_master_db( content_hdr, master_db )
119
+
120
+
121
+ # -- Communicate that the indicated file has just been
122
+ # -- successfully ingested into the safe.
123
+ # --
124
+ print_file_success master_db[ ENV_PATH ], verse_id, file_absolute_path
125
+
126
+ end
127
+
128
+
129
+ private
130
+
131
+
132
+ def print_file_success chapter_id, verse_id, file_url
133
+
134
+ puts ""
135
+ puts "|-"
136
+ puts "|- Chapter ~> #{chapter_id}"
137
+ puts "|- + Verse ~> #{verse_id}"
138
+ puts "|-"
139
+ puts "|- In File ~> #{file_url}"
140
+ puts "|-"
141
+ puts "|- File cocooned inside your safe."
142
+ puts "|-"
143
+ puts "|-Command Options"
144
+ puts "|-"
145
+ puts "|- #{COMMANDMENT} put out.dir ~/this/folder"
146
+ puts "|- #{COMMANDMENT} put out.name new-filename.txt"
147
+ puts "|- #{COMMANDMENT} write"
148
+ puts "|-"
149
+ puts ""
150
+
151
+ end
152
+
153
+
154
+ # Perform pre-conditional validations in preparation to executing the main flow
155
+ # of events for this use case. This method may throw the below exceptions.
156
+ #
157
+ # @raise [SafeDirNotConfigured] if the safe's url has not been configured
158
+ # @raise [EmailAddrNotConfigured] if the email address has not been configured
159
+ # @raise [StoreUrlNotConfigured] if the crypt store url is not configured
160
+ def pre_validation
161
+
162
+
163
+ end
164
+
165
+
166
+ end
167
+
168
+
169
+ end
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # The <b>write use case</b> writes (or overwrites) a file at the
6
+ # out url destination.
7
+ class Write < UseCase
8
+
9
+ attr_writer :file_url
10
+
11
+ # The <b>read use case</b> pulls a file in from either an accessible filesystem
12
+ # or from a remote http, https, git, S3, GoogleDrive and/or ssh source.
13
+ def execute
14
+
15
+ return unless ops_key_exists?
16
+ master_db = get_master_database()
17
+ return if unopened_envelope?( master_db )
18
+
19
+ # Get the open chapter identifier (id).
20
+ # Decide whether chapter already exists.
21
+ # Then get (or instantiate) the chapter's hash data structure
22
+ chapter_id = ENVELOPE_KEY_PREFIX + master_db[ ENV_PATH ]
23
+ verse_id = master_db[ KEY_PATH ]
24
+ chapter_exists = KeyApi.db_envelope_exists?( master_db[ chapter_id ] )
25
+
26
+
27
+ # @todo begin
28
+ # Throw an exception (error) if the chapter
29
+ # either exists and is empty or does not exist.
30
+ # @todo end
31
+
32
+
33
+ # Unlock the chapter data structure by supplying
34
+ # key/value mini-dictionary breadcrumbs sitting
35
+ # within the master database at the section labelled
36
+ # envelope@<<actual_chapter_id>>.
37
+ chapter_data = KeyDb.from_json( KeyApi.content_unlock( master_db[ chapter_id ] ) )
38
+
39
+
40
+ # Unlock the file content by supplying the
41
+ # key/value mini-dictionary breadcrumbs sitting
42
+ # within the chapter's data structure in the
43
+ # section labelled <<verse_id>>.
44
+ file_content = KeyApi.content_unlock( chapter_data[ verse_id ] )
45
+
46
+
47
+ # We read the location url we plan to eject the
48
+ # file out into.
49
+ file_path = @file_url ? @file_url : chapter_data[ verse_id ][ "@out.url" ]
50
+ file_name = ::File.basename( file_path)
51
+
52
+ # If the directory the file will be exported to does
53
+ # not exist we promptly create it.
54
+ FileUtils.mkdir_p( File.dirname( file_path ) )
55
+
56
+ # Create a backup file if we can detect that a
57
+ # file occupies the eject (write) filepath.
58
+ backup_file_path = ::File.join( ::File.dirname( file_path ), KeyNow.yyjjj_hhmm_sst() + "-" + file_name )
59
+ ::File.write( backup_file_path, ::File.read( file_path ) ) if ::File.file?( file_path )
60
+
61
+
62
+ # Now write (and if necessary overwrite) the eject
63
+ # file url path with the previously ingested content.
64
+ ::File.write( file_path, file_content )
65
+
66
+
67
+ # Communicate that the indicated file has just been
68
+ # successfully written out from the safe.
69
+ print_file_success( master_db[ ENV_PATH ], verse_id, file_path )
70
+
71
+ end
72
+
73
+
74
+ private
75
+
76
+
77
+ # Document a successful write of a file cocooned in the safe.
78
+ # @param chapter_id the chapter of the file written out
79
+ # @param verse_id the verse of the file written out
80
+ # @param file_url the filepath the file was written to
81
+ def print_file_success chapter_id, verse_id, file_url
82
+ puts "File [#{file_url}] written out of safe at chapter [#{chapter_id}] and verse [#{verse_id}]."
83
+ end
84
+
85
+
86
+ end
87
+
88
+
89
+ end
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/ruby
2
+
3
+ module SafeDb
4
+
5
+ # Goto is a shortcut (or alias even) for the open command that takes an integer
6
+ # index that effectively specifies which <envelope> and <key> to open.
7
+ #
8
+ # Use <b>view</b> to list the valid integer indices for each envelope and key
9
+ # combination.
10
+ #
11
+ # View maps out and numbers each envelope/key combination.
12
+ # Goto with the number effectively shortcuts the open pin pointer command.
13
+ # Show prints the dictionary at the opened path masking any secrets.
14
+ #
15
+ # Once goto is enacted all path CRUD commands come into play as if you had
16
+ # opened the path. These include put, copy, paste, show, tell and delete.
17
+ class Goto < UseCase
18
+
19
+ # The index (number) starting with 1 of the envelope and key-path
20
+ # combination that should be opened.
21
+ attr_writer :index
22
+
23
+ def execute
24
+
25
+ return unless ops_key_exists?
26
+ master_db = KeyApi.read_master_db()
27
+
28
+ goto_location = 0
29
+ envelope_dictionaries = KeyApi.to_matching_dictionary( master_db, ENVELOPE_KEY_PREFIX )
30
+ envelope_dictionaries.each_pair do | envelope_name, crumb_dictionary |
31
+
32
+ envelope_content = KeyDb.from_json( KeyApi.content_unlock( crumb_dictionary ) )
33
+ envelope_content.each_key do | envelope_key |
34
+
35
+ goto_location += 1
36
+ next unless @index.to_i == goto_location
37
+
38
+ open_uc = Open.new
39
+ open_uc.env_path = envelope_name
40
+ open_uc.key_path = envelope_key
41
+ open_uc.flow_of_events
42
+
43
+ return
44
+
45
+ end
46
+
47
+
48
+ end
49
+
50
+
51
+ end
52
+
53
+
54
+ end
55
+
56
+
57
+ end