parent
84278741a5
commit
fa4f77c365
14 changed files with 222 additions and 32 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,3 +3,4 @@ locale
|
|||
*.swp
|
||||
db/*.sqlite3
|
||||
db/*.sqlite3-*
|
||||
config/environments/development.rb
|
||||
|
|
|
|||
1
Gemfile
1
Gemfile
|
|
@ -11,3 +11,4 @@ gem 'forwardable', '1.3.2'
|
|||
gem 'bcrypt'
|
||||
gem 'gettext'
|
||||
gem 'chartkick'
|
||||
gem 'mail'
|
||||
|
|
|
|||
19
Gemfile.lock
19
Gemfile.lock
|
|
@ -26,6 +26,7 @@ GEM
|
|||
chartkick (5.1.4)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.0)
|
||||
date (3.4.1)
|
||||
drb (2.2.1)
|
||||
erubi (1.13.1)
|
||||
forwardable (1.3.2)
|
||||
|
|
@ -39,10 +40,25 @@ GEM
|
|||
concurrent-ruby (~> 1.0)
|
||||
locale (2.1.4)
|
||||
logger (1.6.6)
|
||||
mail (2.8.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.8)
|
||||
minitest (5.25.5)
|
||||
mustermann (3.0.3)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
net-imap (0.5.8)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.2)
|
||||
timeout
|
||||
net-smtp (0.5.1)
|
||||
net-protocol
|
||||
nio4r (2.7.4)
|
||||
prime (0.1.3)
|
||||
forwardable
|
||||
|
|
@ -76,8 +92,6 @@ GEM
|
|||
singleton (0.3.0)
|
||||
sqlite3 (2.6.0)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
sqlite3 (2.6.0-arm64-darwin)
|
||||
sqlite3 (2.6.0-x86_64-darwin)
|
||||
text (1.3.1)
|
||||
tilt (2.6.0)
|
||||
timeout (0.4.3)
|
||||
|
|
@ -96,6 +110,7 @@ DEPENDENCIES
|
|||
chartkick
|
||||
forwardable (= 1.3.2)
|
||||
gettext
|
||||
mail
|
||||
puma
|
||||
rackup
|
||||
rake
|
||||
|
|
|
|||
5
db/migrate/20250607233053_add_reset_to_users.rb
Normal file
5
db/migrate/20250607233053_add_reset_to_users.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class AddResetToUsers < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
add_column :users, :reset, :string
|
||||
end
|
||||
end
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.2].define(version: 2025_03_28_014902) do
|
||||
ActiveRecord::Schema[7.2].define(version: 2025_06_07_233053) do
|
||||
create_table "candidates", force: :cascade do |t|
|
||||
t.integer "vote_id"
|
||||
t.string "name"
|
||||
|
|
@ -44,6 +44,7 @@ ActiveRecord::Schema[7.2].define(version: 2025_03_28_014902) do
|
|||
t.string "password"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "reset"
|
||||
end
|
||||
|
||||
create_table "votes", force: :cascade do |t|
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-06-07 15:08-0600\n"
|
||||
"POT-Creation-Date: 2025-06-07 18:22-0600\n"
|
||||
"PO-Revision-Date: 2025-03-29 20:41-0600\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -17,34 +17,38 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
||||
|
||||
#: ../vedia.rb:62
|
||||
#: ../vedia.rb:64
|
||||
msgid "Awful"
|
||||
msgstr "Molt malament"
|
||||
|
||||
#: ../vedia.rb:63
|
||||
#: ../vedia.rb:65
|
||||
msgid "Very bad"
|
||||
msgstr "Malament"
|
||||
|
||||
#: ../vedia.rb:64
|
||||
#: ../vedia.rb:66
|
||||
msgid "Bad"
|
||||
msgstr "Poc bé"
|
||||
|
||||
#: ../vedia.rb:65
|
||||
#: ../vedia.rb:67
|
||||
msgid "Mediocre"
|
||||
msgstr "Mig bé"
|
||||
|
||||
#: ../vedia.rb:66
|
||||
#: ../vedia.rb:68
|
||||
msgid "Good"
|
||||
msgstr "Bé"
|
||||
|
||||
#: ../vedia.rb:67
|
||||
#: ../vedia.rb:69
|
||||
msgid "Very good"
|
||||
msgstr "Molt bé"
|
||||
|
||||
#: ../vedia.rb:114
|
||||
#: ../vedia.rb:121
|
||||
msgid "Incorrect email or password."
|
||||
msgstr "Correu o contrasenya incorrecte."
|
||||
|
||||
#: ../vedia.rb:139
|
||||
msgid "Reset your password"
|
||||
msgstr "Reiniciar contrasenya"
|
||||
|
||||
#: ../views/home.erb:1 ../views/layout.erb:14
|
||||
msgid "Home"
|
||||
msgstr "Inici"
|
||||
|
|
@ -93,12 +97,13 @@ msgstr "Desconnexió"
|
|||
msgid "Login"
|
||||
msgstr "Connexió"
|
||||
|
||||
#: ../views/login.erb:9 ../views/signup.erb:24 ../views/votes_edit.erb:51
|
||||
#: ../views/login.erb:9 ../views/reset.erb:5 ../views/reset_change.erb:13
|
||||
#: ../views/signup.erb:24 ../views/votes_edit.erb:51
|
||||
#: ../views/votes_show_closed.erb:85 ../views/votes_show_open.erb:58
|
||||
msgid "Email"
|
||||
msgstr "Correu"
|
||||
|
||||
#: ../views/login.erb:13 ../views/signup.erb:28
|
||||
#: ../views/login.erb:13 ../views/reset_change.erb:17 ../views/signup.erb:28
|
||||
msgid "Password"
|
||||
msgstr "Contrasenya"
|
||||
|
||||
|
|
@ -106,10 +111,40 @@ msgstr "Contrasenya"
|
|||
msgid "Create account"
|
||||
msgstr "Crear un compte"
|
||||
|
||||
#: ../views/signup.erb:6
|
||||
#: ../views/login.erb:19 ../views/reset.erb:1 ../views/reset.erb:8
|
||||
#: ../views/reset_change.erb:1 ../views/reset_change.erb:20
|
||||
#: ../views/reset_invalid.erb:1 ../views/reset_sent.erb:1
|
||||
msgid "Reset password"
|
||||
msgstr "Reiniciar contrasenya"
|
||||
|
||||
#: ../views/reset_change.erb:6 ../views/signup.erb:6
|
||||
msgid "Specify a password."
|
||||
msgstr "Entra una contrasenya."
|
||||
|
||||
#: ../views/reset_email.erb:1
|
||||
msgid "Visit the following link to reset your password:"
|
||||
msgstr "Visita aquest enllaç per reiniciar la teva contrasenya:"
|
||||
|
||||
#: ../views/reset_invalid.erb:3
|
||||
msgid "This password reset link has expired or is invalid."
|
||||
msgstr "Aquest enllaç per reiniciar una contrasenya ha expirat o és invàlid."
|
||||
|
||||
#: ../views/reset_invalid.erb:5
|
||||
msgid "Try resetting your password again."
|
||||
msgstr "Intenta reiniciar la teva contrasenya una altre vegada."
|
||||
|
||||
#: ../views/reset_sent.erb:3
|
||||
msgid ""
|
||||
"If an account exists for %{email}, you will get an email with a link\n"
|
||||
"to reset your password."
|
||||
msgstr ""
|
||||
"Si existeix un compte per %{email}, rebràs un email amb un enllaç\n"
|
||||
"per reiniciar la teva contrasenya."
|
||||
|
||||
#: ../views/reset_sent.erb:6
|
||||
msgid "If you don't receive the email, please check your spam folder."
|
||||
msgstr "Si no reps l'email, revisa el teu correu brossa."
|
||||
|
||||
#: ../views/signup.erb:14
|
||||
msgid "Email is not a valid email address."
|
||||
msgstr "El correu no és una direcció de correu vàlida."
|
||||
|
|
@ -238,7 +273,3 @@ msgstr "Tornar a l'esborrany de votació"
|
|||
#: ../views/votes_show_open.erb:51
|
||||
msgid "Close votes and show results"
|
||||
msgstr "Tancar la votació i veure els resultats"
|
||||
|
||||
#: ../views/layout.erb:5
|
||||
#~ msgid "Vote"
|
||||
#~ msgstr "Votació"
|
||||
|
|
|
|||
57
po/vedia.pot
57
po/vedia.pot
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-06-07 15:08-0600\n"
|
||||
"PO-Revision-Date: 2025-06-07 15:08-0600\n"
|
||||
"POT-Creation-Date: 2025-06-07 18:22-0600\n"
|
||||
"PO-Revision-Date: 2025-06-07 18:22-0600\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
|
|
@ -18,34 +18,38 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
|
||||
|
||||
#: ../vedia.rb:62
|
||||
#: ../vedia.rb:64
|
||||
msgid "Awful"
|
||||
msgstr ""
|
||||
|
||||
#: ../vedia.rb:63
|
||||
#: ../vedia.rb:65
|
||||
msgid "Very bad"
|
||||
msgstr ""
|
||||
|
||||
#: ../vedia.rb:64
|
||||
#: ../vedia.rb:66
|
||||
msgid "Bad"
|
||||
msgstr ""
|
||||
|
||||
#: ../vedia.rb:65
|
||||
#: ../vedia.rb:67
|
||||
msgid "Mediocre"
|
||||
msgstr ""
|
||||
|
||||
#: ../vedia.rb:66
|
||||
#: ../vedia.rb:68
|
||||
msgid "Good"
|
||||
msgstr ""
|
||||
|
||||
#: ../vedia.rb:67
|
||||
#: ../vedia.rb:69
|
||||
msgid "Very good"
|
||||
msgstr ""
|
||||
|
||||
#: ../vedia.rb:114
|
||||
#: ../vedia.rb:121
|
||||
msgid "Incorrect email or password."
|
||||
msgstr ""
|
||||
|
||||
#: ../vedia.rb:139
|
||||
msgid "Reset your password"
|
||||
msgstr ""
|
||||
|
||||
#: ../views/home.erb:1 ../views/layout.erb:14
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
|
@ -94,12 +98,13 @@ msgstr ""
|
|||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: ../views/login.erb:9 ../views/signup.erb:24 ../views/votes_edit.erb:51
|
||||
#: ../views/login.erb:9 ../views/reset.erb:5 ../views/reset_change.erb:13
|
||||
#: ../views/signup.erb:24 ../views/votes_edit.erb:51
|
||||
#: ../views/votes_show_closed.erb:85 ../views/votes_show_open.erb:58
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: ../views/login.erb:13 ../views/signup.erb:28
|
||||
#: ../views/login.erb:13 ../views/reset_change.erb:17 ../views/signup.erb:28
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -107,10 +112,38 @@ msgstr ""
|
|||
msgid "Create account"
|
||||
msgstr ""
|
||||
|
||||
#: ../views/signup.erb:6
|
||||
#: ../views/login.erb:19 ../views/reset.erb:1 ../views/reset.erb:8
|
||||
#: ../views/reset_change.erb:1 ../views/reset_change.erb:20
|
||||
#: ../views/reset_invalid.erb:1 ../views/reset_sent.erb:1
|
||||
msgid "Reset password"
|
||||
msgstr ""
|
||||
|
||||
#: ../views/reset_change.erb:6 ../views/signup.erb:6
|
||||
msgid "Specify a password."
|
||||
msgstr ""
|
||||
|
||||
#: ../views/reset_email.erb:1
|
||||
msgid "Visit the following link to reset your password:"
|
||||
msgstr ""
|
||||
|
||||
#: ../views/reset_invalid.erb:3
|
||||
msgid "This password reset link has expired or is invalid."
|
||||
msgstr ""
|
||||
|
||||
#: ../views/reset_invalid.erb:5
|
||||
msgid "Try resetting your password again."
|
||||
msgstr ""
|
||||
|
||||
#: ../views/reset_sent.erb:3
|
||||
msgid ""
|
||||
"If an account exists for %{email}, you will get an email with a link\n"
|
||||
"to reset your password."
|
||||
msgstr ""
|
||||
|
||||
#: ../views/reset_sent.erb:6
|
||||
msgid "If you don't receive the email, please check your spam folder."
|
||||
msgstr ""
|
||||
|
||||
#: ../views/signup.erb:14
|
||||
msgid "Email is not a valid email address."
|
||||
msgstr ""
|
||||
|
|
|
|||
58
vedia.rb
58
vedia.rb
|
|
@ -4,7 +4,9 @@ require 'bcrypt'
|
|||
require 'gettext'
|
||||
require 'securerandom'
|
||||
require 'chartkick'
|
||||
require 'mail'
|
||||
require_relative 'mj'
|
||||
require_relative "config/environments/#{settings.environment}"
|
||||
|
||||
class Vote < ActiveRecord::Base
|
||||
has_many :candidates, dependent: :destroy
|
||||
|
|
@ -65,6 +67,7 @@ set :values, [ { :id => 1, :label => _("Awful"), :color => '#ff4500' },
|
|||
{ :id => 4, :label => _("Mediocre"), :color => '#9acd32' },
|
||||
{ :id => 5, :label => _("Good"), :color => '#228b22' },
|
||||
{ :id => 6, :label => _("Very good"), :color => '#006400' } ]
|
||||
set :admin_email, 'vedia@potager.org'
|
||||
MajorityJudgment.values = settings.values
|
||||
|
||||
get '/' do
|
||||
|
|
@ -107,6 +110,10 @@ end
|
|||
post '/login' do
|
||||
user = User.find_by(email: params[:email])
|
||||
if user && verify_password(params[:password], user.password)
|
||||
if not user.reset.nil?
|
||||
user.reset = nil
|
||||
user.save
|
||||
end
|
||||
session.clear
|
||||
session[:user_id] = user.id
|
||||
redirect '/'
|
||||
|
|
@ -116,6 +123,57 @@ post '/login' do
|
|||
end
|
||||
end
|
||||
|
||||
get '/reset' do
|
||||
erb :reset
|
||||
end
|
||||
|
||||
post '/reset' do
|
||||
@user = User.find_by(email: params[:email])
|
||||
if @user
|
||||
@user.reset = SecureRandom.uuid
|
||||
@user.save
|
||||
mail = Mail.new
|
||||
mail.from = settings.admin_email
|
||||
mail.to = @user.email
|
||||
mail.subject = _("Reset your password")
|
||||
mail.body = erb :reset_email, :layout => false
|
||||
mail.deliver
|
||||
end
|
||||
erb :reset_sent
|
||||
end
|
||||
|
||||
get '/reset/:uuid' do
|
||||
@user = User.find_by(reset: params[:uuid])
|
||||
if @user
|
||||
erb :reset_change
|
||||
else
|
||||
erb :reset_invalid
|
||||
end
|
||||
end
|
||||
|
||||
post '/reset/:uuid' do
|
||||
@user = User.find_by(reset: params[:uuid])
|
||||
if @user
|
||||
@errors = []
|
||||
if params[:password].empty?
|
||||
@errors << OpenStruct.new(:attribute => :password, :type => :blank)
|
||||
else
|
||||
@user.password = hash_password(params[:password])
|
||||
end
|
||||
if @errors.empty? and @user.valid?
|
||||
@user.reset = nil
|
||||
@user.save
|
||||
session.clear
|
||||
session[:user_id] = @user.id
|
||||
redirect '/'
|
||||
else
|
||||
erb :reset_change
|
||||
end
|
||||
else
|
||||
erb :reset_invalid
|
||||
end
|
||||
end
|
||||
|
||||
get '/logout' do
|
||||
session.clear
|
||||
redirect '/login'
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<p class="error"><%= @error %></p>
|
||||
<% end %>
|
||||
|
||||
<form action="/login" method="POST">
|
||||
<form action="/login" method="post">
|
||||
<p>
|
||||
<label for="email"><%= _("Email") %></label>
|
||||
<input type="text" name="email">
|
||||
|
|
@ -15,4 +15,5 @@
|
|||
</p>
|
||||
<button type="submit"><%= _("Login") %></button>
|
||||
</form>
|
||||
<a href="/signup"><%= _("Create account") %></a>
|
||||
<p><a href="/signup"><%= _("Create account") %></a></p>
|
||||
<p><a href="/reset"><%= _("Reset password") %></a></p>
|
||||
|
|
|
|||
9
views/reset.erb
Normal file
9
views/reset.erb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<h1><%= _("Reset password") %></h1>
|
||||
|
||||
<form action="/reset" method="post">
|
||||
<p>
|
||||
<label for="email"><%= _("Email") %></label>
|
||||
<input type="text" name="email">
|
||||
</p>
|
||||
<button type="submit"><%= _("Reset password") %></button>
|
||||
</form>
|
||||
21
views/reset_change.erb
Normal file
21
views/reset_change.erb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<h1><%= _("Reset password") %></h1>
|
||||
|
||||
<% if @errors %>
|
||||
<% @errors.each do |error| %>
|
||||
<% if error.attribute == :password and error.type == :blank %>
|
||||
<p class="error"><%= _("Specify a password.") %></p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<form action="/reset/<%= params[:uuid] %>" method="post">
|
||||
<p>
|
||||
<label for="email"><%= _("Email") %></label>
|
||||
<span><%= @user.email %></span>
|
||||
</p>
|
||||
<p>
|
||||
<label for="password"><%= _("Password") %></label>
|
||||
<input type="password" name="password" value="<%= params[:password] %>">
|
||||
</p>
|
||||
<button type="submit"><%= _("Reset password") %></button>
|
||||
</form>
|
||||
3
views/reset_email.erb
Normal file
3
views/reset_email.erb
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<%= _("Visit the following link to reset your password:") %>
|
||||
|
||||
<%= "#{settings.base_url}reset/#{@user.reset}" %>
|
||||
5
views/reset_invalid.erb
Normal file
5
views/reset_invalid.erb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<h1><%= _("Reset password") %></h1>
|
||||
|
||||
<p class="error"><%= _("This password reset link has expired or is invalid.") %></p>
|
||||
|
||||
<p><a href="/reset"><%= _("Try resetting your password again.") %></p>
|
||||
6
views/reset_sent.erb
Normal file
6
views/reset_sent.erb
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<h1><%= _("Reset password") %></h1>
|
||||
|
||||
<p><%= _("If an account exists for %{email}, you will get an email with a link
|
||||
to reset your password.") % { email: params[:email] } %></p>
|
||||
|
||||
<p><%= _("If you don't receive the email, please check your spam folder.") %></p>
|
||||
Loading…
Add table
Add a link
Reference in a new issue