mirror of
https://github.com/SrIzan10/hc-harbor.git
synced 2026-05-01 10:45:21 +00:00
Add HCA signin (#684)
This commit is contained in:
@@ -1,14 +1,48 @@
|
||||
class SessionsController < ApplicationController
|
||||
def new
|
||||
redirect_uri = url_for(action: :create, only_path: false)
|
||||
def hca_new
|
||||
redirect_uri = url_for(action: :hca_create, only_path: false)
|
||||
|
||||
redirect_to User.hca_authorize_url(redirect_uri),
|
||||
host: "https://auth.hackclub.com",
|
||||
allow_other_host: "https://auth.hackclub.com"
|
||||
end
|
||||
|
||||
def hca_create
|
||||
if params[:error].present?
|
||||
Rails.logger.error "Slack OAuth error: #{params[:error]}"
|
||||
Sentry.capture_message("Slack OAuth error: #{params[:error]}")
|
||||
redirect_to root_path, alert: "Failed to authenticate with Slack. Error ID: #{Sentry.last_event_id}"
|
||||
return
|
||||
end
|
||||
|
||||
redirect_uri = url_for(action: :hca_create, only_path: false)
|
||||
|
||||
@user = User.from_hca_token(params[:code], redirect_uri)
|
||||
|
||||
# if @user&.persisted?
|
||||
if @user&.persisted?
|
||||
session[:user_id] = @user.id
|
||||
|
||||
if @user.data_migration_jobs.empty?
|
||||
MigrateUserFromHackatimeJob.perform_later(@user.id)
|
||||
end
|
||||
|
||||
redirect_to root_path, notice: "Successfully signed in with Slack! Welcome!"
|
||||
else
|
||||
redirect_to root_path, alert: "Failed to authenticate with Hack Club Auth!"
|
||||
end
|
||||
end
|
||||
|
||||
def slack_new
|
||||
redirect_uri = url_for(action: :slack_create, only_path: false)
|
||||
Rails.logger.info "Starting Slack OAuth flow with redirect URI: #{redirect_uri}"
|
||||
redirect_to User.authorize_url(redirect_uri, close_window: params[:close_window].present?, continue_param: params[:continue]),
|
||||
redirect_to User.slack_authorize_url(redirect_uri, close_window: params[:close_window].present?, continue_param: params[:continue]),
|
||||
host: "https://slack.com",
|
||||
allow_other_host: "https://slack.com"
|
||||
end
|
||||
|
||||
def create
|
||||
redirect_uri = url_for(action: :create, only_path: false)
|
||||
def slack_create
|
||||
redirect_uri = url_for(action: :slack_create, only_path: false)
|
||||
|
||||
if params[:error].present?
|
||||
Rails.logger.error "Slack OAuth error: #{params[:error]}"
|
||||
|
||||
@@ -8,7 +8,7 @@ class User < ApplicationRecord
|
||||
|
||||
after_create :create_signup_activity
|
||||
before_validation :normalize_username
|
||||
encrypts :slack_access_token, :github_access_token
|
||||
encrypts :slack_access_token, :github_access_token, :hca_access_token
|
||||
|
||||
validates :slack_uid, uniqueness: true, allow_nil: true
|
||||
validates :github_uid, uniqueness: { conditions: -> { where.not(github_access_token: nil) } }, allow_nil: true
|
||||
@@ -327,7 +327,18 @@ class User < ApplicationRecord
|
||||
})
|
||||
end
|
||||
|
||||
def self.authorize_url(redirect_uri, close_window: false, continue_param: nil)
|
||||
def self.hca_authorize_url(redirect_uri)
|
||||
params = {
|
||||
redirect_uri:,
|
||||
client_id: ENV["HCA_CLIENT_ID"],
|
||||
response_type: "code",
|
||||
scope: "email"
|
||||
}
|
||||
|
||||
URI.parse("#{HCAService.host}/oauth/authorize?#{params.to_query}")
|
||||
end
|
||||
|
||||
def self.slack_authorize_url(redirect_uri, close_window: false, continue_param: nil)
|
||||
state = {
|
||||
token: SecureRandom.hex(24),
|
||||
close_window: close_window,
|
||||
@@ -355,6 +366,43 @@ class User < ApplicationRecord
|
||||
URI.parse("https://github.com/login/oauth/authorize?#{params.to_query}")
|
||||
end
|
||||
|
||||
def self.from_hca_token(code, redirect_uri)
|
||||
# Exchange code for token
|
||||
response = HTTP.post("#{HCAService.host}/oauth/token", form: {
|
||||
client_id: ENV["HCA_CLIENT_ID"],
|
||||
client_secret: ENV["HCA_CLIENT_SECRET"],
|
||||
redirect_uri: redirect_uri,
|
||||
code: code,
|
||||
grant_type: "authorization_code"
|
||||
})
|
||||
|
||||
data = JSON.parse(response.body.to_s)
|
||||
|
||||
access_token = data["access_token"]
|
||||
return nil if access_token.nil?
|
||||
|
||||
# get user info
|
||||
identity = ::HCAService.me(access_token)
|
||||
# find by HCA ID
|
||||
@user = User.find_by_hca_id(identity["id"]) unless identity["id"].blank?
|
||||
# find by slack_id
|
||||
@user ||= User.find_by_slack_uid(identity["slack_id"]) unless identity["slack_id"].blank?
|
||||
# find by email
|
||||
@user ||= begin
|
||||
EmailAddress.find_by(email: identity["email"])&.user unless identity["email"].blank?
|
||||
end
|
||||
|
||||
# update scopes if user exists
|
||||
@user.update(hca_scopes: identity["scopes"], hca_id: identity["id"]) if @user
|
||||
|
||||
# if no user, create one
|
||||
@user ||= begin
|
||||
u = User.create!(hca_id: identity["id"], slack_uid: identity["slack_id"], hca_scopes: identity["scopes"])
|
||||
EmailAddress.create!(email: identity["email"], user: u) unless identity["email"].blank?
|
||||
u
|
||||
end
|
||||
end
|
||||
|
||||
def self.from_slack_token(code, redirect_uri)
|
||||
# Exchange code for token
|
||||
response = HTTP.post("https://slack.com/api/oauth.v2.access", form: {
|
||||
|
||||
18
app/services/hca_service.rb
Normal file
18
app/services/hca_service.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
module HCAService
|
||||
def host
|
||||
if Rails.env.production?
|
||||
"https://auth.hackclub.com"
|
||||
else
|
||||
"https://hca.dinosaurbbq.org"
|
||||
end
|
||||
end
|
||||
|
||||
def me(user_token)
|
||||
raise ArgumentError, "user_token is required" unless user_token
|
||||
|
||||
response = HTTP.auth("Bearer " + user_token)
|
||||
.get(host + "/api/v1/me")
|
||||
JSON.parse(response.body)
|
||||
end
|
||||
module_function :me, :host
|
||||
end
|
||||
@@ -24,9 +24,16 @@
|
||||
<% else %>
|
||||
<h1 class="font-bold mt-1 mb-1 text-5xl text-center">Track How Much You <span class="text-primary">Code</span></h1>
|
||||
<div class="flex flex-col w-full max-w-[50vw] mx-auto mb-22">
|
||||
<% if params[:hca_auth].present? %>
|
||||
<%= link_to hca_auth_path, class: "inline-flex items-center justify-center px-6 py-3 rounded text-white font-bold cursor-pointer border-none w-full my-2 bg-primary" do %>
|
||||
<img src="/images/slack.png" class="h-8 w-8 mr-2 bg-white rounded-full p-1">
|
||||
<span class="hidden md:flex">Sign in with Hack Club</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to slack_auth_path, class: "inline-flex items-center justify-center px-6 py-3 rounded text-white font-bold cursor-pointer border-none w-full my-2 bg-primary" do %>
|
||||
<img src="/images/slack.png" class="h-8 w-8 mr-2 bg-white rounded-full p-1">
|
||||
<span class="hidden md:flex">Sign in with Hack Club Slack</span>
|
||||
<span class="hidden md:flex">Sign in with Slack</span>
|
||||
<% end %>
|
||||
|
||||
<div class="flex items-center my-4">
|
||||
|
||||
Reference in New Issue
Block a user