From fdcedb262cb2aa8384ca7dd1de32ef65a6d4bc69 Mon Sep 17 00:00:00 2001 From: tanshu Date: Thu, 12 Feb 2015 16:12:32 +0530 Subject: [PATCH] Feature: Added a maintenance mode which locks all other users out --- brewman/__init__.py | 7 +++--- brewman/models/__init__.py | 3 ++- brewman/static/partial/settings.html | 17 ++++++++++++++- brewman/static/scripts/settings.js | 28 ++++++++++++++++++++++-- brewman/subscribers.py | 18 +++++++--------- brewman/views/Management/settings.py | 32 ++++++++++++++++++++++++++-- 6 files changed, 85 insertions(+), 20 deletions(-) diff --git a/brewman/__init__.py b/brewman/__init__.py index a0484a65..c801b91a 100644 --- a/brewman/__init__.py +++ b/brewman/__init__.py @@ -4,7 +4,7 @@ from sqlalchemy import engine_from_config from pyramid.authentication import AuthTktAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy -from pyramid.session import UnencryptedCookieSessionFactoryConfig +from pyramid.session import SignedCookieSessionFactory from brewman.factories import add_route from brewman.models import initialize_sql from brewman.renderers import json_renderer, CSVRenderer @@ -19,7 +19,7 @@ def main(global_config, **settings): engine = engine_from_config(settings, 'sqlalchemy.') initialize_sql(engine) - session_factory = UnencryptedCookieSessionFactoryConfig('secret') + session_factory = SignedCookieSessionFactory('secret') authentication_policy = AuthTktAuthenticationPolicy('brewman', timeout=900, reissue_time=90, callback=groupfinder) authorization_policy = ACLAuthorizationPolicy() @@ -31,8 +31,6 @@ def main(global_config, **settings): authorization_policy=authorization_policy, session_factory=session_factory ) - # This changes in pyramid 1.4 to something similar to "config.add_renderer('myjson', JSON(indent=4))" - # http://docs.pylonsproject.org/projects/pyramid/en/master/api/renderers.html#pyramid.renderers.JSON config.add_renderer(name='json', factory=json_renderer) config.add_renderer(name='csv', factory=CSVRenderer) @@ -99,6 +97,7 @@ def main(global_config, **settings): config.add_route('settings', '/Settings') config.add_route('api_lock_info', '/api/LockInfo') + config.add_route('api_maintenance', '/api/Maintenance') add_route(config, 'attendance', '/Attendance', has_list=False, variable='date') config.add_route('api_attendance_types', '/api/AttendanceTypes') diff --git a/brewman/models/__init__.py b/brewman/models/__init__.py index 1e6162e2..efa23be3 100644 --- a/brewman/models/__init__.py +++ b/brewman/models/__init__.py @@ -83,7 +83,8 @@ def fixtures(engine): Role('Reconcile', uuid.UUID('a5cb51cb-e38e-4705-84a7-cc1e9a8b866b')), Role('Stock Movement', uuid.UUID('20b707ee-2b59-41ad-be87-76d5fe1efca8')), Role('Purchases', uuid.UUID('cf7019c8-3fd3-45b0-9a42-601029ce5b71')), - Role('Dashboard', uuid.UUID('53eecc09-bd06-4890-b6f5-6885dda762d4'))] + Role('Dashboard', uuid.UUID('53eecc09-bd06-4890-b6f5-6885dda762d4')), + Role('Maintenance', uuid.UUID('770532e4-21de-4712-8a6b-4ff9fd63a503'))] for role in roles: DBSession.add(role) diff --git a/brewman/static/partial/settings.html b/brewman/static/partial/settings.html index 3965166b..b15a8c2e 100644 --- a/brewman/static/partial/settings.html +++ b/brewman/static/partial/settings.html @@ -132,8 +132,23 @@
-
+
+ + +
+ +
+
+ +
+
+ Maintenance mode is {{MaintenanceEnabled()}} by user {{maintenance.User}} +
+
diff --git a/brewman/static/scripts/settings.js b/brewman/static/scripts/settings.js index 9adc9c9e..4b565b50 100644 --- a/brewman/static/scripts/settings.js +++ b/brewman/static/scripts/settings.js @@ -1,7 +1,11 @@ 'use strict'; -var SettingsController = ['$scope', '$http', 'asDateFilter', '$modal', 'lockInfo', 'Product', function ($scope, $http, asDate, $modal, lockInfo, Product) { +var SettingsController = ['$scope', '$http', 'asDateFilter', '$modal', 'lockInfo', 'maintenance', 'Product', function ($scope, $http, asDate, $modal, lockInfo, maintenance, Product) { $scope.lockInfo = lockInfo.data; + $scope.maintenance = maintenance.data; + $scope.MaintenanceEnabled = function (){ + return $scope.maintenance.Enabled ? 'Enabled' : 'Disabled'; + }; $scope.rebaseDate = ''; $scope.setLockDate = function () { if ($scope.lockInfo.Start.Locked) { @@ -110,7 +114,11 @@ var SettingsController = ['$scope', '$http', 'asDateFilter', '$modal', 'lockInfo var resetDate = asDate($scope.resetDate); var stockDate = asDate($scope.stockDate); var qty = Number($scope.qty); - $http({method: 'POST', url: '/api/ResetStock/' + $scope.product.ProductID, params: {StockDate: stockDate, ResetDate: resetDate, Quantity: qty}}). + $http({ + method: 'POST', + url: '/api/ResetStock/' + $scope.product.ProductID, + params: {StockDate: stockDate, ResetDate: resetDate, Quantity: qty} + }). success(function () { $scope.toasts.push({Type: 'Success', Message: 'Data rebased!'}); }). @@ -131,6 +139,17 @@ var SettingsController = ['$scope', '$http', 'asDateFilter', '$modal', 'lockInfo $scope.toasts.push({Type: 'Danger', Message: errorMessage}); }); }; + + $scope.setMaintenance = function (status) { + return $http.post('/api/Maintenance', {Enabled: status}). + success(function (data) { + $scope.maintenance = data; + $scope.toasts.push({Type: 'Success', Message: ''}); + }). + error(function (errorMessage) { + $scope.toasts.push({Type: 'Danger', Message: errorMessage}); + }); + }; }]; SettingsController.resolve = { @@ -138,6 +157,11 @@ SettingsController.resolve = { return $http.get('/api/LockInfo', {}).then(function (data) { return data; }); + }], + maintenance: ['$http', function ($http) { + return $http.get('/api/Maintenance', {}).then(function (data) { + return data; + }); }] }; diff --git a/brewman/subscribers.py b/brewman/subscribers.py index 569bb6b9..0af8538e 100644 --- a/brewman/subscribers.py +++ b/brewman/subscribers.py @@ -1,12 +1,10 @@ -from pyramid.events import subscriber, NewRequest +from pyramid.events import subscriber, NewRequest +from pyramid.httpexceptions import HTTPServiceUnavailable +from brewman.models.master import DbSetting + @subscriber(NewRequest) -def csrf_validation(event): - pass -# print(event.request.method, event.request.url, event.request.query_string) -# if event.request.method == "POST" and not event.request.is_xhr: -# token = event.request.POST.get("_csrf") -# print('CSRF POST token is ' + token + ' vs Server ' + event.request.session.get_csrf_token()) - -# if token is None or token != event.request.session.get_csrf_token(): -# raise HTTPForbidden('CSRF token is missing or invalid ' + token + ' Original ' + event.request.session.get_csrf_token()) \ No newline at end of file +def maintenance_mode(event): + maintenance = DbSetting.by_name('Maintenance') + if maintenance is not None and maintenance.data != event.request.authenticated_userid: + raise HTTPServiceUnavailable diff --git a/brewman/views/Management/settings.py b/brewman/views/Management/settings.py index a391ffab..17428f86 100644 --- a/brewman/views/Management/settings.py +++ b/brewman/views/Management/settings.py @@ -1,11 +1,12 @@ import datetime + import pkg_resources from pyramid.response import FileResponse - from pyramid.view import view_config import transaction -from brewman.models import DBSession +from brewman.models import DBSession +from brewman.models.auth import User from brewman.models.master import DbSetting from brewman.models.validation_exception import TryCatchFunction @@ -80,3 +81,30 @@ def get_lock_info(request): else: info['Finish']['Date'] = data['Finish']['Date'].strftime('%d-%b-%Y') return info + + +@view_config(request_method='GET', route_name='api_maintenance', renderer='json', permission='Authenticated') +def get_maintenance(request): + data = DbSetting.by_name('Maintenance') + if data is None: + return {'Enabled': False, 'User': ''} + user = User.by_id(data.data) + return {'Enabled': True, 'User': user.name} + + +@view_config(request_method='POST', route_name='api_maintenance', renderer='json', permission='Maintenance') +@TryCatchFunction +def set_maintenance(request): + status = request.json_body['Enabled'] + maintenance = DbSetting.by_name('Maintenance') + if status is False and maintenance is not None: + DBSession.delete(maintenance) + elif status is True and maintenance is None: + maintenance = DbSetting(name='Maintenance', data=request.authenticated_userid) + DBSession.add(maintenance) + elif status is True and maintenance.data != request.authenticated_userid: + maintenance.data = request.authenticated_userid + transaction.commit() + return get_maintenance(request) + +