Feature: Added a maintenance mode which locks all other users out

This commit is contained in:
tanshu 2015-02-12 16:12:32 +05:30
parent cb7e6e89a5
commit fdcedb262c
6 changed files with 85 additions and 20 deletions

View File

@ -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')

View File

@ -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)

View File

@ -132,8 +132,23 @@
<label class="col-md-2 control-label">Integrity Check</label>
<div class="col-md-2">
<button class="btn btn-block btn-danger" ng-click="checkDb()">Check Database <i
<button class="btn btn-block btn-success" ng-click="checkDb()">Check Database <i
class="glyphicon glyphicon-certificate"></i></button>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Maintenance Mode</label>
<div class="col-md-2">
<button class="btn btn-block btn-danger" ng-click="setMaintenance(true)">Enable <i
class="glyphicon glyphicon-eye-close"></i></button>
</div>
<div class="col-md-2">
<button class="btn btn-block btn-success" ng-click="setMaintenance(false)">Disable <i
class="glyphicon glyphicon-eye-open"></i></button>
</div>
<div class="col-md-6">
Maintenance mode is <strong>{{MaintenanceEnabled()}}</strong> by user <strong>{{maintenance.User}}</strong>
</div>
</div>
</form>

View File

@ -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;
});
}]
};

View File

@ -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())
def maintenance_mode(event):
maintenance = DbSetting.by_name('Maintenance')
if maintenance is not None and maintenance.data != event.request.authenticated_userid:
raise HTTPServiceUnavailable

View File

@ -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)