diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index 916eb55..8409009 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -1,5 +1,5 @@ class MainController < ApplicationController - before_action :set_user_room, only: [:join, :users, :stream] + before_action :set_user_room, only: [:join, :users, :stream, :stemmen] def index end @@ -32,10 +32,19 @@ class MainController < ApplicationController end end + def stemmen + @votes = Vote.where(room_id: @room.id, user_id: @user.id).order(created_at: :desc) + render :votes + end + private def set_user_room @user = User.find_by token: params[:token] - @room = Room.find(@user.room_id) + if @user.nil? + redirect_to 'https://bij1.org/', status: :unauthorized + else + @room = Room.find(@user.room_id) + end end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 47a43fe..b937c1f 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -130,6 +130,9 @@ class UsersController < ApplicationController # DELETE /users/1 # DELETE /users/1.json def destroy + Vote.where(user_id: @user.id).each do |vote| + vote.destroy + end @user.destroy respond_to do |format| format.html { redirect_to room_users_url(@user.room_id), notice: 'User was successfully destroyed.' } @@ -141,6 +144,9 @@ class UsersController < ApplicationController # DELETE /rooms/1/users.json def destroy_all @users.each do |user| + Vote.where(user_id: user.id).each do |vote| + vote.destroy + end user.destroy end respond_to do |format| @@ -162,11 +168,12 @@ class UsersController < ApplicationController require 'csv' - CSV.parse(users_csv, :headers => true) do |row| + users = CSV.parse(users_csv, :headers => true).map { |row| fields = row.to_hash fields[:room_id] = room_id - User.create!(fields) - end + fields + } + User.upsert_all(users, unique_by: [:room_id, :email]) respond_to do |format| format.html { redirect_to room_users_url(room_id), notice: 'Users were successfully created.' } diff --git a/app/controllers/votes_controller.rb b/app/controllers/votes_controller.rb new file mode 100644 index 0000000..ef34536 --- /dev/null +++ b/app/controllers/votes_controller.rb @@ -0,0 +1,81 @@ +class VotesController < ApplicationController + http_basic_authenticate_with name: Rails.application.config.admin_name, + password: Rails.application.config.admin_password + + before_action :set_room, only: [:index, :bulk, :destroy_for_room] + before_action :set_votes, only: [:index, :bulk, :destroy_for_room] + + # GET /rooms/:room_id/votes + # GET /rooms/:room_id/votes.json + def index + respond_to do |format| + format.html { render :index } + # let's protect voter credentials + format.json { render json: [], status: :unauthorized } + end + end + + # GET /rooms/:room_id/votes/bulk + def bulk + @sample = "info@bij1.org,mijn-stemming,1,abcdABCD1234" + end + + # POST /rooms/:room_id/votes/bulk + # POST /rooms/:room_id/votes/bulk.json + def create_bulk + room_id = params[:room_id] + votes_csv = params[:votes_csv] + + require 'csv' + + headers = %i[ + voter_email + short_name + voter_login_id + voter_password + ] + votes = CSV.parse(votes_csv, headers: headers).map { |row| + csv_fields = row.to_hash + email = csv_fields[:voter_email] + user = User.find_by(room_id: room_id, email: email) + { + :room_id => room_id, + :user_id => user.id, + :election_slug => csv_fields[:short_name], + :voter_login_id => csv_fields[:voter_login_id], + :voter_password => csv_fields[:voter_password], + } + } + Vote.upsert_all(votes, unique_by: [:user_id, :election_slug]) + + respond_to do |format| + format.html { redirect_to room_users_url(room_id), notice: 'Votes were successfully created.' } + format.json { render :show, status: :created, location: @room } + end + end + + # DELETE /rooms/:room_id/votes + # DELETE /rooms/:room_id/votes.json + def destroy_for_room + @votes.each do |vote| + vote.destroy + end + + respond_to do |format| + format.html { redirect_to room_users_url(@room.id), notice: 'Votes were successfully destroyed.' } + format.json { render :show, status: :created, location: @room } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + + def set_room + @room = Room.find(params[:room_id]) + end + + def set_votes + @votes = Vote.where(room_id: @room.id) + end + +end diff --git a/app/models/user.rb b/app/models/user.rb index 47e474e..a95f14f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -6,4 +6,7 @@ class User < ApplicationRecord attribute :invited, :boolean, default: false attribute :vote, :boolean, default: true attribute :proxy, :boolean, default: false + + validates :email, uniqueness: { scope: :room_id } + validates :room_id, uniqueness: { scope: :email } end diff --git a/app/models/vote.rb b/app/models/vote.rb new file mode 100644 index 0000000..bafd553 --- /dev/null +++ b/app/models/vote.rb @@ -0,0 +1,6 @@ +class Vote < ApplicationRecord + belongs_to :user + + validates :election_slug, uniqueness: { scope: :user_id } + validates :user_id, uniqueness: { scope: :election_slug } +end diff --git a/app/views/main/votes.html.erb b/app/views/main/votes.html.erb new file mode 100644 index 0000000..fdd44c3 --- /dev/null +++ b/app/views/main/votes.html.erb @@ -0,0 +1,18 @@ +
<%= notice %>
+ +
-csv formaat voor bulk import: email,name,moderator,vote,proxy,invited,presence. kolom volgorde maakt niet uit. komma-separated met header.
+csv formaat voor bulk import: email,name,moderator,vote,proxy,invited,presence
. kolom volgorde maakt niet uit. komma-separated met header.
<% if false %>
download een sample <%= link_to "hier", "/bbb.csv" %>.
<% end %>
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb
index 280828e..44a8eab 100644
--- a/app/views/users/index.html.erb
+++ b/app/views/users/index.html.erb
@@ -50,4 +50,6 @@
<%= link_to 'Present Users', room_present_users_path(id: params[:room_id], v: 1) %> |
<%= link_to 'Absent Users', room_present_users_path(id: params[:room_id], v: 0) %> |
<%= link_to 'Destroy all', destroy_room_users_path(params[:room_id]), method: :delete %> |
+<%= link_to 'Import Votes', bulk_new_room_votes_path(params[:room_id]), method: :get %> |
+<%= link_to 'Destroy Votes', room_votes_path(params[:room_id]), method: :delete %> |
<%= link_to 'Back', room_path(params[:room_id]) %>
diff --git a/app/views/votes/bulk.html.erb b/app/views/votes/bulk.html.erb
new file mode 100644
index 0000000..17f7718
--- /dev/null
+++ b/app/views/votes/bulk.html.erb
@@ -0,0 +1,46 @@
+
+csv formaat voor bulk import, in die volgorde, komma-separated en zonder header: voter_email,short_name,voter_login_id,voter_password
+<% if false %>
+download een sample <%= link_to "hier", "/votes.csv" %>.
+<% end %>
+
voter_email
is het email adres van de stemmer, om de credentials terug te koppelen aan het juiste lid.short_name
is de naam van de stemmingvoter_login_id
is de login id van de stemmer in het stem systeemvoter_password
is het wachtwoord van de stemmer in het stem systeem+De gegevens hiervoor zijn te verkrijgen via commando, gegeven SSH toegang tot de database server: +
+ssh db.bij1.net "sudo psql -U postgres helios -c \"SELECT voter_email, short_name, voter_login_id, voter_password FROM helios_voter JOIN helios_election ON election_id = helios_election.id WHERE helios_election.uuid IN ('UUID1', 'UUID2', ...);\" -tAF,"
+
+... waar 'UUID1', 'UUID2', ...
vervangen dient te worden door de UUIDs van de stemmingen van deze kamer, in de URLs te vinden in Helios.
+
+Gebruikers vinden vervolgens hun stem links op de volgende URL, waar TOKEN
dient te worden vervangen door hun Ingang token:
+
https://vergadering.bij1.org/ingang/TOKEN/stemmen
+ <%= notice %>
+ +ID | +User ID | +Election Slug | +Login ID | +
---|---|---|---|
<%= vote.id %> | +<%= vote.user_id %> | +<%= vote.election_slug %> | +<%= vote.voter_login_id %> | +