From 314897b8bacf883384b53fe447fd302c5c137339 Mon Sep 17 00:00:00 2001 From: skrzepto Date: Jul 20 2016 15:40:23 +0000 Subject: Visit Counter Commit History: added base model for visitcounter and added it to populate.py updating so that when you delete hub the visit_counter is also deleted but when you delete the visit_counter the hub/user is still there adding basic hubs incrementing, having problems with ipsilon to test typo in name, naive implementation works, but its increments 4 times on one load of a page moving increment counter in another location updating to js ajax call, at the moment the route call isnt working debugging stuff changed url str finally working updating route to visit and wrote some unittests removing unecessary lines added login requrired to increment visit counter and make sure the user requesting the increment is the same user removing redundant variable username and just using visited_hub removing the check if user is logged in because @login_required is there, also surrounded get_or_create in try statement even though it should never except adding tests and fixing where try/except goes convering does hub/user exist to one liners cleaning up file --- diff --git a/hubs/app.py b/hubs/app.py index 7e24193..5a1404d 100755 --- a/hubs/app.py +++ b/hubs/app.py @@ -554,6 +554,34 @@ def get_hub(session, name): return hub +@app.route('/visit//', methods=['GET', 'POST']) +@app.route('/visit/', methods=['GET', 'POST']) +@login_required +def increment_counter(visited_hub): + nickname = flask.g.auth.nickname + + if str(visited_hub) != str(nickname): + try: + vc = hubs.models.VisitCounter.get_or_create(session=session, + username=nickname, + visited_hub=visited_hub) + except ValueError: # this should never trip + # flask will 405 if visited_hub is blank + # @login_required forces flask.g.auth to be sets + flask.abort(404) + if flask.request.method == 'POST': + vc.increment_visits(session=session, + username=nickname, + visited_hub=visited_hub) + + return flask.jsonify({'count': vc.count}) + + elif flask.request.method == 'GET': + return flask.jsonify({'count': vc.count}) + else: + return flask.abort(403) + + def get_widget(session, hub, idx): """ Utility shorthand to get a widget and 404 if not found. """ try: diff --git a/hubs/models.py b/hubs/models.py index ad3bc16..ede60dc 100755 --- a/hubs/models.py +++ b/hubs/models.py @@ -419,3 +419,62 @@ class User(BASE): session.commit() return self + + +class VisitCounter(BASE): + __tablename__ = 'visit_counter' + count = sa.Column(sa.Integer, default=0, nullable=False) + + visited_hub = sa.Column(sa.String(50), + sa.ForeignKey('hubs.name'), + primary_key=True) + + username = sa.Column(sa.Text, + sa.ForeignKey('users.username'), + primary_key=True) + + user = relation("User", backref=backref('visit_counters', cascade="all, delete, delete-orphan")) + hub = relation("Hub", backref=backref('visit_counters', cascade="all, delete, delete-orphan")) + + @classmethod + def by_username(cls, session, username): + return session.query(cls).filter_by(username=username).all() + + @classmethod + def get_visits_by_username_hub(cls, session, username, visited_hub): + return session.query(cls).filter_by(username=username, visited_hub=visited_hub).first() + + @classmethod + def increment_visits(cls, session, username, visited_hub): + row = cls.get_or_create(session, username=username, + visited_hub=visited_hub) + row.count += 1 + session.commit() + + @classmethod + def _does_hub_exist(cls, session, hub=''): + return session.query(Hub).filter_by(name=hub).first() is not None + + @classmethod + def _does_user_exist(cls, session, user=''): + return session.query(User).filter_by(username=user).first() is not None + + @classmethod + def get_or_create(cls, session, username, visited_hub): + if not username: + raise ValueError("Must provide an username, not %r" % username) + + if not visited_hub: + raise ValueError("Must provide an hub, not %r" % visited_hub) + + if not cls._does_hub_exist(session, hub=visited_hub) \ + or not cls._does_user_exist(session, user=username): + raise ValueError("Must provide a hub/user that exists") + + self = cls.get_visits_by_username_hub(session, username=username, + visited_hub=visited_hub) + if not self: + self = cls(username=username, visited_hub=visited_hub) + session.add(self) + session.commit() + return self diff --git a/hubs/templates/hubs.html b/hubs/templates/hubs.html index 618c45a..c4e6b92 100644 --- a/hubs/templates/hubs.html +++ b/hubs/templates/hubs.html @@ -274,6 +274,30 @@ function setup_edit_btns() { }); } +function visit_counter() { + if (window.performance.navigation.type == 0) { + var username = '{{ g.auth.nickname }}' + var visited_hub = '{{ hub.name }}' + if(username != null && username != '' && username != visited_hub) { + url_str = '/visit/' + visited_hub; + + $.ajax({ + method: "POST", + url: url_str, + dataType: 'html', + success: function(html) { + console.log('Success: incrementing counter') + }, + error: function() { + console.log('Error: incrementing counter'); + }, + }); + } + } +} + +visit_counter() + function setup_widgets(widgets) { var all_widgets = [{% for widget in hub.widgets %}'{{ widget.idx }}',{% endfor %}]; if (widgets == undefined) { diff --git a/hubs/tests/test_fedora_hubs_flask_api.py b/hubs/tests/test_fedora_hubs_flask_api.py index 7b7dbff..d099987 100644 --- a/hubs/tests/test_fedora_hubs_flask_api.py +++ b/hubs/tests/test_fedora_hubs_flask_api.py @@ -285,5 +285,46 @@ class HubsAPITest(hubs.tests.APPTest): self.assertEqual(result.status_code, 302) self.assertEqual(urlparse(result.location).path, '/ralph/') + def test_hub_visit_counter_logged_in(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + url = '/visit/decause' + result = self.app.get(url) + self.assertEqual(json.loads(result.data), {"count": 0}) + + result = self.app.post(url) + self.assertEqual(json.loads(result.data), {"count": 1}) + + # accessing my hub shouldn't increment the count + url = 'visit/ralph' + result = self.app.post(url) + self.assertEqual(result.status_code, 403) + + # visiting no hub while logged should throw a 405 + url = 'visit/' + result = self.app.post(url) + self.assertEqual(result.status_code, 405) + + # visiting a hub that doesn't exist should 404 + url = 'visit/hub-does-not-exist' + result = self.app.post(url) + self.assertEqual(result.status_code, 404) + + @unittest.skip("Ajax calls don't seem to work in unittests ") + def test_hub_vist_counter_logged_in_2(self): + user = tests.FakeAuthorization('ralph') + with tests.auth_set(app, user): + url = '/visit/decause' + result = self.app.get(url) + self.assertEqual(result.data, '0') + + url = '/decause' + result = self.app.get(url, follow_redirects=True) + + url = '/visit/decause' + result = self.app.get(url) + self.assertEqual(result.data, '1') + + if __name__ == '__main__': unittest.main() diff --git a/hubs/tests/test_models.py b/hubs/tests/test_models.py index e787c68..c3d540d 100644 --- a/hubs/tests/test_models.py +++ b/hubs/tests/test_models.py @@ -88,3 +88,73 @@ class ModelTest(hubs.tests.APPTest): hub = hubs.models.Hub.get(self.session, username) self.assertIsNone(hub) + + def test_visit_counter(self): + username = 'ralph' + hub = 'decause' + # Make sure the table is empty of data + vc = hubs.models.VisitCounter.get_visits_by_username_hub( + session=self.session, username=username, visited_hub=hub) + self.assertIsNone(vc) + + # Insert a new counter row + vc = hubs.models.VisitCounter.get_or_create( + session=self.session, username=username, visited_hub=hub) + # Make sure its init to 0 + self.assertEqual(vc.count, 0) + + # Increment counter and make sure its 1 + hubs.models.VisitCounter.increment_visits( + session=self.session, username=username, visited_hub=hub) + self.assertEqual(vc.count, 1) + + # Delete the counter make sure the hub/user is still arround + vc = hubs.models.VisitCounter.get_or_create( + session=self.session, username=username, visited_hub=hub) + self.session.delete(vc) + hub_obj = hubs.models.Hub.get(self.session, username) + self.assertIsNotNone(hub_obj) + user_obj = hubs.models.User.get(session=self.session, + username=username) + self.assertIsNotNone(user_obj) + + # Delete hub and make sure the visit counter is 0 + vc = hubs.models.VisitCounter.get_visits_by_username_hub( + session=self.session, username=username, visited_hub=hub) + self.session.delete(hub_obj) + self.assertIsNone(vc) + user_obj = hubs.models.User.get(session=self.session, + username=username) + self.assertIsNotNone(user_obj) + + def test_visit_counter_does_not_exist(self): + username = 'ralph' + hub = 'does-not-exist' + self.assertRaises(ValueError, + hubs.models.VisitCounter.get_or_create, + session=self.session, + username=username, + visited_hub=hub) + + username = 'does-not-exist' + hub = 'ralph' + # Make sure the table is empty of data + self.assertRaises(ValueError, + hubs.models.VisitCounter.get_or_create, + session=self.session, + username=username, + visited_hub=hub) + + username = 'does-not-exist' + hub = 'does-not-exist' + # Make sure the table is empty of data + self.assertRaises(ValueError, + hubs.models.VisitCounter.get_or_create, + session=self.session, + username=username, + visited_hub=hub) + + + + + diff --git a/populate.py b/populate.py index a9cbe39..986d5b5 100755 --- a/populate.py +++ b/populate.py @@ -237,7 +237,8 @@ hub.widgets.append(widget) widget = hubs.models.Widget(plugin='dummy', index=3, left=True) hub.widgets.append(widget) - +vc = hubs.models.VisitCounter().get_or_create(session, 'ralph', 'mrichard') +hubs.models.VisitCounter().increment_visits(session, 'ralph', 'mrichard') hub.subscribe(session, hubs.models.User.by_username(session, 'ralph'), 'owner') hub.subscribe(session, hubs.models.User.by_username(session, 'abompard'), 'owner') hub.subscribe(session, hubs.models.User.by_username(session, 'lmacken'), 'owner')