decidim-bulletin_board 0.14.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,14 +10,16 @@ Gem::Specification.new do |s|
10
10
 
11
11
  s.summary = ""
12
12
  s.description = ""
13
- s.homepage = "https://github.com"
13
+ s.homepage = "https://github.com/decidim/decidim-bulletin-board"
14
14
  s.license = "AGPL-3.0"
15
15
  s.required_ruby_version = Gem::Requirement.new(">= 2.6.6")
16
16
 
17
17
  # Specify which files should be added to the gem when it is released.
18
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
19
  s.files = Dir.chdir(File.expand_path(__dir__)) do
20
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ `git ls-files -z`
21
+ .split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
+ .concat(["app/assets/javascripts/decidim/bulletin_board/decidim-bulletin_board.js"])
21
23
  end
22
24
  s.bindir = "exe"
23
25
  s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -8,6 +8,7 @@ require "graphlient"
8
8
  require "wisper"
9
9
 
10
10
  require "decidim/bulletin_board/client"
11
+ require "decidim/bulletin_board/file_client"
11
12
  require "decidim/bulletin_board/engine"
12
13
  require "decidim/bulletin_board/jwk_utils"
13
14
  require "decidim/bulletin_board/message_identifier"
@@ -52,10 +52,11 @@ module Decidim
52
52
  trustees: trustees,
53
53
  description: {
54
54
  name: text(election_data[:title]),
55
- start_date: election_data[:start_date].iso8601,
56
- end_date: election_data[:end_date].iso8601,
55
+ start_date: election_data[:start_date].strftime("%FT%T%:z"),
56
+ end_date: election_data[:end_date].strftime("%FT%T%:z"),
57
57
  candidates: candidates,
58
- contests: contests
58
+ contests: contests,
59
+ ballot_styles: ballot_styles
59
60
  }
60
61
  }
61
62
  end
@@ -69,16 +70,16 @@ module Decidim
69
70
 
70
71
  def bulletin_board
71
72
  {
72
- name: "bulletin-board",
73
- pretty_name: "Bulletin Board",
73
+ slug: "bulletin-board",
74
+ name: "Bulletin Board",
74
75
  public_key: settings.bulletin_board_public_key
75
76
  }
76
77
  end
77
78
 
78
79
  def authority
79
80
  {
80
- name: settings.authority_slug,
81
- pretty_name: settings.authority_name,
81
+ slug: settings.authority_slug,
82
+ name: settings.authority_name,
82
83
  public_key: settings.authority_public_key
83
84
  }
84
85
  end
@@ -86,8 +87,8 @@ module Decidim
86
87
  def trustees
87
88
  election_data[:trustees].map do |trustee|
88
89
  {
89
- name: trustee[:slug],
90
- pretty_name: trustee[:name],
90
+ slug: trustee[:name].parameterize,
91
+ name: trustee[:name],
91
92
  public_key: trustee[:public_key]
92
93
  }
93
94
  end
@@ -101,7 +102,7 @@ module Decidim
101
102
  sequence_order: index,
102
103
  vote_variation: question[:max_selections] == 1 ? "one_of_m" : "n_of_m",
103
104
  name: default_text(question[:title]),
104
- number_elected: question[:answers].count,
105
+ number_elected: question[:max_selections],
105
106
  ballot_title: text(question[:title]),
106
107
  ballot_subtitle: text(question[:description]),
107
108
  ballot_selections: contest_answers(question)
@@ -128,6 +129,15 @@ module Decidim
128
129
  end
129
130
  end
130
131
 
132
+ def ballot_styles
133
+ election_data[:ballot_styles].map do |ballot_style_id, question_ids|
134
+ {
135
+ object_id: ballot_style_id.to_s,
136
+ contests: question_ids
137
+ }
138
+ end
139
+ end
140
+
131
141
  def default_text(field)
132
142
  field[default_locale]
133
143
  end
@@ -33,7 +33,7 @@ module Decidim
33
33
  response = graphql.query do
34
34
  mutation do
35
35
  publishResults(messageId: args[:message_id], signedData: args[:signed_data]) do
36
- election do
36
+ pendingMessage do
37
37
  status
38
38
  end
39
39
  error
@@ -43,7 +43,7 @@ module Decidim
43
43
 
44
44
  return broadcast(:error, response.data.publish_results.error) if response.data.publish_results.error.present?
45
45
 
46
- broadcast(:ok, response.data.publish_results.election)
46
+ broadcast(:ok, response.data.publish_results.pending_message)
47
47
  rescue Graphlient::Errors::ServerError
48
48
  broadcast(:error, "Sorry, something went wrong")
49
49
  end
@@ -14,6 +14,7 @@ require "decidim/bulletin_board/authority/publish_results"
14
14
  require "decidim/bulletin_board/authority/get_election_results"
15
15
  require "decidim/bulletin_board/voter/cast_vote"
16
16
  require "decidim/bulletin_board/voter/get_pending_message_status"
17
+ require "decidim/bulletin_board/test/reset_test_database"
17
18
 
18
19
  module Decidim
19
20
  module BulletinBoard
@@ -101,11 +102,20 @@ module Decidim
101
102
  def publish_results(election_id)
102
103
  publish_results = configure Authority::PublishResults.new(election_id)
103
104
  yield publish_results.message_id if block_given?
104
- publish_results.on(:ok) { |status| return status }
105
+ publish_results.on(:ok) { |pending_message| return pending_message }
105
106
  publish_results.on(:error) { |error_message| raise StandardError, error_message }
106
107
  publish_results.call
107
108
  end
108
109
 
110
+ if Rails.env.test?
111
+ def reset_test_database
112
+ reset_test_database = configure Test::ResetTestDatabase.new
113
+ reset_test_database.on(:ok) { |result| return result }
114
+ reset_test_database.on(:error) { |error_message| raise StandardError, error_message }
115
+ reset_test_database.call
116
+ end
117
+ end
118
+
109
119
  private
110
120
 
111
121
  attr_reader :settings, :graphql
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module BulletinBoard
5
+ # Client to store GraphQL requests to a CSV file instead of sending them to the BulletinBoard
6
+ # It is intended to be used for load testing
7
+ class FileClient < Decidim::BulletinBoard::Client
8
+ def initialize(file_path, config = Decidim::BulletinBoard)
9
+ @settings = Settings.new(config)
10
+ @graphql = Graphql::Factory.client_for_file(settings, file_path)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -310,6 +310,34 @@
310
310
  },
311
311
  "isDeprecated": false,
312
312
  "deprecationReason": null
313
+ },
314
+ {
315
+ "name": "verifiableResultsHash",
316
+ "description": null,
317
+ "args": [
318
+
319
+ ],
320
+ "type": {
321
+ "kind": "SCALAR",
322
+ "name": "String",
323
+ "ofType": null
324
+ },
325
+ "isDeprecated": false,
326
+ "deprecationReason": null
327
+ },
328
+ {
329
+ "name": "verifiableResultsUrl",
330
+ "description": null,
331
+ "args": [
332
+
333
+ ],
334
+ "type": {
335
+ "kind": "SCALAR",
336
+ "name": "String",
337
+ "ofType": null
338
+ },
339
+ "isDeprecated": false,
340
+ "deprecationReason": null
313
341
  }
314
342
  ],
315
343
  "inputFields": null,
@@ -370,6 +398,16 @@
370
398
  "enumValues": null,
371
399
  "possibleTypes": null
372
400
  },
401
+ {
402
+ "kind": "SCALAR",
403
+ "name": "Int",
404
+ "description": "Represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.",
405
+ "fields": null,
406
+ "inputFields": null,
407
+ "interfaces": null,
408
+ "enumValues": null,
409
+ "possibleTypes": null
410
+ },
373
411
  {
374
412
  "kind": "SCALAR",
375
413
  "name": "JSON",
@@ -847,6 +885,20 @@
847
885
  "isDeprecated": false,
848
886
  "deprecationReason": null
849
887
  },
888
+ {
889
+ "name": "resetTestDatabase",
890
+ "description": null,
891
+ "args": [
892
+
893
+ ],
894
+ "type": {
895
+ "kind": "OBJECT",
896
+ "name": "ResetTestDatabaseMutationPayload",
897
+ "ofType": null
898
+ },
899
+ "isDeprecated": false,
900
+ "deprecationReason": null
901
+ },
850
902
  {
851
903
  "name": "startKeyCeremony",
852
904
  "description": null,
@@ -1228,28 +1280,28 @@
1228
1280
  "description": "Autogenerated return type of PublishResultsMutation",
1229
1281
  "fields": [
1230
1282
  {
1231
- "name": "election",
1283
+ "name": "error",
1232
1284
  "description": null,
1233
1285
  "args": [
1234
1286
 
1235
1287
  ],
1236
1288
  "type": {
1237
- "kind": "OBJECT",
1238
- "name": "Election",
1289
+ "kind": "SCALAR",
1290
+ "name": "String",
1239
1291
  "ofType": null
1240
1292
  },
1241
1293
  "isDeprecated": false,
1242
1294
  "deprecationReason": null
1243
1295
  },
1244
1296
  {
1245
- "name": "error",
1297
+ "name": "pendingMessage",
1246
1298
  "description": null,
1247
1299
  "args": [
1248
1300
 
1249
1301
  ],
1250
1302
  "type": {
1251
- "kind": "SCALAR",
1252
- "name": "String",
1303
+ "kind": "OBJECT",
1304
+ "name": "PendingMessage",
1253
1305
  "ofType": null
1254
1306
  },
1255
1307
  "isDeprecated": false,
@@ -1447,6 +1499,37 @@
1447
1499
  "enumValues": null,
1448
1500
  "possibleTypes": null
1449
1501
  },
1502
+ {
1503
+ "kind": "OBJECT",
1504
+ "name": "ResetTestDatabaseMutationPayload",
1505
+ "description": "Autogenerated return type of ResetTestDatabaseMutation",
1506
+ "fields": [
1507
+ {
1508
+ "name": "timestamp",
1509
+ "description": null,
1510
+ "args": [
1511
+
1512
+ ],
1513
+ "type": {
1514
+ "kind": "NON_NULL",
1515
+ "name": null,
1516
+ "ofType": {
1517
+ "kind": "SCALAR",
1518
+ "name": "Int",
1519
+ "ofType": null
1520
+ }
1521
+ },
1522
+ "isDeprecated": false,
1523
+ "deprecationReason": null
1524
+ }
1525
+ ],
1526
+ "inputFields": null,
1527
+ "interfaces": [
1528
+
1529
+ ],
1530
+ "enumValues": null,
1531
+ "possibleTypes": null
1532
+ },
1450
1533
  {
1451
1534
  "kind": "OBJECT",
1452
1535
  "name": "StartKeyCeremonyMutationPayload",
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "decidim/bulletin_board/graphql/file_adapter"
4
+
3
5
  module Decidim
4
6
  module BulletinBoard
5
7
  module Graphql
@@ -12,6 +14,15 @@ module Decidim
12
14
  "Authorization" => settings.authority_api_key
13
15
  })
14
16
  end
17
+
18
+ def self.client_for_file(settings, file_path)
19
+ Graphlient::Client.new(file_path,
20
+ schema_path: File.join(__dir__, "bb_schema.json"),
21
+ http: FileAdapter,
22
+ headers: {
23
+ "Authorization" => settings.authority_api_key
24
+ })
25
+ end
15
26
  end
16
27
  end
17
28
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module Decidim
6
+ module BulletinBoard
7
+ module Graphql
8
+ class FileAdapter
9
+ attr_reader :file_name
10
+
11
+ def initialize(file_name, _options = {}, &_block)
12
+ @file_name = file_name
13
+ end
14
+
15
+ def execute(document:, operation_name: nil, variables: {}, context: {})
16
+ body = {}
17
+ body["query"] = document.to_query_string
18
+ body["variables"] = variables if variables.any?
19
+ body["operationName"] = operation_name if operation_name
20
+
21
+ CSV.open(file_name, "a+", col_sep: ";") do |csv|
22
+ csv << [JSON.generate(body), context[:headers]["Authorization"]]
23
+ end
24
+
25
+ { "data" => { "vote" => {} } }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -60,6 +60,10 @@ module Decidim
60
60
  @message_id
61
61
  end
62
62
 
63
+ def unique_trustee_id(authority_slug, trustee_name)
64
+ "#{authority_slug}.#{trustee_name}"
65
+ end
66
+
63
67
  class << self
64
68
  def format(unique_election_id, type_subtype, author_type, author_id)
65
69
  "#{unique_election_id}.#{type_subtype}+#{INVERTED_AUTHOR_TYPE[author_type]}.#{author_id}"
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module BulletinBoard
5
+ module Test
6
+ # This command uses the GraphQL client to clear the database in test mode.
7
+ class ResetTestDatabase < Decidim::BulletinBoard::Command
8
+ # Executes the command. Broadcasts these events:
9
+ #
10
+ # - :ok when everything is valid and the mutation operation is successful.
11
+ # - :error if query operation was not successful.
12
+ #
13
+ # Returns nothing.
14
+ def call
15
+ graphql.query do
16
+ mutation do
17
+ resetTestDatabase do
18
+ timestamp
19
+ end
20
+ end
21
+ end
22
+
23
+ broadcast(:ok)
24
+ rescue Graphlient::Errors::ServerError
25
+ broadcast(:error, "Sorry, something went wrong")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Decidim
4
4
  module BulletinBoard
5
- VERSION = "0.14.0"
5
+ VERSION = "0.17.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-bulletin_board
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Morcillo
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2021-02-25 00:00:00.000000000 Z
14
+ date: 2021-04-12 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -154,8 +154,6 @@ files:
154
154
  - ".rubocop.yml"
155
155
  - ".ruby-version"
156
156
  - ".travis.yml"
157
- - CHANGELOG.md
158
- - CODE_OF_CONDUCT.md
159
157
  - Gemfile
160
158
  - Gemfile.lock
161
159
  - README.md
@@ -163,7 +161,6 @@ files:
163
161
  - app/assets/config/manifest.js
164
162
  - app/assets/javascripts/decidim/bulletin_board/decidim-bulletin_board.js
165
163
  - bin/console
166
- - bin/release
167
164
  - bin/setup
168
165
  - decidim-bulletin_board.gemspec
169
166
  - lib/decidim/bulletin_board.rb
@@ -178,15 +175,18 @@ files:
178
175
  - lib/decidim/bulletin_board/client.rb
179
176
  - lib/decidim/bulletin_board/command.rb
180
177
  - lib/decidim/bulletin_board/engine.rb
178
+ - lib/decidim/bulletin_board/file_client.rb
181
179
  - lib/decidim/bulletin_board/graphql/bb_schema.json
182
180
  - lib/decidim/bulletin_board/graphql/factory.rb
181
+ - lib/decidim/bulletin_board/graphql/file_adapter.rb
183
182
  - lib/decidim/bulletin_board/jwk_utils.rb
184
183
  - lib/decidim/bulletin_board/message_identifier.rb
185
184
  - lib/decidim/bulletin_board/settings.rb
185
+ - lib/decidim/bulletin_board/test/reset_test_database.rb
186
186
  - lib/decidim/bulletin_board/version.rb
187
187
  - lib/decidim/bulletin_board/voter/cast_vote.rb
188
188
  - lib/decidim/bulletin_board/voter/get_pending_message_status.rb
189
- homepage: https://github.com
189
+ homepage: https://github.com/decidim/decidim-bulletin-board
190
190
  licenses:
191
191
  - AGPL-3.0
192
192
  metadata: {}