def _decorated(view, request, group_id, *args, **kwargs): group_id = int(group_id) # Checked by URL Conf try: group = seaserv.get_group(group_id) except SearpcError as e: logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not group: error_msg = _(u'Group does not exist.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) username = request.user.username try: is_group_member = seaserv.is_group_user(group_id, username) except SearpcError as e: logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not is_group_member: error_msg = _(u'Permission denied') return api_error(status.HTTP_403_FORBIDDEN, error_msg) return func(view, request, group_id, *args, **kwargs)
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 = int(group_id) msg_id = int(msg_id) group = get_group(group_id_int) if not group: raise Http404 # Test whether user is in the group if not is_group_user(group_id_int, 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 seaserv.check_group_staff(group_id, request.user.username) 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')
def post(self, request, email, format=None): # migrate an account's repos and groups to an exist account if not is_valid_username(email): return api_error(status.HTTP_404_NOT_FOUND, 'User not found.') op = request.DATA.get('op', '').lower() if op == 'migrate': from_user = email to_user = request.DATA.get('to_user', '') if not is_valid_username(to_user): return api_error(status.HTTP_400_BAD_REQUEST, '%s is not valid email.' % to_user) try: user2 = User.objects.get(email=to_user) except User.DoesNotExist: return api_error(status.HTTP_400_BAD_REQUEST, '%s does not exist.' % to_user) # transfer owned repos to new user for r in seafile_api.get_owned_repo_list(from_user): seafile_api.set_repo_owner(r.id, user2.username) # transfer joined groups to new user for g in seaserv.get_personal_groups_by_user(from_user): if not seaserv.is_group_user(g.id, user2.username): # add new user to the group on behalf of the group creator ccnet_threaded_rpc.group_add_member(g.id, g.creator_name, to_user) if from_user == g.creator_name: ccnet_threaded_rpc.set_group_creator(g.id, to_user) return Response("success") else: return api_error(status.HTTP_400_BAD_REQUEST, 'Op can only be migrate')
def post(self, request, email, format=None): # migrate an account's repos and groups to an exist account if not is_valid_username(email): return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % email) op = request.data.get('op', '').lower() if op == 'migrate': from_user = email to_user = request.data.get('to_user', '') if not is_valid_username(to_user): return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % to_user) try: user2 = User.objects.get(email=to_user) except User.DoesNotExist: return api_error(status.HTTP_404_NOT_FOUND, 'User %s not found.' % to_user) # transfer owned repos to new user for r in seafile_api.get_owned_repo_list(from_user): seafile_api.set_repo_owner(r.id, user2.username) # transfer joined groups to new user for g in seaserv.get_personal_groups_by_user(from_user): if not seaserv.is_group_user(g.id, user2.username): # add new user to the group on behalf of the group creator ccnet_threaded_rpc.group_add_member(g.id, g.creator_name, to_user) if from_user == g.creator_name: ccnet_threaded_rpc.set_group_creator(g.id, to_user) return Response("success") else: return api_error(status.HTTP_400_BAD_REQUEST, 'op can only be migrate.')
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 = int(group_id) msg_id = int(msg_id) group = get_group(group_id_int) if not group: raise Http404 # Test whether user is in the group if not is_group_user(group_id_int, 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 seaserv.check_group_staff(group_id, request.user.username) 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", )
def _decorated(view, 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 api_error(status.HTTP_404_NOT_FOUND, 'Group not found.') group.is_staff = False if PublicGroup.objects.filter(group_id=group.id): group.is_pub = True else: group.is_pub = False joined = is_group_user(group_id_int, request.user.username) if joined: group.view_perm = "joined" group.is_staff = is_group_staff(group, request.user) return func(view, request, group, *args, **kwargs) if request.user.is_staff: # viewed by system admin group.view_perm = "sys_admin" return func(view, request, group, *args, **kwargs) if group.is_pub: group.view_perm = "pub" return func(view, request, group, *args, **kwargs) # Return group public info page. return api_error(status.HTTP_403_FORBIDDEN, 'Forbid to access this group.')
def group_recommend(request): """ Recommend a file or directory to a group. """ 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_info', args=[group_id]) msg = _(u'Successfully recommended 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)
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=[])) group.is_staff = False if PublicGroup.objects.filter(group_id=group.id): group.is_pub = True else: group.is_pub = False if not request.user.is_authenticated(): if not group.is_pub: login_url = settings.LOGIN_URL path = urlquote(request.get_full_path()) tup = login_url, REDIRECT_FIELD_NAME, path return HttpResponseRedirect('%s?%s=%s' % tup) else: group.view_perm = "pub" return func(request, group, *args, **kwargs) joined = is_group_user(group_id_int, request.user.username) if joined: group.view_perm = "joined" group.is_staff = is_group_staff(group, request.user) return func(request, group, *args, **kwargs) if group.is_pub: group.view_perm = "pub" return func(request, group, *args, **kwargs) return render_to_response('error.html', { 'error_msg': _('Permission denied'), }, context_instance=RequestContext(request))
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) group = get_group(group_id) if not group: return json_error(_(u'Failed to create: the group does not exist.')) # Check whether user belongs to the group. username = request.user.username if not is_group_user(group_id, 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(str(form.errors.values()[0])) # Form is valid, create group repo repo_name = form.cleaned_data['repo_name'] repo_desc = form.cleaned_data['repo_desc'] permission = form.cleaned_data['permission'] encryption = int(form.cleaned_data['encryption']) uuid = form.cleaned_data['uuid'] magic_str = form.cleaned_data['magic_str'] encrypted_file_key = form.cleaned_data['encrypted_file_key'] if is_org_context(request): org_id = request.user.org.org_id try: if encryption: repo_id = seafile_api.create_org_enc_repo(uuid, repo_name, repo_desc, username, magic_str, encrypted_file_key, enc_version=2, org_id=org_id) else: repo_id = seafile_api.create_org_repo(repo_name, repo_desc, username, None, org_id) except SearpcError, e: logger.error(e) return json_error(_(u'Failed to create')) try: seafile_api.add_org_group_repo(repo_id, org_id, group.id, username, permission) except SearpcError, e: logger.error(e) return json_error(_(u'Failed to create: internal error.'))
def get_shared_groups_by_repo_and_user(repo_id, username): """Get all groups which this repo is shared. """ repo_shared_groups = seaserv.get_shared_groups_by_repo(repo_id) # Filter out groups that user is joined. groups = [x for x in repo_shared_groups if seaserv.is_group_user(x.id, username)] return groups
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:
def put(self, request, group_id): """ Rename, transfer a specific group """ group = seaserv.get_group(group_id) username = request.user.username new_group_name = request.data.get('name', None) if new_group_name: # rename a group # Check whether group name is validate. if not validate_group_name(new_group_name): error_msg = _(u'Group name can only contain letters, numbers, blank, hyphen or underscore') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # Check whether group name is duplicated. if check_group_name_conflict(request, new_group_name): error_msg = _(u'There is already a group with that name.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: seaserv.ccnet_threaded_rpc.set_group_name(group_id, new_group_name) except SearpcError as e: logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) new_creator= request.data.get('creator', None) if new_creator: # transfer a group if not is_valid_username(new_creator): error_msg = _('Creator %s is not valid.') % new_creator return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if new_creator == group.creator_name: error_msg = _('%s is already group owner') % new_creator return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: if not seaserv.is_group_user(group_id, new_creator): seaserv.ccnet_threaded_rpc.group_add_member(group_id, username, new_creator) if not seaserv.check_group_staff(group_id, new_creator): seaserv.ccnet_threaded_rpc.group_set_admin(group_id, new_creator) seaserv.ccnet_threaded_rpc.set_group_creator(group_id, new_creator) except SearpcError as e: logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # get new info of this group group_info = get_group_info(request, group_id, GROUP_AVATAR_DEFAULT_SIZE) return Response(group_info)
def get_repo_shared_groups(self): if self.user.org: org_id = self.user.org['org_id'] repo_shared_groups = get_org_groups_by_repo(org_id, self.repo_id) else: repo_shared_groups = get_shared_groups_by_repo(self.repo_id) # Filter out groups that user is joined. groups = [ x for x in repo_shared_groups if \ is_group_user(x.id, self.user.username)] return groups
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) group = get_group(group_id) if not group: return json_error(_(u'Failed to create: the group does not exist.')) # Check whether user belongs to the group. username = request.user.username if not is_group_user(group_id, 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(str(form.errors.values()[0])) # Form is valid, create group repo repo_name = form.cleaned_data['repo_name'] repo_desc = form.cleaned_data['repo_desc'] permission = form.cleaned_data['permission'] encryption = int(form.cleaned_data['encryption']) uuid = form.cleaned_data['uuid'] magic_str = form.cleaned_data['magic_str'] encrypted_file_key = form.cleaned_data['encrypted_file_key'] if is_org_context(request): org_id = request.user.org.org_id try: if encryption: repo_id = seafile_api.create_org_enc_repo( uuid, repo_name, repo_desc, username, magic_str, encrypted_file_key, enc_version=2, org_id=org_id) else: repo_id = seafile_api.create_org_repo(repo_name, repo_desc, username, None, org_id) except SearpcError, e: logger.error(e) return json_error(_(u'Failed to create')) try: seafile_api.add_org_group_repo(repo_id, org_id, group.id, username, permission) except SearpcError, e: logger.error(e) return json_error(_(u'Failed to create: internal error.'))
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', { 'group': group, }, context_instance=RequestContext(request)) return func(request, group, *args, **kwargs)
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)
def attention(request): """ Handle ajax request to query group members used in autocomplete. """ 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 seahub.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)
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)
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=[])) group.is_staff = False if PublicGroup.objects.filter(group_id=group.id): group.is_pub = True else: group.is_pub = False if not request.user.is_authenticated(): if not group.is_pub: login_url = settings.LOGIN_URL path = urlquote(request.get_full_path()) tup = login_url, REDIRECT_FIELD_NAME, path return HttpResponseRedirect("%s?%s=%s" % tup) else: group.view_perm = "pub" return func(request, group, *args, **kwargs) joined = is_group_user(group_id_int, request.user.username) if joined: group.view_perm = "joined" group.is_staff = is_group_staff(group, request.user) return func(request, group, *args, **kwargs) if request.user.is_staff: # viewed by system admin group.view_perm = "sys_admin" return func(request, group, *args, **kwargs) if group.is_pub: group.view_perm = "pub" return func(request, group, *args, **kwargs) return render_to_response( "error.html", {"error_msg": _("Permission denied")}, context_instance=RequestContext(request) )
def message_send(request): """Handle POST request to send message to user(s)/group(s). """ if not request.is_ajax() or request.method != 'POST': raise Http404 content_type = 'application/json; charset=utf-8' result = {} username = request.user.username fr = request.GET.get('from') if not fr: result['error'] = [_(u'Argument missing')] return HttpResponse(json.dumps(result), content_type=content_type) mass_msg = request.POST.get('mass_msg') mass_emails = request.POST.getlist('mass_email') # e.g: [u'[email protected], u'*****@*****.**'] mass_group_ids = [int(x) for x in request.POST.getlist('mass_group')] if not mass_msg: result['error'] = [_(u'message is required')] return HttpResponse(json.dumps(result), content_type=content_type) if not mass_emails and not mass_group_ids: result['error'] = [_(u'contact/group is required')] return HttpResponse(json.dumps(result), content_type=content_type) # attachment selected = request.POST.getlist('selected') # selected files & dirs: [u'<repo_id><path>', ...] attached_items = [] if len(selected) > 0: for item in selected: if item[-1] == '/': # dir is not allowed, for now continue att = {} att['repo_id'] = item[0:36] att['path'] = item[36:] attached_items.append(att) email_sent = [] group_sent = [] errors = [] user_msgs = [] group_msgs = [] for to_email in mass_emails: to_email = to_email.strip() if not to_email or not is_valid_username(to_email): continue if to_email == username: errors.append(_(u'You can not send message to yourself.')) continue if not is_registered_user(to_email): errors.append(_(u'Failed to send message to %s, user not found.') % to_email) continue user_msg = UserMessage.objects.add_unread_message(username, to_email, mass_msg) user_msgs.append(user_msg) if len(attached_items) > 0: for att_item in attached_items: repo_id = att_item['repo_id'] path = att_item['path'] pfds = PrivateFileDirShare.objects.add_read_only_priv_file_share( username, to_email, repo_id, path) UserMsgAttachment.objects.add_user_msg_attachment(user_msg, pfds) email_sent.append(to_email) joined_groups = [] for group_id in mass_group_ids: group = get_group(group_id) if not group: continue joined_groups.append(group) if not is_group_user(group_id, username): errors.append(_(u'You can not send message to group %s, you didn\'t join in.') % group.name) continue group_msg = GroupMessage(group_id=group_id, from_email=username, message=mass_msg) group_msg.save() grpmsg_added.send(sender=GroupMessage, group_id=group_id, from_email=username) group_msgs.append(group_msg) if len(attached_items) > 0: for att_item in attached_items: repo_id = att_item['repo_id'] path = att_item['path'] ma = MessageAttachment(group_message=group_msg, repo_id=repo_id, attach_type='file', path=path, src='recommend') ma.save() group_sent.append(group_id) html = '' if email_sent or group_sent: ctx = {} if fr == 'all': # from 'all_msg_list' page user_msgs = user_msg_info_list(user_msgs, username) group_msgs = group_msg_info_list(joined_groups, username) ctx['msgs'] = sorted(user_msgs.items() + group_msgs.items(), key=lambda x: x[1]['last_time'], reverse=True) html = render_to_string('message/all_msg.html', ctx, context_instance=RequestContext(request)) else: ctx['msg'] = user_msgs[0] html = render_to_string('message/user_msg.html', ctx) return HttpResponse(json.dumps({"html": html, "error": errors}), content_type=content_type) else: return HttpResponse(json.dumps({"html": html, "error": errors}), status=400, content_type=content_type)
def is_group_member(group_id, email): return seaserv.is_group_user(group_id, email)
def view_file(request, repo_id): """ Steps to view file: 1. Get repo id and file path. 2. Check user's permission. 3. Check whether this file can be viewed online. 4.1 Get file content if file is text file. 4.2 Prepare flash if file is document. 4.3 Prepare or use pdfjs if file is pdf. 4.4 Other file return it's raw path. """ username = request.user.username # check arguments repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get("p", "/") obj_id = get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u"File does not exist")) # construct some varibles u_filename = os.path.basename(path) filename_utf8 = urllib2.quote(u_filename.encode("utf-8")) current_commit = get_commits(repo_id, 0, 1)[0] # Check whether user has permission to view file and get file raw path, # render error page if permission is deny. raw_path, user_perm = get_file_view_path_and_perm(request, repo_id, obj_id, u_filename) if not user_perm: return render_permission_error(request, _(u"Unable to view file")) # get file type and extension filetype, fileext = get_file_type_and_ext(u_filename) img_prev = None img_next = None ret_dict = { "err": "", "file_content": "", "encoding": "", "file_enc": "", "file_encoding_list": [], "swf_exists": False, "filetype": filetype, } # Check file size fsize = get_file_size(obj_id) if fsize > FILE_PREVIEW_MAX_SIZE: from django.template.defaultfilters import filesizeformat err = _(u"File size surpasses %s, can not be opened online.") % filesizeformat(FILE_PREVIEW_MAX_SIZE) ret_dict["err"] = err else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, raw_path, ret_dict) if filetype == MARKDOWN: c = ret_dict["file_content"] ret_dict["file_content"] = convert_md_link(c, repo_id, username) elif filetype == DOCUMENT: handle_document(raw_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(raw_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: parent_dir = os.path.dirname(path) dirs = list_dir_by_path(current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == "Image": img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y: cmp(x.lower(), y.lower())) cur_img_index = img_list.index(u_filename) if cur_img_index != 0: img_prev = os.path.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = os.path.join(parent_dir, img_list[cur_img_index + 1]) else: pass # generate file path navigator zipped = gen_path_link(path, repo.name) # file shared link l = FileShare.objects.filter(repo_id=repo_id).filter(username=username).filter(path=path) fileshare = l[0] if len(l) > 0 else None http_or_https = request.is_secure() and "https" or "http" domain = RequestSite(request).domain if fileshare: file_shared_link = gen_shared_link(request, fileshare.token, "f") else: file_shared_link = "" # my contacts used in shared link autocomplete contacts = Contact.objects.filter(user_email=username) """List repo groups""" # Get groups this repo is shared. if request.user.org: org_id = request.user.org["org_id"] repo_shared_groups = get_org_groups_by_repo(org_id, repo_id) else: repo_shared_groups = get_shared_groups_by_repo(repo_id) # Filter out groups that user in joined. groups = [x for x in repo_shared_groups if is_group_user(x.id, username)] if len(groups) > 1: ctx = {} ctx["groups"] = groups repogrp_str = render_to_string("snippets/repo_group_list.html", ctx) else: repogrp_str = "" file_path_hash = md5_constructor(urllib2.quote(path.encode("utf-8"))).hexdigest()[:12] # fetch file contributors and latest contributor contributors, last_modified, last_commit_id = get_file_contributors( repo_id, path.encode("utf-8"), file_path_hash, obj_id ) latest_contributor = contributors[0] if contributors else None # check whether file is starred is_starred = False org_id = -1 if request.user.org: org_id = request.user.org["org_id"] is_starred = is_file_starred(username, repo.id, path.encode("utf-8"), org_id) template = "view_file_%s.html" % ret_dict["filetype"].lower() return render_to_response( template, { "repo": repo, "obj_id": obj_id, "filename": u_filename, "path": path, "zipped": zipped, "current_commit": current_commit, "fileext": fileext, "raw_path": raw_path, "fileshare": fileshare, "protocol": http_or_https, "domain": domain, "file_shared_link": file_shared_link, "contacts": contacts, "err": ret_dict["err"], "file_content": ret_dict["file_content"], "file_enc": ret_dict["file_enc"], "encoding": ret_dict["encoding"], "file_encoding_list": ret_dict["file_encoding_list"], "swf_exists": ret_dict["swf_exists"], "filetype": ret_dict["filetype"], "applet_root": get_ccnetapplet_root(), "groups": groups, "DOCUMENT_CONVERTOR_ROOT": DOCUMENT_CONVERTOR_ROOT, "use_pdfjs": USE_PDFJS, "contributors": contributors, "latest_contributor": latest_contributor, "last_modified": last_modified, "last_commit_id": last_commit_id, "repo_group_str": repogrp_str, "is_starred": is_starred, "user_perm": user_perm, "img_prev": img_prev, "img_next": img_next, }, context_instance=RequestContext(request), )
def view_file(request, repo_id): """ Steps to view file: 1. Get repo id and file path. 2. Check user's permission. 3. Check whether this file can be viewed online. 4.1 Get file content if file is text file. 4.2 Prepare flash if file is document. 4.3 Prepare or use pdfjs if file is pdf. 4.4 Other file return it's raw path. """ username = request.user.username # check arguments repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get('p', '/').rstrip('/') obj_id = get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) # construct some varibles u_filename = os.path.basename(path) current_commit = get_commits(repo_id, 0, 1)[0] # Check whether user has permission to view file and get file raw path, # render error page if permission deny. raw_path, inner_path, user_perm = get_file_view_path_and_perm( request, repo_id, obj_id, path) if not user_perm: return render_permission_error(request, _(u'Unable to view file')) # check if the user is the owner or not, for 'private share' if is_org_context(request): repo_owner = seafile_api.get_org_repo_owner(repo.id) is_repo_owner = True if repo_owner == username else False else: is_repo_owner = seafile_api.is_repo_owner(username, repo.id) # get file type and extension filetype, fileext = get_file_type_and_ext(u_filename) img_prev = None img_next = None ret_dict = { 'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype } fsize = get_file_size(repo.store_id, repo.version, obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: ret_dict['err'] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) if filetype == MARKDOWN: c = ret_dict['file_content'] ret_dict['file_content'] = convert_md_link( c, repo_id, username) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == OPENDOCUMENT: if fsize == 0: ret_dict['err'] = _(u'Invalid file format.') elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: parent_dir = os.path.dirname(path) dirs = seafile_api.list_dir_by_commit_and_path( current_commit.repo_id, current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == 'Image': img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y: cmp(x.lower(), y.lower())) cur_img_index = img_list.index(u_filename) if cur_img_index != 0: img_prev = posixpath.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = posixpath.join(parent_dir, img_list[cur_img_index + 1]) else: pass # generate file path navigator zipped = gen_path_link(path, repo.name) # file shared link l = FileShare.objects.filter(repo_id=repo_id).filter( username=username).filter(path=path) fileshare = l[0] if len(l) > 0 else None http_or_https = request.is_secure() and 'https' or 'http' domain = RequestSite(request).domain if fileshare: file_shared_link = gen_file_share_link(fileshare.token) else: file_shared_link = '' for g in request.user.joined_groups: g.avatar = grp_avatar(g.id, 20) """List repo groups""" # Get groups this repo is shared. if request.user.org: org_id = request.user.org.org_id repo_shared_groups = get_org_groups_by_repo(org_id, repo_id) else: repo_shared_groups = get_shared_groups_by_repo(repo_id) # Filter out groups that user in joined. groups = [x for x in repo_shared_groups if is_group_user(x.id, username)] if len(groups) > 1: ctx = {} ctx['groups'] = groups repogrp_str = render_to_string("snippets/repo_group_list.html", ctx) else: repogrp_str = '' file_path_hash = hashlib.md5(urllib2.quote( path.encode('utf-8'))).hexdigest()[:12] # fetch file contributors and latest contributor contributors, last_modified, last_commit_id = \ FileContributors.objects.get_file_contributors( repo_id, path.encode('utf-8'), file_path_hash, obj_id) latest_contributor = contributors[0] if contributors else None # check whether file is starred is_starred = False org_id = -1 if request.user.org: org_id = request.user.org.org_id is_starred = is_file_starred(username, repo.id, path.encode('utf-8'), org_id) template = 'view_file_%s.html' % ret_dict['filetype'].lower() return render_to_response( template, { 'repo': repo, 'is_repo_owner': is_repo_owner, 'obj_id': obj_id, 'filename': u_filename, 'path': path, 'zipped': zipped, 'current_commit': current_commit, 'fileext': fileext, 'raw_path': raw_path, 'fileshare': fileshare, 'protocol': http_or_https, 'domain': domain, 'file_shared_link': file_shared_link, 'err': ret_dict['err'], 'file_content': ret_dict['file_content'], 'file_enc': ret_dict['file_enc'], 'encoding': ret_dict['encoding'], 'file_encoding_list': ret_dict['file_encoding_list'], 'html_exists': ret_dict['html_exists'], 'html_detail': ret_dict.get('html_detail', {}), 'filetype': ret_dict['filetype'], 'groups': groups, 'use_pdfjs': USE_PDFJS, 'contributors': contributors, 'latest_contributor': latest_contributor, 'last_modified': last_modified, 'last_commit_id': last_commit_id, 'repo_group_str': repogrp_str, 'is_starred': is_starred, 'user_perm': user_perm, 'img_prev': img_prev, 'img_next': img_next, 'highlight_keyword': settings.HIGHLIGHT_KEYWORD, }, context_instance=RequestContext(request))
def post(self, request, group_id): """ Bulk add group members. """ username = request.user.username try: if not is_group_admin_or_owner(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) emails_str = request.data.get('emails', '') emails_list = string2list(emails_str) emails_list = [x.lower() for x in emails_list] result = {} result['failed'] = [] result['success'] = [] emails_need_add = [] org_id = None if is_org_context(request): org_id = request.user.org.org_id for email in emails_list: try: User.objects.get(email=email) except User.DoesNotExist: result['failed'].append({ 'email': email, 'error_msg': 'User %s not found.' % email }) continue if seaserv.is_group_user(group_id, email): result['failed'].append({ 'email': email, 'error_msg': _(u'User %s is already a group member.') % email }) continue # Can only invite organization users to group if org_id and not \ seaserv.ccnet_threaded_rpc.org_user_exists(org_id, email): result['failed'].append({ 'email': email, 'error_msg': _(u'User %s not found in organization.') % email }) continue emails_need_add.append(email) # Add user to group. for email in emails_need_add: try: seaserv.ccnet_threaded_rpc.group_add_member(group_id, username, email) member_info = get_group_member_info(request, group_id, email) result['success'].append(member_info) except SearpcError as e: logger.error(e) result['failed'].append({ 'email': email, 'error_msg': 'Internal Server Error' }) return Response(result)
def group_wiki(request, group, page_name="home"): username = request.user.username # get available modules(wiki, etc) mods_available = get_available_mods_by_group(group.id) mods_enabled = get_enabled_mods_by_group(group.id) wiki_exists = True try: content, repo, dirent = get_group_wiki_page(username, group, page_name) except WikiDoesNotExist: wiki_exists = False group_repos = get_group_repos(group.id, username) group_repos = [r for r in group_repos if not r.encrypted] return render_to_response("group/group_wiki.html", { "group": group, "is_staff": group.is_staff, "wiki_exists": wiki_exists, "mods_enabled": mods_enabled, "mods_available": mods_available, "group_repos": group_repos, }, context_instance=RequestContext(request)) except WikiPageMissing: '''create that page for user if he/she is a group member''' if not is_group_user(group.id, username): raise Http404 repo = get_group_wiki_repo(group, username) # No need to check whether repo is none, since repo is already created filename = page_name_to_file_name(clean_page_name(page_name)) if not post_empty_file(repo.id, "/", filename, username): return render_error( request, _("Failed to create wiki page. Please retry later.")) return HttpResponseRedirect( reverse('group_wiki', args=[group.id, page_name])) else: # fetch file modified time and modifier path = '/' + dirent.obj_name try: dirent = seafile_api.get_dirent_by_path(repo.id, path) if dirent: latest_contributor, last_modified = dirent.modifier, dirent.mtime else: latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 if is_registered_user(username): repo_perm = seafile_api.check_permission_by_path( repo.id, '/', username) else: # when anonymous user visit public group wiki, set permission as 'r' repo_perm = 'r' wiki_index_exists = True index_pagename = 'index' index_content = None try: index_content, index_repo, index_dirent = get_group_wiki_page( username, group, index_pagename) except (WikiDoesNotExist, WikiPageMissing) as e: wiki_index_exists = False return render_to_response( "group/group_wiki.html", { "group": group, "is_staff": group.is_staff, "wiki_exists": wiki_exists, "content": content, "page": os.path.splitext(dirent.obj_name)[0], "last_modified": last_modified, "latest_contributor": latest_contributor or _("Unknown"), "path": path, "repo_id": repo.id, "search_repo_id": repo.id, "search_wiki": True, "mods_enabled": mods_enabled, "mods_available": mods_available, "repo_perm": repo_perm, "wiki_index_exists": wiki_index_exists, "index_content": index_content, }, context_instance=RequestContext(request))
def group_recommend(request): """ Get or post file/directory discussions to a group. """ content_type = "application/json; charset=utf-8" result = {} if request.method == "POST": 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 is a group_id list, e.g. [u'1', u'7'] groups = request.POST.getlist("groups") username = request.user.username groups_not_in = [] groups_posted_to = [] for group_id in groups: # Check group id format try: group_id = int(group_id) except ValueError: result["error"] = _(u"Error: wrong group id") return HttpResponse(json.dumps(result), status=400, content_type=content_type) group = get_group(group_id) if not group: result["error"] = _(u"Error: the group does not exist.") return HttpResponse(json.dumps(result), status=400, content_type=content_type) # TODO: Check whether repo is in the group and Im in the group if not is_group_user(group_id, username): groups_not_in.append(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=username, message=message) # save attachment ma = MessageAttachment( group_message=gm, repo_id=repo_id, attach_type=attach_type, path=path, src="recommend" ) ma.save() # save discussion fd = FileDiscuss(group_message=gm, repo_id=repo_id, path=path) fd.save() group_url = reverse("group_discuss", args=[group_id]) groups_posted_to.append( u'<a href="%(url)s" target="_blank">%(name)s</a>' % {"url": group_url, "name": group.group_name} ) if len(groups_posted_to) > 0: result["success"] = _(u"Successfully posted to %(groups)s.") % {"groups": ", ".join(groups_posted_to)} if len(groups_not_in) > 0: result["error"] = _(u"Error: you are not in group %s.") % (", ".join(groups_not_in)) else: result["error"] = str(form.errors) return HttpResponse(json.dumps(result), status=400, content_type=content_type) # request.method == 'GET' else: repo_id = request.GET.get("repo_id") path = request.GET.get("path", None) repo = get_repo(repo_id) if not repo: result["error"] = _(u"Error: the library does not exist.") return HttpResponse(json.dumps(result), status=400, content_type=content_type) if path is None: result["error"] = _(u"Error: no path.") return HttpResponse(json.dumps(result), status=400, content_type=content_type) # get discussions & replies path_hash = calc_file_path_hash(path) discussions = FileDiscuss.objects.filter(path_hash=path_hash, repo_id=repo_id) msg_ids = [e.group_message_id for e in discussions] grp_msgs = GroupMessage.objects.filter(id__in=msg_ids).order_by("-timestamp") msg_replies = MessageReply.objects.filter(reply_to__in=grp_msgs) for msg in grp_msgs: msg.replies = [] for reply in msg_replies: if msg.id == reply.reply_to_id: msg.replies.append(reply) msg.reply_cnt = len(msg.replies) msg.replies = msg.replies[-3:] ctx = {} ctx["messages"] = grp_msgs html = render_to_string("group/discussion_list.html", ctx) result["html"] = html return HttpResponse(json.dumps(result), content_type=content_type)
def is_group_user(gid, username): return seaserv.is_group_user(gid, username)
def view_file(request, repo_id): """ Steps to view file: 1. Get repo id and file path. 2. Check user's permission. 3. Check whether this file can be viewed online. 4.1 Get file content if file is text file. 4.2 Prepare flash if file is document. 4.3 Prepare or use pdfjs if file is pdf. 4.4 Other file return it's raw path. """ username = request.user.username # check arguments repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get('p', '/') obj_id = get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) # construct some varibles u_filename = os.path.basename(path) current_commit = get_commits(repo_id, 0, 1)[0] # Check whether user has permission to view file and get file raw path, # render error page if permission is deny. raw_path, user_perm = get_file_view_path_and_perm(request, repo_id, obj_id, u_filename) if not user_perm: return render_permission_error(request, _(u'Unable to view file')) # get file type and extension filetype, fileext = get_file_type_and_ext(u_filename) img_prev = None img_next = None ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} fsize = get_file_size(obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: ret_dict['err'] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, raw_path, ret_dict) if filetype == MARKDOWN: c = ret_dict['file_content'] ret_dict['file_content'] = convert_md_link(c, repo_id, username) elif filetype == DOCUMENT: handle_document(raw_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(raw_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: parent_dir = os.path.dirname(path) dirs = list_dir_by_path(current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == 'Image': img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y : cmp(x.lower(), y.lower())) cur_img_index = img_list.index(u_filename) if cur_img_index != 0: img_prev = os.path.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = os.path.join(parent_dir, img_list[cur_img_index + 1]) else: pass # generate file path navigator zipped = gen_path_link(path, repo.name) # file shared link l = FileShare.objects.filter(repo_id=repo_id).filter( username=username).filter(path=path) fileshare = l[0] if len(l) > 0 else None http_or_https = request.is_secure() and 'https' or 'http' domain = RequestSite(request).domain if fileshare: file_shared_link = gen_shared_link(request, fileshare.token, 'f') else: file_shared_link = '' # my contacts used in shared link autocomplete contacts = Contact.objects.filter(user_email=username) """List repo groups""" # Get groups this repo is shared. if request.user.org: org_id = request.user.org['org_id'] repo_shared_groups = get_org_groups_by_repo(org_id, repo_id) else: repo_shared_groups = get_shared_groups_by_repo(repo_id) # Filter out groups that user in joined. groups = [ x for x in repo_shared_groups if is_group_user(x.id, username)] if len(groups) > 1: ctx = {} ctx['groups'] = groups repogrp_str = render_to_string("snippets/repo_group_list.html", ctx) else: repogrp_str = '' file_path_hash = md5_constructor(urllib2.quote(path.encode('utf-8'))).hexdigest()[:12] # fetch file contributors and latest contributor contributors, last_modified, last_commit_id = get_file_contributors(repo_id, path.encode('utf-8'), file_path_hash, obj_id) latest_contributor = contributors[0] if contributors else None # check whether file is starred is_starred = False org_id = -1 if request.user.org: org_id = request.user.org['org_id'] is_starred = is_file_starred(username, repo.id, path.encode('utf-8'), org_id) template = 'view_file_%s.html' % ret_dict['filetype'].lower() search_repo_id = None if not repo.encrypted: search_repo_id = repo.id return render_to_response(template, { 'repo': repo, 'obj_id': obj_id, 'filename': u_filename, 'path': path, 'zipped': zipped, 'current_commit': current_commit, 'fileext': fileext, 'raw_path': raw_path, 'fileshare': fileshare, 'protocol': http_or_https, 'domain': domain, 'file_shared_link': file_shared_link, 'contacts': contacts, 'err': ret_dict['err'], 'file_content': ret_dict['file_content'], 'file_enc': ret_dict['file_enc'], 'encoding': ret_dict['encoding'], 'file_encoding_list':ret_dict['file_encoding_list'], 'html_exists': ret_dict['html_exists'], 'html_detail': ret_dict.get('html_detail', {}), 'filetype': ret_dict['filetype'], "applet_root": get_ccnetapplet_root(), 'groups': groups, 'use_pdfjs':USE_PDFJS, 'contributors': contributors, 'latest_contributor': latest_contributor, 'last_modified': last_modified, 'last_commit_id': last_commit_id, 'repo_group_str': repogrp_str, 'is_starred': is_starred, 'user_perm': user_perm, 'img_prev': img_prev, 'img_next': img_next, 'search_repo_id': search_repo_id, }, context_instance=RequestContext(request))
def view_file(request, repo_id): """ Steps to view file: 1. Get repo id and file path. 2. Check user's permission. 3. Check whether this file can be viewed online. 4.1 Get file content if file is text file. 4.2 Prepare flash if file is document. 4.3 Prepare or use pdfjs if file is pdf. 4.4 Other file return it's raw path. """ username = request.user.username # check arguments repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get('p', '/') obj_id = get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) # construct some varibles u_filename = os.path.basename(path) filename_utf8 = urllib2.quote(u_filename.encode('utf-8')) current_commit = get_commits(repo_id, 0, 1)[0] # Check whether user has permission to view file and get file raw path, # render error page if permission is deny. raw_path, user_perm = get_file_view_path_and_perm(request, repo_id, obj_id, u_filename) if not user_perm: return render_permission_error(request, _(u'Unable to view file')) # get file type and extension filetype, fileext = get_file_type_and_ext(u_filename) img_prev = None img_next = None ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} # Check file size fsize = get_file_size(obj_id) if fsize > FILE_PREVIEW_MAX_SIZE: err = _(u'File size surpasses %s, can not be opened online.') % \ filesizeformat(FILE_PREVIEW_MAX_SIZE) ret_dict['err'] = err elif filetype in (DOCUMENT, PDF) and fsize > OFFICE_PREVIEW_MAX_SIZE: err = _(u'File size surpasses %s, can not be opened online.') % \ filesizeformat(OFFICE_PREVIEW_MAX_SIZE) ret_dict['err'] = err else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, raw_path, ret_dict) if filetype == MARKDOWN: c = ret_dict['file_content'] ret_dict['file_content'] = convert_md_link(c, repo_id, username) elif filetype == DOCUMENT: handle_document(raw_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(raw_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: parent_dir = os.path.dirname(path) dirs = list_dir_by_path(current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == 'Image': img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y : cmp(x.lower(), y.lower())) cur_img_index = img_list.index(u_filename) if cur_img_index != 0: img_prev = os.path.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = os.path.join(parent_dir, img_list[cur_img_index + 1]) else: pass # generate file path navigator zipped = gen_path_link(path, repo.name) # file shared link l = FileShare.objects.filter(repo_id=repo_id).filter( username=username).filter(path=path) fileshare = l[0] if len(l) > 0 else None http_or_https = request.is_secure() and 'https' or 'http' domain = RequestSite(request).domain if fileshare: file_shared_link = gen_shared_link(request, fileshare.token, 'f') else: file_shared_link = '' # my contacts used in shared link autocomplete contacts = Contact.objects.filter(user_email=username) """List repo groups""" # Get groups this repo is shared. if request.user.org: org_id = request.user.org['org_id'] repo_shared_groups = get_org_groups_by_repo(org_id, repo_id) else: repo_shared_groups = get_shared_groups_by_repo(repo_id) # Filter out groups that user in joined. groups = [ x for x in repo_shared_groups if is_group_user(x.id, username)] if len(groups) > 1: ctx = {} ctx['groups'] = groups repogrp_str = render_to_string("snippets/repo_group_list.html", ctx) else: repogrp_str = '' file_path_hash = md5_constructor(urllib2.quote(path.encode('utf-8'))).hexdigest()[:12] # fetch file contributors and latest contributor contributors, last_modified, last_commit_id = get_file_contributors(repo_id, path.encode('utf-8'), file_path_hash, obj_id) latest_contributor = contributors[0] if contributors else None # check whether file is starred is_starred = False org_id = -1 if request.user.org: org_id = request.user.org['org_id'] is_starred = is_file_starred(username, repo.id, path.encode('utf-8'), org_id) template = 'view_file_%s.html' % ret_dict['filetype'].lower() search_repo_id = None if not repo.encrypted: search_repo_id = repo.id return render_to_response(template, { 'repo': repo, 'obj_id': obj_id, 'filename': u_filename, 'path': path, 'zipped': zipped, 'current_commit': current_commit, 'fileext': fileext, 'raw_path': raw_path, 'fileshare': fileshare, 'protocol': http_or_https, 'domain': domain, 'file_shared_link': file_shared_link, 'contacts': contacts, 'err': ret_dict['err'], 'file_content': ret_dict['file_content'], 'file_enc': ret_dict['file_enc'], 'encoding': ret_dict['encoding'], 'file_encoding_list':ret_dict['file_encoding_list'], 'html_exists': ret_dict['html_exists'], 'html_detail': ret_dict.get('html_detail', {}), 'filetype': ret_dict['filetype'], "applet_root": get_ccnetapplet_root(), 'groups': groups, 'use_pdfjs':USE_PDFJS, 'contributors': contributors, 'latest_contributor': latest_contributor, 'last_modified': last_modified, 'last_commit_id': last_commit_id, 'repo_group_str': repogrp_str, 'is_starred': is_starred, 'user_perm': user_perm, 'img_prev': img_prev, 'img_next': img_next, 'search_repo_id': search_repo_id, }, context_instance=RequestContext(request))
def view_file(request, repo_id): """ Steps to view file: 1. Get repo id and file path. 2. Check user's permission. 3. Check whether this file can be viewed online. 4.1 Get file content if file is text file. 4.2 Prepare flash if file is document. 4.3 Prepare or use pdfjs if file is pdf. 4.4 Other file return it's raw path. """ username = request.user.username # check arguments repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get("p", "/").rstrip("/") obj_id = get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u"File does not exist")) # construct some varibles u_filename = os.path.basename(path) current_commit = get_commits(repo_id, 0, 1)[0] # Check whether user has permission to view file and get file raw path, # render error page if permission deny. raw_path, inner_path, user_perm = get_file_view_path_and_perm(request, repo_id, obj_id, path) if not user_perm: return render_permission_error(request, _(u"Unable to view file")) # check if the user is the owner or not, for 'private share' if is_org_context(request): repo_owner = seafile_api.get_org_repo_owner(repo.id) is_repo_owner = True if repo_owner == username else False else: is_repo_owner = seafile_api.is_repo_owner(username, repo.id) # get file type and extension filetype, fileext = get_file_type_and_ext(u_filename) img_prev = None img_next = None ret_dict = { "err": "", "file_content": "", "encoding": "", "file_enc": "", "file_encoding_list": [], "html_exists": False, "filetype": filetype, } fsize = get_file_size(repo.store_id, repo.version, obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: ret_dict["err"] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) if filetype == MARKDOWN: c = ret_dict["file_content"] ret_dict["file_content"] = convert_md_link(c, repo_id, username) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == OPENDOCUMENT: if fsize == 0: ret_dict["err"] = _(u"Invalid file format.") elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: parent_dir = os.path.dirname(path) dirs = seafile_api.list_dir_by_commit_and_path(current_commit.repo_id, current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == "Image": img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y: cmp(x.lower(), y.lower())) cur_img_index = img_list.index(u_filename) if cur_img_index != 0: img_prev = posixpath.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = posixpath.join(parent_dir, img_list[cur_img_index + 1]) else: pass # generate file path navigator zipped = gen_path_link(path, repo.name) # file shared link l = FileShare.objects.filter(repo_id=repo_id).filter(username=username).filter(path=path) fileshare = l[0] if len(l) > 0 else None http_or_https = request.is_secure() and "https" or "http" domain = RequestSite(request).domain if fileshare: file_shared_link = gen_file_share_link(fileshare.token) else: file_shared_link = "" for g in request.user.joined_groups: g.avatar = grp_avatar(g.id, 20) """List repo groups""" # Get groups this repo is shared. if request.user.org: org_id = request.user.org.org_id repo_shared_groups = get_org_groups_by_repo(org_id, repo_id) else: repo_shared_groups = get_shared_groups_by_repo(repo_id) # Filter out groups that user in joined. groups = [x for x in repo_shared_groups if is_group_user(x.id, username)] if len(groups) > 1: ctx = {} ctx["groups"] = groups repogrp_str = render_to_string("snippets/repo_group_list.html", ctx) else: repogrp_str = "" file_path_hash = hashlib.md5(urllib2.quote(path.encode("utf-8"))).hexdigest()[:12] # fetch file contributors and latest contributor contributors, last_modified, last_commit_id = FileContributors.objects.get_file_contributors( repo_id, path.encode("utf-8"), file_path_hash, obj_id ) latest_contributor = contributors[0] if contributors else None # check whether file is starred is_starred = False org_id = -1 if request.user.org: org_id = request.user.org.org_id is_starred = is_file_starred(username, repo.id, path.encode("utf-8"), org_id) template = "view_file_%s.html" % ret_dict["filetype"].lower() return render_to_response( template, { "repo": repo, "is_repo_owner": is_repo_owner, "obj_id": obj_id, "filename": u_filename, "path": path, "zipped": zipped, "current_commit": current_commit, "fileext": fileext, "raw_path": raw_path, "fileshare": fileshare, "protocol": http_or_https, "domain": domain, "file_shared_link": file_shared_link, "err": ret_dict["err"], "file_content": ret_dict["file_content"], "file_enc": ret_dict["file_enc"], "encoding": ret_dict["encoding"], "file_encoding_list": ret_dict["file_encoding_list"], "html_exists": ret_dict["html_exists"], "html_detail": ret_dict.get("html_detail", {}), "filetype": ret_dict["filetype"], "groups": groups, "use_pdfjs": USE_PDFJS, "contributors": contributors, "latest_contributor": latest_contributor, "last_modified": last_modified, "last_commit_id": last_commit_id, "repo_group_str": repogrp_str, "is_starred": is_starred, "user_perm": user_perm, "img_prev": img_prev, "img_next": img_next, "highlight_keyword": settings.HIGHLIGHT_KEYWORD, }, context_instance=RequestContext(request), )
def group_wiki(request, group, page_name="home"): username = request.user.username # get available modules(wiki, etc) mods_available = get_available_mods_by_group(group.id) mods_enabled = get_enabled_mods_by_group(group.id) wiki_exists = True try: content, repo, dirent = get_group_wiki_page(username, group, page_name) except WikiDoesNotExist: wiki_exists = False group_repos = get_group_repos(group.id, username) group_repos = [r for r in group_repos if not r.encrypted] return render_to_response( "group/group_wiki.html", { "group": group, "is_staff": group.is_staff, "wiki_exists": wiki_exists, "mods_enabled": mods_enabled, "mods_available": mods_available, "group_repos": group_repos, }, context_instance=RequestContext(request), ) except WikiPageMissing: """create that page for user if he/she is a group member""" if not is_group_user(group.id, username): raise Http404 repo = get_group_wiki_repo(group, username) # No need to check whether repo is none, since repo is already created filename = page_name_to_file_name(clean_page_name(page_name)) if not post_empty_file(repo.id, "/", filename, username): return render_error(request, _("Failed to create wiki page. Please retry later.")) return HttpResponseRedirect(reverse("group_wiki", args=[group.id, page_name])) else: url_prefix = reverse("group_wiki", args=[group.id]) # fetch file modified time and modifier path = "/" + dirent.obj_name try: dirent = seafile_api.get_dirent_by_path(repo.id, path) if dirent: latest_contributor, last_modified = dirent.modifier, dirent.mtime else: latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 repo_perm = seafile_api.check_repo_access_permission(repo.id, username) wiki_index_exists = True index_pagename = "index" index_content = None try: index_content, index_repo, index_dirent = get_group_wiki_page(username, group, index_pagename) except (WikiDoesNotExist, WikiPageMissing) as e: wiki_index_exists = False return render_to_response( "group/group_wiki.html", { "group": group, "is_staff": group.is_staff, "wiki_exists": wiki_exists, "content": content, "page": os.path.splitext(dirent.obj_name)[0], "last_modified": last_modified, "latest_contributor": latest_contributor or _("Unknown"), "path": path, "repo_id": repo.id, "search_repo_id": repo.id, "search_wiki": True, "mods_enabled": mods_enabled, "mods_available": mods_available, "repo_perm": repo_perm, "wiki_index_exists": wiki_index_exists, "index_content": index_content, }, context_instance=RequestContext(request), )
def post(self, request, group_id): """ Bulk add group members. """ username = request.user.username try: if not is_group_admin_or_owner(group_id, username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) emails_str = request.data.get('emails', '') emails_list = string2list(emails_str) emails_list = [x.lower() for x in emails_list] result = {} result['failed'] = [] result['success'] = [] emails_need_add = [] org_id = None if is_org_context(request): org_id = request.user.org.org_id for email in emails_list: try: User.objects.get(email=email) except User.DoesNotExist: result['failed'].append({ 'email': email, 'error_msg': 'User %s not found.' % email }) continue if seaserv.is_group_user(group_id, email): result['failed'].append({ 'email': email, 'error_msg': _(u'User %s is already a group member.') % email }) continue # Can only invite organization users to group if org_id and not \ seaserv.ccnet_threaded_rpc.org_user_exists(org_id, email): result['failed'].append({ 'email': email, 'error_msg': _(u'User %s not found in organization.') % email }) continue emails_need_add.append(email) # Add user to group. for email in emails_need_add: try: seaserv.ccnet_threaded_rpc.group_add_member( group_id, username, email) member_info = get_group_member_info(request, group_id, email) result['success'].append(member_info) except SearpcError as e: logger.error(e) result['failed'].append({ 'email': email, 'error_msg': 'Internal Server Error' }) return Response(result)
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 managers = [] common_members = [] for member in members: if member.is_staff == 1: managers.append(member) else: common_members.append(member) 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) for repo in repos: repo.user_perm = check_permission(repo.props.id, request.user.username) """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_info.html", { "managers": managers, "common_members": common_members, "members": members, "repos": repos, "group_id": group_id, "group" : group, "is_staff": is_staff, "is_join": joined, "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, 'create_shared_repo': True, 'contacts': contacts, 'group_members_default_display': GROUP_MEMBERS_DEFAULT_DISPLAY, }, context_instance=RequestContext(request));
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 """group messages""" # Show 15 group messages per page. paginator = Paginator(GroupMessage.objects.filter( group_id=group_id).order_by('-timestamp'), 15) # Make sure page request is an int. If not, deliver first page. try: page = int(request.GET.get('page', '1')) except ValueError: page = 1 # If page request (9999) is out of range, deliver last page of results. try: group_msgs = paginator.page(page) except (EmptyPage, InvalidPage): group_msgs = paginator.page(paginator.num_pages) group_msgs.page_range = paginator.get_page_range(group_msgs.number) # Force evaluate queryset to fix some database error for mysql. group_msgs.object_list = list(group_msgs.object_list) attachments = MessageAttachment.objects.filter(group_message__in=group_msgs.object_list) msg_replies = MessageReply.objects.filter(reply_to__in=group_msgs.object_list) reply_to_list = [ r.reply_to_id for r in msg_replies ] for msg in group_msgs.object_list: 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 return render_to_response("group/group_discuss.html", { "members": members, "group_id": group_id, "group" : group, "is_staff": is_staff, "group_msgs": group_msgs, "form": form, 'group_members_default_display': GROUP_MEMBERS_DEFAULT_DISPLAY, }, context_instance=RequestContext(request));
def put(self, request, group_id): """ Rename, transfer a specific group """ group = seaserv.get_group(group_id) username = request.user.username new_group_name = request.data.get('name', None) if new_group_name: # rename a group # Check whether group name is validate. if not validate_group_name(new_group_name): error_msg = _( u'Group name can only contain letters, numbers, blank, hyphen or underscore' ) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # Check whether group name is duplicated. if check_group_name_conflict(request, new_group_name): error_msg = _(u'There is already a group with that name.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: seaserv.ccnet_threaded_rpc.set_group_name( group_id, new_group_name) except SearpcError as e: logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) new_creator = request.data.get('creator', None) if new_creator: # transfer a group if not is_valid_username(new_creator): error_msg = _('Creator %s is not valid.') % new_creator return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if new_creator == group.creator_name: error_msg = _('%s is already group owner') % new_creator return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: if not seaserv.is_group_user(group_id, new_creator): seaserv.ccnet_threaded_rpc.group_add_member( group_id, username, new_creator) if not seaserv.check_group_staff(group_id, new_creator): seaserv.ccnet_threaded_rpc.group_set_admin( group_id, new_creator) seaserv.ccnet_threaded_rpc.set_group_creator( group_id, new_creator) except SearpcError as e: logger.error(e) error_msg = _(u'Internal Server Error') return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # get new info of this group group_info = get_group_info(request, group_id, GROUP_AVATAR_DEFAULT_SIZE) return Response(group_info)
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));
def group_recommend(request): """ Get or post file/directory discussions to a group. """ content_type = 'application/json; charset=utf-8' result = {} if request.method == 'POST': 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 is a group_id list, e.g. [u'1', u'7'] groups = request.POST.getlist('groups') username = request.user.username groups_not_in = [] groups_posted_to = [] for group_id in groups: # Check group id format try: group_id = int(group_id) except ValueError: result['error'] = _(u'Error: wrong group id') return HttpResponse(json.dumps(result), status=400, content_type=content_type) group = get_group(group_id) if not group: result['error'] = _(u'Error: the group does not exist.') return HttpResponse(json.dumps(result), status=400, content_type=content_type) # TODO: Check whether repo is in the group and Im in the group if not is_group_user(group_id, username): groups_not_in.append(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=username, message=message) # save attachment ma = MessageAttachment(group_message=gm, repo_id=repo_id, attach_type=attach_type, path=path, src='recommend') ma.save() # save discussion fd = FileDiscuss(group_message=gm, repo_id=repo_id, path=path) fd.save() group_url = reverse('group_discuss', args=[group_id]) groups_posted_to.append(u'<a href="%(url)s" target="_blank">%(name)s</a>' % \ {'url':group_url, 'name':group.group_name}) if len(groups_posted_to) > 0: result['success'] = _(u'Successfully posted to %(groups)s.') % {'groups': ', '.join(groups_posted_to)} if len(groups_not_in) > 0: result['error'] = _(u'Error: you are not in group %s.') % (', '.join(groups_not_in)) else: result['error'] = str(form.errors) return HttpResponse(json.dumps(result), status=400, content_type=content_type) # request.method == 'GET' else: repo_id = request.GET.get('repo_id') path = request.GET.get('path', None) repo = get_repo(repo_id) if not repo: result['error'] = _(u'Error: the library does not exist.') return HttpResponse(json.dumps(result), status=400, content_type=content_type) if path is None: result['error'] = _(u'Error: no path.') return HttpResponse(json.dumps(result), status=400, content_type=content_type) # get discussions & replies path_hash = calc_file_path_hash(path) discussions = FileDiscuss.objects.filter(path_hash=path_hash, repo_id=repo_id) msg_ids = [ e.group_message_id for e in discussions ] grp_msgs = GroupMessage.objects.filter(id__in=msg_ids).order_by('-timestamp') msg_replies = MessageReply.objects.filter(reply_to__in=grp_msgs) for msg in grp_msgs: msg.replies = [] for reply in msg_replies: if msg.id == reply.reply_to_id: msg.replies.append(reply) msg.reply_cnt = len(msg.replies) msg.replies = msg.replies[-3:] ctx = {} ctx['messages'] = grp_msgs html = render_to_string("group/discussion_list.html", ctx) result['html'] = html return HttpResponse(json.dumps(result), content_type=content_type)