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

[PLAT-926] Add employment and institution information to user serializer #8546

Merged
merged 23 commits into from
Jul 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
510e465
add allow jobs and schools attributes to be updated and validated
Johnetordoff Jul 13, 2018
b6cf748
add tests for v2 updating of jobs and schools attributes
Johnetordoff Jul 13, 2018
9c735bb
add json schema validation and fix tests for that
Johnetordoff Jul 17, 2018
8ae71f9
remove vestigial code
Johnetordoff Jul 17, 2018
130ff07
remove _update_social unnecessary method
Johnetordoff Jul 17, 2018
270702a
fix comments
Johnetordoff Jul 17, 2018
3c6e4c3
add tests for 403s
Johnetordoff Jul 17, 2018
82ecae8
add new line to json files
Johnetordoff Jul 23, 2018
a37c058
use Django builtin validation methods
Johnetordoff Jul 23, 2018
57dabbf
DRY up tests
Johnetordoff Jul 23, 2018
d7338f3
make start year optional
Johnetordoff Jul 23, 2018
699ec81
remove extraneous code
Johnetordoff Jul 23, 2018
198fae1
Merge branch 'develop' of https://github.com/CenterForOpenScience/osf…
Johnetordoff Jul 24, 2018
aed443d
Merge branch 'master' of https://github.com/CenterForOpenScience/osf.…
Johnetordoff Jul 24, 2018
89178ff
Merge branch 'develop' of https://github.com/CenterForOpenScience/osf…
Johnetordoff Jul 24, 2018
39e0c63
unbreak tests after Travis speed up
Johnetordoff Jul 24, 2018
8fd6d66
update schemas and add more tests
Johnetordoff Jul 25, 2018
344f50a
handle startYear with no startMonth
Johnetordoff Jul 26, 2018
811b7b7
add jsonschema validation for ongoing attribute.
Johnetordoff Jul 26, 2018
b7d9324
make the employment/education schema lock tight and remove some custo…
Johnetordoff Jul 27, 2018
72d4a45
add startYear <- endYear dependency
Johnetordoff Jul 30, 2018
53ab147
check for more string types
Johnetordoff Jul 31, 2018
633aa46
move schemas and make utility functions.
Johnetordoff Jul 31, 2018
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
Empty file added api/users/schemas/__init__.py
Empty file.
62 changes: 62 additions & 0 deletions api/users/schemas/education-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"type": "array",
"items": {
"type": "object",
"properties": {
"degree": {
"type": "string"
},
"startYear": {
"type": "integer",
"minimum": 1900
},
"startMonth": {
"type": "integer",
"minimum": 1,
"maximum": 12
},
"endMonth": {
"type": "integer",
"minimum": 1,
"maximum": 12
},
"endYear": {
"type": "integer",
"minimum": 1900
},
"ongoing": {
"oneOf": [{
"enum": [false],
"required": ["startYear", "endYear"]
},
{
"enum": [true],
"required": ["startYear"],
"not": {
"required": ["endYear"]
}
}
],
"type": "boolean"
},
"department": {
"type": "string"
},
"institution": {
"type": "string",
"minLength": 1
}
},
"required": [
"institution"
],
"additionalProperties": false,
"dependencies": {
"endMonth": ["endYear"],
"startMonth": ["startYear"],
"startYear": ["ongoing"],
"endYear": ["ongoing"],
"endYear": ["startYear"]
}
}
}
62 changes: 62 additions & 0 deletions api/users/schemas/employment-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"startYear": {
"type": "integer",
"minimum": 1900
},
"startMonth": {
"type": "integer",
"minimum": 1,
"maximum": 12
},
"endMonth": {
"type": "integer",
"minimum": 1,
"maximum": 12
},
"endYear": {
"type": "integer",
"minimum": 1900
},
"ongoing": {
"oneOf": [{
"enum": [false],
"required": ["startYear", "endYear"]
},
{
"enum": [true],
"required": ["startYear"],
"not": {
"required": ["endYear"]
}
}
],
"type": "boolean"
},
"department": {
"type": "string"
},
"institution": {
"type": "string",
"minLength": 1
}
},
"required": [
"institution"
],
"additionalProperties": false,
"dependencies": {
"endMonth": ["endYear"],
"startMonth": ["startYear"],
"startYear": ["ongoing"],
"endYear": ["ongoing"],
"endYear": ["startYear"]
}
}
}
40 changes: 40 additions & 0 deletions api/users/schemas/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import os
import json
import datetime
import jsonschema

from api.base.exceptions import InvalidModelValueError

here = os.path.split(os.path.abspath(__file__))[0]

def from_json(fname):
with open(os.path.join(here, fname)) as f:
return json.load(f)


def validate_user_json(value, json_schema):
try:
jsonschema.validate(value, from_json(json_schema))
except jsonschema.ValidationError as e:
if len(e.path) > 1:
raise InvalidModelValueError("For '{}' the field value {}".format(e.path[-1], e.message))
raise InvalidModelValueError(e.message)
except jsonschema.SchemaError as e:
raise InvalidModelValueError(e.message)

validate_dates(value)


def validate_dates(info):
for history in info:

if history.get('startYear'):
startDate = datetime.date(history['startYear'], history.get('startMonth', 1), 1)

if not history['ongoing']:
if history.get('endYear'):
endDate = datetime.date(history['endYear'], history.get('endMonth', 1), 1)

if history.get('startYear') and history.get('endYear'):
if (endDate - startDate).days <= 0:
raise InvalidModelValueError(detail='End date must be greater than or equal to the start date.')
17 changes: 13 additions & 4 deletions api/users/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
from api.base.serializers import (
BaseAPISerializer, JSONAPISerializer, JSONAPIRelationshipSerializer,
VersionedDateTimeField, HideIfDisabled, IDField,
Link, LinksField, ListDictField, TypeField, RelationshipField,
WaterbutlerLink, ShowIfCurrentUser, DevOnly
Link, LinksField, ListDictField, TypeField, RelationshipField, JSONAPIListField,
WaterbutlerLink, ShowIfCurrentUser
)
from api.base.utils import absolute_reverse, get_user_auth, waterbutler_api_url_for
from api.files.serializers import QuickFilesSerializer
from osf.exceptions import ValidationValueError, ValidationError
from osf.models import OSFUser, QuickFilesNode
from api.users.schemas.utils import validate_user_json


class QuickFilesRelationshipField(RelationshipField):
Expand Down Expand Up @@ -57,8 +58,8 @@ class UserSerializer(JSONAPISerializer):
timezone = HideIfDisabled(ser.CharField(required=False, help_text="User's timezone, e.g. 'Etc/UTC"))
locale = HideIfDisabled(ser.CharField(required=False, help_text="User's locale, e.g. 'en_US'"))
social = ListDictField(required=False)
employment = DevOnly(ser.ListField(child=ser.DictField(), source='jobs', read_only=True))
education = DevOnly(ser.ListField(child=ser.DictField(), source='schools', read_only=True))
employment = JSONAPIListField(required=False, source='jobs')
education = JSONAPIListField(required=False, source='schools')
can_view_reviews = ShowIfCurrentUser(ser.SerializerMethodField(help_text='Whether the current user has the `view_submissions` permission to ANY reviews provider.'))
accepted_terms_of_service = ShowIfCurrentUser(ser.SerializerMethodField())

Expand Down Expand Up @@ -128,6 +129,14 @@ def profile_image_url(self, user):
size = self.context['request'].query_params.get('profile_image_size')
return user.profile_image_url(size=size)

def validate_employment(self, value):
validate_user_json(value, 'employment-schema.json')
return value

def validate_education(self, value):
validate_user_json(value, 'education-schema.json')
return value

def update(self, instance, validated_data):
assert isinstance(instance, OSFUser), 'instance must be a User'
for attr, value in validated_data.items():
Expand Down
Loading