Repository: fossasia/open-event-server

Issue:
Implement view for individual session in the "My Sessions" Dashboard
From #622.

**URL:** `/events/mysessions/ID` - shows the specific session/sessions that the user has submitted to a specific event.

Prerequisite: #703



Discussion:
Any screenshot?

@mariobehling yes. I'll post in a few hours. I'm out right now. Sorry. 

@mariobehling this is how the UI will look like

![screencapture-localhost-5000-events-mysessions-1-1465749584671](https://cloud.githubusercontent.com/assets/2404372/15992451/72add7a0-30ea-11e6-87a7-5ee2d755543d.png)

@niranjan94 Good. Maybe move Microlocation, track etc. to the bottom.
How does the "editable version" looks like?

@mariobehling I'll move those to the bottom. 
Oh, so the speaker is allowed to edit his/her session ? Okay ... I didn't implement that in this yet.

So, just to confirm - this is the option for the "speaker" to view and edit his submissions.

@mariobehling yes. this is for the **speaker**. I thought they aren't allowed to edit. So, I didn't implement that in this yet But I'll add it as a separate issue. 

@mariobehling which all fields is the speaker allowed to edit ?

A speaker has to submit this through a form as an answer to the Call for Speakers. @SaptakS is working on the form in step 5 of the create event wizard. The speaker should not be able to edit the location for example.

@mariobehling okay ... so, I'll push this current view now (without edit option) ... I'll add the edit option once Saptak is done with the form.

Let's keep it simple. We probably have to add more fields later. Fields are defined in step 5. How about you take out location, track etc. out and implement it later.

@mariobehling  Okay ... Cool I'll make it such that the following fields are editable for now. Rest we can add later if required.
1. title
2. subtitle
3. abstract
4. description


Resolving patch:
diff --git a/open_event/helpers/data_getter.py b/open_event/helpers/data_getter.py
--- a/open_event/helpers/data_getter.py
+++ b/open_event/helpers/data_getter.py
@@ -1,4 +1,6 @@
 """Copyright 2015 Rafal Kowalski"""
+from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
+
 from ..models.event import Event, EventsUsers
 from ..models.session import Session, Level, Format, Language
 from ..models.track import Track
@@ -20,7 +22,6 @@
 
 
 class DataGetter:
-
     @staticmethod
     def get_invite_by_user_id(user_id):
         invite = Invite.query.filter_by(user_id=user_id)
@@ -80,6 +81,19 @@ def get_sessions(event_id, is_accepted=True):
             is_accepted=is_accepted
         )
 
+    @staticmethod
+    def get_sessions_of_user_by_id(session_id):
+        """
+        :return: Return Sessions object with the current user as a speaker by ID
+        """
+        try:
+            return Session.query.filter(Session.speakers.any(Speaker.email == login.current_user.email)).filter(
+                Session.id == session_id).one()
+        except MultipleResultsFound, e:
+            return None
+        except NoResultFound, e:
+            return None
+
     @staticmethod
     def get_sessions_of_user(upcoming_events=True):
         """
@@ -239,7 +253,7 @@ def get_user_events():
 
     @staticmethod
     def get_completed_events():
-        events = Event.query.join(Event.roles, aliased=True).filter_by(user_id=login.current_user.id)\
+        events = Event.query.join(Event.roles, aliased=True).filter_by(user_id=login.current_user.id) \
             .filter(Event.state == 'Completed')
         return events
 
@@ -261,13 +275,13 @@ def get_published_events():
 
     @staticmethod
     def get_current_events():
-        events = Event.query.join(Event.roles, aliased=True).filter_by(user_id=login.current_user.id)\
+        events = Event.query.join(Event.roles, aliased=True).filter_by(user_id=login.current_user.id) \
             .filter(Event.state != 'Completed')
         return events
 
     @staticmethod
     def get_live_events():
-        return Event.query.filter(Event.start_time <= datetime.datetime.now())\
+        return Event.query.filter(Event.start_time <= datetime.datetime.now()) \
             .filter(Event.end_time >= datetime.datetime.now())
 
     @staticmethod
diff --git a/open_event/views/admin/admin.py b/open_event/views/admin/admin.py
--- a/open_event/views/admin/admin.py
+++ b/open_event/views/admin/admin.py
@@ -52,6 +52,7 @@ def _add_views(self):
 
     @staticmethod
     def init_login(app):
+        from flask import request, url_for, redirect
         """Init login"""
         login_manager = login.LoginManager()
         login_manager.init_app(app)
@@ -60,3 +61,8 @@ def init_login(app):
         @login_manager.user_loader
         def load_user(user_id):
             return db.session.query(User).get(user_id)
+
+        @login_manager.unauthorized_handler
+        def unauthorized():
+            # do stuff
+            return redirect(url_for('admin.login_view', next=request.url))
diff --git a/open_event/views/admin/models_views/my_sessions.py b/open_event/views/admin/models_views/my_sessions.py
--- a/open_event/views/admin/models_views/my_sessions.py
+++ b/open_event/views/admin/models_views/my_sessions.py
@@ -1,8 +1,11 @@
+import flask_login
+from flask.ext.restplus import abort
 from flask_admin import BaseView, expose
 from ....helpers.data_getter import DataGetter
 
 class MySessionView(BaseView):
     @expose('/')
+    @flask_login.login_required
     def display_my_sessions_view(self):
         upcoming_events_sessions = DataGetter.get_sessions_of_user(upcoming_events=True)
         past_events_sessions = DataGetter.get_sessions_of_user(upcoming_events=False)
@@ -11,6 +14,9 @@ def display_my_sessions_view(self):
                            upcoming_events_sessions=upcoming_events_sessions, past_events_sessions=past_events_sessions)
 
     @expose('/<session_id>')
+    @flask_login.login_required
     def display_session_view(self, session_id):
-        session = DataGetter.get_session(session_id)
+        session = DataGetter.get_sessions_of_user_by_id(session_id)
+        if not session:
+            abort(404)
         return self.render('/gentelella/admin/mysessions/mysession_detail.html', session=session)


Test patch:
diff --git a/tests/test_my_session.py b/tests/test_my_session.py
--- a/tests/test_my_session.py
+++ b/tests/test_my_session.py
@@ -1,6 +1,10 @@
-"""Copyright 2015 Rafal Kowalski"""
 import unittest
+from datetime import datetime
 
+from open_event.helpers.data import save_to_db
+from open_event.models.session import Session
+from open_event.models.speaker import Speaker
+from tests.object_mother import ObjectMother
 from tests.utils import OpenEventTestCase
 from tests.setup_database import Setup
 from tests.auth_helper import register, logout, login
@@ -10,6 +14,49 @@ class TestMySession(OpenEventTestCase):
     def setUp(self):
         self.app = Setup.create_app()
 
+    def test_my_session_detail(self):
+        with app.test_request_context():
+            speaker = Speaker(name="name",
+                              email="email2@gmail.com",
+                              organisation="FOSSASIA",
+                              country="India")
+            save_to_db(speaker, "Speaker saved")
+            event = ObjectMother.get_event()
+            save_to_db(event, "Event Saved")
+            session = Session(title='test',
+                              description='dsad',
+                              start_time=datetime(2003, 8, 4, 12, 30, 45),
+                              end_time=datetime(2003, 8, 4, 12, 30, 45),
+                              event_id=event.id,
+                              speakers=[speaker],
+                              state='pending')
+            save_to_db(session, "Session saved")
+            register(self.app, u'email2@gmail.com', u'test2')
+            login(self.app, 'email2@gmail.com', 'test2')
+            rv = self.app.get('events/mysessions/' + str(session.id), follow_redirects=True)
+            logout(self.app)
+            self.assertTrue("Description" in rv.data, msg=rv.data)
+
+    def test_my_session_unauthorized_access(self):
+        with app.test_request_context():
+            speaker = Speaker(name="name",
+                              email="email2@gmail.com",
+                              organisation="FOSSASIA",
+                              country="India")
+            save_to_db(speaker, "Speaker saved")
+            session = Session(title='test',
+                              description='dsad',
+                              start_time=datetime(2003, 8, 4, 12, 30, 45),
+                              end_time=datetime(2003, 8, 4, 12, 30, 45),
+                              event_id=1,
+                              speakers=[speaker],
+                              state='pending')
+            save_to_db(session, "Session saved")
+            register(self.app, u'email3@gmail.com', u'test3')
+            login(self.app, 'email3@gmail.com', 'test3')
+            rv = self.app.get('events/mysessions/' + str(session.id), follow_redirects=True)
+            self.assertEqual(rv.status_code, 404)
+
     def test_my_session_list(self):
         with app.test_request_context():
             register(self.app, u'email2@gmail.com', u'test2')
@@ -18,5 +65,6 @@ def test_my_session_list(self):
             logout(self.app)
             self.assertTrue("My Session Proposals" in rv.data, msg=rv.data)
 
+
 if __name__ == '__main__':
     unittest.main()