diff --git a/data/database.py b/data/database.py index b10df6bc1..19bc24e11 100644 --- a/data/database.py +++ b/data/database.py @@ -437,6 +437,7 @@ class User(BaseModel): given_name = CharField(null=True) family_name = CharField(null=True) company = CharField(null=True) + location = CharField(null=True) def delete_instance(self, recursive=False, delete_nullable=False): # If we are deleting a robot account, only execute the subset of queries necessary. diff --git a/data/migrations/versions/cbc8177760d9_add_user_location_field.py b/data/migrations/versions/cbc8177760d9_add_user_location_field.py new file mode 100644 index 000000000..b88f6da42 --- /dev/null +++ b/data/migrations/versions/cbc8177760d9_add_user_location_field.py @@ -0,0 +1,23 @@ +"""Add user location field + +Revision ID: cbc8177760d9 +Revises: 7367229b38d9 +Create Date: 2018-02-02 17:39:16.589623 + +""" + +# revision identifiers, used by Alembic. +revision = 'cbc8177760d9' +down_revision = '7367229b38d9' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql +from util.migrate import UTF8CharField + +def upgrade(tables): + op.add_column('user', sa.Column('location', UTF8CharField(length=255), nullable=True)) + + +def downgrade(tables): + op.drop_column('user', 'location') diff --git a/data/model/user.py b/data/model/user.py index 2de7f9418..c1fd36165 100644 --- a/data/model/user.py +++ b/data/model/user.py @@ -381,12 +381,15 @@ def list_entity_robot_permission_teams(entity_name, include_permissions=False): return TupleSelector(query, fields) -def update_user_metadata(user, given_name=None, family_name=None, company=None): +def update_user_metadata(user, metadata=None): """ Updates the metadata associated with the user, including his/her name and company. """ + metadata = metadata if metadata is not None else {} + with db_transaction(): - user.given_name = given_name or user.given_name - user.family_name = family_name or user.family_name - user.company = company or user.company + user.given_name = metadata.get('given_name') or user.given_name + user.family_name = metadata.get('family_name') or user.family_name + user.company = metadata.get('company') or user.company + user.location = metadata.get('location') or user.location user.save() # Remove any prompts associated with the user's metadata being needed. diff --git a/endpoints/api/user.py b/endpoints/api/user.py index 4146fed1b..35838559a 100644 --- a/endpoints/api/user.py +++ b/endpoints/api/user.py @@ -135,6 +135,7 @@ def user_view(user, previous_username=None): 'company': user.company, 'family_name': user.family_name, 'given_name': user.given_name, + 'location': user.location, }) analytics_metadata = user_analytics.get_user_analytics_metadata(user) @@ -246,6 +247,10 @@ class User(ApiResource): 'type': 'string', 'description': 'The optional entered company for the user', }, + 'location': { + 'type': 'string', + 'description': 'The optional entered location for the user', + }, }, }, 'UserView': { @@ -362,9 +367,15 @@ class User(ApiResource): model.user.update_email(user, new_email, auto_verify=not features.MAILING) if features.USER_METADATA: - if 'given_name' in user_data or 'family_name' in user_data or 'company' in user_data: - model.user.update_user_metadata(user, user_data.get('given_name'), - user_data.get('family_name'), user_data.get('company')) + metadata_fields = ('given_name', 'family_name', 'company', 'location') + if any(field in user_data for field in metadata_fields): + model.user.update_user_metadata(user, { + 'given_name': user_data.get('given_name'), + 'family_name': user_data.get('family_name'), + 'company': user_data.get('company'), + 'location': user_data.get('location'), + }) + ua_mdata_future = user_analytics.change_metadata( user.email, user_data.get('given_name'), diff --git a/endpoints/common_models_interface.py b/endpoints/common_models_interface.py index 4a9978eab..95ccf5685 100644 --- a/endpoints/common_models_interface.py +++ b/endpoints/common_models_interface.py @@ -4,7 +4,11 @@ from collections import namedtuple from six import add_metaclass -class User(namedtuple('User', ['uuid', 'username', 'email', 'given_name', 'family_name', 'company'])): +USER_FIELDS = ['uuid', 'username', 'email', 'given_name', + 'family_name', 'company', 'location'] + + +class User(namedtuple('User', USER_FIELDS)): """ User represents a user. """ diff --git a/endpoints/common_models_pre_oci.py b/endpoints/common_models_pre_oci.py index 833579d90..1f5e01052 100644 --- a/endpoints/common_models_pre_oci.py +++ b/endpoints/common_models_pre_oci.py @@ -9,7 +9,8 @@ class EndpointsCommonDataPreOCIModel(EndpointsCommonDataInterface): return None return User(uuid=user.uuid, username=user.username, email=user.email, - given_name=user.given_name, family_name=user.family_name, company=user.company) + given_name=user.given_name, family_name=user.family_name, + company=user.company, location=user.location) def get_namespace_uuid(self, namespace_name): user = model.user.get_namespace_user(namespace_name) diff --git a/static/partials/update-user.html b/static/partials/update-user.html index 92915f259..dbd835820 100644 --- a/static/partials/update-user.html +++ b/static/partials/update-user.html @@ -68,6 +68,15 @@ +
+ +
+ + + +
+
+
@@ -76,4 +85,4 @@ No thanks
- \ No newline at end of file + diff --git a/static/partials/user-view.html b/static/partials/user-view.html index 3ff99051d..93c341d2e 100644 --- a/static/partials/user-view.html +++ b/static/partials/user-view.html @@ -152,6 +152,12 @@ {{ context.viewuser.company || '(None)' }} + + Location: + + {{ context.viewuser.location || '(None)' }} + + Password: diff --git a/test/data/test.db b/test/data/test.db index c3664e16b..81c56527d 100644 Binary files a/test/data/test.db and b/test/data/test.db differ