safedb 0.7.1001 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +50 -3
  3. data/Dockerfile +46 -0
  4. data/Jenkinsfile +45 -0
  5. data/README.md +16 -0
  6. data/Rakefile +2 -2
  7. data/cucumber-test.sh +55 -0
  8. data/lib/cli.rb +20 -7
  9. data/lib/controller/abstract/controller.rb +2 -3
  10. data/lib/controller/access/init.rb +11 -7
  11. data/lib/controller/access/login.rb +0 -2
  12. data/lib/controller/book/commit.rb +1 -0
  13. data/lib/controller/db/obliterate.feature +45 -0
  14. data/lib/controller/db/obliterate.rb +58 -0
  15. data/lib/controller/db/pull.rb +10 -26
  16. data/lib/controller/db/push.rb +29 -321
  17. data/lib/controller/db/{remote.rb → remote-github-keypair.rb} +11 -6
  18. data/lib/controller/db/remote-github-token.rb +69 -0
  19. data/lib/controller/db/state.rb +63 -0
  20. data/lib/controller/query/publish.rb +27 -0
  21. data/lib/controller/requirer.rb +0 -1
  22. data/lib/manual/git-interaction.md +176 -0
  23. data/lib/manual/remote.md +0 -1
  24. data/lib/model/book.rb +13 -1
  25. data/lib/model/checkin.feature +15 -27
  26. data/lib/model/content.rb +25 -27
  27. data/lib/model/indices.rb +35 -8
  28. data/lib/model/state_evolve.rb +21 -0
  29. data/lib/model/text_chunk.rb +1 -1
  30. data/lib/utils/extend/string.rb +28 -0
  31. data/lib/utils/git/gitflow.rb +565 -0
  32. data/lib/utils/git/github.rb +69 -0
  33. data/lib/utils/identity/machine.id.rb +2 -2
  34. data/lib/utils/keys/keypair.rb +93 -0
  35. data/lib/utils/logs/logger.rb +3 -4
  36. data/lib/utils/time/timestamp.rb +2 -0
  37. data/lib/version.rb +1 -1
  38. data/pod-image-builder.yaml +27 -0
  39. data/pod-image-safetty.yaml +18 -0
  40. data/safedb.gemspec +1 -6
  41. metadata +17 -64
  42. data/genius-decision.txt +0 -25
  43. data/lib/controller/db/model_git_service.rb +0 -399
  44. data/lib/plugin/github.rb +0 -53
  45. data/lib/utils/store/github.rb +0 -27
@@ -0,0 +1,176 @@
1
+
2
+ # safe | git interaction
3
+
4
+ safe uses git for local synchronization and also as one of the many remote backend storage engines together with S3, SSH and Google Drive. As such, the git client is a prerequisite on systems running the safe command line interface (CLI).
5
+
6
+ With Git comes the ability to revert state to any point in time after state-changing command transactions.
7
+
8
+ Now we document the safe use cases that employ the git version control system and we discuss the circumstances surrounding its use.
9
+
10
+
11
+
12
+ ## **`safe init`**
13
+
14
+ The safe init use case creates a book and creates the **`safedb-master-keys.ini`** file and a chapter crypt file under a new book directory.
15
+
16
+ | **git action** | **when is it done?** | **what is done and/or the circumstances in which git is used** |
17
+ |:-------------- |:-------------------- |:------------------------------------------------------------------- |
18
+ | _git init_ | at the beginning | done only once if the master crypts folder is not under git control |
19
+ | _git add_ | just before the end | every init adds master keys and the just created book folder to git |
20
+ | _git commit_ | at the end | the git commit is issued if and only if the git add was invoked |
21
+
22
+
23
+
24
+ ## **`safe login`**
25
+
26
+ The safe init use case creates a book and creates the **`safedb-master-keys.ini`** file and a chapter crypt file under a new book directory.
27
+
28
+ | **git action** | **what is done andr the circumstances under which git is used** |
29
+ |:------------------ |:------------------------------------------------------------------- |
30
+ | _git rm FILENAME_ | remove the outgoing master crypt content file from the repository and working copy |
31
+ | _git add FILENAME_ | add the incoming master crypt content file into git version management |
32
+ | _git add FILENAME_ | add the master indices INI which may have new keys, a new content ID and maybe bootup ID |
33
+ | _git commit_ | commit the hot-swapped crypt files and the master indices file as an atomic (ACID) transaction |
34
+
35
+
36
+
37
+ ## **`safe commit`**
38
+
39
+ The **`safe commit`** use case uses git to **protect the master database from the ills of concurrent access**. The git interactions are not **_spray and pray_**. They are specific to each given file that is added, removed and/or updated.
40
+
41
+ | **git action** | **when is it done?** | **what is done and/or the circumstances in which git is used** |
42
+ |:---------------- |:-------------------- |:------------------------------------------------------------------- |
43
+ | **_git add_** | just before the end | new files incoming to the master crypts are brought under vc |
44
+ | **_git rm_** | just before the end | removed files are expunged from the git repository |
45
+ | **_git commit_** | at the end | the git commit is issued if either git add or git rm was invoked |
46
+
47
+
48
+
49
+ ## **`safe pull`**
50
+
51
+ If the local safe is already under version control the **`safe pull`** command will check for equivalence between the git repository url and the upstream url registered by **`git remote`**. If it isn't - a **`git clone`** will suffice to pull down the safe repository assets.
52
+
53
+ ### safe pull invalidates every branch
54
+
55
+ **Important** - **`safe pull`** invalidates both the master branch and all active branches. Before you issue a safe pull you must **`safe commit`** on every shell branch that contains changes.
56
+
57
+ The commit provides a route back to a previous revision if the pull goes belly up and turns out to be something other than what you expected. Use **`safe compare`** to detail all the active branches that will be invalidated including the their login time and most recent access and change times.
58
+
59
+ | **git action** | **when is it done?** | **what is done and/or the circumstances in which git is used** |
60
+ |:---------------- |:-------------------- |:------------------------------------------------------------------- |
61
+ | **_git remote_** | at the beginning | the upstream url is compared to the url safe pull has a handle to |
62
+ | **_git clone_** | towards the end | if there are no crypts to speak of the git clone pulls them in |
63
+ | **_git pull_** | towards the end | this is a git fetch and git merge to integrate remote repo changes |
64
+
65
+ After a **`safe pull`** you must issue a **`safe login`** to continue working.
66
+
67
+ ### pull first | ask questions later
68
+
69
+ A **`safe pull`** is recommended at the start of your session. Do a **`safe diff`** which does not require you to login in order to assess the differences between the local and remote master crypts.
70
+
71
+
72
+
73
+ ## **`safe push`**
74
+
75
+ After one or more commits a **`safe push`** is called upon to sync the local crypt state with the registered remote repository.
76
+
77
+ However a git push may not be possible if the remote has moved further ahead than the local. This matter would be reported and the user encouraged to perform a **`safe pull`** first followed by a **`safe refresh`**, changes, **`safe commit`** and finally another **`safe push`**.
78
+
79
+ | **git action** | **when is it done?** | **what is done and/or the circumstances in which git is used** |
80
+ |:---------------- |:-------------------- |:------------------------------------------------------------------- |
81
+ | **_git push_** | towards the end | if this is a git fetch and git merge to integrate remote repo changes |
82
+
83
+
84
+
85
+ ## **`safe remote`** or **`safe stage`**
86
+
87
+ **`safe remote`** prints a report on the difference between the local and remote databi.
88
+
89
+ git ls-files --stage --abbrev=8
90
+
91
+ The `ls-files` command is used to list the files that are staged and ready to be pushed up to the remote repository.
92
+
93
+
94
+
95
+ ## **`safe remote --provision`**
96
+
97
+ The **`safe remote`** command is primed to do four key tasks. It
98
+
99
+ - _automagically_ creates a remote repository (using for example **Github's API** integration)
100
+ - it provisions and installs **SSH keypairs** for **`safe push`** to write to the remote backend
101
+ - it uses **`set-upstream-url`** to tell the local repository where to **pull from** and **push to**
102
+ - urges the user commit branch changes **`safe commit`** and mirror them remotely **`safe push`**
103
+
104
+ A safe remote only acts to provision a remote mirror for your crypts when the **local git reposiotory is virginal** in that it has never been paired with a remote repository. In other words the local crypts have been created using **`safe init <<book-name>>`** as opposed to **`safe pull`**.
105
+
106
+ | **git action** | **when is it done?** | **what is done and/or the circumstances in which git is used** |
107
+ |:---------------------------- |:-------------------- |:----------------------------------------------------------------- |
108
+ | **_git set-upstream-url_** | at the beginning | if remote creates the 2nd remote repo the upstream url is changed |
109
+
110
+
111
+ The remote's last responsibility is to urge the user to issue a **`safe commit`** followed by a **`safe push`** so as to make the remote repository mirrors the state of the local safe.
112
+
113
+
114
+
115
+ ## **`safe compare`**
116
+
117
+ The **`safe diff`** command reports on the difference between the local master book and the present local branch book.
118
+
119
+ **`safe compare`** on the other hand tells you that
120
+
121
+ - the remote branch has changed (leaving you behind needing to **`safe pull`**)
122
+ - the local branch has changed (putting you ahead needing to **`safe push`**)
123
+ - you cannot access the remote repository and cannot ascertain the above info
124
+
125
+ | **git action** | **what is done and/or the circumstances in which git is used** |
126
+ |:------------------ |:-------------------------------------------------------------- |
127
+ | **_git compare_** | this command is used to ascertain local vs remote differences |
128
+ | **_git rev-diff_** | another command to ascertain local vs remote differences |
129
+
130
+ So safe compare reports on the local commits informing you which branch made them, when and a rough change count. On the other hand it tells you about the remote commits, who made them and when.
131
+
132
+ ### the worst of both worlds
133
+
134
+ When commits have moved on both the local and remote master branches you are in the worst ofboth worlds. Thankfully this scenario is extremely rare. The rough steps to resolve this are to
135
+
136
+ - export the local books as json
137
+ - pull the remote books down then export them as json
138
+ - externally compare the json and merge them into one
139
+ - import the merged json to create new books
140
+
141
+
142
+
143
+ ## safe remote architecture
144
+
145
+ Due to its meticulous planning the safe adheres to a number of high level design rules. Let's cover these in the context of operating alongside a remote _git_ backend repository.
146
+
147
+
148
+ ### 1. stand alone
149
+
150
+ The term **_stand alone_** refers to a non-networked computer that has no access neither to the internet nor to other computers in its vicinity.
151
+
152
+ The **safe cli** must be able to operate on a stand alone machine. Features like the remote backend mirror must provide succinct legible error messages when remote access is unavailable.
153
+
154
+ Furthermore, the following commands must not be impaired when the machine is in standalone mode.
155
+
156
+ - **`safe diff`** (does not report on remote differences)
157
+ - **`safe commit`** (only changes the master branch)
158
+ - **`safe init`** (only creates a local git repository
159
+
160
+ And these commands must degrade gracefully in standalone mode
161
+
162
+ - **`safe remote`**
163
+ - **`safe push`**
164
+ - **`safe pull`**
165
+ - **`safe compare`**
166
+
167
+
168
+ ### 2. cap theorem
169
+
170
+ #### consistency trumps availability
171
+
172
+ In reference to the CAP theorem, the safe is designed such that **consistency trumps availability**.
173
+
174
+ Failed commits in a manner of speaking are preferable to corrupted files and race conditions. Without git, these corruptions would arise through the use of basic file operations.
175
+
176
+ Automatons like scripts will typically branch and read the database. It is envisaged that humans will perform the vast majority of commits, pushes and pulls thus reducing the frequency of commit failures.
data/lib/manual/remote.md CHANGED
@@ -12,7 +12,6 @@ Before you use safe remote to provision a github git repository backend for your
12
12
  - you have a github account (with username)
13
13
  - you have created a (40 character hexadecimal) github access token
14
14
  - you have inserted this data at a suitable chapter and verse
15
- - you run **`safe remote --provision`** from this opened book/chapter/verse
16
15
 
17
16
  Below is the sequence of commands leading up to **`safe remote --provision`**
18
17
 
data/lib/model/book.rb CHANGED
@@ -384,13 +384,25 @@ module SafeDb
384
384
  end
385
385
 
386
386
 
387
+
388
+ # Print a notie stating the book followed by and open chapter and
389
+ # verse names only if the book is currently opened at a specific
390
+ # chapter and verse. Right after book creation for example there
391
+ # is no open chapter or verse and this method simply prints out
392
+ # a carriage return.
387
393
  def print_book_mark()
388
- bcv_name = "#{book_name()}/#{get_open_chapter_name()}/#{get_open_verse_name()}"
394
+
389
395
  puts ""
396
+ return unless is_opened?()
397
+
398
+ bcv_name = "#{book_name()}:#{get_open_chapter_name()}/#{get_open_verse_name()}"
390
399
  puts "#{bcv_name} (#{get_open_verse_data().length()})\n"
391
400
  puts ""
401
+
392
402
  end
393
403
 
404
+
405
+
394
406
  # Is the verse name in the parameter the book's open verse? An exception
395
407
  # is thrown if the parameter verse name is nil.
396
408
  # @param this_verse_name [String] the name of the verse to test
@@ -1,33 +1,21 @@
1
1
 
2
- ## The typical shells
2
+ Feature: test safedb's version command
3
3
 
4
- Learn to run emacs commands in a batch so that we can open the below in an automated fashion. Learn to robotically communicate with and manipulate emacs. This will improve your efficiency many many fold.
4
+ This test will run both `safe version` and `safe --version`
5
5
 
6
- .% CORE [dir] 856 Dired by name /home/apollo/projects/safedb.net/lib/core/
7
- * SEARCH [shell] 36 Shell:run /home/apollo/projects/safedb.net/
8
- * RAKE [shell] 94 Shell:run /home/apollo/projects/safedb.net/
9
- % USECASE [dir] 1080 Dired by name /home/apollo/projects/safedb.net/lib/usecase/
10
- % safedb.net 924 Dired by name /home/apollo/projects/safedb.net/
11
- * SAFE 2 [shell] 16 Shell:run /home/apollo/
12
- * SAFE 1 [shell] 16 Shell:run /home/apollo/
6
+ # --> Scenario: hip hop hoooray is the value I GET
7
+ # --> When I run `safe version`
8
+ # --> Then the output should contain "v0.8"
13
9
 
14
- # Feature Checkin
10
+ # --> Scenario: right overy here is the blood and the sweat
11
+ # --> When I run `safe --version`
12
+ # --> Then the output should contain "v0.8"
15
13
 
16
- ## In one shell
17
14
 
18
- safe init boys
19
- safe login boys
20
- safe import ~/safedb.test.data.json
21
- safe view
22
- safe show (failure because no open chapter has been set)
23
- safe goto 3
24
- safe checkin
25
-
26
-
27
- ## In Another shell
28
-
29
- safe login boys
30
-
31
- Failure occurs
32
-
33
- R{\370\204m\265^v}\276\223^RZ(\320^N\333e.time":"Wed Apr 10 09:06:37 2019","book.name":"boys","book.init.version":"safedb-v0.3.1012","book.chapter.keys":{"dbms.accounts":{"content.id":"00cxarwaia0s4g","content.iv":"VzbG5IBQEuFdpRFerzGqHPejVKdKekcl","chapter.key.crypt":"Rx5BWXXM9uK5cbiH006WupaHVciXL8q%XooFdogSazMdHnqlJHuulMoeBtZxxJse"},"aws.console.accounts":{"content.id":"r6sc5ope3n3sfi","content.iv":"Jgh4c2aeh2Qjwt@ZaTEJxfK@6A%dzUoz","chapter.key.crypt":"9t5xxjDgyN4jQGQyw%9CHvTzGqJU@MiOWFGFKpGAuz@@fT8FJVO2fjoQIHEjTDfa"},"ops":{"content.id":"uk2u9bnzpynizc","content.iv":"AnvTgyJPbZpBju8kSsT8es0NmHlv2j9d","chapter.key.crypt":"TYyASQ71sgMbzNOxGVgojdb28M1%4iPDDsSDQz8TevjABYY887hqoPTRpvx18xUT"},"git":{"content.id":"r3dso6qr88l5lm","content.iv":"I9hykwLIGrvgp0j2jMQyMJC3QhWg0xSD","chapter.key.crypt":"0QLO7FawspMzEpRnB%6Wb3dVyjiJ36IX5SRp7QNOkU5ut@sMy9%KNYQ42XKA8yTj"}},"book.open.chapter":"aws.console.accounts","book.open.verse":"aimbrain.prod"}
15
+ # --> safe init boys
16
+ # --> safe login boys
17
+ # --> safe import ~/safedb.test.data.json
18
+ # --> safe view
19
+ # --> safe show (failure because no open chapter has been set)
20
+ # --> safe goto 3
21
+ # --> safe checkin
data/lib/model/content.rb CHANGED
@@ -11,6 +11,24 @@ module SafeDb
11
11
  class Content
12
12
 
13
13
 
14
+ # Use the content's external id to find the ciphertext file that is to be unlocked.
15
+ # Then use the unlock key from the parameter along with the random IV that is inside
16
+ # the {DataMap} or {DataStore} to decrypt and return the ciphertext.
17
+ #
18
+ # @param unlock_key [Key] symmetric key that was used to encrypt the ciphertext
19
+ # @param data_store [DataMap] either {DataMap} or {DataStore} containing content id and random iv
20
+ # @return [String] the resulting decrypted text that was encrypted with the parameter key
21
+ def self.unlock_master( unlock_key, data_store )
22
+
23
+ book_id = data_store.section()
24
+ crypt_path = FileTree.master_crypts_filepath( book_id, data_store.get( Indices::CONTENT_IDENTIFIER ) )
25
+ random_iv = KeyIV.in_binary( data_store.get( Indices::CONTENT_RANDOM_IV ) )
26
+ return unlock_it( crypt_path, unlock_key, random_iv )
27
+
28
+ end
29
+
30
+
31
+
14
32
  # Lock the content body provided - place the resulting ciphertext
15
33
  # inside a file named by a random identifier, then write this identifier
16
34
  # along wih the initialization and encryption key into the provided
@@ -19,6 +37,8 @@ module SafeDb
19
37
  # The content ciphertext derived from encrypting the body is stored
20
38
  # in a file underneath the provided content header.
21
39
  #
40
+ # Finally
41
+ #
22
42
  # @param book_id [String] used to determine the book's master crypt folder
23
43
  # @param crypt_key [Key] the key used to (symmetrically) encrypt the content provided
24
44
  # @param data_store [DataMap] either DataMap or DataStore containing the content id and random iv
@@ -79,16 +99,12 @@ module SafeDb
79
99
 
80
100
 
81
101
 
82
- # Lock the content body provided - place the resulting ciphertext
83
- # inside a file named by a random identifier, then write this identifier
84
- # along wih the initialization and encryption key into the provided
85
- # key-value map (hash).
86
- #
87
- # The content ciphertext derived from encrypting the body is stored
88
- # in a file underneath the provided content header.
102
+ # Use the crypt key and random init vector to transform the plain text
103
+ # message into an encrypted ciphertext message.
89
104
  #
90
- # This method returns the highly random key instantiated for the purposes
91
- # of encrypting the content.
105
+ # Use the chunk of plain text (header) information along with the ciphertext
106
+ # and the expected file location at the crypt path to write out the crypt
107
+ # and header content into a file.
92
108
  #
93
109
  # @param crypt_path [File] path to the crypt file holding the encrypted ciphertext
94
110
  # @param crypt_key [Key] the key used to (symmetrically) encrypt the content provided
@@ -104,24 +120,6 @@ module SafeDb
104
120
 
105
121
 
106
122
 
107
- # Use the content's external id to find the ciphertext file that is to be unlocked.
108
- # Then use the unlock key from the parameter along with the random IV that is inside
109
- # the {DataMap} or {DataStore} to decrypt and return the ciphertext.
110
- #
111
- # @param unlock_key [Key] symmetric key that was used to encrypt the ciphertext
112
- # @param data_store [DataMap] either {DataMap} or {DataStore} containing content id and random iv
113
- # @return [String] the resulting decrypted text that was encrypted with the parameter key
114
- def self.unlock_master( unlock_key, data_store )
115
-
116
- book_id = data_store.section()
117
- crypt_path = FileTree.master_crypts_filepath( book_id, data_store.get( Indices::CONTENT_IDENTIFIER ) )
118
- random_iv = KeyIV.in_binary( data_store.get( Indices::CONTENT_RANDOM_IV ) )
119
- return unlock_it( crypt_path, unlock_key, random_iv )
120
-
121
- end
122
-
123
-
124
-
125
123
  # Use the content's external id to find the ciphertext file that is to be unlocked.
126
124
  # Then use the unlock key from the parameter along with the random IV that is inside
127
125
  # the {DataMap} or {DataStore} to decrypt and return the ciphertext.
data/lib/model/indices.rb CHANGED
@@ -13,11 +13,14 @@ module SafeDb
13
13
  # The short url name of the safe personal database.
14
14
  SAFE_URL_NAME = "safedb.net"
15
15
 
16
+ # The name of the safe application and the safe gem as known by the operating system.
17
+ SAFE_APP_NAME = "safedb"
18
+
16
19
  # The desired length of a safe book ergonomic identifier.
17
20
  SAFE_BOOK_ID_LENGTH = 12
18
21
 
19
22
  # The file-system location of the safe database tree
20
- SAFE_DATABASE_FOLDER = File.join( Dir.home, ".#{SAFE_URL_NAME}" )
23
+ SAFE_DATABASE_FOLDER = File.join( File.join( Dir.home, ".config" ), SAFE_APP_NAME )
21
24
 
22
25
  # The fully qualified domain name of the safedb home website
23
26
  SAFE_GEM_WEBSITE = "https://www.#{SAFE_URL_NAME}"
@@ -25,6 +28,11 @@ module SafeDb
25
28
  # The safe database github clonable url for the ruby software
26
29
  SAFE_GITHUB_URL = "https://github.com/devops4me/#{SAFE_URL_NAME}"
27
30
 
31
+
32
+ ### #################################### ###
33
+ ### paths to the master crypts resources ###
34
+ ### #################################### ###
35
+
28
36
  # The name of the master crypts folder.
29
37
  MASTER_CRYPTS_FOLDER_NAME = "safedb-master-crypts"
30
38
 
@@ -34,6 +42,23 @@ module SafeDb
34
42
  # The path to the master crypts .git directory.
35
43
  MASTER_CRYPTS_GIT_PATH = File.join( MASTER_CRYPTS_FOLDER_PATH, ".git" )
36
44
 
45
+ # The master indices file name
46
+ MASTER_INDICES_FILE_NAME = "safedb-master-keys.ini"
47
+
48
+ # The path to the master indices file
49
+ MASTER_INDICES_FILEPATH = File.join( MASTER_CRYPTS_FOLDER_PATH, MASTER_INDICES_FILE_NAME )
50
+
51
+
52
+
53
+ # The name of the backup master crypts folder.
54
+ BACKUP_CRYPTS_FOLDER_NAME = "safedb-backup-crypts"
55
+
56
+ # The path of the backup master crypts folder.
57
+ BACKUP_CRYPTS_FOLDER_PATH = File.join( SAFE_DATABASE_FOLDER, BACKUP_CRYPTS_FOLDER_NAME )
58
+
59
+
60
+
61
+
37
62
  # The name of the branch indices folder.
38
63
  BRANCH_INDICES_FOLDER_NAME = "safedb-branch-keys"
39
64
 
@@ -46,12 +71,6 @@ module SafeDb
46
71
  # The path to the branch crypts folder.
47
72
  BRANCH_CRYPTS_FOLDER_PATH = File.join( SAFE_DATABASE_FOLDER, BRANCH_CRYPTS_FOLDER_NAME )
48
73
 
49
- # The master indices file name
50
- MASTER_INDICES_FILE_NAME = "safedb-master-keys.ini"
51
-
52
- # The path to the master indices file
53
- MASTER_INDICES_FILEPATH = File.join( SAFE_DATABASE_FOLDER, MASTER_INDICES_FILE_NAME )
54
-
55
74
  # The path to the remote storage configuration INI file
56
75
  MACHINE_CONFIG_FILEPATH = File.join( SAFE_DATABASE_FOLDER, "safedb-remote-storage.ini" )
57
76
 
@@ -60,6 +79,7 @@ module SafeDb
60
79
 
61
80
 
62
81
 
82
+
63
83
  # The keyname whose value denotes a local folder path to clone to
64
84
  GIT_CLONE_BASE_PATH = "git.clone.base.path"
65
85
 
@@ -207,7 +227,7 @@ module SafeDb
207
227
  OPENED_VERSE_NAME = "book.open.verse"
208
228
 
209
229
  # The application version that oversaw this book's initialization.
210
- SAFE_VERSION_STRING = "safedb-v#{SafeDb::VERSION}"
230
+ SAFE_PRE_VERSION_STRING = "safedb-v"
211
231
 
212
232
  # Handle to the key name of the ingested file in the submap verse
213
233
  INGESTED_FILE_LINE_NAME_KEY = "safedb.file::"
@@ -231,6 +251,13 @@ module SafeDb
231
251
  ELLIPTIC_CURVE_KEY_TYPE = "secp384r1"
232
252
 
233
253
 
254
+ ### ##################################### ###
255
+ ### Strings printed to the user interface ###
256
+ ### ##################################### ###
257
+
258
+ NOTHING_TO_OBLITERATE = "There is nothing to obliterate."
259
+
260
+
234
261
  end
235
262
 
236
263
 
@@ -68,12 +68,26 @@ module SafeDb
68
68
  the_crypt_key = old_human_key.do_decrypt_key( book_keys.get( Indices::CRYPT_CIPHER_TEXT ) )
69
69
  plain_content = Content.unlock_master( the_crypt_key, book_keys )
70
70
 
71
+ remove_crypt_path = FileTree.master_crypts_filepath( the_book_id, book_keys.get( Indices::CONTENT_IDENTIFIER ) )
72
+
71
73
  first_login_since_boot = StateInspect.is_first_login?( book_keys )
72
74
  the_crypt_key = Key.from_random if first_login_since_boot
73
75
  recycle_keys( the_crypt_key, the_book_id, human_secret, book_keys, plain_content )
74
76
  set_bootup_id( book_keys ) if first_login_since_boot
75
77
 
78
+ create_crypt_path = FileTree.master_crypts_filepath( the_book_id, book_keys.get( Indices::CONTENT_IDENTIFIER ) )
76
79
  branch_id = Identifier.derive_branch_id( Branch.to_token() )
80
+ commit_msg = "safe login to #{the_book_id} at branch #{branch_id} on #{TimeStamp.readable()}."
81
+
82
+ # Remove the master chapter crypt file from the local git repository and add
83
+ # the new master chapter crypt to the local git repository.
84
+ GitFlow.del_file( Indices::MASTER_CRYPTS_FOLDER_PATH, remove_crypt_path )
85
+ GitFlow.add_file( Indices::MASTER_CRYPTS_FOLDER_PATH, create_crypt_path )
86
+ GitFlow.add_file( Indices::MASTER_CRYPTS_FOLDER_PATH, Indices::MASTER_INDICES_FILEPATH )
87
+ GitFlow.list( Indices::MASTER_CRYPTS_FOLDER_PATH )
88
+ GitFlow.list( Indices::MASTER_CRYPTS_FOLDER_PATH, true )
89
+ GitFlow.commit( Indices::MASTER_CRYPTS_FOLDER_PATH, commit_msg )
90
+
77
91
  clone_book_into_branch( the_book_id, branch_id, book_keys, the_crypt_key )
78
92
 
79
93
  return true
@@ -177,6 +191,13 @@ module SafeDb
177
191
  master_keys.set( Indices::CONTENT_IDENTIFIER, branch_keys.get( Indices::CONTENT_IDENTIFIER ) )
178
192
  master_keys.set( Indices::CONTENT_RANDOM_IV, branch_keys.get( Indices::CONTENT_RANDOM_IV ) )
179
193
 
194
+ commit_msg = "safe commit for #{book.book_name()} in branch #{book.branch_id()} on #{TimeStamp.readable()}."
195
+
196
+ GitFlow.stage( Indices::MASTER_CRYPTS_FOLDER_PATH )
197
+ GitFlow.list( Indices::MASTER_CRYPTS_FOLDER_PATH )
198
+ GitFlow.list( Indices::MASTER_CRYPTS_FOLDER_PATH, true )
199
+ GitFlow.commit( Indices::MASTER_CRYPTS_FOLDER_PATH, commit_msg )
200
+
180
201
  end
181
202
 
182
203
 
@@ -21,7 +21,7 @@ module SafeDb
21
21
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22
22
  Safe Book Id := #{book_id}
23
23
  Time Created := #{TimeStamp.readable()}
24
- Safe Version := #{Indices::SAFE_VERSION_STRING}
24
+ Safe Version := #{Indices::SAFE_PRE_VERSION_STRING}#{SafeDb::VERSION}
25
25
  Safe Website := #{Indices::SAFE_GEM_WEBSITE}
26
26
  RubyGems.org := https://rubygems.org/gems/safedb
27
27
  CRYPT_HEADER
@@ -561,6 +561,17 @@ class String
561
561
  # The INFO log level is used to log the lines - if this is not
562
562
  # appropriate create a (level) parameterized log lines method.
563
563
  def log_lines
564
+ log_info()
565
+ end
566
+
567
+
568
+ # Log at the INFO level the string which is expected to be
569
+ # delineated. If the string originated from a file it will
570
+ # be logged line by line.
571
+ #
572
+ # If no line delineation the string will be dumped just as
573
+ # a blob.
574
+ def log_info
564
575
 
565
576
  self.each_line do |line|
566
577
  clean_line = line.chomp.gsub("\\n","")
@@ -569,4 +580,21 @@ class String
569
580
 
570
581
  end
571
582
 
583
+
584
+ # Log at the INFO level the string which is expected to be
585
+ # delineated. If the string originated from a file it will
586
+ # be logged line by line.
587
+ #
588
+ # If no line delineation the string will be dumped just as
589
+ # a blob.
590
+ def log_debug
591
+
592
+ self.each_line do |line|
593
+ clean_line = line.chomp.gsub("\\n","")
594
+ log.debug(x) { line } if clean_line.length > 0
595
+ end
596
+
597
+ end
598
+
599
+
572
600
  end