Dynastie/views.py

814 lines
24 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
Copyright 2012-2013 Grégory Soutadé
This file is part of Dynastie.
Dynastie is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Dynastie is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Dynastie. If not, see <http://www.gnu.org/licenses/>.
"""
import os
from datetime import datetime, date, time
from django.shortcuts import render
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.forms.models import inlineformset_factory
from django.core import mail
from django.core.mail import EmailMultiAlternatives
from dynastie.models import *
from dynastie.forms import *
from dynastie.search import *
from django.template.defaultfilters import register
from django.template import Variable, VariableDoesNotExist
@register.filter
def hash(object, attr):
pseudo_context = { 'object' : object }
try:
value = Variable('object.%s' % attr).resolve(pseudo_context)
except VariableDoesNotExist:
value = None
return value
def have_I_right(request, blog_id=None, post_id=None, must_be_superuser=False):
b = None
p = None
if must_be_superuser and not request.user.is_superuser:
raise Http404
if not post_id is None:
p = Post.objects.get(pk=post_id)
if p is None:
raise Http404
blog_id = p.blog.id
if not blog_id is None:
if not request.user.is_superuser:
b = Blog.objects.filter(pk=blog_id, writers=request.user.id)
if len(b) == 0:
raise Http404
b = b[0]
else:
b = Blog.objects.get(pk=blog_id)
if b is None:
raise Http404
return (b, p)
def createNavigationBar(blog_id, cur_page, nb_pages):
if nb_pages == 0: return ''
navigation_bar = ''
if cur_page == 0:
navigation_bar += '<< <'
else:
navigation_bar += '<a href="/blog/%d?page=0">&lt;&lt;</a> ' % blog_id
navigation_bar += '<a href="/blog/%d?page=%d">&lt;</a> ' % (blog_id, cur_page-1)
for i in range(nb_pages+1):
if i == cur_page:
navigation_bar += ' %d' % (i+1)
else:
navigation_bar += ' <a href="/blog/%d?page=%d">%d</a>' % (blog_id, i, i+1)
if cur_page == nb_pages:
navigation_bar += ' > >>'
else:
navigation_bar += ' <a href="/blog/%d?page=%d">&gt;</a>' % (blog_id, cur_page+1)
navigation_bar += ' <a href="/blog/%d?page=%d">&gt;&gt;</a>' % (blog_id, nb_pages)
return navigation_bar
def index(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/blog')
login_failed = False
if 'login' in request.POST:
user = authenticate(username=request.POST['login'], password=request.POST['password'])
if user is None:
login_failed = True
else:
login(request, user)
if 'next' in request.GET:
return HttpResponseRedirect(request.GET['next'])
else:
return HttpResponseRedirect('/blog')
c = {'login_failed' : login_failed}
return render(request, 'templates/login.html', c)
def disconnect(request):
logout(request)
c = {'login_failed' : False}
return HttpResponseRedirect('/')
@login_required
def user(request):
users = User.objects.all()
c = {'users' : users}
return render(request, 'templates/user.html', c)
@login_required
def add_user(request):
if not request.user.is_superuser:
return HttpResponseRedirect('/user')
if request.method == 'POST':
if 'add' in request.POST:
form = UserForm(request.POST)
if form.is_valid():
form = form.save()
user = User.objects.get(pk=form.id)
user.set_password(request.POST['password'])
user.save()
return HttpResponseRedirect('/user')
else:
return HttpResponseRedirect('/user')
else:
form = UserForm()
return render(request, 'add_user.html', {'form': form})
@login_required
def edit_user(request, user_id):
user = User.objects.get(pk=user_id)
if user is None:
raise Http404
edited = False
if request.method == 'POST':
if int(user_id) != int(request.user.id) and (not request.user.is_superuser):
return HttpResponseRedirect('/user')
if 'edit' in request.POST:
form = UserForm(request.POST, instance=user, initial={'password':''})
if form.is_valid():
form.save()
if request.POST['password'] != '':
user.set_password(request.POST['password'])
user.save()
edited = True
else:
if 'delete' in request.POST and request.user.is_superuser:
User.objects.get(pk=user_id).delete()
return HttpResponseRedirect('/user')
if 'cancel' in request.POST:
return HttpResponseRedirect('/user')
else:
form = UserForm(instance=user, initial={'password':''})
c = {'user_to_edit' : user, 'form' : form, 'edited' : edited}
return render(request, 'templates/edit_user.html', c)
@login_required
def category(request, blog_id):
b,_ = have_I_right(request, blog_id)
categories = Category.objects.filter(blog_id=blog_id)
c = {'categories' : categories, 'blog' : b}
return render(request, 'templates/category.html', c)
@login_required
def add_category(request, blog_id):
b,_ = have_I_right(request, blog_id)
if request.method == 'POST':
if 'add' in request.POST:
form = CategoryForm(request.POST)
form.blog = b
if form.is_valid():
form = form.save()
return HttpResponseRedirect('/category/' + str(b.id))
else:
return HttpResponseRedirect('/category/' + str(b.id))
else:
form = CategoryForm()
return render(request, 'add_category.html', {'form': form})
@login_required
def edit_category(request, category_id):
category = Category.objects.get(pk=category_id)
if category is None:
raise Http404
b,_ = have_I_right(request, category.blog.id)
if request.method == 'POST':
if 'cancel' in request.POST:
return HttpResponseRedirect('/category/' + str(b.id))
if 'edit' in request.POST:
name = category.name
name = name.strip()
form = CategoryForm(request.POST, instance=category)
if form.is_valid():
if request.POST['name'] != name:
category.remove()
form.save()
return HttpResponseRedirect('/category/' + str(b.id))
else:
form = CategoryForm(instance=category)
c = {'category' : category, 'form' : form}
return render(request, 'templates/edit_category.html', c)
@login_required
def delete_category(request, category_id):
category = Category.objects.get(pk=category_id)
if category is None:
raise Http404
b,_ = have_I_right(request, category.blog.id)
category.delete()
return HttpResponseRedirect('/category/' + str(b.id))
@login_required
def tag(request, blog_id):
b,_ = have_I_right(request, blog_id)
tags = Tag.objects.filter(blog_id=blog_id)
c = {'tags' : tags, 'blog' : b}
return render(request, 'templates/tag.html', c)
@login_required
def edit_tag(request, tag_id):
tag = Tag.objects.get(pk=tag_id)
if tag is None:
raise Http404
b,_ = have_I_right(request, tag.blog.id)
if request.method == 'POST':
if 'cancel' in request.POST:
return HttpResponseRedirect('/tag/' + str(b.id))
if 'edit' in request.POST:
name = tag.name
form = TagForm(request.POST, instance=tag)
if form.is_valid():
if request.POST['name'] != name:
tag.remove()
form.save()
return HttpResponseRedirect('/tag/' + str(b.id))
else:
form = TagForm(instance=tag)
c = {'tag' : tag, 'form' : form}
return render(request, 'templates/edit_tag.html', c)
@login_required
def delete_tag(request, tag_id):
tag = Tag.objects.get(pk=tag_id)
if tag is None:
raise Http404
b,_ = have_I_right(request, tag.blog.id)
tag.delete()
return HttpResponseRedirect('/tag/' + str(b.id))
@login_required
def blog(request):
if request.user.is_superuser:
b = Blog.objects.all()
else:
b = Blog.objects.filter(writers=request.user.id)
c = {'blogs' : b}
return render(request, 'templates/blog.html', c)
@login_required
def add_blog(request):
if not request.user.is_superuser:
return HttpResponseRedirect('/blog')
if request.method == 'POST':
if 'add' in request.POST:
form = BlogForm(request.POST)
if form.is_valid():
form = form.save()
form.create()
return HttpResponseRedirect('/blog')
else:
return HttpResponseRedirect('/blog')
else:
form = BlogForm()
return render(request, 'add_blog.html', {'form': form})
@login_required
def view_blog(request, blog_id):
b,_ = have_I_right(request, blog_id)
posts = Post.objects.filter(blog=b)
count = posts.count()
nb_pages = int(count/50)
if 'page' in request.GET:
cur_page = int(request.GET['page'])
else:
if 'cur_page' in request.session:
cur_page = request.session['cur_page']
else:
cur_page = 0
# Prevent error injection
if cur_page < 0 : cur_page = 0
if cur_page > nb_pages : cur_page = nb_pages-1
request.session['cur_page'] = cur_page
start = cur_page * 50
end = start + 50
posts = posts.order_by('-creation_date')[start:end]
form = BlogForm(instance=b)
comments = Comment.objects.all()
dict_comments = {}
for comment in comments:
key = comment.post.id
if not key in dict_comments:
dict_comments[key] = 1
else:
dict_comments[key] = dict_comments[key] + 1
navigation_bar = createNavigationBar(b.id, cur_page, nb_pages)
c = {'blog' : b, 'posts' : posts, 'form' : form, 'comments' : dict_comments, 'navigation_bar' : navigation_bar}
return render(request, 'templates/view_blog.html', c)
@login_required
def edit_blog(request, blog_id):
if not request.user.is_superuser:
return HttpResponseRedirect('/blog/' + str(blog_id))
b = Blog.objects.get(pk=blog_id)
if b is None:
raise Http404
edited = False
if request.method == 'POST':
if 'edit' in request.POST:
form = BlogForm(request.POST, instance=b)
if form.is_valid():
form.save()
edited = True
else:
if 'delete' in request.POST:
b = Blog.objects.get(pk=blog_id)
b.delete()
return HttpResponseRedirect('/blog')
else:
form = BlogForm(instance=b)
posts = Post.objects.filter(blog=b).order_by('-creation_date')
c = {'blog' : b, 'posts' : posts, 'form' : form, 'edited' : edited}
return render(request, 'templates/view_blog.html', c)
@login_required
def add_post(request, blog_id):
(b,_) = have_I_right(request, blog_id)
if request.method == 'POST':
if 'add' in request.POST:
post = Post(blog=Blog.objects.get(pk=blog_id), author=User.objects.get(pk=request.user.id), creation_date=datetime.now(), modification_date=datetime.now())
content = request.POST['content']
# del request.POST['content']
form = PostForm(request.POST, instance=post)
if form.is_valid():
form = form.save()
form.createPost(content, request.POST['text_tags'])
s = Search()
s.index_post(b, form.id)
request.session['cur_page'] = 0
return HttpResponseRedirect('/blog/' + blog_id)
else:
return HttpResponseRedirect('/blog/' + blog_id)
else:
form = PostForm()
return render(request, 'add_post.html', {'form': form, 'blog_id' : blog_id})
@login_required
def edit_post(request, post_id):
(b, post) = have_I_right(request, None, post_id)
title = post.title
blog_id = b.id
if request.method == 'POST':
if 'edit' in request.POST:
form = PostForm(request.POST, instance=post)
if form.is_valid():
if title != request.POST['title']:
post.remove()
form.save()
post.createPost(request.POST['content'], request.POST['text_tags'])
s = Search()
s.edit_post(b, post_id)
return HttpResponseRedirect('/blog/' + str(blog_id))
else:
if 'cancel' in request.POST:
return HttpResponseRedirect('/blog/' + str(blog_id))
else:
form = PostForm(instance=post, initial={'text_tags':', '.join((tag.name) for tag in post.tags.all())})
filename = b.src_path + '/_post/' + str(post.pk)
if os.path.exists(filename):
f = open(filename, 'rb')
content = f.read()
f.close()
else:
content = 'Empty post'
comments = Comment.objects.filter(post=post).order_by('date')
comment_list = []
for comment in comments:
comment_list.append(comment)
return render(request, 'edit_post.html', {
'form': form, 'post_id' : post_id, 'content' : content,
'blog_id' : blog_id, 'comments' : comment_list
})
@login_required
def delete_post(request, post_id):
(b, post) = have_I_right(request, None, post_id)
s = Search()
s.delete_post(b, post_id)
post.delete()
return HttpResponseRedirect('/blog/' + str(b.id))
def _generate(request, blog_id, report):
b,_ = have_I_right(request, blog_id)
posts = Post.objects.filter(blog=b).order_by('-creation_date')
nb_pages = int(posts.count()/50)
posts = posts[0:50]
b = Blog.objects.get(pk=blog_id)
form = BlogForm(instance=b)
comments = Comment.objects.all()
dict_comments = {}
for comment in comments:
key = comment.post.id
if not key in dict_comments:
dict_comments[key] = 1
else:
dict_comments[key] = dict_comments[key] + 1
navigation_bar = createNavigationBar(b.id, 0, nb_pages)
c = {'blog' : b, 'posts' : posts, 'form' : form, 'report': report, 'comments' : dict_comments, 'navigation_bar' : navigation_bar}
return render(request, 'templates/generate.html', c)
@login_required
def generate(request, blog_id):
b,_ = have_I_right(request, blog_id)
report = b.generate()
return _generate(request, blog_id, report)
@login_required
def generate_search(request, blog_id):
b,_ = have_I_right(request, blog_id)
hash_posts = {}
hash_posts_content = {}
s = Search(hash_posts, hash_posts_content)
report = s.create_index(b)
return _generate(request, blog_id, report)
@csrf_exempt
def search(request, blog_id):
from dynastie.generators import search
ref = request.META['HTTP_REFERER']
b = Blog.objects.filter(pk=blog_id)
if len(b) == 0:
return HttpResponseRedirect(ref)
b = b[0]
if 'text' in request.POST:
text = request.POST['text']
else:
return HttpResponseRedirect(ref)
s = Search()
post_list = s.search(b, text)
if post_list is None: post_list = []
hash_posts = {}
hash_posts_content = {}
s = search.Search(hash_posts, hash_posts_content)
res = s.generate(b, b.src_path, b.output_path, post_list)
c = {'result' : res}
# Simple wrapper to HTML content
return render(request, 'templates/search.html', c)
@login_required
def preview(request, blog_id):
from dynastie.generators import post
(b, p) = have_I_right(request, blog_id)
values = {'title' : request.POST['title'], \
'author' : request.user.first_name + ' ' + request.user.last_name, \
'content' : request.POST['content']
}
engine = globals()['post']
for name, obj in inspect.getmembers(engine):
if inspect.isclass(obj) and obj.__module__.startswith("dynastie.generators") \
and obj.__module__.endswith("post"):
e = obj()
content = e.preview(b.src_path, values)
break
output = b.output_path
path = output + '/preview.html'
if os.path.exists(path):
os.unlink(path)
f = open(path, 'wb')
f.write(content)
f.close()
c = {'content' : content}
return HttpResponseRedirect('http://' + b.name + '/preview.html')
# return HttpResponseRedirect('http://' + 'localhost:8080' + '/preview.html')
def _tinymcelist(request, b, year, month):
ret = 'var tinyMCEImageList = new Array('
if month < 10:
suffix = '/images/' + str(year) + '/0' + str(month)
else:
suffix = '/images/' + str(year) + '/' + str(month)
path = b.src_path + '/' + suffix
url = 'http://' + b.name + suffix + '/'
if os.path.exists(path):
files = ''
for p in os.listdir(path):
files += '["' + p + '", "' + url + p + '"],'
# Remove last comma
if len(files) != 0:
ret += files[:-1]
ret += ');'
return ret
@login_required
def tinymcelist_add(request, blog_id):
now = datetime.now()
year = now.year
month = now.month
try:
(b, p) = have_I_right(request, blog_id)
except Http404:
return HttpResponse('', content_type='application/x-javascript')
ret = _tinymcelist(request, b, year, month)
return HttpResponse(ret, content_type='application/x-javascript')
@login_required
def tinymcelist_edit(request, post_id):
try:
(b, post) = have_I_right(request, None, post_id)
except Http404:
return HttpResponse('', content_type='application/x-javascript')
year = post.creation_date.year()
month = post.creation_date.month()
ret = _tinymcelist(request, b, year, month)
return HttpResponse(ret, content_type='application/x-javascript')
@csrf_exempt
def add_comment(request, post_id, parent_id):
from dynastie.generators import post
ref = request.META['HTTP_REFERER']
# Anti robot !!
if request.POST['email'] != '':
print 'fucking robot'
return HttpResponseRedirect(ref)
post = Post.objects.get(pk=post_id)
if post is None:
return HttpResponseRedirect(ref)
blog = Blog.objects.get(pk=post.blog_id)
if blog is None:
return HttpResponseRedirect(ref)
parent_id = int(parent_id)
if parent_id != 0:
parentComment = Comment.objects.get(pk=parent_id)
else:
parentComment = None
if request.POST['author'] == '' or request.POST['the_comment'] == '':
return HttpResponseRedirect(ref)
# Behind nginx proxy
if 'HTTP_X_FORWARDED_FOR' in request.META:
ip = request.META['HTTP_X_FORWARDED_FOR']
else:
ip = request.META['REMOTE_ADDR']
# Avoid script injection
the_comment = request.POST['the_comment']
the_comment = the_comment.replace('<', '&lt;')
the_comment = the_comment.replace('>', '&gt;')
the_comment = the_comment.replace('\n', '<br />')
if 'mel' in request.POST:
mel = request.POST['mel'].strip()
else:
mel = ''
comment = Comment(post=post, parent=parentComment, date=datetime.now(), author=request.POST['author'].strip(),\
email=mel, the_comment=the_comment, ip=ip)
comment.save()
engine = globals()['post']
post_list = [post]
hash_post = {}
hash_post_content = {}
for name, obj in inspect.getmembers(engine):
if inspect.isclass(obj) and obj.__module__.startswith("dynastie.generators") \
and obj.__module__.endswith("post"):
e = obj(hash_post, hash_post_content)
content = e._generate(blog, blog.src_path, blog.output_path, post_list)
break
# Send emails
emails = {}
comments = Comment.objects.filter(post=post).order_by('date')
comment_index = str(len(comments))
for comment in comments:
email = comment.email
if email != '' and email != request.POST['mel'] and not email in emails:
emails[email] = comment.author
if post.author.email not in emails:
emails[post.author.email] = post.author.first_name
if len(emails) > 0:
connection = mail.get_connection(fail_silently=True)
connection.open()
messages = []
subject = '[%s] Nouveau commentaire pour l\'article "%s"' % (blog.name, post.title)
for email,author in emails.items():
text_body = u'Bonjour %s,\n\nUn nouveau commentaire a été posté pour l\'article "%s".\n\n' % (author, post.title)
text_body += u'Pour le consulter, rendez vous sur http://%s%s#comment_%s\n\n----------------\n\n' % (blog.name, post.getPath(), comment_index)
text_body += the_comment
text_body += '\n'
html_body = u'<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /></head><body>'
html_body += u'Bonjour %s,<br/><br/>Un nouveau commentaire a été posté pour l\'article "%s".<br/><br/>' % (author, post.title)
html_body = html_body + u'Pour le consulter, rendez vous sur <a href="http://%s%s#comment_%s">http://%s%s#comment_%s</a><br/><br/>----------------<br/><pre>' % (blog.name, post.getPath(), comment_index, blog.name, post.getPath(), comment_index)
c = comment.the_comment
html_body += the_comment + '</pre>'
html_body += '</body></html>'
msg = EmailMultiAlternatives(subject, text_body, 'no-reply@%s' % blog.name , [email])
msg.attach_alternative(html_body, "text/html")
messages.append(msg)
connection.send_messages(messages)
connection.close()
response = HttpResponseRedirect(ref)
response['Cache-Control'] = 'no-store, no-cache, must-revalidate'
response['Expires'] = 'Thu, 01 Jan 1970 00:00:00 GMT'
response.set_cookie('author', request.POST['author'], domain=blog.name, secure=True, httponly=False);
if mel != '':
response.set_cookie('email', mel, domain=blog.name, secure=True, httponly=False);
return response
@login_required
def edit_comment(request, comment_id):
comment = Comment.objects.get(pk=comment_id)
if comment is None:
return Http404
(b, post) = have_I_right(request, None, comment.post_id)
post_id = comment.post_id
if request.method == 'POST':
if 'edit' in request.POST:
form = CommentForm(request.POST, instance=comment)
if form.is_valid():
form = form.save()
return HttpResponseRedirect('/post/edit/' + str(post_id))
else:
return HttpResponseRedirect('/post/edit/' + str(post_id))
else:
comment._remove_br()
form = CommentForm(instance=comment)
return render(request, 'edit_comment.html', {'form': form, 'comment':comment})
@login_required
def delete_comment(request, comment_id):
comment = Comment.objects.get(pk=comment_id)
if comment is None:
return Http404
(b, post) = have_I_right(request, None, comment.post_id)
post_id = comment.post_id
childs = Comment.objects.filter(parent=comment.id)
try:
parent = comment.parent
except:
parent = None
for child in childs:
child.parent = parent
child.save()
comment.delete()
return HttpResponseRedirect('/post/edit/' + str(post_id))