Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ gem "grape-swagger-entity"
gem "falcon" # The app server

gem "i18n" # Used for translating strings in the views
gem "rack-contrib" # Used for parsing the user's language into a locale

gem "bcrypt" # Used by rodauth for password hashing
gem "jwt" # Used by rodauth jwt
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ GEM
public_suffix (6.0.2)
racc (1.8.1)
rack (3.1.16)
rack-contrib (2.5.0)
rack (< 4)
rack-test (2.2.0)
rack (>= 1.3)
rainbow (3.1.1)
Expand Down Expand Up @@ -480,6 +482,7 @@ DEPENDENCIES
pg
pronto (~> 0.11)
pronto-rubocop
rack-contrib
rack-test
rake
rerun
Expand Down Expand Up @@ -630,6 +633,7 @@ CHECKSUMS
public_suffix (6.0.2) sha256=bfa7cd5108066f8c9602e0d6d4114999a5df5839a63149d3e8b0f9c1d3558394
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
rack (3.1.16) sha256=efb5606c351efc56b85b10c3493055d0d35209d23f44792ec4e1183eb0234635
rack-contrib (2.5.0) sha256=51bd2ce82b8a3270f9173130c4cdaea72aab8b03dce8cd6af1c4344d84a32d02
rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
rake (13.3.0) sha256=96f5092d786ff412c62fde76f793cc0541bd84d2eb579caa529aa8a059934493
Expand Down
35 changes: 33 additions & 2 deletions app/api/rodauth_middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,27 @@ module API
].freeze
# middleware responsible for authentication
class RodauthMiddleware < Roda
class << self
# This function will choose the request locale.
# It use the +request_locale+ key in the +env+ variable if available, otherwise, it checks if the request
# is authenticated and if so takes the locale from the profile preferences. If not, will take from the session and lastly
# from the rack.locale
# It also memoizes the result to the env
#
# @param env [Hash] the env variable for the request
# @param session [Object] the session object from roda for the current request
# @param rodauth [Rodauth] the rodauth object for the current request
# @return [String] The request locale
def choose_request_locale(env, session, rodauth)
return env["request_locale"] if env["request_locale"]

profile_preferences = Persistence::Repository::Account.profile_preferences_from_account_id(account_id: rodauth.account!&.dig(:id))
profile_locale = profile_preferences["locale"] if profile_preferences&.key?("locale")
env["request_locale"] = profile_locale || session["locale"] || env["rack.locale"]
end
end
plugin :public, root: File.expand_path("../assets/images", __dir__)
plugin :flash
# plugin :middleware
plugin :assets, css: "layout.scss", js: "base.js", path: File.expand_path("../assets", __dir__)

plugin :render, views: File.expand_path("../assets/html", __dir__), engine: "haml", engine_opts: { "haml" => { escape_html: false } }, template_opts: { default_encoding: "UTF-8" }
Expand Down Expand Up @@ -95,6 +113,10 @@ class RodauthMiddleware < Roda
render "reset_password"
end

before_rodauth do
I18n.locale = RodauthMiddleware.choose_request_locale(request.env, session, self)
end

before_register do
# Before registering, rodauth allows to authorize the client. Currently we allow any client to register, since the idea is that anyone could make a client.
# This is why the nil, but probably should verify for a logged in user in some cases.
Expand Down Expand Up @@ -123,6 +145,9 @@ class RodauthMiddleware < Roda
r.assets
r.public

r.rodauth
I18n.locale = RodauthMiddleware.choose_request_locale(env, session, rodauth)

r.root do
view(template: "root", layout: "hero")
end
Expand All @@ -132,13 +157,19 @@ class RodauthMiddleware < Roda
r.is("privacy") do
view(:privacy)
end
r.rodauth

check_csrf! unless r.content_type&.include?("application/json") || r.path.start_with?("/api/")
# rodauth.load_oauth_application_management_routes
# rodauth.load_oauth_grant_management_routes
rodauth.load_oauth_server_metadata_route # Loads .well-known/oauth-authorization-server path

r.is("language") do
r.post do
session["locale"] = r.params["locale"] if I18n.available_locales.include?(r.params["locale"].to_sym)
r.redirect("/")
end
end

# Supposed to catch any non-api paths that are not in rodauth
# Should be the last one, otherwise other routes will also 404
# The regex is supposed to mean:
Expand Down
11 changes: 11 additions & 0 deletions app/assets/html/header.haml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,14 @@
- else
%a.navbar-item{href: "/login"}= I18n.t("login")
%a.navbar-item{href: "/create-account"}= I18n.t("sign_up")
.navbar-item.has-dropdown.is-hoverable
.navbar-link
Language selection
.navbar-dropdown.is-right
- I18n.available_locales.each do |locale|
.navbar-item
%form{action: "/language", method: :post}
= csrf_tag("/language")
%input{type: "hidden", name: "locale", value: locale}
- I18n.with_locale(locale) do
%input{type: "submit", class: "button is-white", value: I18n.t("language_name")}
2 changes: 1 addition & 1 deletion app/assets/html/hero.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
%html
%head
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
%title RetromeetWeb
%title Retromeet
%meta{:content => "width=device-width,initial-scale=1", :name => "viewport"}/
%meta{:content => "yes", :name => "apple-mobile-web-app-capable"}/
%meta{:content => "yes", :name => "mobile-web-app-capable"}/
Expand Down
2 changes: 1 addition & 1 deletion app/assets/html/layout.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
%html
%head
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
%title RetromeetWeb
%title Retromeet
%meta{:content => "width=device-width,initial-scale=1", :name => "viewport"}/
%meta{:content => "yes", :name => "apple-mobile-web-app-capable"}/
%meta{:content => "yes", :name => "mobile-web-app-capable"}/
Expand Down
5 changes: 5 additions & 0 deletions app/persistence/datasets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ def profile_blocks
Database.connection[:profile_blocks]
end

# @return [Sequel::Postgres::Dataset]
def profile_preferences
Database.connection[:profile_preferences]
end

# @return [Sequel::Postgres::Dataset]
def conversations
Database.connection[:conversations]
Expand Down
9 changes: 9 additions & 0 deletions app/persistence/repository/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,15 @@ def make_admin(email:)
accounts.where(email:)
.update(type: "admin")
end

# @return [Hash]
def profile_preferences_from_account_id(account_id:)
return {} unless account_id

profile_preferences.where(profile_id: profiles.where(account_id:)
.select(:id))
.get(:preferences)
end
end
end
end
Expand Down
1 change: 1 addition & 0 deletions config.ru
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ require_relative "preload" unless defined?(EnvironmentConfig)

Rack::Request.ip_filter = ->(ip) { EnvironmentConfig.rack_trusted_ips_re.match?(ip) }
use Rack::CommonLogger
use Rack::Locale
use API::RodauthMiddleware

run API::Base
2 changes: 1 addition & 1 deletion config/locales.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

I18n.load_path += Dir["#{File.expand_path("locales", __dir__)}/*.yml"]
I18n.available_locales = %i[en pt-BR]
I18n.available_locales = %i[fr en pt-BR].sort!
I18n.default_locale = :en
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
en:
language_name: "English"
about: "About"
terms: "Terms of service"
privacy_policy: Privacy policy
Expand Down
7 changes: 7 additions & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fr:
language_name: "Français"
login: Se connecter
sign_up: Créer un compte
create_account:
birth_date_help: Nous avons besoin de votre date de naissance pour garantir que vous êtes autorisé à accéder à notre service, conformément à nos conditions d'utilisation. Vous <strong>NE POUVEZ</strong> pas modifier cette date ultérieurement, mais vous pouvez rendre votre âge privé si vous le souhaitez.
2 changes: 2 additions & 0 deletions config/locales/pt-BR.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
---
pt-BR:
language_name: "Português brasileiro"
about: "Sobre"
terms: "Terms de uso"
privacy_policy: Política de Privacidade
login: Fazer login
sign_up: "Criar uma conta"
create_account:
birth_date_help: Precisamos da sua data de nascimento para garantir que você pode acessar nosso serviço, de acordo com nossos termos de uso. Você <strong>NÃO PODE</strong> mudar essa informação depois, mas você pode esconder a sua idade se você quiser.
Loading