Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed Apr 18, 2011
0 parents commit bfb64b2
Show file tree
Hide file tree
Showing 89 changed files with 6,531 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.pyc
*.pyc
*.egg-info
build
dist
.DS_Store
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include README.rst LICENCE
recursive-include bft *.py
recursive-include bft/templates *
recursive-include bft/static *
recursive-include docs/source *
recursive-include docs/build/html *
include docs/Makefile
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. include:: docs/source/index.rst
2 changes: 2 additions & 0 deletions bft/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VERSION = (0, 1, 0)
__version__ = '.'.join(map(str, VERSION))
107 changes: 107 additions & 0 deletions bft/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import app_settings
from django.core.urlresolvers import reverse
from django.contrib import admin
from forms import EmailForm, FileForm, SubmissionForm
from models import Submission, Email, File, FileArchive
import os

#global callables
def delete_row(obj):
return '<a href="%s/delete">Delete</a>' % obj.id
delete_row.allow_tags = True
delete_row.short_description = 'Delete'

def edit_row(obj):
return '<a href="%s">Edit</a>' % obj.id
edit_row.short_description = 'Edit'
edit_row.allow_tags = True

def file_url(obj):
url = reverse('file', args=(obj.slug,))
return '<a href="%s%s">%s</a>' % (url, os.path.basename(obj.file_upload.name), url)
file_url.short_description = 'File URL'
file_url.allow_tags = True

def submission_url(obj):
url = reverse('files', args=(obj.slug,))
return '<a href="%s">%s</a>' % (url, url)
submission_url.short_description = 'Submission URL'
submission_url.allow_tags = True

def submission_admin_url(obj):
url = reverse('admin:bft_submission_change', args=(obj.submission,))
return '<a href="%s">%s</a>' % (url, obj.submission)
submission_admin_url.short_description = 'Submission'
submission_admin_url.allow_tags = True

def attached_files(obj):
files = File.objects.filter(submission=obj.id)
if files:
file_list = []
for file in files:
file_list.append('<a href="/%s/%s">%s</a>' % (file.slug,
os.path.basename(file.file_upload.name), file.slug))
return ' '.join(file_list)
else:
return None
attached_files.allow_tags = True

def attached_submission_date(obj):
return obj.submission.submit_date
attached_submission_date.short_description = 'Upload Date'

def submission_fields():
if app_settings.RANDOM_PASS:
return ('type', 'email_address', 'is_archived', 'email_sent')
else:
return ('type', 'email_address', 'password', 'is_archived', 'email_sent')


#inlines
class EmailInline(admin.StackedInline):
model = Email
form = EmailForm
fields = ('first_name', 'last_name', 'recipients', 'message')

class FileInline(admin.StackedInline):
model = File
form = FileForm
extra = 3

#admin views
class SubmissionAdmin(admin.ModelAdmin):
class Media:
js = (
'https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js',
'/static/scripts/admin.js',
)

list_filter = ('type', 'submit_date')
search_fields = ['email_address', 'slug', 'submit_ip', 'file__slug', 'email__recipients']
fields = submission_fields()
list_display = ('id', submission_url, 'type', 'email_address', 'password',
attached_files, 'submit_date', 'submit_ip', 'browser_meta', delete_row, edit_row)
inlines = [EmailInline, FileInline]
form = SubmissionForm

def save_model(self, request, obj, form, change):
obj.submit_ip = request.META['REMOTE_ADDR']
obj.save()


class FileAdmin(admin.ModelAdmin):
list_display = ('id', file_url, submission_admin_url, 'file_upload',
'file_size', attached_submission_date, delete_row, edit_row)
search_fields = ['file_upload', 'slug', 'submission__pk', 'submission__email_address']

form = FileForm

class FileArchiveAdmin(admin.ModelAdmin):
list_display = ('delete_date', 'submit_date', submission_admin_url, 'file_upload', delete_row)

list_filter = ('submit_date', 'delete_date')
search_fields = ['file_upload', 'submission__pk']

admin.site.register(Submission, SubmissionAdmin)
admin.site.register(File, FileAdmin)
admin.site.register(FileArchive, FileArchiveAdmin)
50 changes: 50 additions & 0 deletions bft/app_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Location of file uploads relative to MEDIA_ROOT
# Do not put a trailing slash!
FILE_UPLOAD_DIR = 'files'

# Do not exceed 2 GB, your web server will not like you!
# This used on the client (flash player) to enforce size limit
MAX_UPLOAD_SIZE = 1073741824 #1GB

# This setting is used my the management commands to
# delete files. Follow documentation to setup a cron job for this.
UPLOAD_EXPIRATION_DAYS = 7

# Set to have Django try to enforce MAX_UPLOAD_SIZE
# It is far better to enforce this using the web server (Apache)
# An example would be:
# LimitRequestBody 1073741824
# ErrorDocument 413 http://servername/413error/
VALIDATE_UPLOAD_SIZE = True

# Feedback form
SHOW_FEEDBACK = True

# General settings
APP_NAME = 'BFT'
REPLY_EMAIL = ''
USE_FLASH = True

# Captcha settings
USE_RECAPTCHA = False
RECAPTCHA_SUBNET = ''
RECAPTCHA_PUB_KEY = ''
RECAPTCHA_PRIVATE_KEY = ''

# Slug generator settings
# This is used to randomize the file and file list urls
RANDOMSLUG_CHARS = "bcdfghjklmnpqrstvwxyz2346789"
RANDOMSLUG_CHAR_NO = 5

# If used, then passwords will not be encrypted regardless.
RANDOM_PASS = False

# Use this to encrypt non random passwords
# RANDOM_PASS must be False for this to work.
ENCRYPT_PASS = True

# Used to generate a random password
RANDOMPASS_CHARS = 'bcdfghjklmnpqrstvwxyz2346789'
RANDOMPASS_CHAR_NO = 8


25 changes: 25 additions & 0 deletions bft/context_processors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from bft import app_settings
from django.conf import settings
from django.core.urlresolvers import reverse

def bft(request):

abs_static_url = "http%s://%s%s" % (
's' if request.is_secure() else None,
request.META['SERVER_NAME'],
settings.STATIC_URL[1:]
)

# Show the password field if RANDOM_PASS is False:
show_password_input = False if app_settings.RANDOM_PASS else True

return {
'app_name' : app_settings.APP_NAME,
'use_flash' : app_settings.USE_FLASH,
'expiry_days' : app_settings.UPLOAD_EXPIRATION_DAYS,
'reply_email' : app_settings.REPLY_EMAIL,
'show_feedback' : app_settings.SHOW_FEEDBACK,
'feedback_url' : reverse('feedback'),
'show_password_input' : show_password_input,
'abs_static_url' : abs_static_url
}
41 changes: 41 additions & 0 deletions bft/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from django import forms
from models import Email, File, Submission
from bft.app_settings import RANDOMPASS_CHAR_NO

TYPE_CHOICES = (
('link', 'Link'),
('email', 'Email'),
)

class EmailForm(forms.ModelForm):
first_name = forms.CharField(error_messages={'required':'Please enter your first name.'})
last_name = forms.CharField(error_messages={'required':'Please enter your last name.'})
recipients = forms.CharField(
error_messages={'required':'Please enter the recipient(s) email separated by commas.'},
widget=forms.Textarea,
help_text="Enter a set of email addresses separated by commas"
)
message = forms.CharField(error_messages={'required':'Please enter a message.'}, widget=forms.Textarea)

class Meta:
exclude = ('submission',)
model = Email

class FileForm(forms.ModelForm):
class Meta:
model = File

class SubmissionForm(forms.ModelForm):
type = forms.ChoiceField(choices=TYPE_CHOICES)
email_address = forms.CharField(error_messages={'required':'Please enter a valid email address.'})
password = forms.CharField(
error_messages={'min_length':'Please ensure that your password is at least 8 characters in length.'},
widget = forms.PasswordInput,
min_length = RANDOMPASS_CHAR_NO,
help_text = "Enter a password that contains at least 8 characters.",
required = False
)

class Meta:
model = Submission

Empty file added bft/management/__init__.py
Empty file.
Empty file.
32 changes: 32 additions & 0 deletions bft/management/commands/deletetempfiles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from datetime import datetime, timedelta
from django.conf import settings
from django.core.management.base import BaseCommand
from sys import stdout
import os

class Command(BaseCommand):
"""
Cron Job that deletes clean up the temp files directory
"""

def handle(self, *args, **options):
path = "%s/tmp/" % settings.BASE_DIR

datediff = datetime.today() - timedelta(days=1)

try:
if os.path.isdir(path):

files = os.listdir(path)

for file in files:

fullpath = os.path.join(path, file)

if os.path.isfile(fullpath) and (datetime.fromtimestamp(os.path.getmtime(fullpath)) < datediff):
os.remove(fullpath)

stdout.write('Temp files have been deleted.\n')

except:
pass
45 changes: 45 additions & 0 deletions bft/management/commands/deleteuploads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from bft.app_settings import APP_NAME
from bft.models import Submission, File
from django.core.mail import mail_admins
from django.core.management.base import BaseCommand
from optparse import make_option
from sys import stdout

class Command(BaseCommand):
"""
Cron Job that checks uploads that are past the expiration period and removes them from the system.
"""

option_list = BaseCommand.option_list + (
make_option('--mailadmins', '-M', dest='mailadmins', default=None,
help='Use this option to email admins of any files that were deleted.'),
)

def handle(self, *args, **options):
deleted_files = []

submissions = Submission.objects.get_expired_submissions()

for submission in submissions:
files = File.objects.filter(submission=submission)

for file in files:
deleted_files.append(file.file_upload.url)
file.delete()

submission.is_archived = True
submission.save()

message = '''
The following files have expired and deleted:
'''
if deleted_files:
body = "%s%s" % (message, '\n'.join(file for file in deleted_files))

if options['mailadmins']:
mail_admins('[%s] File cleanup summary' % APP_NAME, body)

stdout.write(body + '\n')
else:
stdout.write('No expired files were deleted.\n')
Loading

0 comments on commit bfb64b2

Please sign in to comment.