Skip to content

Commit

Permalink
Merge c7aefa2 into f717415
Browse files Browse the repository at this point in the history
  • Loading branch information
dhakim87 committed Feb 6, 2020
2 parents f717415 + c7aefa2 commit f543b96
Show file tree
Hide file tree
Showing 14 changed files with 963 additions and 80 deletions.
148 changes: 125 additions & 23 deletions microsetta_private_api/api/implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from flask import jsonify, render_template
import jwt
from base64 import b64decode

from microsetta_private_api.model.address import Address
from microsetta_private_api.repo.transaction import Transaction
from microsetta_private_api.repo.account_repo import AccountRepo
from microsetta_private_api.repo.source_repo import SourceRepo
Expand All @@ -23,13 +25,16 @@
from microsetta_private_api.repo.survey_answers_repo import SurveyAnswersRepo
from microsetta_private_api.repo.sample_repo import SampleRepo

from microsetta_private_api.model.account import Account
from microsetta_private_api.model.source import Source
from microsetta_private_api.model.source import human_info_from_api
from microsetta_private_api.LEGACY.locale_data import american_gut

from microsetta_private_api.util import vue_adapter

import uuid
import json
from datetime import date

TOKEN_KEY = "QvMWMnlOqBbNsM88AMxpzcJMbBUu/w8U9joIaNYjuEbwEYhLIB5FqEoFWnfLN3JZN4SD0LAtZOwFNqyMLmNruBLqEvbpjQzM6AY+BfXGxDVFL65c9Xw8ocd6t1nF6YvTpHGB4NJhUwngjIQmFx+6TCa5wArtEqUeoIc1ukVTYbioRkxzi5ju8cc9/PoInB0c7wugMz5ihAPWohpDc4kCotYv7C2K/e9J9CPdwbiLJKYKxO4zSQAqk+Sj4wRcn7bJqIOIT6BlvvnzRGXYG33qXAxGylM4UySj7ltwSGOIY0/JUvKEej3fX17C8wWtJvrjbFQacNhoglqfWq2GeOdRSA== " # noqa: E501
TEMP_ACCESS_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbXlhcHAuY29tLyIsInN1YiI6InVzZXJzL3VzZXIxMjM0Iiwic2NvcGUiOiJzZWxmLCBhZG1pbnMiLCJqdGkiOiJkMzBkMzA5ZS1iZTQ5LTRjOWEtYjdhYi1hMGU3MTIwYmFlZDMiLCJpYXQiOjE1NzIzNzY4OTUsImV4cCI6MTU3MjM4MDQ5NX0.EMooERuy2Z4tC_TsXJe6Vx8yCgzTzI_qh84a5DsKPRw" # noqa: E501
Expand Down Expand Up @@ -68,7 +73,38 @@ def verify_and_decode_token(access_token) -> dict:


def register_account(body):
return not_yet_implemented()
# TODO: Do they register with GLOBUS first, then make the account here?
# What should be done with the kit_name?
new_acct_id = str(uuid.uuid4())
with Transaction() as t:
kit_repo = KitRepo(t)
kit = kit_repo.get_kit(body['kit_name'])
if kit is None:
return jsonify(error=403, text="Incorrect kit_name"), 403

acct_repo = AccountRepo(t)
acct_repo.create_account(Account(
new_acct_id,
body['email'],
"standard",
"GLOBUS", # TODO: This is dependent on their login token!
body['first_name'],
body['last_name'],
Address(
body['address']['street'],
body['address']['city'],
body['address']['state'],
body['address']['post_code'],
body['address']['country_code'],
)
))
new_acct = acct_repo.get_account(new_acct_id)
t.commit()

response = jsonify(new_acct.to_api())
response.status_code = 201
response.headers['Location'] = '/api/accounts/%s' % new_acct_id
return response


def read_account(token_info, account_id):
Expand All @@ -92,10 +128,16 @@ def update_account(account_id, body):

# TODO: add 422 handling

acc.first_name = body["first_name"]
acc.last_name = body["last_name"]
acc.email = body["email"]
acc.address = body["address"]
acc.first_name = body['first_name']
acc.last_name = body['last_name']
acc.email = body['email']
acc.address = Address(
body['address']['street'],
body['address']['city'],
body['address']['state'],
body['address']['post_code'],
body['address']['country_code']
)

acct_repo.update_account(acc)
t.commit()
Expand All @@ -115,14 +157,32 @@ def create_source(account_id, body):
with Transaction() as t:
source_repo = SourceRepo(t)
source_id = str(uuid.uuid4())
source_info = None
new_source = Source.from_json(source_id, account_id, source_info)

if body['source_type'] == 'human':
# TODO: Unfortunately, humans require a lot of special handling,
# and we started mixing Source calls used for transforming to/
# from the database with source calls to/from the api.
# Would be nice to split this out better.
new_source = Source(source_id,
account_id,
'human',
human_info_from_api(body,
consent_date=date.today(),
date_revoked=None))
else:
new_source = Source.build_source(source_id, account_id, body)

source_repo.create_source(new_source)

# Must pull from db to get creation_time, update_time
s = source_repo.get_source(account_id, new_source.id)
t.commit()
# TODO: What about 404 and 422 errors?
return jsonify(s.to_api()), 200

response = jsonify(s.to_api())
response.status_code = 201
response.headers['Location'] = '/api/accounts/%s/sources/%s' % \
(account_id, source_id)
return response


def read_source(account_id, source_id):
Expand Down Expand Up @@ -223,36 +283,57 @@ def submit_answered_survey(account_id, source_id, language_tag, body):
# TODO: Rename survey_text to survey_model/model to match Vue's naming?
with Transaction() as t:
survey_answers_repo = SurveyAnswersRepo(t)
success = survey_answers_repo.submit_answered_survey(
survey_answers_id = survey_answers_repo.submit_answered_survey(
account_id,
source_id,
language_tag,
body["survey_template_id"],
body["survey_text"]
)
if success:
t.commit()
return jsonify(''), 201
return jsonify(code=422,
message="Could not submit answered survey"), 422
t.commit()

response = jsonify('')
response.status_code = 201
response.headers['Location'] = '/api/accounts/%s' \
'/sources/%s' \
'/surveys/%s' % \
(account_id,
source_id,
survey_answers_id)
return response


def read_sample_associations(account_id, source_id):
return not_yet_implemented()
with Transaction() as t:
sample_repo = SampleRepo(t)
samples = sample_repo.get_samples_by_source(account_id, source_id)

api_samples = [x.to_api() for x in samples]
return jsonify(api_samples), 200


def associate_sample(account_id, source_id, body):
return not_yet_implemented()
with Transaction() as t:
sample_repo = SampleRepo(t)
sample_repo.associate_sample(account_id,
source_id,
body['sample_id'])
t.commit()
response = jsonify('')
response.status_code = 201
response.headers['Location'] = '/api/accounts/%s/sources/%s/samples/%s' % \
(account_id, source_id, ['sample_id'])
return response


def read_sample_association(account_id, source_id, sample_id):
with Transaction() as t:
sample_repo = SampleRepo(t)
sample = sample_repo.get_sample(sample_id)
sample = sample_repo.get_sample(account_id, source_id, sample_id)
if sample is None:
return jsonify(error=404, text="Sample not found"), 404

return jsonify(sample), 200
return jsonify(sample.to_api()), 200


def update_sample_association(account_id, source_id, sample_id, body):
Expand Down Expand Up @@ -301,12 +382,33 @@ def render_consent_doc(account_id):


def create_human_source_from_consent(account_id, body):
# A human source's participant name becomes the source name. Note pop
# removes the existing `participant_name` key if exists, else errors.
# Must convert consent form body into object processable by create_source.

# Not adding any error handling here because if 'participant_name' isn't
# here, we SHOULD be getting an error.
body['source_name'] = body.pop('participant_name')
source = {
'source_type': "human",
'source_name': body['participant_name'],
'consent': {
'participant_email': body['participant_email'],
'age_range': body['age_range']
}
}

child_keys = ['parent_1_name', 'parent_2_name',
'deceased_parent', 'obtainer_name']

any_in = False
for key in child_keys:
if key in body:
any_in = True

if any_in:
source['consent']['child_info'] = {}
for key in child_keys:
if key in body:
source['consent']['child_info'][key] = body[key]

# NB: Don't expect to handle errors 404, 422 in this function; expect to
# farm out to `create_source`
return create_source(account_id, body)
return create_source(account_id, source)
18 changes: 14 additions & 4 deletions microsetta_private_api/api/microsetta_private_api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ paths:
$ref: '#/components/schemas/account'
'401':
$ref: '#/components/responses/401Unauthorized'
'403':
$ref: '#/components/responses/403Forbidden'
'422':
$ref: '#/components/responses/422UnprocessableEntity'

Expand Down Expand Up @@ -822,7 +824,7 @@ components:
in: path
description: Unique id specifying a sample associated with a source
schema:
$ref: '#/components/schemas/survey_id'
$ref: '#/components/schemas/sample_id'
required: true
survey_id:
name: survey_id
Expand Down Expand Up @@ -871,6 +873,12 @@ components:
responses:
401Unauthorized: # Can be referenced as '#/components/responses/401Unauthorized'
description: Invalid or missing token.
403Forbidden: # Can be referenced as '#/components/responses/403Forbidden'
description: Incorrect required parameter.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
404NotFound: # Can be referenced as '#/components/responses/404NotFound'
description: The specified resource was not found.
422UnprocessableEntity:
Expand Down Expand Up @@ -1065,6 +1073,8 @@ components:
source_type:
type: string
enum: [animal, environmental]
source_name:
type: string
source_description:
type: string
nullable: true
Expand Down Expand Up @@ -1107,8 +1117,8 @@ components:

# survey template section
survey_template_id:
type: string
example: "e928f910-bf11-4cda-93b5-c34c8914b97f"
type: integer
example: 3
survey_template_title:
type: string
example: "Personal Information"
Expand Down Expand Up @@ -1205,7 +1215,7 @@ components:
example: "69f697cb-8e52-4a4f-8db2-efffcfa186a5"
survey_text:
# The contents of this string ARE structured, but their structure is not specified in THIS api.
type: string
type: object
example: '{ |
"1": "Omnivore", |
"2": "No", |
Expand Down
Loading

0 comments on commit f543b96

Please sign in to comment.