1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 07:01:12 +00:00
Files
seahub/group/views.py

1193 lines
44 KiB
Python
Raw Normal View History

2013-01-26 14:25:15 +08:00
# -*- coding: utf-8 -*-
import logging
2012-08-13 21:26:58 +08:00
import os
import simplejson as json
2012-09-19 19:52:35 +08:00
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
2012-08-10 21:16:55 +08:00
from django.contrib import messages
2012-09-19 19:52:35 +08:00
from django.contrib.sites.models import RequestSite
2012-08-08 20:16:00 +08:00
from django.http import HttpResponse, HttpResponseRedirect, Http404, \
HttpResponseBadRequest
2012-05-15 10:59:16 +08:00
from django.shortcuts import render_to_response, redirect
2012-09-19 19:52:35 +08:00
from django.template import Context, loader, RequestContext
from django.template.loader import render_to_string
2012-09-03 19:36:47 +08:00
from django.utils.http import urlquote
2012-09-07 16:14:36 +08:00
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
2012-09-18 14:04:47 +08:00
from django.views.generic.base import TemplateResponseMixin
from django.views.generic.edit import BaseFormView, FormMixin
2012-02-11 11:12:54 +08:00
from auth.decorators import login_required
2013-01-26 14:25:15 +08:00
from seaserv import ccnet_rpc, ccnet_threaded_rpc, seafserv_threaded_rpc, \
2013-03-05 11:56:51 +08:00
seafserv_rpc, \
2012-09-11 10:11:44 +08:00
get_repo, get_group_repos, check_group_staff, get_commits, is_group_user, \
2012-09-22 17:46:56 +08:00
get_personal_groups_by_user, get_group, get_group_members, \
get_personal_groups, create_org_repo, get_org_group_repos, \
2013-03-08 19:34:53 +08:00
get_org_groups_by_user, check_permission, is_passwd_set, \
unshare_group_repo, get_file_id_by_path
2012-05-15 10:59:16 +08:00
from pysearpc import SearpcError
2012-10-22 11:54:06 +08:00
from decorators import group_staff_required
2013-01-26 14:25:15 +08:00
from models import GroupMessage, MessageReply, MessageAttachment
2012-09-18 14:04:47 +08:00
from forms import MessageForm, MessageReplyForm, GroupRecommendForm, \
2012-09-26 17:05:32 +08:00
GroupAddForm, GroupJoinMsgForm
2012-06-27 16:39:49 +08:00
from signals import grpmsg_added, grpmsg_reply_added
2013-01-04 20:11:57 +08:00
from settings import GROUP_MEMBERS_DEFAULT_DISPLAY
2012-08-31 17:28:50 +08:00
from base.decorators import ctx_switch_required
2012-09-18 14:04:47 +08:00
from base.mixins import LoginRequiredMixin
from seahub.contacts.models import Contact
from seahub.contacts.signals import mail_sended
2012-06-25 21:40:18 +08:00
from seahub.notifications.models import UserNotification
from seahub.profile.models import Profile
2012-11-06 19:42:56 +08:00
from seahub.settings import SITE_ROOT, SITE_NAME
2012-08-10 21:16:55 +08:00
from seahub.shortcuts import get_first_object_or_none
from seahub.utils import render_error, render_permission_error, \
2012-09-14 11:39:33 +08:00
validate_group_name, string2list, check_and_get_org_by_group, \
2013-03-05 11:56:51 +08:00
check_and_get_org_by_repo, gen_file_get_url
from seahub.views import is_registered_user
from seahub.forms import RepoCreateForm, SharedRepoCreateForm
2013-01-26 14:25:15 +08:00
# Get an instance of a logger
logger = logging.getLogger(__name__)
2013-03-09 15:27:17 +08:00
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
2012-09-17 21:38:54 +08:00
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)
2012-09-18 14:04:47 +08:00
else:
return HttpResponseBadRequest(json.dumps(form.errors),
content_type=content_type)
2012-09-17 21:38:54 +08:00
### GET ###
joined_groups = get_personal_groups_by_user(username)
2012-09-17 21:38:54 +08:00
return render_to_response('group/groups.html', {
'joined_groups': joined_groups,
}, context_instance=RequestContext(request))
2012-05-22 21:42:29 +08:00
@login_required
def group_remove(request, group_id):
2012-08-03 11:32:11 +08:00
"""
2012-08-04 11:00:04 +08:00
Remove group from groupadmin page. Only system admin can perform this
operation.
2012-08-03 11:32:11 +08:00
"""
2012-08-04 11:00:04 +08:00
# Check whether user is system admin.
if not request.user.is_staff:
return render_permission_error(request, _(u'Only administrators can delete the group.'))
2012-08-04 11:00:04 +08:00
2012-08-03 11:32:11 +08:00
# 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
2012-05-15 10:59:16 +08:00
try:
group_id_int = int(group_id)
except ValueError:
2012-08-03 11:32:11 +08:00
return HttpResponseRedirect(next)
2012-05-15 10:59:16 +08:00
try:
2012-06-25 20:42:19 +08:00
ccnet_threaded_rpc.remove_group(group_id_int, request.user.username)
2012-05-15 10:59:16 +08:00
seafserv_threaded_rpc.remove_repo_group(group_id_int, None)
2012-08-03 11:32:11 +08:00
except SearpcError, e:
2013-01-10 13:35:49 +08:00
return render_error(request, _(e.msg))
2012-08-03 11:32:11 +08:00
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'))
2012-08-03 11:32:11 +08:00
try:
ccnet_threaded_rpc.remove_group(group_id_int, user)
seafserv_threaded_rpc.remove_repo_group(group_id_int, None)
2012-06-20 19:39:21 +08:00
if request.user.org:
2012-07-26 17:08:31 +08:00
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]))
2012-08-03 11:32:11 +08:00
2012-05-15 10:59:16 +08:00
except SearpcError, e:
2013-01-10 13:35:49 +08:00
return render_error(request, _(e.msg))
2012-08-03 11:32:11 +08:00
return HttpResponseRedirect(reverse('group_list'))
2012-05-15 10:59:16 +08:00
2012-05-22 21:42:29 +08:00
@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.'))
2012-05-22 21:42:29 +08:00
try:
2012-06-25 20:42:19 +08:00
ccnet_threaded_rpc.quit_group(group_id_int, request.user.username)
2012-05-26 20:52:53 +08:00
seafserv_threaded_rpc.remove_repo_group(group_id_int,
request.user.username)
2012-05-22 21:42:29 +08:00
except SearpcError, e:
2013-01-10 13:35:49 +08:00
return render_error(request, _(e.msg))
2012-05-22 21:42:29 +08:00
return HttpResponseRedirect(reverse('group_list', args=[]))
2012-06-25 14:57:14 +08:00
def render_group_info(request, group_id, form):
2012-10-27 11:32:53 +08:00
group_id_int = int(group_id) # Checkeb by URL Conf
2012-09-06 16:57:54 +08:00
# remove user notifications
UserNotification.objects.filter(to_user=request.user.username,
msg_type='group_msg',
detail=str(group_id)).delete()
2012-10-27 11:32:53 +08:00
group = get_group(group_id_int)
2012-05-15 10:59:16 +08:00
if not group:
return HttpResponseRedirect(reverse('group_list', args=[]))
2012-05-15 14:43:52 +08:00
2012-09-26 17:05:32 +08:00
# 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))
2012-09-11 10:11:44 +08:00
is_staff = True if check_group_staff(group.id, request.user) else False
2012-05-15 10:59:16 +08:00
2012-08-31 17:28:50 +08:00
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)
2013-01-26 14:25:15 +08:00
recent_commits = []
2013-01-26 14:25:15 +08:00
cmt_repo_dict = {}
for repo in repos:
repo.user_perm = check_permission(repo.props.id, request.user.username)
2013-01-26 14:25:15 +08:00
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))
2013-01-26 14:25:15 +08:00
recent_commits = recent_commits[:15]
for cmt in recent_commits:
2013-01-26 14:25:15 +08:00
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]
2013-01-26 14:25:15 +08:00
2012-10-18 19:54:00 +08:00
2012-05-15 10:59:16 +08:00
return render_to_response("group/group_info.html", {
2012-08-19 13:36:32 +08:00
"members": members,
2012-05-15 10:59:16 +08:00
"repos": repos,
"recent_commits": recent_commits,
2012-05-15 10:59:16 +08:00
"group_id": group_id,
2012-05-17 23:50:04 +08:00
"group" : group,
2012-05-15 14:43:52 +08:00
"is_staff": is_staff,
2012-05-26 20:52:53 +08:00
"is_join": joined,
2012-06-25 14:57:14 +08:00
"form": form,
'create_shared_repo': True,
2013-01-04 20:11:57 +08:00
'group_members_default_display': GROUP_MEMBERS_DEFAULT_DISPLAY,
2012-05-15 10:59:16 +08:00
}, context_instance=RequestContext(request));
2012-10-18 10:57:02 +08:00
@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")}),
2012-10-25 16:48:08 +08:00
content_type='application/json; charset=utf-8')
2012-10-18 10:57:02 +08:00
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()
2012-10-25 16:48:08 +08:00
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.")}),
2012-10-25 16:48:08 +08:00
content_type='application/json; charset=utf-8')
2012-10-18 10:57:02 +08:00
2012-06-25 14:57:14 +08:00
@login_required
def msg_reply(request, msg_id):
"""Show group message replies, and process message reply in ajax"""
2012-08-08 20:16:00 +08:00
content_type = 'application/json; charset=utf-8'
2012-06-25 14:57:14 +08:00
if request.is_ajax():
2012-08-16 20:20:41 +08:00
ctx = {}
2012-06-25 14:57:14 +08:00
if request.method == 'POST':
2012-06-27 11:27:00 +08:00
form = MessageReplyForm(request.POST)
2012-06-25 14:57:14 +08:00
# TODO: invalid form
if form.is_valid():
msg = form.cleaned_data['message']
try:
group_msg = GroupMessage.objects.get(id=msg_id)
except GroupMessage.DoesNotExist:
2012-08-08 20:16:00 +08:00
return HttpResponseBadRequest(content_type=content_type)
2012-06-25 14:57:14 +08:00
msg_reply = MessageReply()
msg_reply.reply_to = group_msg
msg_reply.from_email = request.user.username
msg_reply.message = msg
msg_reply.save()
2012-06-27 16:39:49 +08:00
# 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)
2012-08-16 20:20:41 +08:00
ctx['reply'] = msg_reply
html = render_to_string("group/group_reply_new.html", ctx)
2012-08-14 16:33:16 +08:00
else:
2012-08-16 20:20:41 +08:00
try:
msg = GroupMessage.objects.get(id=msg_id)
except GroupMessage.DoesNotExist:
raise HttpResponse(status=400)
2012-08-14 16:33:16 +08:00
replies = MessageReply.objects.filter(reply_to=msg)
ctx['replies'] = replies
2012-08-16 20:20:41 +08:00
html = render_to_string("group/group_reply_list.html", ctx)
2012-08-14 16:33:16 +08:00
serialized_data = json.dumps({"html": html})
return HttpResponse(serialized_data, content_type=content_type)
2012-06-25 14:57:14 +08:00
else:
return HttpResponseBadRequest(content_type=content_type)
2012-06-25 14:57:14 +08:00
2012-06-27 16:39:49 +08:00
@login_required
def msg_reply_new(request):
notes = UserNotification.objects.filter(to_user=request.user.username)
2012-09-11 10:11:44 +08:00
grpmsg_reply_list = [ n.detail for n in notes if \
n.msg_type == 'grpmsg_reply']
2012-06-27 16:39:49 +08:00
group_msgs = []
for msg_id in grpmsg_reply_list:
try:
m = GroupMessage.objects.get(id=msg_id)
2012-08-16 17:54:21 +08:00
except GroupMessage.DoesNotExist:
continue
else:
2012-06-27 19:56:11 +08:00
# get group name
2012-08-01 22:45:58 +08:00
group = get_group(m.group_id)
if not group:
continue
2012-06-27 19:56:11 +08:00
m.group_name = group.group_name
2012-08-16 17:13:03 +08:00
# 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
2012-06-27 16:39:49 +08:00
# get message replies
reply_list = MessageReply.objects.filter(reply_to=m)
m.reply_list = reply_list
2012-08-16 17:54:21 +08:00
m.reply_cnt = reply_list.count()
2012-06-27 16:39:49 +08:00
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))
2012-06-25 14:57:14 +08:00
@login_required
2012-08-31 17:28:50 +08:00
@ctx_switch_required
2012-06-25 14:57:14 +08:00
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()
2012-06-25 21:40:18 +08:00
2012-06-26 14:20:37 +08:00
# send signal
grpmsg_added.send(sender=GroupMessage, group_id=group_id,
from_email=request.user.username)
2012-08-16 19:11:28 +08:00
# Always return an HttpResponseRedirect after successfully dealing
# with POST data.
return HttpResponseRedirect(reverse('group_info', args=[group_id]))
2012-06-25 14:57:14 +08:00
else:
form = MessageForm()
op = request.GET.get('op', '')
if op == 'delete':
return group_remove(request, group_id)
2012-08-03 11:32:11 +08:00
elif op == 'dismiss':
return group_dismiss(request, group_id)
2012-06-25 14:57:14 +08:00
elif op == 'quit':
return group_quit(request, group_id)
return render_group_info(request, group_id, form)
2012-05-15 10:59:16 +08:00
@login_required
2012-08-31 17:28:50 +08:00
@ctx_switch_required
2012-10-22 11:54:06 +08:00
@group_staff_required
2013-03-09 15:40:58 +08:00
@group_check
def group_manage(request, group):
2012-10-22 11:54:06 +08:00
user = request.user.username
2012-05-22 21:42:29 +08:00
if request.method == 'POST':
"""
Add group members.
"""
2012-09-06 17:20:15 +08:00
result = {}
content_type = 'application/json; charset=utf-8'
2012-10-22 11:54:06 +08:00
member_name_str = request.POST.get('user_name', '')
2012-08-10 21:16:55 +08:00
member_list = string2list(member_name_str)
2012-10-22 11:54:06 +08:00
# Add users to contacts.
for email in member_list:
mail_sended.send(sender=None, user=user, email=email)
2012-10-22 17:50:09 +08:00
mail_sended_list = []
2012-10-22 11:54:06 +08:00
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
2012-10-22 11:54:06 +08:00
result['error'] = err_msg
return HttpResponse(json.dumps(result), status=400,
content_type=content_type)
else:
try:
2013-03-09 15:40:58 +08:00
ccnet_threaded_rpc.group_add_member(group.id,
2012-10-22 11:54:06 +08:00
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',
2012-11-06 19:42:56 +08:00
'site_name': SITE_NAME,
2012-10-22 11:54:06 +08:00
}
try:
2013-01-10 14:47:07 +08:00
send_mail(_(u'Your friend added you to a group at Seafile.'),
2012-10-22 11:54:06 +08:00
t.render(Context(c)), None, [email],
fail_silently=False)
2012-10-22 17:50:09 +08:00
mail_sended_list.append(email)
2012-10-22 11:54:06 +08:00
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.
2012-06-20 19:39:21 +08:00
try:
2013-03-09 15:40:58 +08:00
ccnet_threaded_rpc.group_add_member(group.id,
2012-10-22 11:54:06 +08:00
user, email)
2012-06-20 19:39:21 +08:00
except SearpcError, e:
2012-09-07 16:14:36 +08:00
result['error'] = _(e.msg)
2012-09-19 19:52:35 +08:00
return HttpResponse(json.dumps(result), status=500,
2012-09-06 17:20:15 +08:00
content_type=content_type)
2012-06-20 19:39:21 +08:00
else:
2012-10-22 11:54:06 +08:00
# 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.')
2012-10-22 11:54:06 +08:00
result['error'] = err_msg % email
2012-09-26 20:22:09 +08:00
return HttpResponse(json.dumps(result), status=400,
content_type=content_type)
2012-09-19 19:52:35 +08:00
# Add user to group.
try:
2013-03-09 15:40:58 +08:00
ccnet_threaded_rpc.group_add_member(group.id,
2012-10-22 11:54:06 +08:00
user, email)
2012-09-19 19:52:35 +08:00
except SearpcError, e:
result['error'] = _(e.msg)
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
2012-10-22 17:50:09 +08:00
if mail_sended_list:
msg = ungettext(
'Successfully added. An email has been sent.',
'Successfully added. %(count)s emails have been sent.',
2012-11-13 11:40:30 +08:00
len(mail_sended_list)) % {
'count': len(mail_sended_list),
}
messages.success(request, msg)
2012-10-22 17:50:09 +08:00
else:
messages.success(request, _(u'Successfully added.'))
2012-09-19 19:52:35 +08:00
return HttpResponse(json.dumps('success'), status=200,
2012-09-06 17:20:15 +08:00
content_type=content_type)
### GET ###
2013-03-09 15:40:58 +08:00
members_all = ccnet_threaded_rpc.get_group_members(group.id)
2012-10-22 17:50:09 +08:00
admins = [ m for m in members_all if m.is_staff ]
2012-10-22 11:54:06 +08:00
contacts = Contact.objects.filter(user_email=user)
return render_to_response('group/group_manage.html', {
2012-05-17 23:50:04 +08:00
'group' : group,
2012-10-22 16:22:55 +08:00
'members': members_all,
2012-10-19 10:33:54 +08:00
'admins': admins,
'contacts': contacts,
}, context_instance=RequestContext(request))
2012-10-18 19:54:00 +08:00
@login_required
2012-10-22 16:22:55 +08:00
@group_staff_required
2012-10-18 19:54:00 +08:00
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
2012-10-18 19:54:00 +08:00
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)
2012-10-18 19:54:00 +08:00
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.'))
2012-10-18 19:54:00 +08:00
return HttpResponse(json.dumps('success'), status=200,
content_type=content_type)
2012-10-22 16:22:55 +08:00
@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.'))
2012-10-22 16:22:55 +08:00
except SearpcError, e:
2013-01-10 13:35:49 +08:00
messages.error(request, _(e.msg))
2012-10-22 16:22:55 +08:00
return HttpResponseRedirect(reverse('group_members', args=[group_id]))
2012-05-22 21:42:29 +08:00
@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'))
2012-05-22 21:42:29 +08:00
if not check_group_staff(group_id_int, request.user):
2012-09-28 10:47:51 +08:00
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:
2013-01-10 13:35:49 +08:00
messages.error(request, _(u'Failed%s') % _(e.msg))
2012-05-22 21:42:29 +08:00
return HttpResponseRedirect(reverse('group_members', args=[group_id]))
2012-09-03 12:03:06 +08:00
def group_share_repo(request, repo_id, group_id, from_email, permission):
2012-05-15 14:29:37 +08:00
"""
2012-05-22 21:42:29 +08:00
Share a repo to a group.
2012-05-15 14:29:37 +08:00
"""
2012-05-22 21:42:29 +08:00
# Check whether group exists
2012-08-01 22:45:58 +08:00
group = get_group(group_id)
2012-05-15 14:29:37 +08:00
if not group:
return render_error(request, _(u"Failed to share: the group doesn't exist."))
2012-05-15 14:29:37 +08:00
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."))
2012-05-15 14:29:37 +08:00
def group_unshare_repo(request, repo_id, group_id, from_email):
"""
2012-09-03 12:03:06 +08:00
Unshare a repo in group.
2012-05-15 14:29:37 +08:00
"""
2012-05-22 21:42:29 +08:00
# Check whether group exists
2012-08-01 22:45:58 +08:00
group = get_group(group_id)
2012-05-15 14:29:37 +08:00
if not group:
return render_error(request, _(u"Failed to unshare: the group doesn't exist."))
2012-05-15 14:29:37 +08:00
2012-05-22 21:42:29 +08:00
# 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."))
2012-05-15 14:29:37 +08:00
2013-02-20 20:51:37 +08:00
if unshare_group_repo(repo_id, group_id, from_email) != 0:
return render_error(request, _(u"Failed to unshare: internal error."))
2012-08-10 21:16:55 +08:00
@login_required
def group_recommend(request):
"""
2012-08-13 15:58:54 +08:00
Recommend a file or directory to a group.
2012-08-10 21:16:55 +08:00
"""
if request.method != 'POST':
raise Http404
next = request.META.get('HTTP_REFERER', None)
if not next:
next = SITE_ROOT
2012-08-13 15:58:54 +08:00
form = GroupRecommendForm(request.POST)
2012-08-10 21:16:55 +08:00
if form.is_valid():
repo_id = form.cleaned_data['repo_id']
2012-08-13 15:58:54 +08:00
attach_type = form.cleaned_data['attach_type']
path = form.cleaned_data['path']
2012-08-10 21:16:55 +08:00
message = form.cleaned_data['message']
2012-10-20 15:22:27 +08:00
groups = request.POST.getlist('groups') # groups is a group_id list, e.g. [u'1', u'7']
2012-09-14 11:39:33 +08:00
username = request.user.username
2012-10-20 15:22:27 +08:00
# Check group id format
for group_id in groups:
2012-08-10 21:16:55 +08:00
try:
2012-10-20 15:22:27 +08:00
group_id = int(group_id)
except ValueError:
messages.error(request, _(u'Error: wrong group id'))
2012-10-20 15:22:27 +08:00
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.')
2012-10-20 15:22:27 +08:00
messages.error(request, err_msg % group.group_name)
2012-08-10 21:16:55 +08:00
continue
2012-09-14 11:39:33 +08:00
2012-10-20 15:22:27 +08:00
# save message to group
gm = GroupMessage(group_id=group_id, from_email=username,
message=message)
gm.save()
2012-09-14 11:39:33 +08:00
2012-10-20 15:22:27 +08:00
# send signal
grpmsg_added.send(sender=GroupMessage, group_id=group_id,
from_email=request.user.username)
2012-08-16 17:54:21 +08:00
2012-10-20 15:22:27 +08:00
# 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_info', args=[group_id])
msg = _(u'Successfully recommended to <a href="%(url)s" target="_blank">%(name)s</a>.') %\
2012-10-20 15:22:27 +08:00
{'url':group_url, 'name':group.group_name}
messages.add_message(request, messages.INFO, msg)
2012-08-10 21:16:55 +08:00
else:
messages.add_message(request, messages.ERROR, _(u'Failed to recommend.'))
return HttpResponseRedirect(next)
2012-08-18 17:25:08 +08:00
@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.'))
2012-08-18 17:25:08 +08:00
2012-09-11 10:11:44 +08:00
# 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.'))
2012-08-18 17:25:08 +08:00
form = SharedRepoCreateForm(request.POST)
2012-08-18 17:25:08 +08:00
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']
2012-08-18 17:25:08 +08:00
encrypted = form.cleaned_data['encryption']
passwd = form.cleaned_data['passwd']
user = request.user.username
2012-09-01 11:54:59 +08:00
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'))
2012-08-18 17:25:08 +08:00
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)
2012-08-18 17:25:08 +08:00
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
2012-08-18 17:25:08 +08:00
if status != 0:
seafserv_threaded_rpc.remove_repo(repo_id)
return json_error(_(u'Failed to create: internal error.'))
2012-08-18 17:25:08 +08:00
else:
result = {'success': True}
return HttpResponse(json.dumps(result),
content_type=content_type)
2012-09-11 10:11:44 +08:00
2012-09-26 17:05:32 +08:00
@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.')
2012-09-26 17:05:32 +08:00
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,
2012-11-06 19:42:56 +08:00
'group_name': group.group_name,
2012-09-26 17:05:32 +08:00
'group_join_msg': group_join_msg,
2012-11-06 19:42:56 +08:00
'site_name': SITE_NAME,
2012-09-26 17:05:32 +08:00
}
try:
send_mail(_(u'apply to join the group'), t.render(Context(c)), None, [staff],
2012-09-26 17:05:32 +08:00
fail_silently=False)
messages.success(request, _(u'Sent successfully, the group admin will handle it.'))
2012-09-26 17:05:32 +08:00
return HttpResponse(json.dumps('success'),
content_type=content_type)
except:
err = _(u'Failed to send. You can try it again later.')
2012-09-26 17:05:32 +08:00
return HttpResponse(json.dumps({'error': err}), status=500,
content_type=content_type)
else:
return HttpResponseBadRequest(json.dumps(form.errors),
content_type=content_type)
2012-09-28 22:43:25 +08:00
def attention(request):
"""
Handle ajax request to query group members used in autocomplete.
"""
if not request.is_ajax():
raise Http404
user = request.user.username
2012-10-20 19:43:56 +08:00
name_str = request.GET.get('name_startsWith')
gids = request.GET.get('gids', '')
result = []
2012-09-28 22:43:25 +08:00
2012-10-20 19:43:56 +08:00
members = []
for gid in gids.split('_'):
2012-10-20 19:43:56 +08:00
try:
gid = int(gid)
except ValueError:
continue
2012-09-28 22:43:25 +08:00
2012-10-20 19:43:56 +08:00
if not is_group_user(gid, user):
continue
# Get all group users
members += get_group_members(gid)
member_names = []
2012-09-28 22:43:25 +08:00
for m in members:
2013-01-04 20:11:57 +08:00
if len(result) == 10: # Return at most 10 results.
break
2012-09-28 22:43:25 +08:00
if m.user_name == user:
continue
2013-01-04 20:11:57 +08:00
2012-10-20 19:43:56 +08:00
if m.user_name in member_names:
# Remove duplicated member names
continue
else:
member_names.append(m.user_name)
2012-09-28 22:43:25 +08:00
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)
2013-03-04 20:23:59 +08:00
@login_required
def group_discus(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)
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'))
per_page= int(request.GET.get('per_page', '15'))
except ValueError:
current_page = 1
per_page = 15
msgs_plus_one = GroupMessage.objects.filter(
group_id=group_id).order_by(
'-timestamp')[per_page*(current_page-1) : per_page*current_page+1]
if len(msgs_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
group_msgs = msgs_plus_one[:per_page]
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)
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
contacts = Contact.objects.filter(user_email=request.user.username)
return render_to_response("group/group_discus.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,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
'contacts': contacts,
'group_members_default_display': GROUP_MEMBERS_DEFAULT_DISPLAY,
}, context_instance=RequestContext(request));
2013-03-05 11:56:51 +08:00
2013-03-08 19:34:53 +08:00
class WikiDoesNotExist(Exception):
pass
class WikiPageMissing(Exception):
pass
2013-03-05 11:56:51 +08:00
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):
2013-03-08 19:34:53 +08:00
obj_id = get_file_id_by_path(repo_id, path)
if not obj_id:
raise WikiPageMissing
2013-03-05 11:56:51 +08:00
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)
2013-03-08 19:34:53 +08:00
if not repo:
raise WikiDoesNotExist
2013-03-05 11:56:51 +08:00
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()
2013-03-08 19:34:53 +08:00
return content, repo.id
2013-03-05 11:56:51 +08:00
2013-03-08 19:34:53 +08:00
def convert_wiki_link(content, group, repo_id):
2013-03-05 11:56:51 +08:00
import re
def repl(matchobj):
linkname = matchobj.group(1)
filename = linkname + ".md"
path = "/" + filename
2013-03-08 19:34:53 +08:00
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)
2013-03-05 11:56:51 +08:00
return re.sub(r'\[\[(.+)\]\]', repl, content)
@login_required
2013-03-09 15:27:17 +08:00
@group_check
def group_wiki(request, group, page_name="home"):
2013-03-05 11:56:51 +08:00
is_staff = True if check_group_staff(group.id, request.user) else False
2013-03-08 19:34:53 +08:00
content = ''
wiki_exists, wiki_page_missing = True, False
try:
2013-03-09 15:27:17 +08:00
content, repo_id = get_wiki_page(request, group.id, page_name)
2013-03-08 19:34:53 +08:00
except WikiDoesNotExist:
wiki_exists = False
except WikiPageMissing:
wiki_page_missing = True
else:
content = convert_wiki_link(content, group, repo_id)
2013-03-05 11:56:51 +08:00
return render_to_response("group/group_wiki.html", {
2013-03-09 15:27:17 +08:00
"group_id": group.id,
2013-03-05 11:56:51 +08:00
"group" : group,
"is_staff": is_staff,
"content": content,
"page": page_name,
2013-03-08 19:34:53 +08:00
"wiki_exists": wiki_exists,
"wiki_page_missing": wiki_page_missing,
}, context_instance=RequestContext(request))
2013-03-05 11:56:51 +08:00
@login_required
2013-03-09 15:27:17 +08:00
@group_check
def group_wiki_create(request, group):
2013-03-05 11:56:51 +08:00
# 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.'))
2013-03-08 19:34:53 +08:00
# create home page
page_name = "home.md"
seafserv_threaded_rpc.post_empty_file(repo_id, "/", page_name, user)
2013-03-07 12:05:30 +08:00
2013-03-08 19:34:53 +08:00
return HttpResponseRedirect(reverse('group_info', args=[group_id]))
2013-03-07 12:05:30 +08:00
@login_required
2013-03-09 15:27:17 +08:00
@group_check
def group_wiki_page_new(request, group, page_name="home"):
2013-03-07 12:05:30 +08:00
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
2013-03-09 15:27:17 +08:00
@group_check
def group_wiki_page_edit(request, group, page_name="home"):
2013-03-07 12:05:30 +08:00
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)