Move omniauthable to a concern

This commit is contained in:
Eugene Burmakin 2025-11-14 18:54:35 +01:00
parent a4dcd0387f
commit bedac89821
10 changed files with 111 additions and 96 deletions

View file

@ -1,50 +0,0 @@
# OAuth Configuration
# GitHub OAuth
GITHUB_OAUTH_CLIENT_ID=
GITHUB_OAUTH_CLIENT_SECRET=
# Google OAuth2
GOOGLE_OAUTH_CLIENT_ID=
GOOGLE_OAUTH_CLIENT_SECRET=
# Generic OpenID Connect (for Authelia, Authentik, Keycloak, etc.)
# Option 1: Using OIDC Discovery (Recommended)
# Set OIDC_ISSUER to your provider's issuer URL (e.g., https://auth.example.com)
# The provider must support OpenID Connect Discovery (.well-known/openid-configuration)
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_ISSUER=
OIDC_REDIRECT_URI=
# Option 2: Manual Endpoint Configuration (if discovery is not supported)
# Use this if your provider doesn't support OIDC discovery
# OIDC_CLIENT_ID=
# OIDC_CLIENT_SECRET=
# OIDC_HOST=auth.example.com
# OIDC_SCHEME=https
# OIDC_PORT=443
# OIDC_AUTHORIZATION_ENDPOINT=/authorize
# OIDC_TOKEN_ENDPOINT=/token
# OIDC_USERINFO_ENDPOINT=/userinfo
# OIDC_REDIRECT_URI=https://yourdomain.com/users/auth/openid_connect/callback
# Example configurations:
#
# Authelia:
# OIDC_ISSUER=https://auth.example.com
# OIDC_CLIENT_ID=your-client-id
# OIDC_CLIENT_SECRET=your-client-secret
# OIDC_REDIRECT_URI=https://dawarich.example.com/users/auth/openid_connect/callback
#
# Authentik:
# OIDC_ISSUER=https://authentik.example.com/application/o/dawarich/
# OIDC_CLIENT_ID=your-client-id
# OIDC_CLIENT_SECRET=your-client-secret
# OIDC_REDIRECT_URI=https://dawarich.example.com/users/auth/openid_connect/callback
#
# Keycloak:
# OIDC_ISSUER=https://keycloak.example.com/realms/your-realm
# OIDC_CLIENT_ID=dawarich
# OIDC_CLIENT_SECRET=your-client-secret
# OIDC_REDIRECT_URI=https://dawarich.example.com/users/auth/openid_connect/callback

View file

@ -23,7 +23,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Implemented authentication via GitHub and Google for Dawarich Cloud. - Implemented authentication via GitHub and Google for Dawarich Cloud.
- Implemented OpenID Connect authentication for self-hosted Dawarich instances. #66 - Implemented OpenID Connect authentication for self-hosted Dawarich instances. #66
- Added Patreon OAuth integration for Dawarich Cloud, allowing users to connect their Patreon accounts in account settings.
## TODO: ## TODO:

View file

@ -5,7 +5,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby File.read('.ruby-version').strip ruby File.read('.ruby-version').strip
gem 'activerecord-postgis-adapter', '~> 11.0' gem 'activerecord-postgis-adapter', '11.0'
# https://meta.discourse.org/t/cant-rebuild-due-to-aws-sdk-gem-bump-and-new-aws-data-integrity-protections/354217/40 # https://meta.discourse.org/t/cant-rebuild-due-to-aws-sdk-gem-bump-and-new-aws-data-integrity-protections/354217/40
gem 'aws-sdk-core', '~> 3.215.1', require: false gem 'aws-sdk-core', '~> 3.215.1', require: false
gem 'aws-sdk-kms', '~> 1.96.0', require: false gem 'aws-sdk-kms', '~> 1.96.0', require: false

View file

@ -110,6 +110,7 @@ GEM
bcrypt (3.1.20) bcrypt (3.1.20)
benchmark (0.4.1) benchmark (0.4.1)
bigdecimal (3.3.1) bigdecimal (3.3.1)
bindata (2.5.1)
bootsnap (1.18.6) bootsnap (1.18.6)
msgpack (~> 1.2) msgpack (~> 1.2)
brakeman (7.1.0) brakeman (7.1.0)
@ -163,6 +164,8 @@ GEM
dotenv (= 3.1.8) dotenv (= 3.1.8)
railties (>= 6.1) railties (>= 6.1)
drb (2.2.3) drb (2.2.3)
email_validator (2.2.4)
activemodel
erb (5.1.3) erb (5.1.3)
erubi (1.13.1) erubi (1.13.1)
et-orbi (1.4.0) et-orbi (1.4.0)
@ -384,6 +387,17 @@ GEM
raabro (1.4.0) raabro (1.4.0)
racc (1.8.1) racc (1.8.1)
rack (3.2.3) rack (3.2.3)
rack-oauth2 (2.3.0)
activesupport
attr_required
faraday (~> 2.0)
faraday-follow_redirects
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
rack-protection (4.2.1)
base64 (>= 0.1.0)
logger (>= 1.6.0)
rack (>= 3.0.0, < 4)
rack-session (2.1.1) rack-session (2.1.1)
base64 (>= 0.1.0) base64 (>= 0.1.0)
rack (>= 3.0.0) rack (>= 3.0.0)
@ -558,6 +572,11 @@ GEM
attr_extras (>= 6.2.4) attr_extras (>= 6.2.4)
diff-lcs diff-lcs
patience_diff patience_diff
swd (2.0.3)
activesupport (>= 3)
attr_required (>= 0.0.5)
faraday (~> 2.0)
faraday-follow_redirects
tailwindcss-rails (3.3.2) tailwindcss-rails (3.3.2)
railties (>= 7.0.0) railties (>= 7.0.0)
tailwindcss-ruby (~> 3.0) tailwindcss-ruby (~> 3.0)
@ -614,7 +633,7 @@ PLATFORMS
x86_64-linux x86_64-linux
DEPENDENCIES DEPENDENCIES
activerecord-postgis-adapter (~> 11.0) activerecord-postgis-adapter (= 11.0)
aws-sdk-core (~> 3.215.1) aws-sdk-core (~> 3.215.1)
aws-sdk-kms (~> 1.96.0) aws-sdk-kms (~> 1.96.0)
aws-sdk-s3 (~> 1.177.0) aws-sdk-s3 (~> 1.177.0)

View file

@ -0,0 +1,40 @@
# frozen_string_literal: true
module Omniauthable
extend ActiveSupport::Concern
class_methods do
def from_omniauth(access_token)
data = access_token.info
provider = access_token.provider
uid = access_token.uid
# First, try to find user by provider and uid (for linked accounts)
user = find_by(provider: provider, uid: uid)
if user
# User found by provider/uid
return user
end
# If not found, try to find by email
user = find_by(email: data['email'])
if user
# Update provider and uid for existing user (first-time linking)
user.update(provider: provider, uid: uid)
return user
end
# Create new user if not found
user = create(
email: data['email'],
password: Devise.friendly_token[0, 20],
provider: provider,
uid: uid
)
user
end
end
end

View file

@ -2,6 +2,7 @@
class User < ApplicationRecord # rubocop:disable Metrics/ClassLength class User < ApplicationRecord # rubocop:disable Metrics/ClassLength
include UserFamily include UserFamily
include Omniauthable
devise :database_authenticatable, :registerable, devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :trackable, :recoverable, :rememberable, :validatable, :trackable,
@ -147,39 +148,6 @@ class User < ApplicationRecord # rubocop:disable Metrics/ClassLength
points.where.not(city: [nil, '']).distinct.pluck(:city).compact points.where.not(city: [nil, '']).distinct.pluck(:city).compact
end end
def self.from_omniauth(access_token)
data = access_token.info
provider = access_token.provider
uid = access_token.uid
# First, try to find user by provider and uid (for linked accounts)
user = User.find_by(provider: provider, uid: uid)
if user
# User found by provider/uid
return user
end
# If not found, try to find by email
user = User.find_by(email: data['email'])
if user
# Update provider and uid for existing user (first-time linking)
user.update(provider: provider, uid: uid)
return user
end
# Create new user if not found
user = User.create(
email: data['email'],
password: Devise.friendly_token[0, 20],
provider: provider,
uid: uid
)
user
end
private private
def create_api_key def create_api_key

View file

@ -72,10 +72,7 @@
<% unless DawarichSettings.self_hosted? %> <% unless DawarichSettings.self_hosted? %>
<div> <div>
<h2 class="text-2xl font-bold mb-4 flex items-center"> <h2 class="text-2xl font-bold mb-4 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-link mr-2 text-primary"> <%= icon 'link', class: "h-6 w-6 text-info-content" %>Connected Accounts
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
</svg>Connected Accounts
</h2> </h2>
<div class="bg-base-100 p-5 rounded-lg shadow-sm space-y-4"> <div class="bg-base-100 p-5 rounded-lg shadow-sm space-y-4">
<p class="text-sm text-base-content/70"> <p class="text-sm text-base-content/70">

View file

@ -266,8 +266,8 @@ Devise.setup do |config|
# Add a new OmniAuth provider. Check the wiki for more information on setting # Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks. # up on your models and hooks.
# Cloud version: only GitHub, Google, and Patreon OAuth (when env vars present) # Cloud version: only GitHub, Google (when env vars present)
unless SELF_HOSTED if !SELF_HOSTED
if ENV['GITHUB_OAUTH_CLIENT_ID'].present? && ENV['GITHUB_OAUTH_CLIENT_SECRET'].present? if ENV['GITHUB_OAUTH_CLIENT_ID'].present? && ENV['GITHUB_OAUTH_CLIENT_SECRET'].present?
config.omniauth :github, ENV['GITHUB_OAUTH_CLIENT_ID'], ENV['GITHUB_OAUTH_CLIENT_SECRET'], scope: 'user:email' config.omniauth :github, ENV['GITHUB_OAUTH_CLIENT_ID'], ENV['GITHUB_OAUTH_CLIENT_SECRET'], scope: 'user:email'
Rails.logger.info 'OAuth: GitHub configured' Rails.logger.info 'OAuth: GitHub configured'

View file

@ -1,4 +0,0 @@
# frozen_string_literal: true
# Load custom OmniAuth strategies
# (none currently needed)

View file

@ -139,3 +139,49 @@ APP_MEMORY_LIMIT=4G
# SECRET_KEY_BASE=your-generated-secret-key # SECRET_KEY_BASE=your-generated-secret-key
# SELF_HOSTED=true # SELF_HOSTED=true
# PROMETHEUS_EXPORTER_ENABLED=true # PROMETHEUS_EXPORTER_ENABLED=true
# =============================================================================
# Example of configuration for OpenID Connect (OIDC) authentication
#
# =============================================================================
# Generic OpenID Connect (for Authelia, Authentik, Keycloak, etc.)
# Option 1: Using OIDC Discovery (Recommended)
# Set OIDC_ISSUER to your provider's issuer URL (e.g., https://auth.example.com)
# The provider must support OpenID Connect Discovery (.well-known/openid-configuration)
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_ISSUER=
OIDC_REDIRECT_URI=
# Option 2: Manual Endpoint Configuration (if discovery is not supported)
# Use this if your provider doesn't support OIDC discovery
# OIDC_CLIENT_ID=
# OIDC_CLIENT_SECRET=
# OIDC_HOST=auth.example.com
# OIDC_SCHEME=https
# OIDC_PORT=443
# OIDC_AUTHORIZATION_ENDPOINT=/authorize
# OIDC_TOKEN_ENDPOINT=/token
# OIDC_USERINFO_ENDPOINT=/userinfo
# OIDC_REDIRECT_URI=https://yourdomain.com/users/auth/openid_connect/callback
# Example configurations:
#
# Authelia:
# OIDC_ISSUER=https://auth.example.com
# OIDC_CLIENT_ID=your-client-id
# OIDC_CLIENT_SECRET=your-client-secret
# OIDC_REDIRECT_URI=https://dawarich.example.com/users/auth/openid_connect/callback
#
# Authentik:
# OIDC_ISSUER=https://authentik.example.com/application/o/dawarich/
# OIDC_CLIENT_ID=your-client-id
# OIDC_CLIENT_SECRET=your-client-secret
# OIDC_REDIRECT_URI=https://dawarich.example.com/users/auth/openid_connect/callback
#
# Keycloak:
# OIDC_ISSUER=https://keycloak.example.com/realms/your-realm
# OIDC_CLIENT_ID=dawarich
# OIDC_CLIENT_SECRET=your-client-secret
# OIDC_REDIRECT_URI=https://dawarich.example.com/users/auth/openid_connect/callback