ccs 3.0.0 → 3.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddc7a13cb4e185260a511ead10fd9f75387fecdd42a4138d19e0a0de35cd9caf
4
- data.tar.gz: 8c99aa2c31cbd7a66bb1023f8b32872478691268b475b80f9bf6c203ebb978a1
3
+ metadata.gz: ce4380f6f1c426727a7147117ba50c7dc21866ec766ecf01083846e5340d8d79
4
+ data.tar.gz: 162d1b0bebdcbec23a1bb72b2c82d7ad4b6994c4ab6fc4258d1ebeebe29c61b9
5
5
  SHA512:
6
- metadata.gz: 6c8f8bff758c7917bee0a1f779f5a97594c863d19ae96a673b8ca630cfe0189649d326130c44b622799ce489b9486492c1bf9fb74ee38c6e998167f29a7cb8a5
7
- data.tar.gz: 0ac4cd8805f4addd47e7b224a7eff2a7fab360856294aed60444846946d9563c294d415bdbba9f72da3d7fe2f966b1cec18d5f51b97fc615e6a0da49d6da8d94
6
+ metadata.gz: 70e1cd7ac88384e75d62093429b4fa37a4b2aba6c6b3439e47c856653b2eac54c56b2e55d11281b2258ee0497a6e5008cc365b3f402ae3277e6612764af9e502
7
+ data.tar.gz: 8b580583449616952eedf65b13e7c893464cfb7fd3595ff2f238eaf933741211dad276df92d31008b54b7d0976ed727bc9a9471d109dc6d8697e3caa047e2f3c
@@ -0,0 +1,10 @@
1
+ ## 3.1.0 2020-11-23
2
+
3
+
4
+ ### Added
5
+
6
+ - `force` argument to overwrite remote documents when uploading (paweljw)
7
+ - YARD documentation (paweljw)
8
+
9
+
10
+ [Compare 3.0.0...3.1.0](https://github.com/occson/ccs/compare/3.0.0...3.1.0)
data/README.md CHANGED
@@ -6,9 +6,7 @@ Configuration control system
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
9
- ```ruby
10
- gem 'ccs'
11
- ```
9
+ gem 'ccs'
12
10
 
13
11
  And then execute:
14
12
 
@@ -27,6 +25,7 @@ Or install it yourself as:
27
25
  --access-token
28
26
  -p CCS_PASSPHRASE, CCS Passphrase
29
27
  --passphrase
28
+ -f, --[no-]force Overwrite remote documents when uploading
30
29
 
31
30
 
32
31
  ## Example
@@ -45,6 +44,10 @@ Upload local file
45
44
 
46
45
  ccs cp /local/path/to/file.yml ccs://workspace-name/0.1.0/path/to/file.yml
47
46
 
47
+ Upload local file, overwriting remote document if any'
48
+
49
+ ccs cp --force /local/path/to/file.yml ccs://workspace-name/0.1.0/path/to/file.yml
50
+
48
51
  Upload content from STDIN
49
52
 
50
53
  echo "{ a: 1 }" | ccs cp - ccs://workspace-name/0.1.0/path/to/file.yml
@@ -79,6 +82,13 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
79
82
 
80
83
  To install this gem onto your local machine, run `bin/rake install`. To release a new version, update the version number in `version.rb`, and then run `bin/rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
81
84
 
85
+ ## Documentation
86
+
87
+ Documentation for the code should be written in YARD format. It can be generated locally into the `doc` directory by running
88
+
89
+ bundle exec yard
90
+
91
+
82
92
  ## Contributing
83
93
 
84
94
  Bug reports and pull requests are welcome on GitHub at https://github.com/occson/ccs. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/exe/ccs CHANGED
@@ -42,6 +42,10 @@ when 'cp'
42
42
  options['passphrase'] = v
43
43
  end
44
44
 
45
+ option_parser.on('-f', '--[no-]force', 'Overwrite remote documents when uploading') do |v|
46
+ options['force'] = v
47
+ end
48
+
45
49
  option_parser.separator ''
46
50
  option_parser.separator 'Configure via environment variables:'
47
51
  option_parser.separator ' CCS_ACCESS_TOKEN'
@@ -57,6 +61,8 @@ when 'cp'
57
61
  option_parser.separator ' ccs cp ccs://workspace-name/0.1.0/path/to/file.yml /local/path/to/file.yml'
58
62
  option_parser.separator ' Upload local file'
59
63
  option_parser.separator ' ccs cp /local/path/to/file.yml ccs://workspace-name/0.1.0/path/to/file.yml'
64
+ option_parser.separator ' Upload local file, overwriting remote document if any'
65
+ option_parser.separator ' ccs cp --force /local/path/to/file.yml ccs://workspace-name/0.1.0/path/to/file.yml'
60
66
  option_parser.separator ' Upload content from STDIN'
61
67
  option_parser.separator ' echo "{ a: 1 }" | ccs cp - ccs://workspace-name/0.1.0/path/to/file.yml'
62
68
  option_parser.separator ' cat /local/path/to/file.yml | ccs cp - ccs://workspace-name/0.1.0/path/to/file.yml'
@@ -77,7 +83,7 @@ when 'cp'
77
83
  raise OptionParser::MissingArgument, 'source' unless arguments.fetch(0, nil)
78
84
  raise OptionParser::MissingArgument, 'destination' unless arguments.fetch(1, nil)
79
85
 
80
- exit(1) unless Ccs::Commands::Copy.new(arguments[0], arguments[1], options['access_token'], options['passphrase']).call
86
+ exit(1) unless Ccs::Commands::Copy.new(arguments[0], arguments[1], options['access_token'], options['passphrase'], force: options.fetch('force', false)).call
81
87
  else
82
88
  puts option_parser
83
89
  exit(1)
data/lib/ccs.rb CHANGED
@@ -12,6 +12,8 @@ require 'ccs/decrypter'
12
12
  require 'ccs/uploader'
13
13
  require 'ccs/downloader'
14
14
  require 'ccs/document'
15
+
15
16
  require 'ccs/commands/copy'
16
17
 
18
+ # Top level `Ccs` namespace.
17
19
  module Ccs; end
@@ -2,14 +2,37 @@
2
2
 
3
3
  module Ccs
4
4
  module Commands
5
+ # The copy command, responsible for copying a target to a destination, performing encryption
6
+ # and decryption as necessary.
7
+ #
8
+ # The target and destinations can be:
9
+ #
10
+ # - STDIN/STDOUT: a `-` sign is interpreted as these standard streams
11
+ #
12
+ # - The Occson server: strings beginning with `ccs://` or `http(s)://` are interpreted as such
13
+ #
14
+ # - local files: everything not matching the previous descriptions is assumed to
15
+ # be a path on the local system
5
16
  class Copy
6
- def initialize(source, destination, access_token, passphrase)
17
+ # Builds an instance of the Copy command.
18
+ #
19
+ # @param source [String] `-` for STDIN, an URI or a local file path
20
+ # @param destination [String] `-` for STDOUT, an URI or a local file path
21
+ # @param access_token [String] Occson access token
22
+ # @param passphrase [String] Passphrase used for encryption of the document
23
+ # @param force [Boolean] Whether to overwrite target document in Occson, if any. Default `false`.
24
+ def initialize(source, destination, access_token, passphrase, force: false)
7
25
  @source = source
8
26
  @destination = destination
9
27
  @access_token = access_token
10
28
  @passphrase = passphrase
29
+ @force = force
11
30
  end
12
31
 
32
+ # Performs a transfer between locations - an upload if `@source` is local or STDIN,
33
+ # a download if `@source` is an URI.
34
+ #
35
+ # No guarantees are made about the return values of this method.
13
36
  def call
14
37
  download? ? download : upload
15
38
  end
@@ -29,7 +52,7 @@ module Ccs
29
52
 
30
53
  def upload
31
54
  content = @source.eql?('-') ? STDIN.read : File.read(@source)
32
- Document.new(@destination, @access_token, @passphrase).upload(content)
55
+ Document.new(@destination, @access_token, @passphrase).upload(content, force: @force)
33
56
  end
34
57
  end
35
58
  end
@@ -1,12 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # Handles client-side decryption for documents.
5
+ #
6
+ # The decrypter uses AES-256 in CBC mode internally. A salt is
7
+ # expected in bytes 8..15, with ciphertext occupying the
8
+ # further bytes.
4
9
  class Decrypter
10
+ # Constructs a Decrypter instance with given passphrase and content.
11
+ #
12
+ # @example
13
+ # Ccs::Decrypter.new('the content passphrase', content)
14
+ #
15
+ # @param passphrase [String] Passphrase for content decryption
16
+ # @param content [String] Encrypted document content
5
17
  def initialize(passphrase, content)
6
18
  @passphrase = passphrase
7
19
  @content = content
8
20
  end
9
21
 
22
+ # Performs decryption, returning plaintext if passphrase matched.
23
+ #
24
+ # @return [String] Plaintext document content
10
25
  def call
11
26
  decryptor.pkcs5_keyivgen(@passphrase, ciphertext_salt, 1)
12
27
  result = decryptor.update(encrypted)
@@ -1,17 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # An abstraction for the Document concept. Simplifies building URLs,
5
+ # uploading and downloading contents. Abstracts away workspaces due to
6
+ # the use of access tokens in constructions.
4
7
  class Document
8
+ # Constructs a Document instance from a given URI, access token and passphrase.
9
+ #
10
+ # @example
11
+ # uri = 'ccs://path/to/file.yml'
12
+ # access_token = 'f30b5450421362c9ca0b'
13
+ # passphrase = 'my document passphrase'
14
+ #
15
+ # Ccs::Document.new(uri, access_token, passphrase)
16
+ #
17
+ # @param uri [String] Document URI. Accepts `ccs://` as shorthand for Occson location.
18
+ # @param access_token [String] Occson access token.
19
+ # @param passphrase [String] Document passphrase, used in encryption and decryption.
5
20
  def initialize(uri, access_token, passphrase)
6
21
  @uri = build_uri(uri)
7
22
  @access_token = access_token
8
23
  @passphrase = passphrase
9
24
  end
10
25
 
11
- def upload(content)
12
- Uploader.new(@uri, content, @access_token, @passphrase).call
26
+ # Uploads the given plaintext `content` to target URI.
27
+ #
28
+ # @example
29
+ # document.upload('My example plaintext.')
30
+ #
31
+ # @param content [String] Plaintext to be encrypted and uploaded.
32
+ # @param force [Boolean] Whether to overwrite target document in Occson, if any. Default `false`.
33
+ def upload(content, force: false)
34
+ Uploader.new(@uri, content, @access_token, @passphrase, force: force).call
13
35
  end
14
36
 
37
+ # Downloads the encrypted document at `@uri` and returns the plaintext
38
+ # contents (given that `@passphrase` matches).
39
+ #
40
+ # @example
41
+ # plaintext = document.download
42
+ #
43
+ # @return [String] Decrypted document contents
15
44
  def download
16
45
  Downloader.new(@uri, @access_token, @passphrase).call
17
46
  end
@@ -1,13 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # Downloads and decrypts the document at given URI with given access token.
5
+ # Decryption occurs using given passphrase.
4
6
  class Downloader
7
+ # Constructs a Downloader instance from a given URI, access token and passphrase.
8
+ #
9
+ # @example
10
+ # uri = 'ccs://path/to/file.yml'
11
+ # access_token = 'f30b5450421362c9ca0b'
12
+ # passphrase = 'my document passphrase'
13
+ #
14
+ # Ccs::Downloader.new(uri, access_token, passphrase)
15
+ #
16
+ # @param uri [String] Document URI. Accepts `ccs://` as shorthand for Occson location.
17
+ # @param access_token [String] Occson access token.
18
+ # @param passphrase [String] Document passphrase, used in encryption and decryption.
5
19
  def initialize(uri, access_token, passphrase)
6
20
  @uri = uri
7
21
  @access_token = access_token
8
22
  @passphrase = passphrase
9
23
  end
10
24
 
25
+ # Performs the download and decryption of document.
26
+ #
27
+ # @return [String|nil] Decrypted body of the document or `nil` in case the
28
+ # server did not respond with a `200` HTTP code.
11
29
  def call
12
30
  response = http.request(request)
13
31
  body = response.body
@@ -1,13 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # Encrypts the given content for transmission. Uses AES-256 in CBC
5
+ # mode internally, with salting.
4
6
  class Encrypter
7
+ # Constructs an Encrypter instance with given passphrase, content and salt.
8
+ # Salt _must_ be exactly 8 characters long.
9
+ #
10
+ # @example
11
+ # passphrase = 'my long document passphrase'
12
+ # content = 'very secret content'
13
+ # salt = '12345678'
14
+ #
15
+ # Ccs::Encrypter.new(passphrase, content, salt)
16
+ #
17
+ # @param passphrase [String] Document passphrase.
18
+ # @param content [String] Plaintext content to be encrypted.
19
+ # @param salt [String] Salt to reinforce the encryption, included in
20
+ # plaintext in the encrypted document.
5
21
  def initialize(passphrase, content, salt)
6
22
  @passphrase = passphrase
7
23
  @content = content
8
24
  @salt = salt
9
25
  end
10
26
 
27
+ # Performs the actual encryption, returning base64-encoded ciphertext.
28
+ #
29
+ # @return [String] base64-encoded ciphertext
11
30
  def call
12
31
  encryptor.pkcs5_keyivgen(@passphrase, @salt, 1)
13
32
  encrypted = encryptor.update(@content)
@@ -1,17 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
+ # Encrypts and uploads the document to Occson.
4
5
  class Uploader
5
- def initialize(uri, content, access_token, passphrase)
6
+ # Constructs an Uploader instance from a given URI, content, access token and passphrase.
7
+ #
8
+ # @example
9
+ # uri = 'ccs://path/to/file.yml'
10
+ # content = 'my very secret message'
11
+ # access_token = 'f30b5450421362c9ca0b'
12
+ # passphrase = 'my document passphrase'
13
+ #
14
+ # Ccs::Uploader.new(uri, access_token, passphrase)
15
+ #
16
+ # @param uri [String] Document URI. Accepts `ccs://` as shorthand for Occson location.
17
+ # @param content [String] Plaintext for encryption and upload.
18
+ # @param access_token [String] Occson access token.
19
+ # @param passphrase [String] Document passphrase, used in encryption and decryption.
20
+ # @param force [Boolean] Whether to overwrite target document in Occson, if any. Default `false`.
21
+ def initialize(uri, content, access_token, passphrase, force: false)
6
22
  @uri = uri
7
23
  @content = content
8
24
  @access_token = access_token
9
25
  @passphrase = passphrase
26
+ @force = force.to_s
10
27
  end
11
28
 
29
+ # Performs the actual upload to server.
30
+ #
31
+ # @return [Boolean] `true` for a successful upload, `false` otherwise
12
32
  def call
13
- request.body = { encrypted_content: encrypted_content }.to_json
14
- http.request(request).code.eql? '201'
33
+ request.body = { encrypted_content: encrypted_content, force: @force }.to_json
34
+ %w[200 201].include?(http.request(request).code)
15
35
  end
16
36
 
17
37
  private
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ccs
4
- VERSION = '3.0.0'
4
+ # Ccs gem version definition
5
+ VERSION = '3.1.0'
5
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ccs
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tkowalewski
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-10-23 00:00:00.000000000 Z
12
+ date: 2020-11-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: inch