306 lines
10 KiB
Python
306 lines
10 KiB
Python
import os
|
|
import datetime as dt
|
|
import random
|
|
import hashlib
|
|
|
|
from django.db.models import Model, ForeignKey, \
|
|
DateTimeField, CharField, FileField, ManyToManyField, \
|
|
TextField, Manager, BooleanField, OneToOneField
|
|
from django.contrib.auth.models import User, Group
|
|
from django.template.defaultfilters import slugify
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.forms import ValidationError
|
|
|
|
DOCBOW_APP = _('docbow')
|
|
DOCBOW_APP = _('Docbow_App')
|
|
DOCBOW_APP2 = _('Docbow_app')
|
|
|
|
class GetByNameManager(Manager):
|
|
def get_by_natural_key(self, name):
|
|
return self.get(name=name)
|
|
|
|
class ContentManager(Manager):
|
|
def get_by_natural_key(self, description):
|
|
return self.get(description=description)
|
|
|
|
class NameNaturalKey(object):
|
|
def natural_key(self):
|
|
return (self.name,)
|
|
|
|
class FileType(NameNaturalKey, Model):
|
|
'''
|
|
A type of file that can be sent inside the application.
|
|
'''
|
|
objects = GetByNameManager()
|
|
|
|
name = CharField(max_length=128, unique=True)
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
class Meta:
|
|
ordering = ['name']
|
|
verbose_name = _('File type')
|
|
verbose_name_plural = _('File types')
|
|
|
|
class Content(Model):
|
|
'''Predefined content type'''
|
|
objects = ContentManager()
|
|
|
|
description = CharField(max_length=128, unique=True)
|
|
|
|
def __unicode__(self):
|
|
return self.description
|
|
|
|
class Meta:
|
|
ordering = ['description']
|
|
verbose_name = _('Content')
|
|
verbose_name_plural = _('Contents')
|
|
|
|
def username(user):
|
|
return user.get_full_name() or user.username
|
|
|
|
def generate_filename(instance, filename):
|
|
now = dt.date.today()
|
|
# Keep all underscores and points
|
|
parts = filename.split('.')
|
|
parts = map(slugify, parts)
|
|
filename = '.'.join(parts)
|
|
return os.path.join('files', now.isoformat(), '%d_%s' % (random.randint(0,10000000), filename))
|
|
|
|
class Document(Model):
|
|
'''
|
|
Represent a file sent between a user and some targets, user or groups.
|
|
'''
|
|
class Meta:
|
|
ordering = ['-date']
|
|
verbose_name = _('Document')
|
|
verbose_name_plural = _('Documents')
|
|
|
|
sender = ForeignKey(User, verbose_name=_('Sender'),
|
|
related_name='documents_sent')
|
|
date = DateTimeField(default=dt.datetime.now,
|
|
verbose_name=_("Date d'envoi"))
|
|
to_user = ManyToManyField(User, related_name='directly_received_documents',
|
|
blank=True, null=True, verbose_name=_('Users to send to'))
|
|
to_list = ManyToManyField('MailingList', blank=True, null=True,
|
|
verbose_name=_('Groups to send to'))
|
|
filetype = ForeignKey(FileType, verbose_name=_('Document type'))
|
|
comment = TextField(blank=True, verbose_name=_('Comments'))
|
|
|
|
def __unicode__(self):
|
|
ctx = {
|
|
'sender': username(self.sender),
|
|
'date': self.date.date().isoformat(),
|
|
'filename': self.filenames(),
|
|
'filetype': self.filetype,
|
|
'comment': self.comment }
|
|
return _('%(comment)s; %(filetype)s, %(filename)s de %(sender)s le %(date)s') % ctx
|
|
|
|
def filenames(self):
|
|
files = [ attached_file for attached_file in self.attached_files.all() ]
|
|
return ', '.join([f.filename() for f in files])
|
|
filenames.short_description = _('Attached files')
|
|
|
|
def filename_links(self):
|
|
links = []
|
|
for attached_file in self.attached_files.all():
|
|
name = attached_file.filename()
|
|
url = attached_file.link()
|
|
links.append(u'<a href="%s">%s</a>' % (url, name))
|
|
return ', '.join(links)
|
|
filename_links.short_description = _('Attached files')
|
|
filename_links.allow_tags = True
|
|
|
|
def user_human_to(self):
|
|
return sorted(map(username, self.to_user.all()))
|
|
|
|
def group_human_to(self):
|
|
return sorted(map(unicode, self.to_list.all()))
|
|
|
|
def human_to(self):
|
|
return sorted(map(username, self.to_user.all()) + \
|
|
map(unicode, self.to_list.all()))
|
|
|
|
def recipients(self):
|
|
return ', '.join(self.human_to())
|
|
recipients.short_description = _('Recipients')
|
|
|
|
def to(self):
|
|
q = self.to_user.all() | \
|
|
User.objects.filter(mailing_lists__in=self.to_list.all())
|
|
return q.distinct()
|
|
|
|
def post(self):
|
|
to = self.to()
|
|
for user in to:
|
|
if user.is_active:
|
|
Mailbox.objects.get_or_create(owner=user,document=self)
|
|
# Add to outbox
|
|
Mailbox.objects.get_or_create(owner=self.sender, outbox=True, document=self)
|
|
return to.count()
|
|
|
|
def timestamp_blob(self):
|
|
blob = {}
|
|
blob['from'] = username(self.sender)
|
|
blob['date'] = self.date.isoformat()
|
|
blob['to'] = self.recipients()
|
|
blob['filetype'] = unicode(self.filetype)
|
|
blob['comment'] = self.comment
|
|
blob['files'] = []
|
|
for f in self.attached_files.all():
|
|
d = dict(name=f.filename(), size=f.content.size,
|
|
digest=hashlib.sha1(f.content.read()).hexdigest())
|
|
blob['files'].append(d)
|
|
return blob
|
|
|
|
class DocumentForwarded(Model):
|
|
'''Model to store tags applied to models.
|
|
|
|
First use will be to mark message as having been forwarded.
|
|
'''
|
|
from_document = ForeignKey(Document, related_name='document_forwarded_to')
|
|
to_document = ForeignKey(Document, related_name='document_forwarded_from')
|
|
date = DateTimeField(auto_now=True,
|
|
auto_now_add=True)
|
|
automatic = BooleanField(default=False)
|
|
|
|
def list_to_csv(l, mapping_func=None):
|
|
if mapping_func:
|
|
l = map(mapping_func, l)
|
|
return u', '.join(map(unicode, l))
|
|
|
|
|
|
class AutomaticForwarding(Model):
|
|
'''
|
|
Choice of sender and filetype to transfer mail automatically to a list
|
|
of recipients.
|
|
'''
|
|
filetypes = ManyToManyField(FileType, related_name='forwarding_rules',
|
|
verbose_name=_('filetype'))
|
|
originaly_to_user = ManyToManyField(User, related_name='as_original_recipient_forwarding_rules',
|
|
blank=True, null=True, verbose_name=_('Original recipients'),
|
|
help_text=_('At least one recipient must match for the rule to '
|
|
'apply.'))
|
|
forward_to_user = ManyToManyField(User, related_name='as_recipient_forwarding_rules',
|
|
blank=True, null=True, verbose_name=_('Users to forward to'))
|
|
forward_to_list = ManyToManyField('MailingList', blank=True, null=True,
|
|
verbose_name=_('Groups to forward to'), related_name='as_recipient_forwarding_rules')
|
|
|
|
def __unicode__(self):
|
|
ctx = {
|
|
'filetypes': list_to_csv(self.filetypes.all()),
|
|
'to': list_to_csv(map(username, self.forward_to_user.all())
|
|
+ list(self.forward_to_list.all())) }
|
|
return _('Forward documents of type %(filetypes)s automatically to %(to)s') % ctx
|
|
|
|
class Meta:
|
|
verbose_name = _('Automatic forwarding rule')
|
|
verbose_name_plural = _('Automatic forwarding rules')
|
|
|
|
class AttachedFile(Model):
|
|
name = CharField(max_length=128, verbose_name=_('Name'))
|
|
content = FileField(upload_to=generate_filename, verbose_name=_('File'))
|
|
document = ForeignKey(Document, verbose_name=_('Attached to'),
|
|
related_name='attached_files')
|
|
|
|
def filename(self):
|
|
filename = os.path.basename(self.content.name)
|
|
try:
|
|
prefix, true_filename = filename.split('_', 1)
|
|
if prefix.isdigit():
|
|
return true_filename
|
|
except:
|
|
pass
|
|
|
|
return filename
|
|
|
|
def link(self):
|
|
return '/admin/docbow/attachedfile/%s/download/' % self.id
|
|
|
|
def __unicode__(self):
|
|
return '<AttachedFile pk: %s>' % self.pk
|
|
|
|
class Delegation(Model):
|
|
'''
|
|
Delegate account, managable by user themselves.
|
|
'''
|
|
class Meta:
|
|
ordering = [ 'by' ]
|
|
verbose_name = _('Account delegation')
|
|
verbose_name_plural = _('Account delegations')
|
|
app_label = 'auth'
|
|
by = ForeignKey(User, related_name='delegations_to')
|
|
to = ForeignKey(User, related_name='delegations_by')
|
|
guest_delegate = BooleanField(blank=True)
|
|
|
|
class MailingList(NameNaturalKey, Model):
|
|
class Meta:
|
|
ordering = [ 'name' ]
|
|
verbose_name = _('Mailing list')
|
|
verbose_name_plural = _('Mailing lists')
|
|
name = CharField(max_length=128, verbose_name=_('Name'))
|
|
members = ManyToManyField(User, verbose_name=_('Members'), blank=True,
|
|
null=True, related_name='mailing_lists')
|
|
|
|
objects = GetByNameManager()
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
class Mailbox(Model):
|
|
'''List of document received by a user'''
|
|
owner = ForeignKey(User, verbose_name=_('Mailbox owner'),
|
|
related_name='documents')
|
|
document = ForeignKey(Document, verbose_name=('Document'),
|
|
related_name='mailboxes')
|
|
seen = BooleanField(verbose_name=_('Seen'), blank=True)
|
|
deleted = BooleanField(verbose_name=_('Deleted'), blank=True)
|
|
outbox = BooleanField(verbose_name=_('Outbox message'), blank=True,
|
|
default=False)
|
|
date = DateTimeField(auto_now=True,
|
|
auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = [ '-date' ]
|
|
verbose_name = _('Mailbox')
|
|
verbose_name_plural = _('Mailboxes')
|
|
|
|
class DocbowUser(User):
|
|
class Meta:
|
|
verbose_name = _('Docbow admin user')
|
|
proxy = True
|
|
app_label = 'auth'
|
|
|
|
class DocbowGroup(Group):
|
|
class Meta:
|
|
verbose_name = _('Docbow admin group')
|
|
app_label = 'auth'
|
|
proxy = True
|
|
|
|
class Inbox(Mailbox):
|
|
class Meta:
|
|
proxy = True
|
|
verbose_name = _('Inbox')
|
|
verbose_name_plural = _('Inboxes')
|
|
|
|
class Outbox(Mailbox):
|
|
class Meta:
|
|
proxy = True
|
|
verbose_name = _('Outbox')
|
|
verbose_name_plural = _('Outboxes')
|
|
|
|
class SendingLimitation(Model):
|
|
mailing_list = OneToOneField(MailingList, unique=True,
|
|
verbose_name=MailingList._meta.verbose_name)
|
|
filetypes = ManyToManyField(FileType, blank=True,
|
|
related_name='filetype_limitation',
|
|
verbose_name=_('Limitation des types de fichier'))
|
|
lists = ManyToManyField(MailingList, related_name='lists_limitation',
|
|
verbose_name=_('Limitation des destinataires'))
|
|
|
|
class Meta:
|
|
verbose_name = _('Limitation par liste de destinataires')
|
|
verbose_name = _('Limitation par liste de destinataires')
|
|
verbose_name_plural = verbose_name
|