Repository: fossasia/open-event-server

Issue:
User can see draft events
Like event list API, draft events should only be visible to the admins or organizers. But, right now, draft events can be seen by anyone with event identifier. Event detail API should behave similar to event list API. 

- [ ] Fix the bug
- [ ] Add the test


Discussion:
can I try to work upon it ?
Go ahead

Resolving patch:
diff --git a/app/api/events.py b/app/api/events.py
--- a/app/api/events.py
+++ b/app/api/events.py
@@ -659,6 +659,13 @@ def before_get_object(self, view_kwargs):
             else:
                 view_kwargs['id'] = None
 
+    def after_get_object(self, event, view_kwargs):
+        if event.state == "draft":
+            if 'Authorization' not in request.headers or not has_access(
+                'is_coorganizer', event_id=event.id
+            ):
+                raise ObjectNotFound({'parameter': '{id}'}, "Event: not found")
+
     def before_patch(self, args, kwargs, data=None):
         """
         before patch method to verify if the event location is provided before publishing the event and checks that
@@ -724,6 +731,7 @@ def after_update_object(self, event, data, view_kwargs):
         'methods': {
             'before_update_object': before_update_object,
             'before_get_object': before_get_object,
+            'after_get_object': after_get_object,
             'after_update_object': after_update_object,
             'before_patch': before_patch,
         },
diff --git a/app/models/event.py b/app/models/event.py
--- a/app/models/event.py
+++ b/app/models/event.py
@@ -73,7 +73,7 @@ class Event(SoftDeletionModel):
     feedbacks = db.relationship('Feedback', backref="event")
     attendees = db.relationship('TicketHolder', backref="event")
     privacy = db.Column(db.String, default="public")
-    state = db.Column(db.String, default="Draft")
+    state = db.Column(db.String, default="draft")
     event_type_id = db.Column(
         db.Integer, db.ForeignKey('event_types.id', ondelete='CASCADE')
     )


Test patch:
diff --git a/tests/all/integration/api/event/test_event_view_access.py b/tests/all/integration/api/event/test_event_view_access.py
new file mode 100644
--- /dev/null
+++ b/tests/all/integration/api/event/test_event_view_access.py
@@ -0,0 +1,61 @@
+from tests.factories.event import EventFactoryBasic
+from app.api.helpers.db import get_or_create
+from app.models.role import Role
+from app.models.users_events_role import UsersEventsRoles
+
+
+def get_event(db, user=None):
+    event = EventFactoryBasic(state='draft')
+    if user:
+        role, _ = get_or_create(Role, name='owner', title_name='Owner')
+        UsersEventsRoles(user=user, event=event, role=role)
+    db.session.commit()
+
+    return event
+
+
+def test_event_draft_get_unauthenticated_error(db, client):
+    event = get_event(db)
+
+    response = client.get(
+        f'/v1/events/{event.id}',
+        content_type='application/vnd.api+json',
+    )
+
+    assert response.status_code == 404
+
+
+def test_event_draft_get_normal_error(db, client, jwt):
+    event = get_event(db)
+
+    response = client.get(
+        f'/v1/events/{event.id}',
+        content_type='application/vnd.api+json',
+        headers=jwt,
+    )
+
+    assert response.status_code == 404
+
+
+def test_event_draft_get_owner(db, client, user, jwt):
+    event = get_event(db, user)
+
+    response = client.get(
+        f'/v1/events/{event.id}',
+        content_type='application/vnd.api+json',
+        headers=jwt,
+    )
+
+    assert response.status_code == 200
+
+
+def test_event_draft_get_admin(db, client, admin_jwt):
+    event = get_event(db)
+
+    response = client.get(
+        f'/v1/events/{event.id}',
+        content_type='application/vnd.api+json',
+        headers=admin_jwt,
+    )
+
+    assert response.status_code == 200