safedb 0.01.0001

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.
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