mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 17:21:38 -05:00
Move omniauthable to a concern
This commit is contained in:
parent
a4dcd0387f
commit
bedac89821
10 changed files with 111 additions and 96 deletions
|
|
@ -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
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
2
Gemfile
2
Gemfile
|
|
@ -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
|
||||||
|
|
|
||||||
21
Gemfile.lock
21
Gemfile.lock
|
|
@ -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)
|
||||||
|
|
|
||||||
40
app/models/concerns/omniauthable.rb
Normal file
40
app/models/concerns/omniauthable.rb
Normal 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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# Load custom OmniAuth strategies
|
|
||||||
# (none currently needed)
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue