Fixed password change not allowed for non Privilaged users.
Fixed storing utc dates in message tables. Created utc class for time-aware dates. Updated home to show age of Threads and open in new window available. Modified message detail template to show editable by privileged user. Added subscribers to thread detail. Improved markup for message-detail to use less space. Improved the chosen directive for when there is no create option. Added method 'Names' to user resource for use in message subscribers. Payment and Receipt clear typeahead on adding ledgers. TODO: Implement thread read status per user. TODO: Implemented edit post functionality for privileged user. TODO: Implement thread filtering on main page for subscribers Signed-off-by: Tanshu <tanshu@gmail.com>
This commit is contained in:
parent
d5dcd392f7
commit
01298ebadb
|
@ -130,6 +130,10 @@ class User(Base):
|
||||||
def list(cls):
|
def list(cls):
|
||||||
return DBSession.query(cls).order_by(cls.name).all()
|
return DBSession.query(cls).order_by(cls.name).all()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def query(cls):
|
||||||
|
return DBSession.query(cls)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def filtered_list(cls, name):
|
def filtered_list(cls, name):
|
||||||
query = DBSession.query(cls)
|
query = DBSession.query(cls)
|
||||||
|
|
|
@ -63,7 +63,7 @@ class Thread(Base):
|
||||||
|
|
||||||
def __init__(self, title=None, creation_date=None, user_id=None, priority=5, public=False, closed=False):
|
def __init__(self, title=None, creation_date=None, user_id=None, priority=5, public=False, closed=False):
|
||||||
self.title = title
|
self.title = title
|
||||||
self.creation_date = datetime.now() if creation_date is None else creation_date
|
self.creation_date = datetime.utcnow() if creation_date is None else creation_date
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
self.priority = priority
|
self.priority = priority
|
||||||
self.public = public
|
self.public = public
|
||||||
|
@ -96,7 +96,7 @@ class Post(Base):
|
||||||
|
|
||||||
def __init__(self, content='', creation_date=None, user_id=None, date=None):
|
def __init__(self, content='', creation_date=None, user_id=None, date=None):
|
||||||
self.content = content
|
self.content = content
|
||||||
self.creation_date = datetime.now() if creation_date is None else creation_date
|
self.creation_date = datetime.utcnow() if creation_date is None else creation_date
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
self.date = self.creation_date if date is None else date
|
self.date = self.creation_date if date is None else date
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ class Subscriber(Base):
|
||||||
|
|
||||||
user = relationship('User', primaryjoin="User.id==Subscriber.user_id", cascade=None)
|
user = relationship('User', primaryjoin="User.id==Subscriber.user_id", cascade=None)
|
||||||
|
|
||||||
def __init__(self, thread_id=None, user_id=None, read=None):
|
def __init__(self, thread_id=None, user_id=None, read=False):
|
||||||
self.thread_id = thread_id
|
self.thread_id = thread_id
|
||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
self.read = read
|
self.read = read
|
|
@ -0,0 +1,35 @@
|
||||||
|
from datetime import timedelta, tzinfo, datetime
|
||||||
|
|
||||||
|
__author__ = 'tanshu'
|
||||||
|
|
||||||
|
|
||||||
|
ZERO = timedelta(0)
|
||||||
|
HOUR = timedelta(hours=1)
|
||||||
|
|
||||||
|
# A UTC class.
|
||||||
|
|
||||||
|
class UTC(tzinfo):
|
||||||
|
"""UTC"""
|
||||||
|
|
||||||
|
def utcoffset(self, dt):
|
||||||
|
return ZERO
|
||||||
|
|
||||||
|
def tzname(self, dt):
|
||||||
|
return "UTC"
|
||||||
|
|
||||||
|
def dst(self, dt):
|
||||||
|
return ZERO
|
||||||
|
|
||||||
|
utc = UTC()
|
||||||
|
|
||||||
|
|
||||||
|
def get_age(old_date):
|
||||||
|
now = datetime.utcnow().replace(tzinfo=utc)
|
||||||
|
delta = now - old_date
|
||||||
|
if delta.days > 0:
|
||||||
|
return '{0} days'.format(delta.days)
|
||||||
|
if delta.seconds > 3600:
|
||||||
|
return '{0} hours'.format(delta.seconds // 3600)
|
||||||
|
if delta.seconds > 60:
|
||||||
|
return '{0} minutes'.format(delta.seconds // 3600)
|
||||||
|
return '{0} seconds'.format(delta.seconds)
|
|
@ -1,6 +1,6 @@
|
||||||
CACHE MANIFEST
|
CACHE MANIFEST
|
||||||
|
|
||||||
# version 2013-05-30.1
|
# version 2013-06-06.1
|
||||||
|
|
||||||
CACHE:
|
CACHE:
|
||||||
/partial/404.html
|
/partial/404.html
|
||||||
|
|
|
@ -18,17 +18,28 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="widget-content nopadding">
|
<div class="widget-content nopadding">
|
||||||
<table class="table table-bordered table-striped">
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<input type="checkbox" ng-model="allChecked" ng-click="markAll(allChecked)">
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<h5>Details</h5>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="item in info">
|
<tr ng-repeat="item in info">
|
||||||
<td><input type="checkbox" ng-model="item.selected"></td>
|
<td><input type="checkbox" ng-model="item.selected"></td>
|
||||||
<td>
|
<td>
|
||||||
<span class="user-info">User: {{item.User}} at {{item.CreationDate | localTime}}</span>
|
<span class="user-info">User: {{item.User}} {{item.Age}} ago. Updated {{item.LastUpdated}} ago.</span>
|
||||||
|
|
||||||
<p><a ng-click="openMessage(item)">{{item.Title}}</a></p>
|
<p><a href="/Message/{{item.ThreadID}}">{{item.Title}}</a></p>
|
||||||
<a class="btn btn-mini" ng-repeat="tag in item.Tags"> {{tag}}</a>
|
<a class="btn btn-mini" ng-repeat="tag in item.Tags"> {{tag}}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<label for="txtTitle" class="control-label">Title</label>
|
<label for="txtTitle" class="control-label">Title</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" id="txtTitle" class="input-block-level" ng-model="message.Title" ng-disabled="message.ThreadID"/>
|
<input type="text" id="txtTitle" class="input-block-level" ng-model="message.Title"
|
||||||
|
ng-disabled="message.ThreadID"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
@ -32,13 +33,30 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="txtUsers" class="control-label">Users</label>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<select id="txtUsers" data-placeholder="Users" multiple class="input-block-level chzn-select" chosen="users"
|
||||||
|
ng-model="message.Subscribers" ng-options="user for user in users">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<ul class="media-list">
|
<ul class="media-list">
|
||||||
<li class="media" ng-repeat="post in message.Posts" ng-disabled="post.PostID">
|
<li class="media" ng-repeat="post in message.Posts" ng-disabled="post.PostID">
|
||||||
<div ng-switch="!$last" class="media-body">
|
<div ng-switch="!$last" class="media-body">
|
||||||
<div ng-switch-when="true" class="media">
|
<div ng-switch-when="true" class="media">
|
||||||
<div class="controls my-markdown">
|
<div class="controls widget-box">
|
||||||
<span class="md-title">Created on {{post.CreationDate}} by {{post.User}} (Dated: {{post.Date}})</span>
|
<div class="widget-title">
|
||||||
<div class="md-body" ng-bind-html-unsafe="post.Content | md"></div>
|
<h5>Created on {{post.CreationDate | localTime}} by {{post.User}} (Dated: {{post.Date}})</h5>
|
||||||
|
<ul class="nav nav-tabs pull-right">
|
||||||
|
<li>
|
||||||
|
<a href="#" ng-hide="!perms['Messages']"><b class="icon-edit"></b></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="widget-content" ng-bind-html-unsafe="post.Content | md"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-switch-when="false" class="media">
|
<div ng-switch-when="false" class="media">
|
||||||
|
|
|
@ -297,6 +297,14 @@ overlord_directive.directive('chosen', ['$parse', function ($parse) {
|
||||||
createFunction = attrs['createFunction'],
|
createFunction = attrs['createFunction'],
|
||||||
options = {};
|
options = {};
|
||||||
|
|
||||||
|
if (typeof createFunction !== 'undefined') {
|
||||||
|
options['create_option'] = function (data) {
|
||||||
|
var fn = $parse(attrs['createFunction'] + '("' + data + '")');
|
||||||
|
scope.$apply(function () {
|
||||||
|
fn(scope);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
scope.$watch(list, function () {
|
scope.$watch(list, function () {
|
||||||
element.trigger('liszt:updated');
|
element.trigger('liszt:updated');
|
||||||
}, true);
|
}, true);
|
||||||
|
@ -306,16 +314,7 @@ overlord_directive.directive('chosen', ['$parse', function ($parse) {
|
||||||
element.trigger("liszt:updated");
|
element.trigger("liszt:updated");
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
element.chosen({
|
element.chosen(options);
|
||||||
create_option: function (data) {
|
|
||||||
if (typeof createFunction !== 'undefined') {
|
|
||||||
var fn = $parse(attrs['createFunction'] + '("' + data + '")');
|
|
||||||
scope.$apply(function () {
|
|
||||||
fn(scope);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -51,7 +51,8 @@ overlord_service.factory('AccountType', ['$resource', function ($resource) {
|
||||||
overlord_service.factory('User', ['$resource', function ($resource) {
|
overlord_service.factory('User', ['$resource', function ($resource) {
|
||||||
return $resource('/api/User/:id',
|
return $resource('/api/User/:id',
|
||||||
{id:'@UserID'}, {
|
{id:'@UserID'}, {
|
||||||
query:{method:'GET', params:{list:true}, isArray:true}
|
query:{method:'GET', params:{list:true}, isArray:true},
|
||||||
|
names:{method:'GET', params:{names:true}, isArray:true}
|
||||||
});
|
});
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ var JournalCtrl = ['$scope', '$location', 'voucher', function ($scope, $location
|
||||||
return journals[i];
|
return journals[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.addJournal = function () {
|
$scope.addJournal = function () {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var MessageCtrl = ['$scope', '$location', 'message', 'tags', 'priorities', function ($scope, $location, message, tags, priorities) {
|
var MessageCtrl = ['$scope', '$location', 'message', 'tags', 'users', 'priorities', function ($scope, $location, message, tags, users, priorities) {
|
||||||
$scope.message = message;
|
$scope.message = message;
|
||||||
$scope.priorities = priorities
|
$scope.priorities = priorities
|
||||||
$scope.tags = tags;
|
$scope.tags = tags;
|
||||||
|
$scope.users = users;
|
||||||
|
|
||||||
message.Posts.push({});
|
message.Posts.push({});
|
||||||
|
|
||||||
|
@ -52,6 +53,20 @@ MessageCtrl.resolve = {
|
||||||
Tag.query({}, successCb);
|
Tag.query({}, successCb);
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}],
|
}],
|
||||||
|
users: ['$q', 'User', function ($q, User) {
|
||||||
|
var deferred = $q.defer();
|
||||||
|
var successCb = function (result) {
|
||||||
|
var len = result.length;
|
||||||
|
var i = 0;
|
||||||
|
var list = []
|
||||||
|
for (i=0; i<len; i++){
|
||||||
|
list.push(result[i].Name);
|
||||||
|
}
|
||||||
|
deferred.resolve(list);
|
||||||
|
};
|
||||||
|
User.names({}, successCb);
|
||||||
|
return deferred.promise;
|
||||||
|
}],
|
||||||
priorities: ['$q', function ($q) {
|
priorities: ['$q', function ($q) {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
deferred.resolve([
|
deferred.resolve([
|
||||||
|
|
|
@ -9,7 +9,6 @@ function PaymentCtrl($scope, $location, voucher, ledgers) {
|
||||||
return journals[i];
|
return journals[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.addJournal = function () {
|
$scope.addJournal = function () {
|
||||||
|
@ -25,6 +24,7 @@ function PaymentCtrl($scope, $location, voucher, ledgers) {
|
||||||
}
|
}
|
||||||
delete $scope.ledger;
|
delete $scope.ledger;
|
||||||
delete $scope.amount;
|
delete $scope.amount;
|
||||||
|
$('#txtLedger').val('');
|
||||||
$('#txtLedger').focus();
|
$('#txtLedger').focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ function ReceiptCtrl($scope, $routeParams, $location, voucher, ledgers, Voucher)
|
||||||
}
|
}
|
||||||
delete $scope.ledger;
|
delete $scope.ledger;
|
||||||
delete $scope.amount;
|
delete $scope.amount;
|
||||||
|
$('#txtLedger').val('');
|
||||||
$('#txtLedger').focus();
|
$('#txtLedger').focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,115 +1,153 @@
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
from pyramid.response import Response
|
from pyramid.response import Response
|
||||||
|
from pyramid.security import authenticated_userid
|
||||||
|
|
||||||
from pyramid.view import view_config
|
from pyramid.view import view_config
|
||||||
import transaction
|
import transaction
|
||||||
|
from brewman import groupfinder
|
||||||
from brewman.models import DBSession
|
from brewman.models import DBSession
|
||||||
from brewman.models.auth import User, Group
|
from brewman.models.auth import User, Group
|
||||||
|
|
||||||
from brewman.models.validation_exception import TryCatchFunction
|
from brewman.models.validation_exception import TryCatchFunction, ValidationError
|
||||||
|
|
||||||
|
|
||||||
@view_config(route_name='user_list', renderer='brewman:templates/angular_base.mako', permission='Users')
|
class view_user(object):
|
||||||
@view_config(request_method='GET', route_name='user_id', renderer='brewman:templates/angular_base.mako',
|
def __init__(self, request):
|
||||||
permission='Users')
|
self.request = request
|
||||||
@view_config(request_method='GET', route_name='user', renderer='brewman:templates/angular_base.mako',
|
self.user = authenticated_userid(request)
|
||||||
permission='Users')
|
self.permissions = None
|
||||||
def html(request):
|
self.HasPermission = False
|
||||||
return {}
|
if self.user is not None:
|
||||||
|
self.user = User.by_id(self.user)
|
||||||
|
self.HasPermission = 'User' in groupfinder(self.user.id, request)
|
||||||
|
|
||||||
|
@view_config(route_name='user_list', renderer='brewman:templates/angular_base.mako', permission='Users')
|
||||||
|
@view_config(request_method='GET', route_name='user_id', renderer='brewman:templates/angular_base.mako',
|
||||||
|
permission='Authenticated')
|
||||||
|
@view_config(request_method='GET', route_name='user', renderer='brewman:templates/angular_base.mako',
|
||||||
|
permission='Users')
|
||||||
|
def html(self):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='POST', route_name='api_user', renderer='json', permission='Users')
|
@view_config(request_method='POST', route_name='api_user', renderer='json', permission='Users')
|
||||||
@TryCatchFunction
|
@TryCatchFunction
|
||||||
def save(request):
|
def save(self):
|
||||||
user = User(request.json_body['Name'], request.json_body['Password'], request.json_body['LockedOut'])
|
user = User(self.request.json_body['Name'], self.request.json_body['Password'],
|
||||||
DBSession.add(user)
|
self.request.json_body['LockedOut'])
|
||||||
add_groups(user, request.json_body['Groups'])
|
DBSession.add(user)
|
||||||
transaction.commit()
|
self.add_groups(user, self.request.json_body['Groups'])
|
||||||
return user_info(user.id)
|
transaction.commit()
|
||||||
|
return self.user_info(user.id)
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='POST', route_name='api_user_id', renderer='json', permission='Users')
|
@view_config(request_method='POST', route_name='api_user_id', renderer='json', permission='Authenticated')
|
||||||
@TryCatchFunction
|
def update(self):
|
||||||
def update(request):
|
id = self.request.matchdict['id']
|
||||||
id = request.matchdict['id']
|
p = re.compile('^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$')
|
||||||
p = re.compile('^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$')
|
if p.match(id):
|
||||||
if p.match(id):
|
user = User.by_id(uuid.UUID(id))
|
||||||
user = User.by_id(uuid.UUID(id))
|
else:
|
||||||
else:
|
user = User.by_name(id)
|
||||||
user = User.by_name(id)
|
return self.update_user(user)
|
||||||
user.name = request.json_body['Name']
|
|
||||||
user.locked_out = request.json_body['LockedOut']
|
@TryCatchFunction
|
||||||
if request.json_body['Password'] != '' and request.json_body['Password'] != user.password:
|
def update_user(self, user):
|
||||||
user.password = request.json_body['Password']
|
if user is None:
|
||||||
add_groups(user, request.json_body['Groups'])
|
raise ValidationError('User name / id not found')
|
||||||
transaction.commit()
|
if self.HasPermission:
|
||||||
return user_info(user.id)
|
user.name = self.request.json_body['Name']
|
||||||
|
user.locked_out = self.request.json_body['LockedOut']
|
||||||
|
self.add_groups(user, self.request.json_body['Groups'])
|
||||||
|
|
||||||
|
if self.request.json_body['Password'] != '' and self.request.json_body['Password'] != user.password:
|
||||||
|
user.password = self.request.json_body['Password']
|
||||||
|
transaction.commit()
|
||||||
|
return self.user_info(user.id)
|
||||||
|
|
||||||
|
|
||||||
def add_groups(user, groups):
|
@view_config(request_method='DELETE', route_name='api_user_id', renderer='json', permission='Users')
|
||||||
for group in groups:
|
def delete(self):
|
||||||
id = uuid.UUID(group['GroupID'])
|
id = self.request.matchdict.get('id', None)
|
||||||
ug = [g for g in user.groups if g.id == id]
|
if id is None:
|
||||||
ug = None if len(ug) == 0 else ug[0]
|
response = Response("User is Null")
|
||||||
if group['Enabled'] and ug is None:
|
response.status_int = 500
|
||||||
user.groups.append(Group.by_id(id))
|
return response
|
||||||
elif not group['Enabled'] and ug:
|
else:
|
||||||
user.groups.remove(ug)
|
response = Response("User deletion not implemented")
|
||||||
|
response.status_int = 500
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='DELETE', route_name='api_user_id', renderer='json', permission='Users')
|
@view_config(request_method='GET', route_name='api_user_id', renderer='json', permission='Authenticated')
|
||||||
def delete(request):
|
def show_id(self):
|
||||||
id = request.matchdict.get('id', None)
|
id = self.request.matchdict['id']
|
||||||
if id is None:
|
p = re.compile('^[A-Za-z0-9]{8}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{12}$')
|
||||||
response = Response("User is Null")
|
if p.match(id):
|
||||||
response.status_int = 500
|
id = uuid.UUID(id)
|
||||||
return response
|
return self.user_info(id)
|
||||||
else:
|
|
||||||
response = Response("User deletion not implemented")
|
|
||||||
response.status_int = 500
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='GET', route_name='api_user_id', renderer='json', permission='Users')
|
@view_config(request_method='GET', route_name='api_user', renderer='json', permission='Users')
|
||||||
def show_id(request):
|
def show_blank(self):
|
||||||
id = request.matchdict['id']
|
return self.user_info(None)
|
||||||
p = re.compile('^[A-Za-z0-9]{8}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{12}$')
|
|
||||||
if p.match(id):
|
|
||||||
id = uuid.UUID(id)
|
|
||||||
return user_info(id)
|
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='GET', route_name='api_user', renderer='json', permission='Users')
|
@view_config(request_method='GET', route_name='api_user', renderer='json', request_param='list', permission='Users')
|
||||||
def show_blank(request):
|
def show_list(self):
|
||||||
return user_info(None)
|
list = User.list()
|
||||||
|
users = []
|
||||||
|
for item in list:
|
||||||
|
user = {'Name': item.name, 'LockedOut': item.locked_out,
|
||||||
|
'Groups': [], 'Url': self.request.route_url('user_id', id=item.name)}
|
||||||
|
for group in item.groups:
|
||||||
|
user['Groups'].append(group.name)
|
||||||
|
users.append(user)
|
||||||
|
return users
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='GET', route_name='api_user', renderer='json', request_param='list', permission='Users')
|
@view_config(request_method='GET', route_name='api_user', renderer='json', request_param='names', permission='Authenticated')
|
||||||
def show_list(request):
|
def show_name(self):
|
||||||
list = User.list()
|
list = User.query().filter(User.locked_out == False).order_by(User.name).all()
|
||||||
users = []
|
users = [{'Name': item.name} for item in list]
|
||||||
for item in list:
|
# for item in list:
|
||||||
user = {'Name': item.name, 'LockedOut': item.locked_out,
|
# users.append({'Name': item.name})
|
||||||
'Groups': [], 'Url': request.route_url('user_id', id=item.name)}
|
return users
|
||||||
for group in item.groups:
|
|
||||||
user['Groups'].append(group.name)
|
|
||||||
users.append(user)
|
|
||||||
return users
|
|
||||||
|
|
||||||
|
|
||||||
def user_info(id):
|
def user_info(self, id):
|
||||||
if id is None:
|
if id is None:
|
||||||
account = {'Name': '', 'LockedOut': False, 'Groups': []}
|
account = {'Name': '', 'LockedOut': False, 'Groups': []}
|
||||||
for item in Group.list():
|
for item in Group.list():
|
||||||
account['Groups'].append({'GroupID': item.id, 'Name': item.name, 'Enabled': False})
|
account['Groups'].append({'GroupID': item.id, 'Name': item.name, 'Enabled': False})
|
||||||
else:
|
return account
|
||||||
|
|
||||||
if isinstance(id, uuid.UUID):
|
if isinstance(id, uuid.UUID):
|
||||||
user = User.by_id(id)
|
user = User.by_id(id)
|
||||||
else:
|
else:
|
||||||
user = User.by_name(id)
|
user = User.by_name(id)
|
||||||
account = {'UserID': user.id, 'Name': user.name, 'Password': '', 'LockedOut': user.locked_out, 'Groups': []}
|
|
||||||
for item in Group.list():
|
if self.HasPermission:
|
||||||
account['Groups'].append(
|
account = {'UserID': user.id, 'Name': user.name, 'Password': '', 'LockedOut': user.locked_out, 'Groups': []}
|
||||||
{'GroupID': item.id, 'Name': item.name, 'Enabled': True if item in user.groups else False})
|
for item in Group.list():
|
||||||
return account
|
account['Groups'].append(
|
||||||
|
{'GroupID': item.id, 'Name': item.name, 'Enabled': True if item in user.groups else False})
|
||||||
|
elif self.user.id == user.id:
|
||||||
|
account = {'UserID': user.id, 'Name': user.name, 'Password': '', 'LockedOut': user.locked_out, 'Groups': []}
|
||||||
|
else:
|
||||||
|
response = Response("User can only update his/her password")
|
||||||
|
response.status_int = 500
|
||||||
|
return response
|
||||||
|
return account
|
||||||
|
|
||||||
|
|
||||||
|
def add_groups(self, user, groups):
|
||||||
|
for group in groups:
|
||||||
|
id = uuid.UUID(group['GroupID'])
|
||||||
|
ug = [g for g in user.groups if g.id == id]
|
||||||
|
ug = None if len(ug) == 0 else ug[0]
|
||||||
|
if group['Enabled'] and ug is None:
|
||||||
|
user.groups.append(Group.by_id(id))
|
||||||
|
elif not group['Enabled'] and ug:
|
||||||
|
user.groups.remove(ug)
|
|
@ -3,10 +3,13 @@ import uuid
|
||||||
from pyramid.security import authenticated_userid
|
from pyramid.security import authenticated_userid
|
||||||
|
|
||||||
from pyramid.view import view_config
|
from pyramid.view import view_config
|
||||||
|
from sqlalchemy.orm import joinedload_all
|
||||||
import transaction
|
import transaction
|
||||||
from brewman.models import DBSession
|
from brewman.models import DBSession
|
||||||
|
from brewman.models.auth import User
|
||||||
|
|
||||||
from brewman.models.messaging import Thread, Post, Tag
|
from brewman.models.messaging import Thread, Post, Tag, Subscriber
|
||||||
|
from brewman.models.tzinfoutc import get_age
|
||||||
from brewman.models.validation_exception import TryCatchFunction
|
from brewman.models.validation_exception import TryCatchFunction
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +38,10 @@ def save(request):
|
||||||
tag = Tag(name=name)
|
tag = Tag(name=name)
|
||||||
DBSession.add(tag)
|
DBSession.add(tag)
|
||||||
thread.tags.append(tag)
|
thread.tags.append(tag)
|
||||||
|
for item in request.json_body['Subscribers']:
|
||||||
|
subscriber = Subscriber(user_id=User.by_name(item).id, read=False)
|
||||||
|
thread.subscribers.append(subscriber)
|
||||||
|
DBSession.add(subscriber)
|
||||||
transaction.commit()
|
transaction.commit()
|
||||||
return thread_info(thread.id)
|
return thread_info(thread.id)
|
||||||
|
|
||||||
|
@ -74,13 +81,17 @@ def update(request):
|
||||||
post = Post(content=item['Content'].strip(), date=dt, user_id=user_id)
|
post = Post(content=item['Content'].strip(), date=dt, user_id=user_id)
|
||||||
thread.posts.append(post)
|
thread.posts.append(post)
|
||||||
DBSession.add(post)
|
DBSession.add(post)
|
||||||
|
for subscriber in thread.subscribers:
|
||||||
|
subscriber.read = False
|
||||||
transaction.commit()
|
transaction.commit()
|
||||||
return thread_info(thread.id)
|
return thread_info(thread.id)
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='GET', route_name='api_message', renderer='json', permission='Authenticated')
|
@view_config(request_method='GET', route_name='api_message', renderer='json', permission='Authenticated')
|
||||||
def show_blank(request):
|
def show_blank(request):
|
||||||
return thread_info(None)
|
user = User.by_id(authenticated_userid(request)).name
|
||||||
|
return {'Title': '', 'User': user, 'Tags': [], 'Priority': 4, 'Public': False,
|
||||||
|
'Posts': [], 'Closed': False, 'Subscribers': [user]}
|
||||||
|
|
||||||
|
|
||||||
@view_config(request_method='GET', route_name='api_message_id', renderer='json', permission='Authenticated')
|
@view_config(request_method='GET', route_name='api_message_id', renderer='json', permission='Authenticated')
|
||||||
|
@ -91,43 +102,51 @@ def show_id(request):
|
||||||
@view_config(request_method='GET', route_name='api_message', renderer='json', request_param='list')
|
@view_config(request_method='GET', route_name='api_message', renderer='json', request_param='list')
|
||||||
def show_list(request):
|
def show_list(request):
|
||||||
list = Thread.query().filter(Thread.closed == False)
|
list = Thread.query().filter(Thread.closed == False)
|
||||||
|
# Thread.subscribers, Thread.posts,
|
||||||
if authenticated_userid(request) is None:
|
if authenticated_userid(request) is None:
|
||||||
list = list.filter(Thread.public == True)
|
list = list.filter(Thread.public == True)
|
||||||
|
# else:
|
||||||
|
# list.filter(Thread.subscribers.any(Subscriber.user_id == uuid.UUID(authenticated_userid(request))))
|
||||||
list = list.order_by(Thread.priority).all()
|
list = list.order_by(Thread.priority).all()
|
||||||
tags = {}
|
tags = {}
|
||||||
threads = []
|
threads = []
|
||||||
for item in list:
|
for item in list:
|
||||||
thread = {'ThreadID': item.id, 'Title': item.title,
|
thread = {'ThreadID': item.id, 'Title': item.title, 'Age': get_age(item.creation_date),
|
||||||
'CreationDate': item.creation_date.strftime('%d-%b-%Y %H:%M'), 'User': item.user.name,
|
'CreationDate': item.creation_date.strftime('%d-%b-%Y %H:%M'), 'User': item.user.name,
|
||||||
'Priority': item.priority, 'Public': item.public, 'Tags': [], 'Posts': []}
|
'Priority': item.priority, 'Public': item.public, 'Tags': [], 'Posts': [], 'Subscribers': []}
|
||||||
for tag in item.tags:
|
for tag in item.tags:
|
||||||
thread['Tags'].append(tag.name)
|
thread['Tags'].append(tag.name)
|
||||||
if not tag.name in tags:
|
if not tag.name in tags:
|
||||||
tags[tag.name] = 1
|
tags[tag.name] = 1
|
||||||
else:
|
else:
|
||||||
tags[tag.name] += 1
|
tags[tag.name] += 1
|
||||||
|
for subscriber in item.subscribers:
|
||||||
|
thread['Subscribers'].append(subscriber.user.name)
|
||||||
|
last_updated = item.creation_date
|
||||||
for post in item.posts:
|
for post in item.posts:
|
||||||
thread['Posts'].append({'PostID': post.id, 'Content': post.content, 'User': post.user.name,
|
if post.creation_date > last_updated:
|
||||||
'Date': post.date.strftime('%d-%b-%Y %H:%M'),
|
last_updated = post.creation_date
|
||||||
'CreationDate': post.creation_date.strftime('%d-%b-%Y %H:%M')})
|
# thread['Posts'].append({'PostID': post.id, 'Content': post.content, 'User': post.user.name,
|
||||||
|
# 'Date': post.date.strftime('%d-%b-%Y %H:%M'),
|
||||||
|
# 'CreationDate': post.creation_date.strftime('%d-%b-%Y %H:%M')})
|
||||||
threads.append(thread)
|
threads.append(thread)
|
||||||
|
thread['LastUpdated'] = get_age(last_updated)
|
||||||
return {'Tags': tags, 'Threads': threads}
|
return {'Tags': tags, 'Threads': threads}
|
||||||
|
|
||||||
|
|
||||||
def thread_info(id):
|
def thread_info(id):
|
||||||
if id is None:
|
item = Thread.by_id(id)
|
||||||
thread = {'Title': '', 'Tags': [], 'Priority': 4, 'Public': False, 'Posts': [], 'Closed': False}
|
thread = {'ThreadID': item.id, 'Title': item.title, 'Closed': item.closed,
|
||||||
else:
|
'CreationDate': item.creation_date.strftime('%d-%b-%Y %H:%M'), 'User': item.user.name,
|
||||||
item = Thread.by_id(id)
|
'Priority': item.priority, 'Public': item.public, 'Tags': [], 'Posts': [], 'Subscribers': []}
|
||||||
thread = {'ThreadID': item.id, 'Title': item.title, 'Closed': item.closed,
|
for tag in item.tags:
|
||||||
'CreationDate': item.creation_date.strftime('%d-%b-%Y %H:%M'), 'User': item.user.name,
|
thread['Tags'].append(tag.name)
|
||||||
'Priority': item.priority, 'Public': item.public, 'Tags': [], 'Posts': []}
|
for subscriber in item.subscribers:
|
||||||
for tag in item.tags:
|
thread['Subscribers'].append(subscriber.user.name)
|
||||||
thread['Tags'].append(tag.name)
|
for post in item.posts:
|
||||||
for post in item.posts:
|
thread['Posts'].append({'PostID': post.id, 'Content': post.content, 'User': post.user.name,
|
||||||
thread['Posts'].append({'PostID': post.id, 'Content': post.content, 'User': post.user.name,
|
'Date': post.date.strftime('%d-%b-%Y'),
|
||||||
'Date': post.date.strftime('%d-%b-%Y %H:%M'),
|
'CreationDate': post.creation_date.strftime('%d-%b-%Y %H:%M')})
|
||||||
'CreationDate': post.creation_date.strftime('%d-%b-%Y %H:%M')})
|
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue