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

Refactor: can use MOOC.fi tokens to authenticate #541

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ group :development, :test do
gem 'pry'
gem 'pry-byebug'
gem 'pry-rails'

gem 'solargraph' # vscode
gem 'database_cleaner', '~> 2.0'
gem 'launchy' # for capybara's save_and_open_page
gem 'mimic', '~> 0.4'
Expand Down
27 changes: 27 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ GEM
ast (2.4.2)
autoprefixer-rails (10.2.5.0)
execjs (< 2.8.0)
backport (1.2.0)
benchmark (0.1.1)
bootstrap (4.6.0)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 1.14.3, < 2)
Expand Down Expand Up @@ -114,6 +116,7 @@ GEM
unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.5.1)
railties (>= 5)
e2mmap (0.1.0)
erubi (1.10.0)
eventmachine (1.2.7)
execjs (2.7.0)
Expand Down Expand Up @@ -182,6 +185,7 @@ GEM
io-console (0.5.9)
irb (1.3.5)
reline (>= 0.1.5)
jaro_winkler (1.5.4)
jquery-rails (4.4.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
Expand All @@ -190,6 +194,10 @@ GEM
json-schema (2.8.1)
addressable (>= 2.4)
jwt (2.2.3)
kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
launchy (2.5.0)
addressable (~> 2.7)
letter_opener (1.7.0)
Expand Down Expand Up @@ -321,6 +329,8 @@ GEM
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
retriable (3.1.2)
reverse_markdown (2.0.0)
nokogiri
rexml (3.2.5)
rspec (3.10.0)
rspec-core (~> 3.10.0)
Expand Down Expand Up @@ -403,6 +413,21 @@ GEM
rack (~> 2.2)
rack-protection (= 2.1.0)
tilt (~> 2.0)
solargraph (0.43.0)
backport (~> 1.2)
benchmark
bundler (>= 1.17.2)
diff-lcs (~> 1.4)
e2mmap
jaro_winkler (~> 1.5)
kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.1)
parser (~> 3.0)
reverse_markdown (>= 1.0.5, < 3)
rubocop (>= 0.52)
thor (~> 1.0)
tilt (~> 2.0)
yard (~> 0.9, >= 0.9.24)
sprockets (4.0.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
Expand Down Expand Up @@ -434,6 +459,7 @@ GEM
xml-simple (1.1.8)
xpath (3.2.0)
nokogiri (~> 1.8)
yard (0.9.26)
zeitwerk (2.4.2)

PLATFORMS
Expand Down Expand Up @@ -494,6 +520,7 @@ DEPENDENCIES
ruby-prof (~> 1.4)
sassc-rails (~> 2.1)
simplecov
solargraph
sprockets-rails
swagger-blocks (~> 3.0)
uglifier (~> 4.2)
Expand Down
81 changes: 81 additions & 0 deletions app/controllers/api/v8/base_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'json'
require 'rest-client'

module Api
module V8
Expand Down Expand Up @@ -36,9 +37,16 @@ def present(hash)
private
def authenticate_user!
return @current_user if @current_user

if doorkeeper_token
@current_user ||= User.find_by(id: doorkeeper_token.resource_owner_id)
raise 'Invalid token' unless @current_user
else
moocfi_user = validate_moocfi_user
# raise 'Invalid token' unless moocfi_user

@current_user ||= User.find_by(id: moocfi_user['upstream_id']) || create_or_update_user_from_moocfi(moocfi_user)
# raise 'Invalid token' unless @current_user
end
@current_user ||= user_from_session || Guest.new
end
Expand Down Expand Up @@ -125,6 +133,79 @@ def check_client_minimum_version(client_name, client_version)
end
end
end

def bearer_token
pattern = /^Bearer /
authorization = request.authorization
authorization.gsub(pattern, '') if authorization && authorization.match(pattern)
end

def validate_moocfi_user
base_url_for_moocfi = SiteSetting.value('base_url_for_moocfi')

begin
res = RestClient::Request.execute(method: :get, url: "#{base_url_for_moocfi}/auth/validate", headers: { 'Authorization': request.authorization })
moocfi_response = JSON.parse(res.body)

moocfi_response['user']
rescue RestClient::ExceptionWithResponse => e
raise 'Invalid MOOC.fi token' if (400..499).include? e.http_code.to_i
raise 'Internal error' if e.http_code.to_i >= 500
end
end

def create_or_update_user_from_moocfi(moocfi_user)
# in case we have a discrepancy, ie. MOOC.fi user and TMC user both exist, but MOOC.fi user doesn't have TMC id
user = User.find_by(email: moocfi_user['email'])

if user
update_moocfi_user(user)
user
else
ActiveRecord::Base.transaction do
user = User.create!(
login: SecureRandom.uuid,
email: moocfi_user['email'],
password: SecureRandom.base64(12),
administrator: moocfi_user['administrator'] || false,
)
UserFieldValue.create!(field_name: 'first_name', user_id: user.id, value: moocfi_user['first_name'])
UserFieldValue.create!(field_name: 'last_name', user_id: user.id, value: moocfi_user['last_name'])
UserFieldValue.create!(field_name: 'organizational_id', user_id: user.id, value: moocfi_user['real_student_number'] || '')

update_moocfi_user(user)

UserMailer.email_confirmation(user, nil, nil).deliver_now

user
rescue StandardError, ScriptError
raise ActiveRecord::Rollback
end
end
end

def update_moocfi_user(user)
base_url_for_moocfi = SiteSetting.value('base_url_for_moocfi')
moocfi_update_secret = SiteSetting.value('moocfi_update_secret')

begin
res = RestClient::Request.execute(
method: :patch,
url: "#{base_url_for_moocfi}/api/user",
payload: { 'upstream_id': user['id'], 'secret': moocfi_update_secret }.to_json,
headers: {
'Authorization': request.authorization,
'Content-Type': 'application/json'
}
)
moocfi_response = JSON.parse(res.body)

raise "Error updating MOOC.fi user: #{moocfi_response.message}" unless moocfi_response['success']
rescue RestClient::ExceptionWithResponse => e
raise 'Error updating MOOC.fi user' if (400..499).include? e.http_code.to_i
raise 'Internal error' if e.http_code.to_i >= 500
end
end
end
end
end
4 changes: 3 additions & 1 deletion config/site.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ valid_clients:
min_version: 1.4.0
kafka_bridge_url: "test"
kafka_bridge_secret: "test"
moocfi_service_id: "test"
moocfi_service_id: "test"
moocfi_update_secret: "test"
base_url_for_moocfi: http://localhost:4000