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

Update to Support MyMLH v4 #15

Closed
wants to merge 9 commits into from
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ on:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['2.7', '3.2']
ruby: ['3.2']
steps:
- uses: actions/checkout@v2
- name: Set up Ruby ${{ matrix.ruby }}
Expand Down
2 changes: 1 addition & 1 deletion lib/omniauth-mlh/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module OmniAuth
module MLH
VERSION = '1.0.1'
VERSION = '2.0.0'
end
end
68 changes: 46 additions & 22 deletions lib/omniauth/strategies/mlh.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,62 @@ class MLH < OmniAuth::Strategies::OAuth2 # :nodoc:
option :client_options, {
site: 'https://my.mlh.io',
authorize_url: 'oauth/authorize',
token_url: 'oauth/token'
token_url: 'https://api.mlh.com/v4/oauth/token'
}

uid { data[:id] }
option :auth_token_params, {
mode: :body
}

option :fields, [] # Allow configurable field expansion

uid { raw_info['id'] }

info do
data.slice(
:email,
:created_at,
:updated_at,
:first_name,
:last_name,
:level_of_study,
:major,
:date_of_birth,
:gender,
:phone_number,
:profession_type,
:company_name,
:company_title,
:scopes,
:school
)
{
id: raw_info['id'],
email: raw_info['email'],
first_name: raw_info['first_name'],
last_name: raw_info['last_name'],
created_at: raw_info['created_at'],
updated_at: raw_info['updated_at'],
roles: raw_info['roles'],
phone_number: raw_info['phone_number']
}
end

extra do
{
'raw_info' => raw_info,
'profile' => raw_info['profile'],
'address' => raw_info['address'],
'social_profiles' => raw_info['social_profiles'],
'professional_experience' => raw_info['professional_experience'],
'education' => raw_info['education'],
'identifiers' => raw_info['identifiers']
}
end

def data
@data ||= begin
access_token.get('/api/v3/user.json').parsed.deep_symbolize_keys[:data]
def raw_info
@raw_info ||= begin
access_token.get(
"https://api.mlh.com/v4/users/me#{build_fields_param}",
headers: { 'Authorization' => "Bearer #{access_token.token}" }
).parsed
rescue StandardError
{}
end
end

private

def build_fields_param
fields_array = Array(options.fields)
return '' if fields_array.empty?

fields = fields_array.map { |field| "expand[]=#{field}" }
"?#{fields.join('&')}"
end
end
end
end
Expand Down
206 changes: 205 additions & 1 deletion spec/omni_auth/mlh_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
end

it 'has correct token url' do
expect(omniauth_mlh.client.options[:token_url]).to eq('oauth/token')
expect(omniauth_mlh.client.options[:token_url]).to eq('https://api.mlh.com/v4/oauth/token')
end

it 'runs the setup block if passed one' do
Expand All @@ -36,4 +36,208 @@
expect(omniauth_mlh.callback_path).to eq('/auth/mlh/callback')
end
end

describe '#raw_info' do
let(:access_token) { instance_double('AccessToken', get: response, token: 'test_token') }
before do
allow(omniauth_mlh).to receive(:access_token).and_return(access_token)
end

context 'when the API call succeeds' do
let(:response) { instance_double('Response', parsed: { 'id' => '123' }) }

it 'returns the parsed response' do
expect(omniauth_mlh.raw_info).to eq({ 'id' => '123' })
end
end

context 'when the API call fails' do
let(:response) { instance_double('Response') }
before do
allow(response).to receive(:parsed).and_raise(StandardError)
end

it 'returns an empty hash' do
expect(omniauth_mlh.raw_info).to eq({})
end
end
end

describe '#build_fields_param' do
context 'when no fields are specified' do
it 'returns an empty string' do
expect(omniauth_mlh.send(:build_fields_param)).to eq('')
end
end

context 'when fields are specified' do
before do
@options = { fields: ['education', 'experience'] }
end

it 'returns correctly formatted query string' do
expect(omniauth_mlh.send(:build_fields_param)).to eq('?expand[]=education&expand[]=experience')
end
end

context 'when a single field is specified' do
before do
@options = { fields: 'education' }
end

it 'handles single field correctly' do
expect(omniauth_mlh.send(:build_fields_param)).to eq('?expand[]=education')
end
end
end

describe '#info' do
let(:access_token) { instance_double('AccessToken', get: response, token: 'test_token') }
before do
allow(omniauth_mlh).to receive(:access_token).and_return(access_token)
end

context 'when all fields are present' do
let(:raw_info) do
{
'id' => '123',
'email' => '[email protected]',
'first_name' => 'John',
'last_name' => 'Doe',
'created_at' => '2024-01-01T00:00:00Z',
'updated_at' => '2024-01-02T00:00:00Z',
'roles' => ['hacker', 'organizer'],
'phone_number' => '+1234567890'
}
end
let(:response) { instance_double('Response', parsed: raw_info) }

it 'returns a hash with all user information' do
expect(omniauth_mlh.info).to eq({
id: '123',
email: '[email protected]',
first_name: 'John',
last_name: 'Doe',
created_at: '2024-01-01T00:00:00Z',
updated_at: '2024-01-02T00:00:00Z',
roles: ['hacker', 'organizer'],
phone_number: '+1234567890'
})
end
end

context 'when some fields are missing' do
let(:raw_info) do
{
'id' => '123',
'email' => '[email protected]',
'first_name' => 'John'
}
end
let(:response) { instance_double('Response', parsed: raw_info) }

it 'returns a hash with available information and nil for missing fields' do
expect(omniauth_mlh.info).to eq({
id: '123',
email: '[email protected]',
first_name: 'John',
last_name: nil,
created_at: nil,
updated_at: nil,
roles: nil,
phone_number: nil
})
end
end

context 'when raw_info is empty' do
let(:response) { instance_double('Response', parsed: {}) }

it 'returns a hash with all nil values except id' do
expect(omniauth_mlh.info).to eq({
id: nil,
email: nil,
first_name: nil,
last_name: nil,
created_at: nil,
updated_at: nil,
roles: nil,
phone_number: nil
})
end
end
end

describe '#extra' do
let(:access_token) { instance_double('AccessToken', get: response, token: 'test_token') }
before do
allow(omniauth_mlh).to receive(:access_token).and_return(access_token)
end

context 'when all extra fields are present' do
let(:raw_info) do
{
'id' => '123',
'profile' => { 'bio' => 'Hacker', 'skills' => ['Ruby', 'Python'] },
'address' => { 'city' => 'New York', 'country' => 'USA' },
'social_profiles' => { 'github' => 'johndoe', 'linkedin' => 'john-doe' },
'professional_experience' => [{ 'company' => 'MLH', 'role' => 'Developer' }],
'education' => [{ 'school' => 'University', 'degree' => 'CS' }],
'identifiers' => { 'github_id' => '12345' }
}
end
let(:response) { instance_double('Response', parsed: raw_info) }

it 'returns a hash with all extra information' do
expect(omniauth_mlh.extra).to eq({
'raw_info' => raw_info,
'profile' => { 'bio' => 'Hacker', 'skills' => ['Ruby', 'Python'] },
'address' => { 'city' => 'New York', 'country' => 'USA' },
'social_profiles' => { 'github' => 'johndoe', 'linkedin' => 'john-doe' },
'professional_experience' => [{ 'company' => 'MLH', 'role' => 'Developer' }],
'education' => [{ 'school' => 'University', 'degree' => 'CS' }],
'identifiers' => { 'github_id' => '12345' }
})
end
end

context 'when some extra fields are missing' do
let(:raw_info) do
{
'id' => '123',
'profile' => { 'bio' => 'Hacker' },
'education' => [{ 'school' => 'University' }]
}
end
let(:response) { instance_double('Response', parsed: raw_info) }

it 'returns a hash with available extra information and nil for missing fields' do
expect(omniauth_mlh.extra).to eq({
'raw_info' => raw_info,
'profile' => { 'bio' => 'Hacker' },
'address' => nil,
'social_profiles' => nil,
'professional_experience' => nil,
'education' => [{ 'school' => 'University' }],
'identifiers' => nil
})
end
end

context 'when raw_info is empty' do
let(:response) { instance_double('Response', parsed: {}) }

it 'returns a hash with empty raw_info and nil values' do
expect(omniauth_mlh.extra).to eq({
'raw_info' => {},
'profile' => nil,
'address' => nil,
'social_profiles' => nil,
'professional_experience' => nil,
'education' => nil,
'identifiers' => nil
})
end
end
end
end
Loading