diff --git a/seahub/api2/endpoints/wikis.py b/seahub/api2/endpoints/wikis.py index e548832d5a..d934c5a7ea 100644 --- a/seahub/api2/endpoints/wikis.py +++ b/seahub/api2/endpoints/wikis.py @@ -62,7 +62,8 @@ class WikisView(APIView): username = request.user.username try: - wiki = Wiki.objects.add(name, permission, username, org_id) + wiki = Wiki.objects.add(name, username, permission=permission, + org_id=org_id) except DuplicateWikiNameError: result['error'] = _('%s is taken by others, please try another name.') % name return HttpResponse(json.dumps(result), status=400, @@ -95,4 +96,4 @@ class WikiView(APIView): Wiki.objects.filter(slug=slug).delete() - return Response({"success": True}) + return Response() diff --git a/seahub/urls.py b/seahub/urls.py index 6e4de0e87d..c6851afacb 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -283,7 +283,7 @@ urlpatterns = patterns( ## user::wiki url(r'^api/v2.1/wikis/$', WikisView.as_view(), name='api-v2.1-wikis'), - url(r'^api/v2.1/wikis/(?P[^/]+)/$', WikiView.as_view(), name='api-v2.1-wikis'), + url(r'^api/v2.1/wikis/(?P[^/]+)/$', WikiView.as_view(), name='api-v2.1-wiki'), ## admin::sysinfo url(r'^api/v2.1/admin/sysinfo/$', SysInfo.as_view(), name='api-v2.1-sysinfo'), diff --git a/seahub/wiki/management/__init__.py b/seahub/wiki/management/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/seahub/wiki/management/commands/__init__.py b/seahub/wiki/management/commands/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/seahub/wiki/management/commands/migrate_personal_wiki.py b/seahub/wiki/management/commands/migrate_personal_wiki.py new file mode 100644 index 0000000000..a1802704ae --- /dev/null +++ b/seahub/wiki/management/commands/migrate_personal_wiki.py @@ -0,0 +1,27 @@ +# Copyright (c) 2012-2016 Seafile Ltd. +# encoding: utf-8 +import os +import logging + +from django.core.management.base import BaseCommand + +from seahub.wiki.models import PersonalWiki, Wiki, DuplicateWikiNameError + +# Get an instance of a logger +logger = logging.getLogger(__name__) + +class Command(BaseCommand): + help = 'Migrate records in wiki_personal_wiki table to wiki_wiki table.' + label = "wiki_migrate_personal_wiki" + + def handle(self, *args, **options): + print 'Start to migrate...' + for r in PersonalWiki.objects.all(): + try: + Wiki.objects.add(wiki_name=r.username.split('@')[0], + username=r.username, repo_id=r.repo_id) + except DuplicateWikiNameError: + print 'Multiple personal wiki records found, user: %s, repo_id: %s. Skip.' % (r.username, r.repo_id) + continue + + print 'Done.' diff --git a/seahub/wiki/models.py b/seahub/wiki/models.py index 41e469ecec..b9f7bb2f13 100644 --- a/seahub/wiki/models.py +++ b/seahub/wiki/models.py @@ -59,7 +59,8 @@ class DuplicateWikiNameError(Exception): class WikiManager(models.Manager): - def add(self, wiki_name, username, permission='private', org_id=-1): + def add(self, wiki_name, username, permission='private', repo_id=None, + org_id=-1): if not permission: permission = 'private' @@ -68,18 +69,20 @@ class WikiManager(models.Manager): if self.filter(slug=slug).count() > 0: raise DuplicateWikiNameError - if org_id > 0: - repo_id = seafile_api.create_org_repo(wiki_name, '', username, - passwd=None, org_id=org_id) - else: - repo_id = seafile_api.create_repo(wiki_name, '', username, - passwd=None) + if repo_id is None: # create new repo to store the wiki pages + if org_id > 0: + repo_id = seafile_api.create_org_repo(wiki_name, '', username, + passwd=None, org_id=org_id) + else: + repo_id = seafile_api.create_repo(wiki_name, '', username, + passwd=None) wiki = self.model(username=username, name=wiki_name, slug=slug, repo_id=repo_id, permission=permission) wiki.save(using=self._db) return wiki + class Wiki(models.Model): """New wiki model to enable a user has multiple wikis and replace personal wiki. @@ -108,12 +111,22 @@ class Wiki(models.Model): @property def updated_at(self): + assert len(self.repo_id) == 36 + repo = seafile_api.get_repo(self.repo_id) if not repo: return '' return repo.last_modify + def has_read_perm(self, user): + if self.permisson == 'public': + return True + elif self.permission == 'login-user': + return True if user.is_authenticated() else False + else: # private + return True if user.username == self.username else False + def to_dict(self): return { 'id': self.pk, diff --git a/seahub/wiki/views.py b/seahub/wiki/views.py index 94cbd282f0..667ffafef3 100644 --- a/seahub/wiki/views.py +++ b/seahub/wiki/views.py @@ -1,12 +1,13 @@ import os import logging +import urllib2 import seaserv from seaserv import seafile_api from django.core.urlresolvers import reverse from django.http import HttpResponse, HttpResponseBadRequest, Http404, \ HttpResponseRedirect -from django.shortcuts import render_to_response +from django.shortcuts import render_to_response, get_object_or_404 from django.template import Context, loader, RequestContext from django.utils.translation import ugettext as _ @@ -16,18 +17,92 @@ from pysearpc import SearpcError from seahub.auth.decorators import login_required from seahub.base.decorators import user_mods_check -from seahub.wiki.models import PersonalWiki, WikiDoesNotExist, WikiPageMissing +from seahub.wiki.models import Wiki, WikiDoesNotExist, WikiPageMissing from seahub.wiki import get_personal_wiki_page, get_personal_wiki_repo, \ convert_wiki_link, get_wiki_pages from seahub.wiki.forms import WikiCreateForm, WikiNewPageForm -from seahub.wiki.utils import clean_page_name, page_name_to_file_name +from seahub.wiki.utils import (clean_page_name, page_name_to_file_name, + get_wiki_dirent, get_inner_file_url) from seahub.utils import render_error from seahub.views import check_folder_permission # Get an instance of a logger logger = logging.getLogger(__name__) - -@login_required def slug(request, slug, page_name="home"): - assert False, 'TODO' + """Show wiki page. + """ + username = request.user.username + # get or 404 + wiki = get_object_or_404(Wiki, slug=slug) + + # perm check + if not wiki.has_read_perm(request.user): + raise Http404 + + # show contents + if request.cloud_mode and request.user.org is not None: + org_id = request.user.org.org_id + joined_groups = seaserv.get_org_groups_by_user(org_id, username) + else: + joined_groups = seaserv.get_personal_groups_by_user(username) + + if joined_groups: + joined_groups.sort(lambda x, y: cmp(x.group_name.lower(), y.group_name.lower())) + + wiki_exists = True # TODO: remove + # 1. get wiki repo + repo = seafile_api.get_repo(wiki.repo_id) + if not repo: + assert False, "TODO" + + # 2. get wiki repo content, ref: wiki/utils.py:get_personal_wiki_page + try: + wiki_dirent = get_wiki_dirent(repo.id, page_name) + except WikiPageMissing: + # create missing page... + filename = page_name_to_file_name(clean_page_name(page_name)) + if not seaserv.post_empty_file(repo.id, "/", filename, username): + return render_error(request, _("Failed to create wiki page. Please retry later.")) + # ...and redirect + return HttpResponseRedirect(reverse('wiki:slug', args=[slug, page_name])) + + url = get_inner_file_url(repo, wiki_dirent.obj_id, wiki_dirent.obj_name) + file_response = urllib2.urlopen(url) + content = file_response.read() + + # fetch file modified time and modifier + path = '/' + wiki_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 + + wiki_index_exists = True + index_pagename = 'index' + index_content = None + try: + index_content, index_repo, index_dirent = get_personal_wiki_page(username, index_pagename) + except (WikiDoesNotExist, WikiPageMissing): + wiki_index_exists = False + + return render_to_response( + "wiki/personal_wiki.html", { + "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, + "wiki_index_exists": wiki_index_exists, + "index_content": index_content, + "grps": joined_groups, + }, context_instance=RequestContext(request)) diff --git a/tests/api/endpoints/test_wikis.py b/tests/api/endpoints/test_wikis.py new file mode 100644 index 0000000000..98f3c04828 --- /dev/null +++ b/tests/api/endpoints/test_wikis.py @@ -0,0 +1,59 @@ +import json + +from django.core.urlresolvers import reverse +import seaserv +from seaserv import seafile_api, ccnet_api + +from seahub.wiki.models import Wiki +from seahub.test_utils import BaseTestCase + + +class WikisViewTest(BaseTestCase): + def setUp(self): + self.url = reverse('api-v2.1-wikis') + self.login_as(self.user) + + def test_can_list(self): + resp = self.client.get(self.url) + self.assertEqual(200, resp.status_code) + + json_resp = json.loads(resp.content) + assert len(json_resp['data']) == 0 + + wiki = Wiki.objects.add('test wiki', self.user.username, + repo_id=self.repo.id) + resp = self.client.get(self.url) + self.assertEqual(200, resp.status_code) + + json_resp = json.loads(resp.content) + assert len(json_resp['data']) == 1 + assert json_resp['data'][0]['name'] == wiki.name + assert 'wikis/test-wiki' in json_resp['data'][0]['link'] + + def test_can_add(self): + assert len(Wiki.objects.all()) == 0 + + resp = self.client.post(self.url, { + 'name': 'test wiki', + 'permission': 'private', + }) + self.assertEqual(200, resp.status_code) + + assert len(Wiki.objects.all()) == 1 + + +class WikiViewTest(BaseTestCase): + def setUp(self): + wiki = Wiki.objects.add('test wiki', self.user.username, + repo_id=self.repo.id) + + self.url = reverse('api-v2.1-wiki', args=[wiki.slug]) + self.login_as(self.user) + + def test_can_delete(self): + assert len(Wiki.objects.all()) == 1 + + resp = self.client.delete(self.url) + self.assertEqual(200, resp.status_code) + + assert len(Wiki.objects.all()) == 0