-
Notifications
You must be signed in to change notification settings - Fork 46
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
[WIP] OH integration #438
[WIP] OH integration #438
Changes from 8 commits
6c0b965
045ecf9
6e3831d
2137966
ffb92bb
b4de79a
a562047
74eaa46
d4f875c
63bed79
7ad4dc3
3a640e4
351c023
fecae22
136a182
bafefe4
abae3aa
682d03f
38b9218
685f591
5190efc
b343b70
4f5686b
83b8cd7
736fd08
191cb4b
e55ec4b
4089227
d8bad8b
953d10b
925daaf
2d7797b
a039afe
35f19cb
9fcdc3c
ae2d762
097be95
ede8af2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# frozen_string_literal: true | ||
|
||
class OpenHumansProfilesController < ApplicationController | ||
before_filter :require_user, except: [:index] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer before_action over before_filter. |
||
|
||
def start_auth | ||
# there's little to do for the start. Just read the .env for our client_id | ||
# then lead ppl to OH.org to give us a key | ||
client_id = ENV.fetch('OH_client_id') | ||
redirect_to "https://www.openhumans.org/direct-sharing/projects/oauth2/authorize/?client_id=#{client_id}&response_type=code" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line is too long. [128/100] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line is too long. [128/100] |
||
end | ||
|
||
def authorize | ||
# let's get the current user and their code | ||
@user = current_user | ||
@code = params[:code] | ||
oh_service = OpenHumansService.new() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not use parentheses for method calls with no arguments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not use parentheses for method calls with no arguments. |
||
|
||
# does the user have an OH profile on openSNP? if not, create one | ||
if @user.open_humans_profile == nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer the use of the nil? predicate. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer the use of the nil? predicate. |
||
@user.open_humans_profile = OpenHumansProfile.new | ||
@user.save | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was confused because an |
||
# lets convert | ||
oh_service.get_access_tokens(@user,@code) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space missing after comma. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space missing after comma. |
||
oh_service.set_open_humans_ids(@user.open_humans_profile) | ||
# delete old files if there are any | ||
begin | ||
oh_service.delete_opensnp_id(@user) | ||
end | ||
oh_service.upload_opensnp_id(@user) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
class OpenHumansProfile < ActiveRecord::Base | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add an empty line after magic comments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add an empty line after magic comments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Models should subclass ApplicationRecord. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For that we'd need Rails5, first... 🐩 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What exactly do you mean here? Follows the same convention as all other models? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rubocop wants the models to subclass a common There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok! |
||
belongs_to :user | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
class OpenHumansService | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing magic comment # frozen_string_literal: true. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is fixed… |
||
# used to do the interfacing w/ Open Humans | ||
|
||
def get_access_tokens(user,code) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space missing after comma. |
||
# authenticate w/ our client id/secret against API | ||
# post with the key the user provided us with. | ||
url = URI.parse('https://www.openhumans.org/oauth2/token/') | ||
req = Net::HTTP::Post.new(url.request_uri) | ||
req.basic_auth ENV.fetch('OH_client_id'), ENV.fetch('OH_client_secret') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The convention for environment variables is all-caps. |
||
req.set_form_data({ 'grant_type' => 'authorization_code', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant curly braces around a hash parameter. |
||
'code' => code, | ||
'redirect_uri' => "http://localhost:3000/openhumans/authorize" }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
# set up request to use https | ||
http = Net::HTTP.new(url.host, url.port) | ||
http.use_ssl = (url.scheme == 'https') | ||
# do actual request, get the json it returns | ||
response = http.request(req) | ||
response_json = JSON.parse(response.body) | ||
update_tokens(user.open_humans_profile, response_json) | ||
end | ||
|
||
def refresh_token(user) | ||
oh_profile = user.open_humans_profile | ||
url = URI.parse('https://www.openhumans.org/oauth2/token/') | ||
req = Net::HTTP::Post.new(url.request_uri) | ||
req.set_form_data({ 'grant_type' => 'refresh_token', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant curly braces around a hash parameter. |
||
'refresh_token' => oh_profile.refresh_token }) | ||
http = Net::HTTP.new(url.host, url.port) | ||
http.use_ssl = (url.scheme == 'https') | ||
response = http.request(req) | ||
response_json = JSON.parse(response.body) | ||
update_tokens(oh_profile, response_json) | ||
end | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line detected. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line detected. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra blank line detected. |
||
def set_open_humans_ids(oh_profile) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use empty lines between method definitions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use empty lines between method definitions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use empty lines between method definitions. |
||
uri = URI.parse('https://www.openhumans.org/api/direct-sharing/project/exchange-member/') | ||
uri_params = {:access_token => oh_profile.access_token} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space inside { missing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space inside { missing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space inside { missing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space inside { missing. |
||
uri.query = URI.encode_www_form(uri_params) | ||
res = Net::HTTP.get_response(uri) | ||
res_json = JSON.parse(res.body) | ||
oh_profile.project_member_id = res_json['project_member_id'] | ||
oh_profile.open_humans_user_id = res_json['username'] | ||
oh_profile.save | ||
end | ||
|
||
def upload_opensnp_id(user) | ||
base_url = 'https://www.openhumans.org/api/direct-sharing/project/files/upload/?access_token=' | ||
uri = URI.parse(base_url + user.open_humans_profile.access_token) | ||
boundary = '0P3NSNPH34RT50PENHUM4N5' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❤️ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could put that into a constant, too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done :) |
||
http = Net::HTTP.new(uri.host, uri.port) | ||
http.use_ssl = (uri.scheme == 'https') | ||
upload = Net::HTTP::Post.new(uri.request_uri) | ||
upload.content_type = "multipart/form-data; boundary=#{boundary}" | ||
post_body = generate_form_body(user,boundary) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space missing after comma. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space missing after comma. |
||
upload.body = post_body.join | ||
puts post_body.join | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not write to stdout. Use Rails's logger if you want to log. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not write to stdout. Use Rails's logger if you want to log. |
||
http.request(upload) | ||
end | ||
|
||
def delete_opensnp_id(user) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you use the |
||
base_url = 'https://www.openhumans.org/api/direct-sharing/project/files/delete/?access_token=' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could put the part of the URL all uses have in comon into a constant. You would get rid of the repetition and rubocop complaining about the long lines. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done :) |
||
url = URI.parse(base_url + user.open_humans_profile.access_token) | ||
req = Net::HTTP::Post.new(url.request_uri) | ||
oh_profile = user.open_humans_profile | ||
req.set_form_data({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant curly braces around a hash parameter. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant curly braces around a hash parameter. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant curly braces around a hash parameter. |
||
project_member_id: oh_profile.project_member_id, | ||
all_files: true | ||
}) | ||
http = Net::HTTP.new(url.host, url.port) | ||
http.use_ssl = (url.scheme == 'https') | ||
#http.set_debug_output($stdout) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing space after #. |
||
http.request(req) | ||
end | ||
|
||
private | ||
|
||
def update_tokens(oh_profile,tokens) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space missing after comma. |
||
oh_profile.expires_in = Time.current + tokens['expires_in'] | ||
oh_profile.access_token = tokens['access_token'] | ||
oh_profile.refresh_token = tokens['refresh_token'] | ||
oh_profile.save | ||
end | ||
|
||
def generate_json(user) | ||
json = { user_name: user.name, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Useless assignment to variable - json. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Useless assignment to variable - json. |
||
user_id: user.id, | ||
has_sequence: user.has_sequence, | ||
user_uri: "https://opensnp.org/users/#{user.id}" } | ||
end | ||
|
||
def generate_metadata(user) | ||
metadata = generate_json(user) | ||
metadata['tags'] = ['opensnp'] | ||
metadata['description'] = "links to openSNP user #{user.id}" | ||
return metadata | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant return detected. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is actually not redundant as it otherwise breaks the hash… There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be pretty redundant, as it is the last expression in the method. Am I missing something? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know. If I'm not running the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aaaaah! Now I get it. 💡 You don't need the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant return detected. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant return detected. |
||
end | ||
|
||
def generate_form_body(user, boundary) | ||
metadata = generate_metadata(user) | ||
file_content = generate_json(user) | ||
post_body = [] | ||
post_body << "--#{boundary}\r\n" | ||
post_body << "Content-Disposition: form-data; name=\"project_member_id\"\r\n\r\n" | ||
post_body << user.open_humans_profile.project_member_id | ||
post_body << "\r\n--#{boundary}\r\n" | ||
post_body << "Content-Disposition: form-data; name=\"metadata\"\r\n\r\n" | ||
post_body << metadata.to_json | ||
post_body << "\r\n--#{boundary}\r\n" | ||
post_body << "Content-Disposition: form-data; " | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer single-quoted strings when you don't need string interpolation or special symbols. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. breaks the form if i do that… There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure this is the only format the API accepts? This is usually what the browser generates from a form. If so, maybe you could put the whole thing in some form of template or a heredoc: def generate_form_body(user, boundary)
metadata = generate_metadata(user)
file_content = generate_json(user)
<<-POST_BODY.strip_heredoc
--#{boundary}\r
Content-Disposition: form-data; name="project_member_id"\r\n\r
#{user.open_humans_profile.project_member_id}\r
--#{boundary}\r
Content-Disposition: form-data; name="metadata"\r\n\r
#{metadata.to_json}\r
--#{boundary}\r
Content-Disposition: form-data; name="data_file"; filename="#{user.id}.json"\r\n\r
#{file_content.to_json}\r
--#{boundary}--\r\n\r
POST_BODY
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're right on this, it works! Thanks! 😍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer single-quoted strings when you don't need string interpolation or special symbols. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. breaks the form if i do that… |
||
post_body << "name=\"data_file\"; filename=\"#{user.id}.json\"\r\n\r\n" | ||
post_body << file_content.to_json | ||
post_body << "\r\n\r\n--#{boundary}--\r\n" | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<div class="general__container container"> | ||
<div class="row"> | ||
<div class="col-md-6"> | ||
<h3>Authorize</h3> | ||
</div> | ||
</div> | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# frozen_string_literal: true | ||
|
||
class CreateOpenHumansProfiles < ActiveRecord::Migration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add an empty line after magic comments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add an empty line after magic comments. |
||
def self.up | ||
create_table :open_humans_profiles do |t| | ||
t.string :open_humans_user_id | ||
t.string :project_member_id | ||
t.belongs_to :user | ||
t.string :access_token | ||
t.string :refresh_token | ||
t.timestamp :expires_in | ||
t.timestamps | ||
end | ||
end | ||
|
||
def self.down | ||
drop_table :open_humans_profiles | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer before_action over before_filter.