decidim-bulletin_board 0.3.1 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 834f029e86c9fad845c573cc2c72e6294767de95193f985e7d6d79997e616b30
4
- data.tar.gz: 44c6711314e297ca4b876b6ef535f0443acfe66e1c5dfda93bc7307a1529dc69
3
+ metadata.gz: 14ab42b976ab2c16370b405c995cc97045680383a53b72005d8b2306b488a79b
4
+ data.tar.gz: 3dcad6e5e2a5b6a97bd430e31cba7b32b101533f418a709b3d010e43827be6f7
5
5
  SHA512:
6
- metadata.gz: 2ac8ef1bee39287b22c036c4f2abfd69c7e7922884295b44a87696be2be68e56e9392646774bcfe8f6ccf5b3c7fdcf0164a2f95499bdb7165598316b6b46d4cf
7
- data.tar.gz: ff16f63812d6cb53fbb2126ce2bbd9debf5aec15f8f5728d0ed74a7f715d1f657401a21011b198646c4e02e7988af22e56f61b3cc50d69fc6aa810661a145036
6
+ metadata.gz: 34ad882ded057af2c4935c10e1f3ef524bb0037627a22893a58b27c1ac29d1106b70626510cf6bb86bc4338bc7f8bc86860699b83def828e486f297d3e9b4561
7
+ data.tar.gz: 3cd06a69f5a15c24441c0ecdf257638acda1d17487a6a1835f47fc20a6e020951bb5ae40b146db83b495d59e05901a31483226b37f4fd902e86c4b70d872f598
@@ -5,7 +5,42 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.5.2] - 2020-12-20
9
+
10
+ ### Fixed
11
+
12
+ - Include the schema definition within the gem to avoid extra trips to the server
13
+
14
+ ## [0.5.1] - 2020-12-19
15
+
16
+ ### Fixed
17
+
18
+ - Include the missing `close_ballot_box` method from the 0.4.0 release.
19
+ - Fixes for the client methods
20
+
21
+ ## [0.5.0] - 2020-12-19
22
+
23
+ ### Changed
24
+
25
+ - Renamed `setup_election` to `create_election` and moved `election_id` from the `election_data` to a separate argument.
26
+
27
+ ### Fixed
28
+
29
+ - Include the missing `open_ballot_box` methods from the 0.4.0 release.
30
+ - Added missing namespace on the seed task
31
+
32
+ ## [0.4.0] - 2020-12-18
33
+
34
+ ### Added
35
+
36
+ - `content_hash` field for the `LogEntry` records with the hash of the `content` field, if included in the message.
37
+ - `Command` base class for all the classes representing GraphQL queries or mutations sent to the Bulletin Board.
38
+ - `open_ballot_box` and `close_ballot_box` methods to the `Decidim::BulletinBoard::Client`.
39
+
40
+ ### Changed
41
+
42
+ - New format for the messages: `iat`, `message_id` and Bulletin Board fields in the root message, and `content` for the Voting Scheme messages.
43
+ - Improved consistency between methods included by `Decidim::BulletinBoard::Client`.
9
44
 
10
45
  ## [0.3.1] - 2020-12-10
11
46
 
@@ -1,24 +1,25 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- decidim-bulletin_board (0.3.1)
5
- activemodel (~> 5.0, >= 5.0.0.1)
6
- activesupport (~> 5.0, >= 5.0.0.1)
4
+ decidim-bulletin_board (0.5.3)
5
+ activemodel (>= 5.0.0)
6
+ activesupport (>= 5.0.0)
7
7
  byebug (~> 11.0)
8
8
  graphlient (~> 0.4.0)
9
- jwt
9
+ jwt (~> 2.2.2)
10
10
  wisper (~> 2.0.0)
11
11
 
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
- activemodel (5.2.4.4)
16
- activesupport (= 5.2.4.4)
17
- activesupport (5.2.4.4)
15
+ activemodel (6.1.0)
16
+ activesupport (= 6.1.0)
17
+ activesupport (6.1.0)
18
18
  concurrent-ruby (~> 1.0, >= 1.0.2)
19
- i18n (>= 0.7, < 2)
20
- minitest (~> 5.1)
21
- tzinfo (~> 1.1)
19
+ i18n (>= 1.6, < 2)
20
+ minitest (>= 5.1)
21
+ tzinfo (~> 2.0)
22
+ zeitwerk (~> 2.3)
22
23
  addressable (2.7.0)
23
24
  public_suffix (>= 2.0.2, < 5.0)
24
25
  ast (2.4.1)
@@ -87,9 +88,8 @@ GEM
87
88
  rubocop-ast (>= 0.7.1)
88
89
  ruby-progressbar (1.10.1)
89
90
  ruby2_keywords (0.0.2)
90
- thread_safe (0.3.6)
91
- tzinfo (1.2.8)
92
- thread_safe (~> 0.1)
91
+ tzinfo (2.0.4)
92
+ concurrent-ruby (~> 1.0)
93
93
  unicode-display_width (1.7.0)
94
94
  webmock (3.10.0)
95
95
  addressable (>= 2.3.6)
@@ -97,9 +97,11 @@ GEM
97
97
  hashdiff (>= 0.4.0, < 2.0.0)
98
98
  wisper (2.0.1)
99
99
  wisper-rspec (1.1.0)
100
+ zeitwerk (2.4.2)
100
101
 
101
102
  PLATFORMS
102
103
  ruby
104
+ x86_64-linux
103
105
 
104
106
  DEPENDENCIES
105
107
  decidim-bulletin_board!
@@ -112,4 +114,4 @@ DEPENDENCIES
112
114
  wisper-rspec (~> 1.1.0)
113
115
 
114
116
  BUNDLED WITH
115
- 2.1.4
117
+ 2.2.0
@@ -23,11 +23,11 @@ Gem::Specification.new do |s|
23
23
  s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  s.require_paths = ["lib"]
25
25
 
26
- s.add_dependency "activemodel", "~> 5.0", ">= 5.0.0.1"
27
- s.add_dependency "activesupport", "~> 5.0", ">= 5.0.0.1"
26
+ s.add_dependency "activemodel", ">= 5.0.0"
27
+ s.add_dependency "activesupport", ">= 5.0.0"
28
28
  s.add_dependency "byebug", "~> 11.0"
29
29
  s.add_dependency "graphlient", "~> 0.4.0"
30
- s.add_dependency "jwt"
30
+ s.add_dependency "jwt", "~> 2.2.2"
31
31
  s.add_dependency "wisper", "~> 2.0.0"
32
32
 
33
33
  s.add_development_dependency "rake", "~> 13.0"
@@ -1,17 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_model"
4
+ require "active_support/configurable"
3
5
  require "decidim/bulletin_board/version"
6
+ require "jwt"
4
7
  require "graphlient"
5
8
  require "wisper"
6
- require "active_model"
9
+
7
10
  require "decidim/bulletin_board/jwk_utils"
11
+ require "decidim/bulletin_board/message_identifier"
12
+
8
13
  require "decidim/bulletin_board/client"
9
- require "decidim/bulletin_board/graphql/client"
10
- require "decidim/bulletin_board/create_election"
14
+ require "decidim/bulletin_board/authority"
11
15
  require "decidim/bulletin_board/voter"
12
- require "decidim/bulletin_board/authority/get_election_status"
13
- require "active_support/configurable"
14
- require "jwt"
15
16
 
16
17
  module Decidim
17
18
  # This module holds all the logic for the Bulletin Board Ruby Client to connect
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/bulletin_board/authority/create_election"
4
+ require "decidim/bulletin_board/authority/get_election_status"
5
+ require "decidim/bulletin_board/authority/open_ballot_box"
6
+ require "decidim/bulletin_board/authority/close_ballot_box"
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module BulletinBoard
5
+ module Authority
6
+ # This command uses the GraphQL client to request the closing of the ballot box.
7
+ class CloseBallotBox < Decidim::BulletinBoard::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # election_id - The local election identifier
11
+ def initialize(election_id)
12
+ @election_id = election_id
13
+ end
14
+
15
+ # Executes the command. Broadcasts these events:
16
+ #
17
+ # - :ok when everything is valid and the query operation is successful.
18
+ # - :error if query operation was not successful.
19
+ #
20
+ # Returns nothing.
21
+ def call
22
+ message_id = message_id(unique_election_id(election_id), "close_ballot_box")
23
+ signed_data = sign_message(message_id, {})
24
+
25
+ begin
26
+ response = client.query do
27
+ mutation do
28
+ closeBallotBox(messageId: message_id, signedData: signed_data) do
29
+ election do
30
+ status
31
+ end
32
+ error
33
+ end
34
+ end
35
+ end
36
+
37
+ return broadcast(:error, response.data.close_ballot_box.error) if response.data.close_ballot_box.error.present?
38
+
39
+ broadcast(:ok, response.data.close_ballot_box.election)
40
+ rescue Graphlient::Errors::ServerError
41
+ broadcast(:error, "Sorry, something went wrong")
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :election_id
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module BulletinBoard
5
+ module Authority
6
+ # This class handles the creation of an election.
7
+ class CreateElection < Decidim::BulletinBoard::Command
8
+ def initialize(election_id, election_data)
9
+ @election_id = election_id
10
+ @election_data = election_data
11
+ end
12
+
13
+ def call
14
+ message_id = message_id(unique_election_id(election_id), "create_election")
15
+ signed_data = sign_message(message_id, election_data)
16
+
17
+ begin
18
+ response = client.query do
19
+ mutation do
20
+ createElection(messageId: message_id, signedData: signed_data) do
21
+ election do
22
+ status
23
+ end
24
+ error
25
+ end
26
+ end
27
+ end
28
+
29
+ return broadcast(:error, response.data.create_election.error) if response.data.create_election.error.present?
30
+
31
+ broadcast(:ok, response.data.create_election.election)
32
+ rescue Graphlient::Errors::ServerError
33
+ broadcast(:error, "Sorry, something went wrong")
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :election_data, :election_id
40
+ end
41
+ end
42
+ end
43
+ end
@@ -4,11 +4,10 @@ module Decidim
4
4
  module BulletinBoard
5
5
  module Authority
6
6
  # This command uses the GraphQL client to get the status of the election.
7
- class GetElectionStatus
8
- include Wisper::Publisher
7
+ class GetElectionStatus < Decidim::BulletinBoard::Command
9
8
  # Public: Initializes the command.
10
9
  #
11
- # election - The election to receive the status from.
10
+ # election_id - The local election identifier
12
11
  def initialize(election_id)
13
12
  @election_id = election_id
14
13
  end
@@ -20,14 +19,12 @@ module Decidim
20
19
  #
21
20
  # Returns nothing.
22
21
  def call
23
- args = {
24
- unique_id: election_id
25
- }
22
+ unique_id = unique_election_id(election_id)
26
23
 
27
24
  begin
28
25
  response = client.query do
29
26
  query do
30
- election(uniqueId: args[:unique_id]) do
27
+ election(uniqueId: unique_id) do
31
28
  status
32
29
  end
33
30
  end
@@ -42,10 +39,6 @@ module Decidim
42
39
  private
43
40
 
44
41
  attr_reader :election_id
45
-
46
- def client
47
- @client ||= BulletinBoard::Graphql::Client.client
48
- end
49
42
  end
50
43
  end
51
44
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module BulletinBoard
5
+ module Authority
6
+ # This command uses the GraphQL client to request the opening of the ballot box.
7
+ class OpenBallotBox < Decidim::BulletinBoard::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # election_id - The local election identifier
11
+ def initialize(election_id)
12
+ @election_id = election_id
13
+ end
14
+
15
+ # Executes the command. Broadcasts these events:
16
+ #
17
+ # - :ok when everything is valid and the query operation is successful.
18
+ # - :error if query operation was not successful.
19
+ #
20
+ # Returns nothing.
21
+ def call
22
+ message_id = message_id(unique_election_id(election_id), "open_ballot_box")
23
+ signed_data = sign_message(message_id, {})
24
+
25
+ begin
26
+ response = client.query do
27
+ mutation do
28
+ openBallotBox(messageId: message_id, signedData: signed_data) do
29
+ election do
30
+ status
31
+ end
32
+ error
33
+ end
34
+ end
35
+ end
36
+
37
+ return broadcast(:error, response.data.open_ballot_box.error) if response.data.open_ballot_box.error.present?
38
+
39
+ broadcast(:ok, response.data.open_ballot_box.election)
40
+ rescue Graphlient::Errors::ServerError
41
+ broadcast(:error, "Sorry, something went wrong")
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :election_id
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "decidim/bulletin_board/command"
4
+
3
5
  module Decidim
4
6
  module BulletinBoard
5
7
  # The Bulletin Board client
@@ -34,26 +36,36 @@ module Decidim
34
36
  private_key && server && api_key
35
37
  end
36
38
 
37
- def sign_data(data)
38
- JWT.encode(data, private_key.keypair, "RS256")
39
+ def create_election(election_id, election_data)
40
+ create_election = Decidim::BulletinBoard::Authority::CreateElection.new(election_id, election_data)
41
+ create_election.on(:ok) { |election| return election }
42
+ create_election.on(:error) { |error_message| raise StandardError, error_message }
43
+ create_election.call
44
+ end
45
+
46
+ def open_ballot_box(election_id)
47
+ open_ballot_box = Decidim::BulletinBoard::Authority::OpenBallotBox.new(election_id)
48
+ open_ballot_box.on(:ok) { |election| return election }
49
+ open_ballot_box.on(:error) { |error_message| raise StandardError, error_message }
50
+ open_ballot_box.call
39
51
  end
40
52
 
41
- def setup_election(election_data)
42
- message_id = "#{election_data[:election_id]}.create_election+a.#{authority_slug}"
43
- Decidim::BulletinBoard::CreateElection.call(election_data, message_id)
53
+ def close_ballot_box(election_id)
54
+ close_ballot_box = Decidim::BulletinBoard::Authority::CloseBallotBox.new(election_id)
55
+ close_ballot_box.on(:ok) { |election| return election }
56
+ close_ballot_box.on(:error) { |error_message| raise StandardError, error_message }
57
+ close_ballot_box.call
44
58
  end
45
59
 
46
- def cast_vote(election_data, voter_data, encrypted_vote)
47
- form = Decidim::BulletinBoard::Voter::VoteForm.new(self, election_data, voter_data, encrypted_vote)
48
- cast_vote = Decidim::BulletinBoard::Voter::CastVote.new(form)
60
+ def cast_vote(election_id, voter_id, encrypted_vote)
61
+ cast_vote = Decidim::BulletinBoard::Voter::CastVote.new(election_id, voter_id, encrypted_vote)
49
62
  cast_vote.on(:ok) { |pending_message| return pending_message }
50
63
  cast_vote.on(:error) { |error_message| raise StandardError, error_message }
51
64
  cast_vote.call
52
65
  end
53
66
 
54
67
  def get_status(election_id)
55
- unique_election_id = "#{authority_slug}.#{election_id}"
56
- get_status = Decidim::BulletinBoard::Authority::GetElectionStatus.new(unique_election_id)
68
+ get_status = Decidim::BulletinBoard::Authority::GetElectionStatus.new(election_id)
57
69
  get_status.on(:ok) { |status| return status }
58
70
  get_status.on(:error) { |error_message| raise StandardError, error_message }
59
71
  get_status.call
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/bulletin_board/graphql/client"
4
+
5
+ module Decidim
6
+ module BulletinBoard
7
+ # The base class for all commands.
8
+ class Command
9
+ include Wisper::Publisher
10
+
11
+ delegate :authority_slug, :private_key, to: :class
12
+
13
+ def unique_election_id(election_id)
14
+ Decidim::BulletinBoard::MessageIdentifier.unique_election_id(authority_slug, election_id)
15
+ end
16
+
17
+ def message_id(unique_election_id, type_subtype, voter_id = nil)
18
+ Decidim::BulletinBoard::MessageIdentifier.format(unique_election_id, type_subtype, voter_id ? :voter : :authority, voter_id || authority_slug)
19
+ end
20
+
21
+ def sign_message(message_id, message)
22
+ JWT.encode(complete_message(message_id, message), private_key.keypair, "RS256")
23
+ end
24
+
25
+ def client
26
+ @client ||= BulletinBoard::Graphql::Client.client
27
+ end
28
+
29
+ def complete_message(message_id, message)
30
+ message.merge({
31
+ iat: Time.now.to_i,
32
+ message_id: message_id
33
+ })
34
+ end
35
+
36
+ class << self
37
+ def self.call(*args)
38
+ new(*args).call
39
+ end
40
+
41
+ def private_key
42
+ @private_key ||= JwkUtils.import_private_key(BulletinBoard.identification_private_key)
43
+ end
44
+
45
+ def authority_slug
46
+ @authority_slug ||= BulletinBoard.authority_name.parameterize
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end