Implement Doorkeeper gem (#3504)
* Add doorkeeper gem * Generate files with Doorkeeper's generator * Create Doorkeeper tables * Add new associations to User * Update associations * Remove confusing schemas * Change oauth2_provider name
This commit is contained in:
parent
b837f5b43d
commit
3071ac8c76
9 changed files with 602 additions and 0 deletions
1
Gemfile
1
Gemfile
|
|
@ -31,6 +31,7 @@ gem "dalli", "~> 2.7" # High performance memcached client for Ruby
|
|||
gem "delayed_job_active_record", "~> 4.1" # ActiveRecord backend for Delayed::Job
|
||||
gem "delayed_job_web", "~> 1.4" # Web interface for delayed_job
|
||||
gem "devise", "~> 4.6" # Flexible authentication solution for Rails
|
||||
gem "doorkeeper", "~> 5.1" # Oauth 2 provider
|
||||
gem "draper", "~> 3.1" # Draper adds an object-oriented layer of presentation logic to your Rails apps
|
||||
gem "dry-struct", "~> 1.0" # Typed structs and value objects
|
||||
gem "email_validator", "~> 2.0" # Email validator for Rails and ActiveModel
|
||||
|
|
|
|||
|
|
@ -251,6 +251,8 @@ GEM
|
|||
docile (1.3.2)
|
||||
domain_name (0.5.20180417)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
doorkeeper (5.1.0)
|
||||
railties (>= 5)
|
||||
draper (3.1.0)
|
||||
actionpack (>= 5.0)
|
||||
activemodel (>= 5.0)
|
||||
|
|
@ -863,6 +865,7 @@ DEPENDENCIES
|
|||
delayed_job_web (~> 1.4)
|
||||
derailed_benchmarks (~> 1.3)
|
||||
devise (~> 4.6)
|
||||
doorkeeper (~> 5.1)
|
||||
draper (~> 3.1)
|
||||
dry-struct (~> 1.0)
|
||||
email_validator (~> 2.0)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ class User < ApplicationRecord
|
|||
has_many :poll_votes
|
||||
has_many :poll_skips
|
||||
has_many :backup_data, foreign_key: "instance_user_id", inverse_of: :instance_user, class_name: "BackupData"
|
||||
has_many :access_grants, class_name: "Doorkeeper::AccessGrant", foreign_key: :resource_owner_id, inverse_of: :resource_owner, dependent: :delete_all
|
||||
has_many :access_tokens, class_name: "Doorkeeper::AccessToken", foreign_key: :resource_owner_id, inverse_of: :resource_owner, dependent: :delete_all
|
||||
|
||||
mount_uploader :profile_image, ProfileImageUploader
|
||||
|
||||
|
|
|
|||
333
config/initializers/doorkeeper.rb
Normal file
333
config/initializers/doorkeeper.rb
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Doorkeeper.configure do
|
||||
# Change the ORM that doorkeeper will use (needs plugins)
|
||||
orm :active_record
|
||||
|
||||
# This block will be called to check whether the resource owner is authenticated or not.
|
||||
resource_owner_authenticator do
|
||||
# raise "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
|
||||
# Put your resource owner authentication logic here.
|
||||
# Example implementation:
|
||||
# User.find_by_id(session[:user_id]) || redirect_to(new_user_session_url)
|
||||
current_user || warden.authenticate!(scope: :user)
|
||||
end
|
||||
|
||||
# If you didn't skip applications controller from Doorkeeper routes in your application routes.rb
|
||||
# file then you need to declare this block in order to restrict access to the web interface for
|
||||
# adding oauth authorized applications. In other case it will return 403 Forbidden response
|
||||
# every time somebody will try to access the admin web interface.
|
||||
#
|
||||
admin_authenticator do
|
||||
# Put your admin authentication logic here.
|
||||
# Example implementation:
|
||||
|
||||
if current_user
|
||||
head :forbidden unless current_user.admin?
|
||||
else
|
||||
redirect_to sign_in_url
|
||||
end
|
||||
end
|
||||
|
||||
# If you are planning to use Doorkeeper in Rails 5 API-only application, then you might
|
||||
# want to use API mode that will skip all the views management and change the way how
|
||||
# Doorkeeper responds to a requests.
|
||||
#
|
||||
# api_only
|
||||
|
||||
# Enforce token request content type to application/x-www-form-urlencoded.
|
||||
# It is not enabled by default to not break prior versions of the gem.
|
||||
#
|
||||
# enforce_content_type
|
||||
|
||||
# Authorization Code expiration time (default 10 minutes).
|
||||
#
|
||||
# authorization_code_expires_in 10.minutes
|
||||
|
||||
# Access token expiration time (default 2 hours).
|
||||
# If you want to disable expiration, set this to nil.
|
||||
#
|
||||
# access_token_expires_in 2.hours
|
||||
|
||||
# Assign custom TTL for access tokens. Will be used instead of access_token_expires_in
|
||||
# option if defined. In case the block returns `nil` value Doorkeeper fallbacks to
|
||||
# `access_token_expires_in` configuration option value. If you really need to issue a
|
||||
# non-expiring access token (which is not recommended) then you need to return
|
||||
# Float::INFINITY from this block.
|
||||
#
|
||||
# `context` has the following properties available:
|
||||
#
|
||||
# `client` - the OAuth client application (see Doorkeeper::OAuth::Client)
|
||||
# `grant_type` - the grant type of the request (see Doorkeeper::OAuth)
|
||||
# `scopes` - the requested scopes (see Doorkeeper::OAuth::Scopes)
|
||||
#
|
||||
# custom_access_token_expires_in do |context|
|
||||
# context.client.application.additional_settings.implicit_oauth_expiration
|
||||
# end
|
||||
|
||||
# Use a custom class for generating the access token.
|
||||
# See https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
||||
#
|
||||
# access_token_generator '::Doorkeeper::JWT'
|
||||
|
||||
# The controller Doorkeeper::ApplicationController inherits from.
|
||||
# Defaults to ActionController::Base.
|
||||
# See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
|
||||
#
|
||||
# base_controller 'ApplicationController'
|
||||
|
||||
# Reuse access token for the same resource owner within an application (disabled by default).
|
||||
#
|
||||
# This option protects your application from creating new tokens before old valid one becomes
|
||||
# expired so your database doesn't bloat. Keep in mind that when this option is `on` Doorkeeper
|
||||
# doesn't updates existing token expiration time, it will create a new token instead.
|
||||
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
||||
#
|
||||
# You can not enable this option together with +hash_token_secrets+.
|
||||
#
|
||||
# reuse_access_token
|
||||
|
||||
# Set a limit for token_reuse if using reuse_access_token option
|
||||
#
|
||||
# This option limits token_reusability to some extent.
|
||||
# If not set then access_token will be reused unless it expires.
|
||||
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
|
||||
#
|
||||
# This option should be a percentage(i.e. (0,100])
|
||||
#
|
||||
# token_reuse_limit 100
|
||||
|
||||
# Hash access and refresh tokens before persisting them.
|
||||
# This will disable the possibility to use +reuse_access_token+
|
||||
# since plain values can no longer be retrieved.
|
||||
#
|
||||
# Note: If you are already a user of doorkeeper and have existing tokens
|
||||
# in your installation, they will be invalid without enabling the additional
|
||||
# setting `fallback_to_plain_secrets` below.
|
||||
#
|
||||
# hash_token_secrets
|
||||
# By default, token secrets will be hashed using the
|
||||
# +Doorkeeper::Hashing::SHA256+ strategy.
|
||||
#
|
||||
# If you wish to use another hashing implementation, you can override
|
||||
# this strategy as follows:
|
||||
#
|
||||
# hash_token_secrets using: '::Doorkeeper::Hashing::MyCustomHashImpl'
|
||||
#
|
||||
# Keep in mind that changing the hashing function will invalidate all existing
|
||||
# secrets, if there are any.
|
||||
|
||||
# Hash application secrets before persisting them.
|
||||
#
|
||||
# hash_application_secrets
|
||||
#
|
||||
# By default, applications will be hashed
|
||||
# with the +Doorkeeper::SecretStoring::SHA256+ strategy.
|
||||
#
|
||||
# If you wish to use bcrypt for application secret hashing, uncomment
|
||||
# this line instead:
|
||||
#
|
||||
# hash_application_secrets using: '::Doorkeeper::SecretStoring::BCrypt'
|
||||
|
||||
# When the above option is enabled,
|
||||
# and a hashed token or secret is not found,
|
||||
# you can allow to fall back to another strategy.
|
||||
# For users upgrading doorkeeper and wishing to enable hashing,
|
||||
# you will probably want to enable the fallback to plain tokens.
|
||||
#
|
||||
# This will ensure that old access tokens and secrets
|
||||
# will remain valid even if the hashing above is enabled.
|
||||
#
|
||||
# fallback_to_plain_secrets
|
||||
|
||||
# Issue access tokens with refresh token (disabled by default), you may also
|
||||
# pass a block which accepts `context` to customize when to give a refresh
|
||||
# token or not. Similar to `custom_access_token_expires_in`, `context` has
|
||||
# the properties:
|
||||
#
|
||||
# `client` - the OAuth client application (see Doorkeeper::OAuth::Client)
|
||||
# `grant_type` - the grant type of the request (see Doorkeeper::OAuth)
|
||||
# `scopes` - the requested scopes (see Doorkeeper::OAuth::Scopes)
|
||||
#
|
||||
# use_refresh_token
|
||||
|
||||
# Provide support for an owner to be assigned to each registered application (disabled by default)
|
||||
# Optional parameter confirmation: true (default false) if you want to enforce ownership of
|
||||
# a registered application
|
||||
# NOTE: you must also run the rails g doorkeeper:application_owner generator
|
||||
# to provide the necessary support
|
||||
#
|
||||
# enable_application_owner confirmation: false
|
||||
|
||||
# Define access token scopes for your provider
|
||||
# For more information go to
|
||||
# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
|
||||
#
|
||||
# default_scopes :public
|
||||
# optional_scopes :write, :update
|
||||
|
||||
# Define scopes_by_grant_type to restrict only certain scopes for grant_type
|
||||
# By default, all the scopes will be available for all the grant types.
|
||||
#
|
||||
# Keys to this hash should be the name of grant_type and
|
||||
# values should be the array of scopes for that grant type.
|
||||
# Note: scopes should be from configured_scopes(i.e. deafult or optional)
|
||||
#
|
||||
# scopes_by_grant_type password: [:write], client_credentials: [:update]
|
||||
|
||||
# Forbids creating/updating applications with arbitrary scopes that are
|
||||
# not in configuration, i.e. `default_scopes` or `optional_scopes`.
|
||||
# (disabled by default)
|
||||
#
|
||||
# enforce_configured_scopes
|
||||
|
||||
# Change the way client credentials are retrieved from the request object.
|
||||
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
||||
# falls back to the `:client_id` and `:client_secret` params from the `params` object.
|
||||
# Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated
|
||||
# for more information on customization
|
||||
#
|
||||
# client_credentials :from_basic, :from_params
|
||||
|
||||
# Change the way access token is authenticated from the request object.
|
||||
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
||||
# falls back to the `:access_token` or `:bearer_token` params from the `params` object.
|
||||
# Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated
|
||||
# for more information on customization
|
||||
#
|
||||
# access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
|
||||
|
||||
# Change the native redirect uri for client apps
|
||||
# When clients register with the following redirect uri, they won't be redirected to
|
||||
# any server and the authorizationcode will be displayed within the provider
|
||||
# The value can be any string. Use nil to disable this feature. When disabled, clients
|
||||
# must providea valid URL
|
||||
# (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
|
||||
#
|
||||
# native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
|
||||
|
||||
# Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
|
||||
# by default in non-development environments). OAuth2 delegates security in
|
||||
# communication to the HTTPS protocol so it is wise to keep this enabled.
|
||||
#
|
||||
# Callable objects such as proc, lambda, block or any object that responds to
|
||||
# #call can be used in order to allow conditional checks (to allow non-SSL
|
||||
# redirects to localhost for example).
|
||||
#
|
||||
# force_ssl_in_redirect_uri !Rails.env.development?
|
||||
#
|
||||
# force_ssl_in_redirect_uri { |uri| uri.host != 'localhost' }
|
||||
|
||||
# Specify what redirect URI's you want to block during Application creation.
|
||||
# Any redirect URI is whitelisted by default.
|
||||
#
|
||||
# You can use this option in order to forbid URI's with 'javascript' scheme
|
||||
# for example.
|
||||
#
|
||||
# forbid_redirect_uri { |uri| uri.scheme.to_s.downcase == 'javascript' }
|
||||
|
||||
# Allows to set blank redirect URIs for Applications in case Doorkeeper configured
|
||||
# to use URI-less OAuth grant flows like Client Credentials or Resource Owner
|
||||
# Password Credentials. The option is on by default and checks configured grant
|
||||
# types, but you **need** to manually drop `NOT NULL` constraint from `redirect_uri`
|
||||
# column for `oauth_applications` database table.
|
||||
#
|
||||
# You can completely disable this feature with:
|
||||
#
|
||||
# allow_blank_redirect_uri false
|
||||
#
|
||||
# Or you can define your custom check:
|
||||
#
|
||||
# allow_blank_redirect_uri do |grant_flows, client|
|
||||
# client.superapp?
|
||||
# end
|
||||
|
||||
# Specify how authorization errors should be handled.
|
||||
# By default, doorkeeper renders json errors when access token
|
||||
# is invalid, expired, revoked or has invalid scopes.
|
||||
#
|
||||
# If you want to render error response yourself (i.e. rescue exceptions),
|
||||
# set handle_auth_errors to `:raise` and rescue Doorkeeper::Errors::InvalidToken
|
||||
# or following specific errors:
|
||||
#
|
||||
# Doorkeeper::Errors::TokenForbidden, Doorkeeper::Errors::TokenExpired,
|
||||
# Doorkeeper::Errors::TokenRevoked, Doorkeeper::Errors::TokenUnknown
|
||||
#
|
||||
# handle_auth_errors :raise
|
||||
|
||||
# Customize token introspection response.
|
||||
# Allows to add your own fields to default one that are required by the OAuth spec
|
||||
# for the introspection response. It could be `sub`, `aud` and so on.
|
||||
# This configuration option can be a proc, lambda or any Ruby object responds
|
||||
# to `.call` method and result of it's invocation must be a Hash.
|
||||
#
|
||||
# custom_introspection_response do |token, context|
|
||||
# {
|
||||
# "sub": "Z5O3upPC88QrAjx00dis",
|
||||
# "aud": "https://protected.example.net/resource",
|
||||
# "username": User.find(token.resource_owner_id).username
|
||||
# }
|
||||
# end
|
||||
#
|
||||
# or
|
||||
#
|
||||
# custom_introspection_response CustomIntrospectionResponder
|
||||
|
||||
# Specify what grant flows are enabled in array of Strings. The valid
|
||||
# strings and the flows they enable are:
|
||||
#
|
||||
# "authorization_code" => Authorization Code Grant Flow
|
||||
# "implicit" => Implicit Grant Flow
|
||||
# "password" => Resource Owner Password Credentials Grant Flow
|
||||
# "client_credentials" => Client Credentials Grant Flow
|
||||
#
|
||||
# If not specified, Doorkeeper enables authorization_code and
|
||||
# client_credentials.
|
||||
#
|
||||
# implicit and password grant flows have risks that you should understand
|
||||
# before enabling:
|
||||
# http://tools.ietf.org/html/rfc6819#section-4.4.2
|
||||
# http://tools.ietf.org/html/rfc6819#section-4.4.3
|
||||
#
|
||||
# grant_flows %w[authorization_code client_credentials]
|
||||
|
||||
# Hook into the strategies' request & response life-cycle in case your
|
||||
# application needs advanced customization or logging:
|
||||
#
|
||||
# before_successful_strategy_response do |request|
|
||||
# puts "BEFORE HOOK FIRED! #{request}"
|
||||
# end
|
||||
#
|
||||
# after_successful_strategy_response do |request, response|
|
||||
# puts "AFTER HOOK FIRED! #{request}, #{response}"
|
||||
# end
|
||||
|
||||
# Hook into Authorization flow in order to implement Single Sign Out
|
||||
# or add any other functionality.
|
||||
#
|
||||
# before_successful_authorization do |controller|
|
||||
# Rails.logger.info(params.inspect)
|
||||
# end
|
||||
#
|
||||
# after_successful_authorization do |controller|
|
||||
# controller.session[:logout_urls] <<
|
||||
# Doorkeeper::Application
|
||||
# .find_by(controller.request.params.slice(:redirect_uri))
|
||||
# .logout_uri
|
||||
# end
|
||||
|
||||
# Under some circumstances you might want to have applications auto-approved,
|
||||
# so that the user skips the authorization step.
|
||||
# For example if dealing with a trusted application.
|
||||
#
|
||||
# skip_authorization do |resource_owner, client|
|
||||
# client.superapp? or resource_owner.admin?
|
||||
# end
|
||||
|
||||
# WWW-Authenticate Realm (default "Doorkeeper").
|
||||
#
|
||||
# realm "Doorkeeper"
|
||||
end
|
||||
|
||||
Doorkeeper::AccessGrant.belongs_to :resource_owner, class_name: "User"
|
||||
Doorkeeper::AccessToken.belongs_to :resource_owner, class_name: "User"
|
||||
138
config/locales/doorkeeper.en.yml
Normal file
138
config/locales/doorkeeper.en.yml
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
en:
|
||||
activerecord:
|
||||
attributes:
|
||||
doorkeeper/application:
|
||||
name: 'Name'
|
||||
redirect_uri: 'Redirect URI'
|
||||
errors:
|
||||
models:
|
||||
doorkeeper/application:
|
||||
attributes:
|
||||
redirect_uri:
|
||||
fragment_present: 'cannot contain a fragment.'
|
||||
invalid_uri: 'must be a valid URI.'
|
||||
relative_uri: 'must be an absolute URI.'
|
||||
secured_uri: 'must be an HTTPS/SSL URI.'
|
||||
forbidden_uri: 'is forbidden by the server.'
|
||||
scopes:
|
||||
not_match_configured: "doesn't match configured on the server."
|
||||
|
||||
doorkeeper:
|
||||
applications:
|
||||
confirmations:
|
||||
destroy: 'Are you sure?'
|
||||
buttons:
|
||||
edit: 'Edit'
|
||||
destroy: 'Destroy'
|
||||
submit: 'Submit'
|
||||
cancel: 'Cancel'
|
||||
authorize: 'Authorize'
|
||||
form:
|
||||
error: 'Whoops! Check your form for possible errors'
|
||||
help:
|
||||
confidential: 'Application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.'
|
||||
redirect_uri: 'Use one line per URI'
|
||||
blank_redirect_uri: "Leave it blank if you configured your provider to use Client Credentials, Resource Owner Password Credentials or any other grant type that doesn't require redirect URI."
|
||||
native_redirect_uri: 'Use %{native_redirect_uri} if you want to add localhost URIs for development purposes'
|
||||
scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
|
||||
edit:
|
||||
title: 'Edit application'
|
||||
index:
|
||||
title: 'Your applications'
|
||||
new: 'New Application'
|
||||
name: 'Name'
|
||||
callback_url: 'Callback URL'
|
||||
confidential: 'Confidential?'
|
||||
actions: 'Actions'
|
||||
confidentiality:
|
||||
'yes': 'Yes'
|
||||
'no': 'No'
|
||||
new:
|
||||
title: 'New Application'
|
||||
show:
|
||||
title: 'Application: %{name}'
|
||||
application_id: 'Application UID'
|
||||
secret: 'Secret'
|
||||
scopes: 'Scopes'
|
||||
confidential: 'Confidential'
|
||||
callback_urls: 'Callback urls'
|
||||
actions: 'Actions'
|
||||
|
||||
authorizations:
|
||||
buttons:
|
||||
authorize: 'Authorize'
|
||||
deny: 'Deny'
|
||||
error:
|
||||
title: 'An error has occurred'
|
||||
new:
|
||||
title: 'Authorization required'
|
||||
prompt: 'Authorize %{client_name} to use your account?'
|
||||
able_to: 'This application will be able to'
|
||||
show:
|
||||
title: 'Authorization code'
|
||||
|
||||
authorized_applications:
|
||||
confirmations:
|
||||
revoke: 'Are you sure?'
|
||||
buttons:
|
||||
revoke: 'Revoke'
|
||||
index:
|
||||
title: 'Your authorized applications'
|
||||
application: 'Application'
|
||||
created_at: 'Created At'
|
||||
date_format: '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
pre_authorization:
|
||||
status: 'Pre-authorization'
|
||||
|
||||
errors:
|
||||
messages:
|
||||
# Common error messages
|
||||
invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
|
||||
invalid_redirect_uri: "The requested redirect uri is malformed or doesn't match client redirect URI."
|
||||
unauthorized_client: 'The client is not authorized to perform this request using this method.'
|
||||
access_denied: 'The resource owner or authorization server denied the request.'
|
||||
invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
|
||||
invalid_code_challenge_method: 'The code challenge method must be plain or S256.'
|
||||
server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
|
||||
temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
|
||||
|
||||
# Configuration error messages
|
||||
credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
|
||||
resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfigured.'
|
||||
admin_authenticator_not_configured: 'Access to admin panel is forbidden due to Doorkeeper.configure.admin_authenticator being unconfigured.'
|
||||
|
||||
# Access grant errors
|
||||
unsupported_response_type: 'The authorization server does not support this response type.'
|
||||
|
||||
# Access token errors
|
||||
invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
|
||||
invalid_grant: 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'
|
||||
unsupported_grant_type: 'The authorization grant type is not supported by the authorization server.'
|
||||
|
||||
invalid_token:
|
||||
revoked: "The access token was revoked"
|
||||
expired: "The access token expired"
|
||||
unknown: "The access token is invalid"
|
||||
|
||||
flash:
|
||||
applications:
|
||||
create:
|
||||
notice: 'Application created.'
|
||||
destroy:
|
||||
notice: 'Application deleted.'
|
||||
update:
|
||||
notice: 'Application updated.'
|
||||
authorized_applications:
|
||||
destroy:
|
||||
notice: 'Application revoked.'
|
||||
|
||||
layouts:
|
||||
admin:
|
||||
title: 'Doorkeeper'
|
||||
nav:
|
||||
oauth2_provider: 'DEV OAuth2 Provider'
|
||||
applications: 'Applications'
|
||||
home: 'Home'
|
||||
application:
|
||||
title: 'OAuth authorization required'
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
# rubocop:disable Metrics/BlockLength
|
||||
|
||||
Rails.application.routes.draw do
|
||||
use_doorkeeper
|
||||
devise_for :users, controllers: {
|
||||
omniauth_callbacks: "omniauth_callbacks",
|
||||
session: "sessions",
|
||||
|
|
|
|||
76
db/migrate/20190717220437_create_doorkeeper_tables.rb
Normal file
76
db/migrate/20190717220437_create_doorkeeper_tables.rb
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
class CreateDoorkeeperTables < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :oauth_applications do |t|
|
||||
t.string :name, null: false
|
||||
t.string :uid, null: false
|
||||
t.string :secret, null: false
|
||||
|
||||
# Remove `null: false` if you are planning to use grant flows
|
||||
# that doesn't require redirect URI to be used during authorization
|
||||
# like Client Credentials flow or Resource Owner Password.
|
||||
t.text :redirect_uri, null: false
|
||||
t.string :scopes, null: false, default: ''
|
||||
t.boolean :confidential, null: false, default: true
|
||||
t.timestamps null: false
|
||||
end
|
||||
|
||||
add_index :oauth_applications, :uid, unique: true
|
||||
|
||||
create_table :oauth_access_grants do |t|
|
||||
t.references :resource_owner, null: false
|
||||
t.references :application, null: false
|
||||
t.string :token, null: false
|
||||
t.integer :expires_in, null: false
|
||||
t.text :redirect_uri, null: false
|
||||
t.datetime :created_at, null: false
|
||||
t.datetime :revoked_at
|
||||
t.string :scopes
|
||||
end
|
||||
|
||||
add_index :oauth_access_grants, :token, unique: true
|
||||
add_foreign_key(
|
||||
:oauth_access_grants,
|
||||
:oauth_applications,
|
||||
column: :application_id
|
||||
)
|
||||
|
||||
create_table :oauth_access_tokens do |t|
|
||||
t.references :resource_owner, index: true
|
||||
t.references :application, null: false
|
||||
|
||||
# If you use a custom token generator you may need to change this column
|
||||
# from string to text, so that it accepts tokens larger than 255
|
||||
# characters. More info on custom token generators in:
|
||||
# https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
|
||||
#
|
||||
# t.text :token, null: false
|
||||
t.string :token, null: false
|
||||
|
||||
t.string :refresh_token
|
||||
t.integer :expires_in
|
||||
t.datetime :revoked_at
|
||||
t.datetime :created_at, null: false
|
||||
t.string :scopes
|
||||
|
||||
# If there is a previous_refresh_token column,
|
||||
# refresh tokens will be revoked after a related access token is used.
|
||||
# If there is no previous_refresh_token column,
|
||||
# previous tokens are revoked as soon as a new access token is created.
|
||||
# Comment out this line if you'd rather have refresh tokens
|
||||
# instantly revoked.
|
||||
t.string :previous_refresh_token, null: false, default: ""
|
||||
end
|
||||
|
||||
add_index :oauth_access_tokens, :token, unique: true
|
||||
add_index :oauth_access_tokens, :refresh_token, unique: true
|
||||
add_foreign_key(
|
||||
:oauth_access_tokens,
|
||||
:oauth_applications,
|
||||
column: :application_id
|
||||
)
|
||||
|
||||
# Uncomment below to ensure a valid reference to the resource owner's table
|
||||
add_foreign_key :oauth_access_grants, :users, column: :resource_owner_id
|
||||
add_foreign_key :oauth_access_tokens, :users, column: :resource_owner_id
|
||||
end
|
||||
end
|
||||
46
db/schema.rb
46
db/schema.rb
|
|
@ -549,6 +549,48 @@ ActiveRecord::Schema.define(version: 2019_07_23_094834) do
|
|||
t.index ["user_id"], name: "index_notifications_on_user_id"
|
||||
end
|
||||
|
||||
create_table "oauth_access_grants", force: :cascade do |t|
|
||||
t.bigint "application_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.integer "expires_in", null: false
|
||||
t.text "redirect_uri", null: false
|
||||
t.bigint "resource_owner_id", null: false
|
||||
t.datetime "revoked_at"
|
||||
t.string "scopes"
|
||||
t.string "token", null: false
|
||||
t.index ["application_id"], name: "index_oauth_access_grants_on_application_id"
|
||||
t.index ["resource_owner_id"], name: "index_oauth_access_grants_on_resource_owner_id"
|
||||
t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true
|
||||
end
|
||||
|
||||
create_table "oauth_access_tokens", force: :cascade do |t|
|
||||
t.bigint "application_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.integer "expires_in"
|
||||
t.string "previous_refresh_token", default: "", null: false
|
||||
t.string "refresh_token"
|
||||
t.bigint "resource_owner_id"
|
||||
t.datetime "revoked_at"
|
||||
t.string "scopes"
|
||||
t.string "token", null: false
|
||||
t.index ["application_id"], name: "index_oauth_access_tokens_on_application_id"
|
||||
t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
|
||||
t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
|
||||
t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true
|
||||
end
|
||||
|
||||
create_table "oauth_applications", force: :cascade do |t|
|
||||
t.boolean "confidential", default: true, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.string "name", null: false
|
||||
t.text "redirect_uri", null: false
|
||||
t.string "scopes", default: "", null: false
|
||||
t.string "secret", null: false
|
||||
t.string "uid", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
|
||||
end
|
||||
|
||||
create_table "organization_memberships", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.bigint "organization_id", null: false
|
||||
|
|
@ -1095,6 +1137,10 @@ ActiveRecord::Schema.define(version: 2019_07_23_094834) do
|
|||
add_foreign_key "chat_channel_memberships", "users"
|
||||
add_foreign_key "messages", "chat_channels"
|
||||
add_foreign_key "messages", "users"
|
||||
add_foreign_key "oauth_access_grants", "oauth_applications", column: "application_id"
|
||||
add_foreign_key "oauth_access_grants", "users", column: "resource_owner_id"
|
||||
add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id"
|
||||
add_foreign_key "oauth_access_tokens", "users", column: "resource_owner_id"
|
||||
add_foreign_key "push_notification_subscriptions", "users"
|
||||
add_foreign_key "sponsorships", "organizations"
|
||||
add_foreign_key "sponsorships", "users"
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ RSpec.describe User, type: :model do
|
|||
it { is_expected.to validate_length_of(:username).is_at_most(30).is_at_least(2) }
|
||||
it { is_expected.to validate_length_of(:name).is_at_most(100) }
|
||||
it { is_expected.to validate_inclusion_of(:inbox_type).in_array(%w[open private]) }
|
||||
it { is_expected.to have_many(:access_grants).class_name("Doorkeeper::AccessGrant").with_foreign_key("resource_owner_id").dependent(:delete_all) }
|
||||
it { is_expected.to have_many(:access_tokens).class_name("Doorkeeper::AccessToken").with_foreign_key("resource_owner_id").dependent(:delete_all) }
|
||||
|
||||
it "validates username against reserved words" do
|
||||
user = build(:user, username: "readinglist")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue