Repository: fossasia/open-event-server

Issue:
Enhance user model/api
**Rename fields:**

- [ ] `avatar` -> `avatar_url`
- [ ] `firstname` -> `first_name`
- [ ] `lastname` -> `last_name`
- [ ] `facebook` -> `facebook_url`
- [ ] `twitter` -> `twitter_url`
- [ ] `instagram` -> `instagram_url`
- [ ] `google` -> `google_plus_url`
- [ ] `thumbnail` -> `thumbnail_image_url`
- [ ] `small` -> `small_image_url`
- [ ] `icon` -> `icon_image_url`
- [ ] `avatar` -> `original_image_url`

**Remove fields:**

- [ ] `avatar_uploaded` -> remove. no use. 
- [ ] `signup_at` -> remove. `created_at` provides the same data.

**Handle image resizing and save:**

When ever `original_image_url` changes (ignore any changes to `small_image_url`, `thumbnail_image_url`, `icon_image_url`), download, resize it appropriately, upload it back to the storage and update `small_image_url`, `thumbnail_image_url`, `icon_image_url` fields with the new URLs



Discussion:
@niranjan94 I think the handling image resizing will be done in #3738 
From #3738 description

> When you process the data, if that URL has changed from what was before, do what you have to do to the image. Download from the URL. Process it. Store in different sizes. Get the new URLs for the different sizes. Add that info to the other image url fields.

This should be handled individually in each model/api irrespective of whether #3738 is there or not.

Resolving patch:
diff --git a/app/api/users.py b/app/api/users.py
--- a/app/api/users.py
+++ b/app/api/users.py
@@ -9,7 +9,6 @@
 from app.models.user import User
 from app.models.notification import Notification
 from app.models.event_invoice import EventInvoice
-from app.models.event import Event
 from app.api.helpers.permissions import is_admin, is_user_itself, jwt_required
 
 
@@ -17,7 +16,6 @@ class UserSchema(Schema):
     """
     Api schema for User Model
     """
-
     class Meta:
         """
         Meta class for User Api Schema
@@ -31,42 +29,42 @@ class Meta:
     id = fields.Str(dump_only=True)
     email = fields.Email(required=True)
     password = fields.Str(required=True, load_only=True)
-    avatar = fields.Str()
+    avatar_url = fields.Url()
     is_super_admin = fields.Boolean(dump_only=True)
     is_admin = fields.Boolean(dump_only=True)
     is_verified = fields.Boolean(dump_only=True)
-    signup_at = fields.DateTime(dump_only=True)
     last_accessed_at = fields.DateTime(dump_only=True)
     created_at = fields.DateTime(dump_only=True)
     deleted_at = fields.DateTime(dump_only=True)
-    firstname = fields.Str()
-    lastname = fields.Str()
+    first_name = fields.Str()
+    last_name = fields.Str()
     details = fields.Str()
     contact = fields.Str()
-    facebook = fields.Str()
-    twitter = fields.Str()
-    instagram = fields.Str()
-    google = fields.Str()
-    avatar_uploaded = fields.Str()
-    thumbnail_url = fields.Url(attribute='thumbnail')
-    small_url = fields.Url(attribute='small')
-    icon_url = fields.Url(attribute='icon')
-    notification = Relationship(attribute='notification',
-                                self_view='v1.user_notification',
-                                self_view_kwargs={'id': '<id>'},
-                                related_view='v1.notification_list',
-                                related_view_kwargs={'user_id': '<id>'},
-                                schema='NotificationSchema',
-                                many=True,
-                                type_='notification')
-    event_invoice = Relationship(attribute='event_invoice',
-                                 self_view='v1.user_event_invoice',
-                                 self_view_kwargs={'id': '<id>'},
-                                 related_view='v1.event_invoice_list',
-                                 related_view_kwargs={'user_id': '<id>'},
-                                 schema='EventInvoiceSchema',
-                                 many=True,
-                                 type_='event-invoice')
+    facebook_url = fields.Url()
+    twitter_url = fields.Url()
+    instagram_url = fields.Url()
+    google_plus_url = fields.Url()
+    thumbnail_image_url = fields.Url(attribute='thumbnail_image_url')
+    small_image_url = fields.Url(attribute='small_image_url')
+    icon_image_url = fields.Url(attribute='icon_image_url')
+    notification = Relationship(
+        attribute='notification',
+        self_view='v1.user_notification',
+        self_view_kwargs={'id': '<id>'},
+        related_view='v1.notification_list',
+        related_view_kwargs={'user_id': '<id>'},
+        schema='NotificationSchema',
+        many=True,
+        type_='notification')
+    event_invoice = Relationship(
+        attribute='event_invoice',
+        self_view='v1.user_event_invoice',
+        self_view_kwargs={'id': '<id>'},
+        related_view='v1.event_invoice_list',
+        related_view_kwargs={'user_id': '<id>'},
+        schema='EventInvoiceSchema',
+        many=True,
+        type_='event-invoice')
 
 
 class UserList(ResourceList):
@@ -85,7 +83,7 @@ class UserDetail(ResourceDetail):
     """
 
     def before_get_object(self, view_kwargs):
-        if view_kwargs.get('notification_id'):
+        if view_kwargs.get('notification_id') is not None:
             try:
                 notification = self.session.query(Notification).filter_by(
                     id=view_kwargs['notification_id']).one()
@@ -98,7 +96,7 @@ def before_get_object(self, view_kwargs):
                 else:
                     view_kwargs['id'] = None
 
-        if view_kwargs.get('event_invoice_id'):
+        if view_kwargs.get('event_invoice_id') is not None:
             try:
                 event_invoice = self.session.query(EventInvoice).filter_by(
                     id=view_kwargs['event_invoice_id']).one()
@@ -111,7 +109,7 @@ def before_get_object(self, view_kwargs):
                 else:
                     view_kwargs['id'] = None
 
-    decorators = (is_user_itself,)
+    decorators = (is_user_itself, )
     schema = UserSchema
     data_layer = {'session': db.session,
                   'model': User,
@@ -119,7 +117,8 @@ def before_get_object(self, view_kwargs):
 
 
 class UserRelationship(ResourceRelationship):
-    decorators = (jwt_required,)
+
+    decorators = (jwt_required, )
     schema = UserSchema
     data_layer = {'session': db.session,
                   'model': User}
diff --git a/app/models/user.py b/app/models/user.py
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -48,24 +48,22 @@ class User(db.Model):
     _password = db.Column(db.String(128))
     reset_password = db.Column(db.String(128))
     salt = db.Column(db.String(128))
-    avatar = db.Column(db.String)
+    avatar_url = db.Column(db.String)
     tokens = db.Column(db.Text)
-    firstname = db.Column(db.String)
-    lastname = db.Column(db.String)
+    first_name = db.Column(db.String)
+    last_name = db.Column(db.String)
     details = db.Column(db.String)
     contact = db.Column(db.String)
-    facebook = db.Column(db.String)
-    twitter = db.Column(db.String)
-    instagram = db.Column(db.String)
-    google = db.Column(db.String)
-    avatar_uploaded = db.Column(db.String)
-    thumbnail = db.Column(db.String)
-    small = db.Column(db.String)
-    icon = db.Column(db.String)
+    facebook_url = db.Column(db.String)
+    twitter_url = db.Column(db.String)
+    instagram_url = db.Column(db.String)
+    google_plus_url = db.Column(db.String)
+    thumbnail_image_url = db.Column(db.String)
+    small_image_url = db.Column(db.String)
+    icon_image_url = db.Column(db.String)
     is_super_admin = db.Column(db.Boolean, default=False)
     is_admin = db.Column(db.Boolean, default=False)
     is_verified = db.Column(db.Boolean, default=False)
-    signup_at = db.Column(db.DateTime(timezone=True))
     last_accessed_at = db.Column(db.DateTime(timezone=True))
     created_at = db.Column(db.DateTime(timezone=True), default=datetime.now(pytz.utc))
     deleted_at = db.Column(db.DateTime(timezone=True))
diff --git a/migrations/versions/c79e6d36a194_.py b/migrations/versions/c79e6d36a194_.py
new file mode 100644
--- /dev/null
+++ b/migrations/versions/c79e6d36a194_.py
@@ -0,0 +1,52 @@
+"""empty message
+
+Revision ID: c79e6d36a194
+Revises: af9215895b80
+Create Date: 2017-06-16 12:37:11.548426
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'c79e6d36a194'
+down_revision = 'af9215895b80'
+
+from alembic import op
+import sqlalchemy as sa
+import sqlalchemy_utils
+from sqlalchemy.dialects import postgresql
+
+
+def upgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.alter_column('users', 'avatar', new_column_name='avatar_url')
+    op.alter_column('users', 'facebook', new_column_name='facebook_url')
+    op.alter_column('users', 'firstname', new_column_name='first_name')
+    op.alter_column('users', 'google', new_column_name='google_plus_url')
+    op.alter_column('users', 'icon', new_column_name='icon_image_url')
+    op.alter_column('users', 'instagram', new_column_name='instagram_url')
+    op.alter_column('users', 'lastname', new_column_name='last_name')
+    op.alter_column('users', 'small', new_column_name='small_image_url')
+    op.alter_column('users', 'thumbnail', new_column_name='thumbnail_image_url')
+    op.alter_column('users', 'twitter', new_column_name='twitter_url')
+    op.drop_column('users', 'signup_at')
+    op.drop_column('users', 'avatar_uploaded')
+    ### end Alembic commands ###
+
+
+def downgrade():
+    ### commands auto generated by Alembic - please adjust! ###
+    op.add_column('users', sa.Column('avatar_uploaded',
+                                     sa.VARCHAR(), autoincrement=False, nullable=True))
+    op.add_column('users', sa.Column('signup_at', postgresql.TIMESTAMP(
+        timezone=True), autoincrement=False, nullable=True))
+    op.alter_column('users', 'twitter_url', new_column_name='twitter')
+    op.alter_column('users', 'thumbnail_image_url', new_column_name='thumbnail')
+    op.alter_column('users', 'small_image_url', new_column_name='small')
+    op.alter_column('users', 'last_name', new_column_name='lastname')
+    op.alter_column('users', 'instagram_url', new_column_name='instagram')
+    op.alter_column('users', 'icon_image_url', new_column_name='icon')
+    op.alter_column('users', 'google_plus_url', new_column_name='google')
+    op.alter_column('users', 'first_name', new_column_name='firstname')
+    op.alter_column('users', 'facebook_url', new_column_name='facebook')
+    op.alter_column('users', 'avatar_url', new_column_name='avatar')
+    ### end Alembic commands ###


Test patch: