1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-31 14:42:10 +00:00
Files
seahub/group/views.py

1222 lines
45 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
import logging
import os
import simplejson as json
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.contrib.sites.models import RequestSite
from django.http import HttpResponse, HttpResponseRedirect, Http404, \
HttpResponseBadRequest
from django.shortcuts import render_to_response, redirect
from django.template import Context, loader, RequestContext
from django.template.loader import render_to_string
from django.utils.http import urlquote
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
from django.views.generic.base import TemplateResponseMixin
from django.views.generic.edit import BaseFormView, FormMixin
from auth.decorators import login_required
from seaserv import ccnet_rpc, ccnet_threaded_rpc, seafserv_threaded_rpc, \
seafserv_rpc, \
get_repo, get_group_repos, check_group_staff, get_commits, is_group_user, \
get_personal_groups_by_user, get_group, get_group_members, \
get_personal_groups, create_org_repo, get_org_group_repos, \
get_org_groups_by_user, check_permission, is_passwd_set, \
unshare_group_repo, get_file_id_by_path
from pysearpc import SearpcError
from decorators import group_staff_required
from models import GroupMessage, MessageReply, MessageAttachment
from forms import MessageForm, MessageReplyForm, GroupRecommendForm, \
GroupAddForm, GroupJoinMsgForm
from signals import grpmsg_added, grpmsg_reply_added
from settings import GROUP_MEMBERS_DEFAULT_DISPLAY
from base.decorators import ctx_switch_required
from base.mixins import LoginRequiredMixin
from seahub.contacts.models import Contact
from seahub.contacts.signals import mail_sended
from seahub.notifications.models import UserNotification
from seahub.profile.models import Profile
from seahub.settings import SITE_ROOT, SITE_NAME
from seahub.shortcuts import get_first_object_or_none
from seahub.utils import render_error, render_permission_error, \
validate_group_name, string2list, check_and_get_org_by_group, \
check_and_get_org_by_repo, gen_file_get_url
from seahub.views import is_registered_user
from seahub.forms import RepoCreateForm, SharedRepoCreateForm
# Get an instance of a logger
logger = logging.getLogger(__name__)
def group_check(func):
"""
Decorator for initial group permission check tasks
"""
def _decorated(request, group_id, *args, **kwargs):
group_id_int = int(group_id) # Checked by URL Conf
group = get_group(group_id_int)
if not group:
return HttpResponseRedirect(reverse('group_list', args=[]))
joined = is_group_user(group_id_int, request.user.username)
if not joined and not request.user.is_staff:
# Return group public info page.
return render_to_response('group/group_pubinfo.html', {
'members': members,
'group': group,
}, context_instance=RequestContext(request))
return func(request, group, *args, **kwargs)
return _decorated
@login_required
def group_list(request):
username = request.user.username
if request.method == 'POST':
"""
Add a new group.
"""
result = {}
content_type = 'application/json; charset=utf-8'
form = GroupAddForm(request.POST)
if form.is_valid():
group_name = form.cleaned_data['group_name']
# Check whether group name is duplicated.
if request.cloud_mode:
checked_groups = get_personal_groups_by_user(username)
else:
checked_groups = get_personal_groups(-1, -1)
for g in checked_groups:
if g.group_name == group_name:
result['error'] = _(u'There is already a group with that name.')
return HttpResponse(json.dumps(result), status=400,
content_type=content_type)
# Group name is valid, create that group.
try:
ccnet_threaded_rpc.create_group(group_name.encode('utf-8'),
username)
return HttpResponse(json.dumps({'success': True}),
content_type=content_type)
except SearpcError, e:
result['error'] = _(e.msg)
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
else:
return HttpResponseBadRequest(json.dumps(form.errors),
content_type=content_type)
### GET ###
joined_groups = get_personal_groups_by_user(username)
return render_to_response('group/groups.html', {
'joined_groups': joined_groups,
}, context_instance=RequestContext(request))
@login_required
def group_remove(request, group_id):
"""
Remove group from groupadmin page. Only system admin can perform this
operation.
"""
# Check whether user is system admin.
if not request.user.is_staff:
return render_permission_error(request, _(u'Only administrators can delete the group.'))
# Request header may missing HTTP_REFERER, we need to handle that case.
next = request.META.get('HTTP_REFERER', None)
if not next:
next = SITE_ROOT
try:
group_id_int = int(group_id)
except ValueError:
return HttpResponseRedirect(next)
try:
ccnet_threaded_rpc.remove_group(group_id_int, request.user.username)
seafserv_threaded_rpc.remove_repo_group(group_id_int, None)
except SearpcError, e:
return render_error(request, _(e.msg))
return HttpResponseRedirect(next)
@login_required
def group_dismiss(request, group_id):
"""
Dismiss a group, only group staff can perform this operation.
"""
next = request.META.get('HTTP_REFERER', None)
if not next:
next = SITE_ROOT
try:
group_id_int = int(group_id)
except ValueError:
return HttpResponseRedirect(next)
# Check whether user is group staff
user = request.user.username
if not ccnet_threaded_rpc.check_group_staff(group_id_int, user):
return render_permission_error(request, _(u'Only administrators can dismiss the group'))
try:
ccnet_threaded_rpc.remove_group(group_id_int, user)
seafserv_threaded_rpc.remove_repo_group(group_id_int, None)
if request.user.org:
org_id = request.user.org['org_id']
url_prefix = request.user.org['url_prefix']
ccnet_threaded_rpc.remove_org_group(org_id, group_id_int)
return HttpResponseRedirect(reverse('org_groups',
args=[url_prefix]))
except SearpcError, e:
return render_error(request, _(e.msg))
return HttpResponseRedirect(reverse('group_list'))
@login_required
def group_quit(request, group_id):
try:
group_id_int = int(group_id)
except ValueError:
return render_error(request, _(u'group id is not a valid argument.'))
try:
ccnet_threaded_rpc.quit_group(group_id_int, request.user.username)
seafserv_threaded_rpc.remove_repo_group(group_id_int,
request.user.username)
except SearpcError, e:
return render_error(request, _(e.msg))
return HttpResponseRedirect(reverse('group_list', args=[]))
def render_group_info(request, group_id, form):
group_id_int = int(group_id) # Checkeb by URL Conf
# remove user notifications
UserNotification.objects.filter(to_user=request.user.username,
msg_type='group_msg',
detail=str(group_id)).delete()
group = get_group(group_id_int)
if not group:
return HttpResponseRedirect(reverse('group_list', args=[]))
# Get all group members.
members = get_group_members(group_id_int)
# Check whether user belongs to the group.
joined = is_group_user(group_id_int, request.user.username)
if not joined and not request.user.is_staff:
# Return group public info page.
return render_to_response('group/group_pubinfo.html', {
'members': members,
'group': group,
}, context_instance=RequestContext(request))
is_staff = True if check_group_staff(group.id, request.user) else False
org = request.user.org
if org:
repos = get_org_group_repos(org['org_id'], group_id_int,
request.user.username)
else:
repos = get_group_repos(group_id_int, request.user.username)
recent_commits = []
cmt_repo_dict = {}
for repo in repos:
repo.user_perm = check_permission(repo.props.id, request.user.username)
cmmts = get_commits(repo.props.id, 0, 10)
for c in cmmts:
cmt_repo_dict[c.id] = repo
recent_commits += cmmts
recent_commits.sort(lambda x, y : cmp(y.props.ctime, x.props.ctime))
recent_commits = recent_commits[:15]
for cmt in recent_commits:
cmt.repo = cmt_repo_dict[cmt.id]
cmt.repo.password_set = is_passwd_set(cmt.props.repo_id,
request.user.username)
cmt.tp = cmt.props.desc.split(' ')[0]
return render_to_response("group/group_info.html", {
"members": members,
"repos": repos,
"recent_commits": recent_commits,
"group_id": group_id,
"group" : group,
"is_staff": is_staff,
"is_join": joined,
"form": form,
'create_shared_repo': True,
'group_members_default_display': GROUP_MEMBERS_DEFAULT_DISPLAY,
}, context_instance=RequestContext(request));
@login_required
def group_message_remove(request, group_id, msg_id):
"""
Remove group message and all message replies and attachments.
"""
# Checked by URL Conf
group_id = int(group_id)
msg_id = int(msg_id)
# Test whether user is in the group
if not is_group_user(group_id, request.user.username):
raise Http404
try:
gm = GroupMessage.objects.get(id=msg_id)
except GroupMessage.DoesNotExist:
return HttpResponse(json.dumps({'success': False, 'err_msg':_(u"The message doesn't exist")}),
content_type='application/json; charset=utf-8')
else:
# Test whether user is group admin or message owner.
if check_group_staff(group_id, request.user) or \
gm.from_email == request.user.username:
gm.delete()
return HttpResponse(json.dumps({'success': True}),
content_type='application/json; charset=utf-8')
else:
return HttpResponse(json.dumps({'success': False, 'err_msg': _(u"You don't have the permission.")}),
content_type='application/json; charset=utf-8')
@login_required
def msg_reply(request, msg_id):
"""Show group message replies, and process message reply in ajax"""
content_type = 'application/json; charset=utf-8'
if request.is_ajax():
ctx = {}
try:
group_msg = GroupMessage.objects.get(id=msg_id)
except GroupMessage.DoesNotExist:
return HttpResponseBadRequest(content_type=content_type)
if request.method == 'POST':
form = MessageReplyForm(request.POST)
# TODO: invalid form
if form.is_valid():
msg = form.cleaned_data['message']
msg_reply = MessageReply()
msg_reply.reply_to = group_msg
msg_reply.from_email = request.user.username
msg_reply.message = msg
msg_reply.save()
# send signal if reply other's message
if group_msg.from_email != request.user.username:
grpmsg_reply_added.send(sender=MessageReply,
msg_id=msg_id,
from_email=request.user.username)
replies = MessageReply.objects.filter(reply_to=group_msg)
r_num = len(replies)
if r_num < 4:
ctx['replies'] = replies
else:
ctx['replies'] = replies[r_num - 3:]
html = render_to_string("group/group_reply_list.html", ctx)
serialized_data = json.dumps({"r_num": r_num, "html": html})
return HttpResponse(serialized_data, content_type=content_type)
else:
replies = MessageReply.objects.filter(reply_to=group_msg)
r_num = len(replies)
ctx['replies'] = replies
html = render_to_string("group/group_reply_list.html", ctx)
serialized_data = json.dumps({"r_num": r_num, "html": html})
return HttpResponse(serialized_data, content_type=content_type)
else:
return HttpResponseBadRequest(content_type=content_type)
@login_required
def msg_reply_new(request):
notes = UserNotification.objects.filter(to_user=request.user.username)
grpmsg_reply_list = [ n.detail for n in notes if \
n.msg_type == 'grpmsg_reply']
group_msgs = []
for msg_id in grpmsg_reply_list:
try:
m = GroupMessage.objects.get(id=msg_id)
except GroupMessage.DoesNotExist:
continue
else:
# get group name
group = get_group(m.group_id)
if not group:
continue
m.group_name = group.group_name
# get attachement
attachment = get_first_object_or_none(m.messageattachment_set.all())
if attachment:
path = attachment.path
if path == '/':
repo = get_repo(attachment.repo_id)
if not repo:
continue
attachment.name = repo.name
else:
attachment.name = os.path.basename(path)
m.attachment = attachment
# get message replies
reply_list = MessageReply.objects.filter(reply_to=m)
m.reply_cnt = reply_list.count()
if m.reply_cnt > 3:
m.replies = reply_list[m.reply_cnt - 3:]
else:
m.replies = reply_list
group_msgs.append(m)
# remove new group msg reply notification
UserNotification.objects.filter(to_user=request.user.username,
msg_type='grpmsg_reply').delete()
return render_to_response("group/new_msg_reply.html", {
'group_msgs': group_msgs,
}, context_instance=RequestContext(request))
@login_required
@ctx_switch_required
def group_info(request, group_id):
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
msg = form.cleaned_data['message']
message = GroupMessage()
message.group_id = group_id
message.from_email = request.user.username
message.message = msg
message.save()
# send signal
grpmsg_added.send(sender=GroupMessage, group_id=group_id,
from_email=request.user.username)
# Always return an HttpResponseRedirect after successfully dealing
# with POST data.
return HttpResponseRedirect(reverse('group_info', args=[group_id]))
else:
form = MessageForm()
op = request.GET.get('op', '')
if op == 'delete':
return group_remove(request, group_id)
elif op == 'dismiss':
return group_dismiss(request, group_id)
elif op == 'quit':
return group_quit(request, group_id)
return render_group_info(request, group_id, form)
@login_required
@ctx_switch_required
@group_staff_required
@group_check
def group_manage(request, group):
user = request.user.username
if request.method == 'POST':
"""
Add group members.
"""
result = {}
content_type = 'application/json; charset=utf-8'
member_name_str = request.POST.get('user_name', '')
member_list = string2list(member_name_str)
# Add users to contacts.
for email in member_list:
mail_sended.send(sender=None, user=user, email=email)
mail_sended_list = []
if request.cloud_mode:
if request.user.org:
# Can only invite org users to group.
org_id = request.user.org['org_id']
for email in member_list:
if not ccnet_threaded_rpc.org_user_exists(org_id, email):
err_msg = _(u'Failed to add, %s is not in current organization.') % email
result['error'] = err_msg
return HttpResponse(json.dumps(result), status=400,
content_type=content_type)
else:
try:
ccnet_threaded_rpc.group_add_member(group.id,
user, email)
except SearpcError, e:
result['error'] = _(e.msg)
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
else:
# Can invite unregistered user to group.
for email in member_list:
if not is_registered_user(email):
use_https = request.is_secure()
domain = RequestSite(request).domain
t = loader.get_template('group/add_member_email.html')
c = {
'email': user,
'to_email': email,
'group': group,
'domain': domain,
'protocol': use_https and 'https' or 'http',
'site_name': SITE_NAME,
}
try:
send_mail(_(u'Your friend added you to a group at Seafile.'),
t.render(Context(c)), None, [email],
fail_silently=False)
mail_sended_list.append(email)
except:
data = json.dumps({'error': _(u'Failed to send mail.')})
return HttpResponse(data, status=500,
content_type=content_type)
# Add user to group, unregistered user will see the group
# when he logs in.
try:
ccnet_threaded_rpc.group_add_member(group.id,
user, email)
except SearpcError, e:
result['error'] = _(e.msg)
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
else:
# Can only invite registered user to group if not in cloud mode.
for email in member_list:
if not is_registered_user(email):
err_msg = _(u'Failed to add, %s is not registerd.')
result['error'] = err_msg % email
return HttpResponse(json.dumps(result), status=400,
content_type=content_type)
# Add user to group.
try:
ccnet_threaded_rpc.group_add_member(group.id,
user, email)
except SearpcError, e:
result['error'] = _(e.msg)
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
if mail_sended_list:
msg = ungettext(
'Successfully added. An email has been sent.',
'Successfully added. %(count)s emails have been sent.',
len(mail_sended_list)) % {
'count': len(mail_sended_list),
}
messages.success(request, msg)
else:
messages.success(request, _(u'Successfully added.'))
return HttpResponse(json.dumps('success'), status=200,
content_type=content_type)
### GET ###
members_all = ccnet_threaded_rpc.get_group_members(group.id)
admins = [ m for m in members_all if m.is_staff ]
contacts = Contact.objects.filter(user_email=user)
return render_to_response('group/group_manage.html', {
'group' : group,
'members': members_all,
'admins': admins,
'contacts': contacts,
}, context_instance=RequestContext(request))
@login_required
@group_staff_required
def group_add_admin(request, group_id):
"""
Add group admin.
"""
group_id = int(group_id) # Checked by URL Conf
if request.method != 'POST' or not request.is_ajax():
raise Http404
result = {}
content_type = 'application/json; charset=utf-8'
member_name_str = request.POST.get('user_name', '')
member_list = string2list(member_name_str)
for member_name in member_list:
# Add user to contacts.
mail_sended.send(sender=None, user=request.user.username,
email=member_name)
if not is_registered_user(member_name):
err_msg = _(u'Failed to add, %s is not registrated.') % member_name
result['error'] = err_msg
return HttpResponse(json.dumps(result), status=400,
content_type=content_type)
# Check whether user is in the group
if is_group_user(group_id, member_name):
try:
ccnet_threaded_rpc.group_set_admin(group_id, member_name)
except SearpcError, e:
result['error'] = _(e.msg)
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
else:
try:
ccnet_threaded_rpc.group_add_member(group_id,
request.user.username,
member_name)
ccnet_threaded_rpc.group_set_admin(group_id, member_name)
except SearpcError, e:
result['error'] = _(e.msg)
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
messages.success(request, _(u'Operation succeeded.'))
return HttpResponse(json.dumps('success'), status=200,
content_type=content_type)
@login_required
@group_staff_required
def group_remove_admin(request, group_id):
"""
Remove group admin, and becomes normal group member.
"""
user = request.GET.get('u', '')
try:
ccnet_threaded_rpc.group_unset_admin(int(group_id), user)
messages.success(request, _(u'Operation succeeded.'))
except SearpcError, e:
messages.error(request, _(e.msg))
return HttpResponseRedirect(reverse('group_members', args=[group_id]))
@login_required
def group_member_operations(request, group_id, user_name):
if request.GET.get('op','') == 'delete':
return group_remove_member(request, group_id, user_name)
else:
return HttpResponseRedirect(reverse('group_members', args=[group_id]))
@login_required
def group_remove_member(request, group_id, user_name):
try:
group_id_int = int(group_id)
except ValueError:
return render_error(request, _(u'group id is not valid'))
if not check_group_staff(group_id_int, request.user):
raise Http404
try:
ccnet_threaded_rpc.group_remove_member(group_id_int,
request.user.username,
user_name)
seafserv_threaded_rpc.remove_repo_group(group_id_int, user_name)
messages.success(request, _(u'Operation succeeded.'))
except SearpcError, e:
messages.error(request, _(u'Failed%s') % _(e.msg))
return HttpResponseRedirect(reverse('group_members', args=[group_id]))
def group_share_repo(request, repo_id, group_id, from_email, permission):
"""
Share a repo to a group.
"""
# Check whether group exists
group = get_group(group_id)
if not group:
return render_error(request, _(u"Failed to share: the group doesn't exist."))
if seafserv_threaded_rpc.group_share_repo(repo_id, group_id, from_email, permission) != 0:
return render_error(request, _(u"Failed to share: internal error."))
def group_unshare_repo(request, repo_id, group_id, from_email):
"""
Unshare a repo in group.
"""
# Check whether group exists
group = get_group(group_id)
if not group:
return render_error(request, _(u"Failed to unshare: the group doesn't exist."))
# Check whether user is group staff or the one share the repo
if not check_group_staff(group_id, from_email) and \
seafserv_threaded_rpc.get_group_repo_owner(repo_id) != from_email:
return render_permission_error(request, _(u"Operation failed: only administrators and the owner of the library can unshare it."))
if unshare_group_repo(repo_id, group_id, from_email) != 0:
return render_error(request, _(u"Failed to unshare: internal error."))
@login_required
def group_recommend(request):
"""
Recommend a file or directory to a group.
now changed to 'post a discussion'
"""
if request.method != 'POST':
raise Http404
next = request.META.get('HTTP_REFERER', None)
if not next:
next = SITE_ROOT
form = GroupRecommendForm(request.POST)
if form.is_valid():
repo_id = form.cleaned_data['repo_id']
attach_type = form.cleaned_data['attach_type']
path = form.cleaned_data['path']
message = form.cleaned_data['message']
groups = request.POST.getlist('groups') # groups is a group_id list, e.g. [u'1', u'7']
username = request.user.username
# Check group id format
for group_id in groups:
try:
group_id = int(group_id)
except ValueError:
messages.error(request, _(u'Error: wrong group id'))
return HttpResponseRedirect(next)
# Get that group
group = get_group(group_id)
# TODO: Check whether repo is in the group and Im in the group
if not is_group_user(group_id, username):
err_msg = _(u'Error: you are not in group %s.')
messages.error(request, err_msg % group.group_name)
continue
# save message to group
gm = GroupMessage(group_id=group_id, from_email=username,
message=message)
gm.save()
# send signal
grpmsg_added.send(sender=GroupMessage, group_id=group_id,
from_email=request.user.username)
# save attachment
ma = MessageAttachment(group_message=gm, repo_id=repo_id,
attach_type=attach_type, path=path,
src='recommend')
ma.save()
group_url = reverse('group_discuss', args=[group_id])
msg = _(u'Successfully posted to <a href="%(url)s" target="_blank">%(name)s</a>.') %\
{'url':group_url, 'name':group.group_name}
messages.add_message(request, messages.INFO, msg)
else:
messages.add_message(request, messages.ERROR, _(u'Failed to recommend.'))
return HttpResponseRedirect(next)
@login_required
def create_group_repo(request, group_id):
"""Create a repo and share it to current group"""
content_type = 'application/json; charset=utf-8'
def json_error(err_msg):
result = {'error': [err_msg]}
return HttpResponseBadRequest(json.dumps(result),
content_type=content_type)
group_id = int(group_id)
if not get_group(group_id):
return json_error(_(u'Failed to create: the group does not exist.'))
# Check whether user belongs to the group.
if not is_group_user(group_id, request.user.username):
return json_error(_(u'Failed to create: you are not in the group.'))
form = SharedRepoCreateForm(request.POST)
if not form.is_valid():
return json_error(form.errors)
else:
repo_name = form.cleaned_data['repo_name']
repo_desc = form.cleaned_data['repo_desc']
permission = form.cleaned_data['permission']
encrypted = form.cleaned_data['encryption']
passwd = form.cleaned_data['passwd']
user = request.user.username
org, base_template = check_and_get_org_by_group(group_id, user)
if org:
# create group repo in org context
try:
repo_id = create_org_repo(repo_name, repo_desc, user, passwd,
org.org_id)
except:
repo_id = None
if not repo_id:
return json_error(_(u'Failed to create'))
try:
status = seafserv_threaded_rpc.add_org_group_repo(repo_id,
org.org_id,
group_id,
user,
permission)
except SearpcError, e:
status = -1
# if share failed, remove the newly created repo
if status != 0:
seafserv_threaded_rpc.remove_repo(repo_id)
return json_error(_(u'Failed to create: internal error.'))
else:
result = {'success': True}
return HttpResponse(json.dumps(result),
content_type=content_type)
else:
# create group repo in user context
try:
repo_id = seafserv_threaded_rpc.create_repo(repo_name,
repo_desc,
user, passwd)
except:
repo_id = None
if not repo_id:
return json_error(_(u'Failed to create'))
try:
status = seafserv_threaded_rpc.group_share_repo(repo_id,
group_id,
user,
permission)
except SearpcError, e:
status = -1
# if share failed, remove the newly created repo
if status != 0:
seafserv_threaded_rpc.remove_repo(repo_id)
return json_error(_(u'Failed to create: internal error.'))
else:
result = {'success': True}
return HttpResponse(json.dumps(result),
content_type=content_type)
@login_required
def group_joinrequest(request, group_id):
"""
Handle post request to join a group.
"""
if not request.is_ajax() or request.method != 'POST':
raise Http404
result = {}
content_type = 'application/json; charset=utf-8'
group_id = int(group_id)
group =get_group(group_id)
if not group:
raise Http404
user = request.user.username
# TODO: Group creator is group staff now, but may changed in future.
staff = group.creator_name
if is_group_user(group_id, user):
# Already in the group. Normally, this case should not happen.
err = _(u'You are already in the group.')
return HttpResponseBadRequest(json.dumps({'error': err}),
content_type=content_type)
else:
form = GroupJoinMsgForm(request.POST)
if form.is_valid():
group_join_msg = form.cleaned_data['group_join_msg']
# Send the message to group staff.
use_https = request.is_secure()
domain = RequestSite(request).domain
t = loader.get_template('group/group_join_email.html')
c = {
'staff': staff,
'user': user,
'group_name': group.group_name,
'group_join_msg': group_join_msg,
'site_name': SITE_NAME,
}
try:
send_mail(_(u'apply to join the group'), t.render(Context(c)), None, [staff],
fail_silently=False)
messages.success(request, _(u'Sent successfully, the group admin will handle it.'))
return HttpResponse(json.dumps('success'),
content_type=content_type)
except:
err = _(u'Failed to send. You can try it again later.')
return HttpResponse(json.dumps({'error': err}), status=500,
content_type=content_type)
else:
return HttpResponseBadRequest(json.dumps(form.errors),
content_type=content_type)
def attention(request):
"""
Handle ajax request to query group members used in autocomplete.
"""
if not request.is_ajax():
raise Http404
user = request.user.username
name_str = request.GET.get('name_startsWith')
gids = request.GET.get('gids', '')
result = []
members = []
for gid in gids.split('_'):
try:
gid = int(gid)
except ValueError:
continue
if not is_group_user(gid, user):
continue
# Get all group users
members += get_group_members(gid)
member_names = []
for m in members:
if len(result) == 10: # Return at most 10 results.
break
if m.user_name == user:
continue
if m.user_name in member_names:
# Remove duplicated member names
continue
else:
member_names.append(m.user_name)
from base.templatetags.seahub_tags import email2nickname, char2pinyin
nickname = email2nickname(m.user_name)
pinyin = char2pinyin(nickname)
if nickname.startswith(name_str) or pinyin.startswith(name_str):
result.append({'contact_name': nickname})
content_type = 'application/json; charset=utf-8'
return HttpResponse(json.dumps(result), content_type=content_type)
@login_required
def group_discuss(request, group_id):
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
msg = form.cleaned_data['message']
message = GroupMessage()
message.group_id = group_id
message.from_email = request.user.username
message.message = msg
message.save()
# send signal
grpmsg_added.send(sender=GroupMessage, group_id=group_id,
from_email=request.user.username)
# Always return an HttpResponseRedirect after successfully dealing
# with POST data.
return HttpResponseRedirect(reverse('group_discuss', args=[group_id]))
else:
form = MessageForm()
op = request.GET.get('op', '')
if op == 'delete':
return group_remove(request, group_id)
elif op == 'dismiss':
return group_dismiss(request, group_id)
elif op == 'quit':
return group_quit(request, group_id)
group_id_int = int(group_id) # Checkeb by URL Conf
# remove user notifications
UserNotification.objects.filter(to_user=request.user.username,
msg_type='group_msg',
detail=str(group_id)).delete()
group = get_group(group_id_int)
if not group:
return HttpResponseRedirect(reverse('group_list', args=[]))
# Check whether user belongs to the group.
joined = is_group_user(group_id_int, request.user.username)
if not joined and not request.user.is_staff:
# Return group public info page.
return render_to_response('group/group_pubinfo.html', {
'members': members,
'group': group,
}, context_instance=RequestContext(request))
# Get all group members.
members = get_group_members(group_id_int)
is_staff = True if check_group_staff(group.id, request.user) else False
managers = []
common_members = []
for member in members:
if member.is_staff == 1:
managers.append(member)
else:
common_members.append(member)
"""group messages"""
# Make sure page request is an int. If not, deliver first page.
try:
current_page = int(request.GET.get('page', '1'))
except ValueError:
current_page = 1
per_page = 45
group_msgs = GroupMessage.objects.filter(
group_id=group_id).order_by(
'-timestamp')[per_page*(current_page-1) : per_page*current_page]
group_msgs = list(group_msgs) # Force evaluate queryset to fix some database error for mysql
attachments = MessageAttachment.objects.filter(group_message__in=group_msgs)
msg_replies = MessageReply.objects.filter(reply_to__in=group_msgs)
reply_to_list = [ r.reply_to_id for r in msg_replies ]
for msg in group_msgs:
msg.reply_cnt = reply_to_list.count(msg.id)
msg.replies = []
for r in msg_replies:
if msg.id == r.reply_to_id:
msg.replies.append(r)
msg.replies = msg.replies[-3:]
for att in attachments:
if msg.id == att.group_message_id:
# Attachment name is file name or directory name.
# If is top directory, use repo name instead.
path = att.path
if path == '/':
repo = get_repo(att.repo_id)
if not repo:
# TODO: what should we do here, tell user the repo
# is no longer exists?
continue
att.name = repo.name
else:
# cut out last '/'
if path[-1] == '/':
path = path[:-1]
att.name = os.path.basename(path)
msg.attachment = att
per_show = 15
if current_page == 1 and len(group_msgs) > per_show:
msgs_more = True
else:
msgs_more = False
msg_total_num = GroupMessage.objects.filter(group_id=group_id).count()
total_page = msg_total_num/per_page
if msg_total_num % per_page > 0:
total_page += 1
page_next = True if current_page < total_page else False
# get page numbers shown in the web page
first_page = 1
if total_page <= 10:
last_page = total_page
else:
if current_page < 6:
last_page = 10
else:
first_page = current_page - 5
last_page = current_page + 4 if current_page + 4 < total_page else total_page
pages_show = range(first_page, last_page + 1)
return render_to_response("group/group_discuss.html", {
"managers": managers,
"common_members": common_members,
"members": members,
"group_id": group_id,
"group" : group,
"is_staff": is_staff,
"group_msgs": group_msgs,
"form": form,
'per_show': per_show,
'msgs_more': msgs_more,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'page_next': page_next,
'pages_show': pages_show,
'group_members_default_display': GROUP_MEMBERS_DEFAULT_DISPLAY,
}, context_instance=RequestContext(request));
class WikiDoesNotExist(Exception):
pass
class WikiPageMissing(Exception):
pass
def find_wiki_repo(request, group_id):
repos = get_group_repos(group_id, request.user.username)
for repo in repos:
if repo.name == "wiki":
return repo
return None
def get_file_url(repo_id, path, filename):
obj_id = get_file_id_by_path(repo_id, path)
if not obj_id:
raise WikiPageMissing
access_token = seafserv_rpc.web_get_access_token(repo_id, obj_id,
'view', '')
url = gen_file_get_url(access_token, filename)
return url
def get_wiki_page(request, group_id, page_name):
import urllib2
repo = find_wiki_repo(request, group_id)
if not repo:
raise WikiDoesNotExist
path = "/" + page_name + ".md"
filename = page_name + ".md"
url = get_file_url(repo.id, path, filename)
file_response = urllib2.urlopen(url)
content = file_response.read()
return content, repo.id
def convert_wiki_link(content, group, repo_id):
import re
def repl(matchobj):
linkname = matchobj.group(1)
filename = linkname + ".md"
path = "/" + filename
if get_file_id_by_path(repo_id, path):
a_tag = "<a href='%sgroup/%d/wiki/%s/'>%s</a>"
return a_tag % (SITE_ROOT, group.id, linkname, linkname)
else:
a_tag = '''<a class="wiki-page-missing" href='%sgroup/%d/wiki/%s/'>%s</a>'''
return a_tag % (SITE_ROOT, group.id, linkname, linkname)
return re.sub(r'\[\[(.+)\]\]', repl, content)
@login_required
@group_check
def group_wiki(request, group, page_name="home"):
is_staff = True if check_group_staff(group.id, request.user) else False
content = ''
wiki_exists, wiki_page_missing = True, False
try:
content, repo_id = get_wiki_page(request, group.id, page_name)
except WikiDoesNotExist:
wiki_exists = False
except WikiPageMissing:
wiki_page_missing = True
else:
content = convert_wiki_link(content, group, repo_id)
return render_to_response("group/group_wiki.html", {
"group_id": group.id,
"group" : group,
"is_staff": is_staff,
"content": content,
"page": page_name,
"wiki_exists": wiki_exists,
"wiki_page_missing": wiki_page_missing,
}, context_instance=RequestContext(request))
@login_required
@group_check
def group_wiki_create(request, group):
# create group repo in user context
repo_name = "wiki"
repo_desc = "Wiki Pages"
user = request.user.username
passwd = None
permission = "rw"
content_type = 'application/json; charset=utf-8'
def json_error(err_msg):
result = {'error': [err_msg]}
return HttpResponseBadRequest(json.dumps(result),
content_type=content_type)
try:
repo_id = seafserv_threaded_rpc.create_repo(repo_name,
repo_desc,
user, passwd)
except:
return json_error(_(u'Failed to create'))
try:
status = seafserv_threaded_rpc.group_share_repo(repo_id,
int(group_id),
user,
permission)
except SearpcError, e:
seafserv_threaded_rpc.remove_repo(repo_id)
print e
return json_error(_(u'Failed to create: internal error.'))
# create home page
page_name = "home.md"
seafserv_threaded_rpc.post_empty_file(repo_id, "/", page_name, user)
return HttpResponseRedirect(reverse('group_info', args=[group_id]))
@login_required
@group_check
def group_wiki_page_new(request, group, page_name="home"):
if request.method == 'POST':
form = MessageForm(request.POST)
page_name = request.POST.get('page_name', '')
if not page_name:
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
repo = find_wiki_repo(request, group.id)
if not repo:
# todo
return None
filename = page_name + ".md"
filepath = "/" + page_name + ".md"
seafserv_threaded_rpc.post_empty_file(
repo.id, "/", filename, request.user.username)
url = "%srepo/%s/file/edit/?p=%s" % (SITE_ROOT, repo.id, filepath)
return HttpResponseRedirect(url)
@login_required
@group_check
def group_wiki_page_edit(request, group, page_name="home"):
repo = find_wiki_repo(request, group.id)
if not repo:
# todo
return None
filepath = "/" + page_name + ".md"
url = "%srepo/%s/file/edit/?p=%s" % (SITE_ROOT, repo.id, filepath)
return HttpResponseRedirect(url)