Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth Login for Staging #9712

Merged
merged 23 commits into from
Aug 8, 2024
Merged
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
3 changes: 3 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ OIDC_SECRET_KEY=oidc-development-secret
PAYPAL_BASE_URL=https://api-m.sandbox.paypal.com
WCA_REGISTRATIONS_URL=http://localhost:8000
WCA_REGISTRATIONS_BACKEND_URL=http://wca_registration_handler:3000
STAGING_OAUTH_URL=https://staging.worldcubeassociation.org
STAGING_OAUTH_CLIENT=example-application-id
STAGING_OAUTH_SECRET=example-secret
3 changes: 3 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ PAYPAL_CLIENT_SECRET=EIknLp919Gbuj2CYmEWECyKH5HwJTWQNuqFuCr1qFMrGNzwkF8dD0VkwzwI
PAYPAL_ATTRIBUTION_CODE=FLAVORsb-noyt529176316_MP
PAYPAL_BASE_URL=https://api-m.sandbox.paypal.com
WCA_REGISTRATIONS_BACKEND_URL=http://wca_registration_handler:3000
STAGING_OAUTH_URL=https://staging.worldcubeassociation.org
STAGING_OAUTH_CLIENT=example-application-id
STAGING_OAUTH_SECRET=example-secret
4 changes: 4 additions & 0 deletions app/assets/stylesheets/wca.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
font-family: monospace;
}

.watermark {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='100px' width='100px'><text transform='translate(20, 100) rotate(-45)' fill='rgb(0,0,0)' opacity='0.15' font-size='12'>WCA Testing Site</text></svg>");
}

table.table {
// From http://stackoverflow.com/a/10688485
&.table-nonfluid {
Expand Down
37 changes: 37 additions & 0 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,43 @@ class SessionsController < Devise::SessionsController
# Make sure this happens always before any before_action
protect_from_forgery with: :exception, prepend: true

def staging_oauth_login
return if EnvConfig.WCA_LIVE_SITE?

client = OAuth2::Client.new(AppSecrets.STAGING_OAUTH_CLIENT, AppSecrets.STAGING_OAUTH_SECRET,
site: EnvConfig.STAGING_OAUTH_URL)
redirect_uri = staging_login_url

unless params[:code].present?
return redirect_to client.auth_code.authorize_url(
redirect_uri: redirect_uri,
), allow_other_host: true
end

access_token = client.auth_code.get_token(
params[:code], redirect_uri: redirect_uri
).token

# Get /me to figure out which user we are
connection = Faraday.new(
url: EnvConfig.STAGING_OAUTH_URL,
headers: {
'Authorization' => "Bearer #{access_token}",
'Content-Type' => 'application/json',
},
)

results = connection.get("/api/v0/me").body

user = User.find(results["me"]["id"])
if user
sign_in(user)
redirect_to root_url, notice: "Successfully logged in as #{user.wca_id}"
else
redirect_to root_url, alert: "Your user is not yet imported into our Staging Website, please try again later"
end
end

def new
super
# Remove any lingering user data from previous login attempt
Expand Down
9 changes: 9 additions & 0 deletions app/views/devise/sessions/_live_login.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div class="panel panel-default">
<div class="panel-heading">
<h4><%= t('devise.sessions.new.sign_in') %></h4>
</div>

<div class="panel-body">
<%= render 'password_form' %>
</div>
</div>
33 changes: 33 additions & 0 deletions app/views/devise/sessions/_password_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<%= form_for(resource, as: resource_name, url: session_path(resource_name), html: { role: "form" }) do |f| %>
<div class="form-group">
<%= f.label :login %>
<%= f.text_field :login, autofocus: false, class: "form-control", tabindex: "1" %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= link_to t("devise.passwords.new.forgot_your_password"), new_user_password_path %><br />
<%= f.password_field :password, autocomplete: "off", class: "form-control", tabindex: "2" %>
<% if ServerSetting.exists?(DatabaseDumper::DEV_TIMESTAMP_NAME) %>
<p class="help-block">
Hint! It looks like you are using the
<a href="https://github.com/thewca/worldcubeassociation.org/wiki/Developer-database-export" target="_blank">developer export</a>
<% unless DbDumpHelper.use_staging_password? %>
, every user's password is "wca"
<% end %>
. You can find email addresses to log in with over on
<%= link_to "the delegates page", delegates_path %>.
</p>
<% end %>
</div>
<% if devise_mapping.rememberable? %>
<div class="checkbox">
<label>
<%= f.check_box :remember_me, tabindex: "3" %>
<%= f.label :remember_me %>
</label>
</div>
<% end %>
<%= f.submit t('devise.sessions.new.sign_in'), class: "btn btn-primary", tabindex: "3" %>
<%= t 'wca.devise.no_account' %> <%= link_to t('devise.shared.links.sign_up'), new_user_registration_path %>!
<% end %>

25 changes: 25 additions & 0 deletions app/views/devise/sessions/_staging_login.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<div class="panel panel-default">
<div class="panel-heading">
<h4>Recommended: Automatic Sign In</h4>
</div>
<div class="panel-body">
<div>
<button class="btn btn-success"><%= link_to 'Sign in using your WCA Account', staging_login_url, style: "color: white" %></button>
</div>
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading" role="tab" id="dev-sign-in-heading">
<p class="panel-title">
<a href="#manual-sign-in" aria-controls="manual-sign-in" role="button" data-toggle="collapse">Developers Only: Manual Sign In</a>
</p>
</div>

<div role="tabpanel" class="panel-collapse collapse" id="manual-sign-in" aria-labelledby="dev-sign-in-heading">
<div class="panel-body">
<%= render 'password_form' %>
</div>
</div>
</div>

44 changes: 5 additions & 39 deletions app/views/devise/sessions/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,10 @@
<% # i18n-tasks-use t('devise.failure.not_found_in_database') %>
<% # i18n-tasks-use t('devise.failure.unconfirmed') %>
<%= render layout: "devise/conversion_message", locals: { user: resource } do %>
<div class="panel panel-default">
<div class="panel-heading">
<h4><%= t('devise.sessions.new.sign_in') %></h4>
</div>
<div class="panel-body">
<%= form_for(resource, as: resource_name, url: session_path(resource_name), html: { role: "form" }) do |f| %>
<div class="form-group">
<%= f.label :login %>
<%= f.text_field :login, autofocus: true, class: "form-control", tabindex: "1" %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= link_to t("devise.passwords.new.forgot_your_password"), new_user_password_path %><br />
<%= f.password_field :password, autocomplete: "off", class: "form-control", tabindex: "2" %>
<% if ServerSetting.exists?(DatabaseDumper::DEV_TIMESTAMP_NAME) %>
<p class="help-block">
Hint! It looks like you are using the
<a href="https://github.com/thewca/worldcubeassociation.org/wiki/Developer-database-export" target="_blank">developer export</a>
<% unless DbDumpHelper.use_staging_password? %>
, every user's password is "wca"
<% end %>
. You can find email addresses to log in with over on
<%= link_to "the delegates page", delegates_path %>.
</p>
<% end %>
</div>
<% if devise_mapping.rememberable? %>
<div class="checkbox">
<label>
<%= f.check_box :remember_me, tabindex: "3" %>
<%= f.label :remember_me %>
</label>
</div>
<% end %>
<%= f.submit t('devise.sessions.new.sign_in'), class: "btn btn-primary", tabindex: "3" %>
<%= t 'wca.devise.no_account' %> <%= link_to t('devise.shared.links.sign_up'), new_user_registration_path %>!
<% end %>
</div>
</div>
<% if Rails.env.production? && !EnvConfig.WCA_LIVE_SITE? %>
FinnIckler marked this conversation as resolved.
Show resolved Hide resolved
<%= render 'staging_login' %>
<% else %>
<%= render 'live_login' %>
<% end %>
<% end %>
</div>
2 changes: 1 addition & 1 deletion app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
</script>
<% end %>
</head>
<body data-rails-controller-name="<%= controller_name %>" data-rails-controller-action-name="<%= action_name %>">
<body data-rails-controller-name="<%= controller_name %>" data-rails-controller-action-name="<%= action_name %>" class="<%= "watermark" if Rails.env.production? && !EnvConfig.WCA_LIVE_SITE? %>">

<% hide_wca_navbars = yield(:hide_wca_navbars).present? %>
<% if !hide_wca_navbars %>
Expand Down
8 changes: 8 additions & 0 deletions app_secrets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ def vault_file(secret_name, file_path, refresh: true)
vault :OIDC_SECRET_KEY
vault :SLACK_WST_BOT_TOKEN
vault :TNOODLE_PUBLIC_KEY

# To allow logging in to staging with your prod account
unless EnvConfig.WCA_LIVE_SITE?
vault :STAGING_OAUTH_CLIENT
vault :STAGING_OAUTH_SECRET
end
else
mandatory :DATABASE_PASSWORD, :string
mandatory :GOOGLE_MAPS_API_KEY, :string
Expand All @@ -96,6 +102,8 @@ def vault_file(secret_name, file_path, refresh: true)
mandatory :STRIPE_PUBLISHABLE_KEY, :string
mandatory :JWT_KEY, :string
mandatory :OIDC_SECRET_KEY, :string
mandatory :STAGING_OAUTH_CLIENT, :string
mandatory :STAGING_OAUTH_SECRET, :string

optional :AWS_ACCESS_KEY_ID, :string, ''
optional :AWS_SECRET_ACCESS_KEY, :string, ''
Expand Down
20 changes: 20 additions & 0 deletions config/initializers/faraday_default_options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module FaradayDefaultOptions
def new_builder(block)
super.tap do |builder|
# Sets headers and parses jsons automatically
builder.request :json
builder.response :json

# Raises an error on 4xx and 5xx responses.
builder.response :raise_error

# Logs requests and responses.
# By default, it only logs the request method and URL, and the request/response headers.
builder.response :logger, ::Logger.new($stdout), bodies: true if Rails.env.development?
end
end
end

Faraday::ConnectionOptions.prepend(FaradayDefaultOptions)
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
# https://github.com/plataformatec/devise/wiki/How-To:-Disable-user-from-destroying-their-account
devise_for :users, skip: :registrations, controllers: { sessions: "sessions" }
devise_scope :user do
get 'staging_login', to: 'sessions#staging_oauth_login' unless EnvConfig.WCA_LIVE_SITE?
resource :registration,
only: [:new, :create],
path: 'users',
Expand All @@ -39,6 +40,7 @@
post 'users/authenticate-sensitive' => 'users#authenticate_user_for_sensitive_edit'
delete 'users/sign-out-other' => 'sessions#destroy_other', as: :destroy_other_user_sessions
end

# TODO: This can be removed after deployment, this is so we don't have any users error out if they click on pay
# while the deployment happens
get 'registration/:id/payment-completion' => 'registrations#payment_completion_legacy', as: :registration_payment_completion_legacy
Expand Down
3 changes: 3 additions & 0 deletions env_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@
# For server status
optional :BUILD_TAG, :string, "local"

# To allow logging in to staging with your prod account
optional :STAGING_OAUTH_URL, :string, ""

# For Asset Compilation
optional :ASSETS_COMPILATION, :bool, false
end
Expand Down
4 changes: 4 additions & 0 deletions infra/wca_on_rails/staging/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ locals {
name = "SIDEKIQ_REDIS_URL"
value = "redis://redis-main-staging-001.iebvzt.0001.usw2.cache.amazonaws.com:6379"
},
{
name = "STAGING_OAUTH_URL"
value = "https://www.worldcubeassociation.org"
},
{
name = "STORAGE_AWS_BUCKET"
value = aws_s3_bucket.storage-bucket.id
Expand Down