1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-11 03:42:16 +00:00

update publish draft api

This commit is contained in:
lian 2019-05-31 15:57:32 +08:00
parent ed28451ed7
commit c75c4d76b4
3 changed files with 101 additions and 110 deletions

View File

@ -1,28 +1,23 @@
# Copyright (c) 2012-2016 Seafile Ltd. # Copyright (c) 2012-2016 Seafile Ltd.
import os
import logging import logging
import posixpath
from rest_framework import status from rest_framework import status
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from seaserv import seafile_api, edit_repo from seaserv import seafile_api
from pysearpc import SearpcError
from django.core.urlresolvers import reverse
from django.db import IntegrityError
from django.db.models import Count
from django.http import HttpResponse
from django.utils.translation import ugettext as _
from seahub.api2.authentication import TokenAuthentication from seahub.api2.authentication import TokenAuthentication
from seahub.api2.endpoints.utils import add_org_context from seahub.api2.endpoints.utils import add_org_context
from seahub.api2.throttling import UserRateThrottle from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error from seahub.api2.utils import api_error
from seahub.constants import PERMISSION_READ_WRITE from seahub.constants import PERMISSION_READ_WRITE
from seahub.drafts.models import Draft, DraftFileExist, DraftFileConflict from seahub.drafts.models import Draft, DraftFileExist
from seahub.tags.models import FileUUIDMap from seahub.tags.models import FileUUIDMap
from seahub.views import check_folder_permission from seahub.views import check_folder_permission
from seahub.utils import gen_file_get_url
from seahub.drafts.utils import send_draft_publish_msg from seahub.drafts.utils import send_draft_publish_msg
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -53,29 +48,45 @@ class DraftsView(APIView):
def post(self, request, org_id, format=None): def post(self, request, org_id, format=None):
"""Create a file draft if the user has read-write permission to the origin file """Create a file draft if the user has read-write permission to the origin file
""" """
repo_id = request.POST.get('repo_id', '')
file_path = request.POST.get('file_path', '')
# argument check
repo_id = request.data.get('repo_id', '')
if not repo_id:
error_msg = 'repo_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
file_path = request.data.get('file_path', '')
if not file_path:
error_msg = 'file_path invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id) repo = seafile_api.get_repo(repo_id)
if not repo: if not repo:
error_msg = 'Library %s not found.' % repo_id error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# perm check file_id = seafile_api.get_file_id_by_path(repo_id, file_path)
perm = check_folder_permission(request, repo.id, file_path) if not file_id:
error_msg = 'File %s not found.' % file_path
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
perm = check_folder_permission(request, repo_id, file_path)
if perm != PERMISSION_READ_WRITE: if perm != PERMISSION_READ_WRITE:
error_msg = 'Permission denied.' error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
file_id = seafile_api.get_file_id_by_path(repo.id, file_path)
if not file_id:
return api_error(status.HTTP_404_NOT_FOUND,
"File %s not found" % file_path)
username = request.user.username username = request.user.username
try:
d = Draft.objects.add(username, repo, file_path, file_id)
# create drafts dir if does not exist
draft_dir_id = seafile_api.get_dir_id_by_path(repo_id, '/Drafts')
if draft_dir_id is None:
seafile_api.post_dir(repo_id, '/', 'Drafts', username)
# create draft
try:
d = Draft.objects.add(username, repo, file_path, file_id=file_id)
return Response(d.to_dict()) return Response(d.to_dict())
except DraftFileExist: except DraftFileExist:
return api_error(status.HTTP_409_CONFLICT, 'Draft already exists.') return api_error(status.HTTP_409_CONFLICT, 'Draft already exists.')
@ -92,39 +103,77 @@ class DraftView(APIView):
def put(self, request, pk, format=None): def put(self, request, pk, format=None):
"""Publish a draft if the user has read-write permission to the origin file """Publish a draft if the user has read-write permission to the origin file
"""
op = request.data.get('operation', '')
if op != 'publish':
return api_error(status.HTTP_400_BAD_REQUEST,
'Operation invalid.')
Process:
1. Overwrite the origin file with the draft file.
If origin file's parent folder does NOT exist, move draft file to library's root folder.
2. Update draft database info.
3. Send draft file publish msg.
"""
# resource check
try: try:
d = Draft.objects.get(pk=pk) draft = Draft.objects.get(pk=pk)
except Draft.DoesNotExist: except Draft.DoesNotExist:
return api_error(status.HTTP_404_NOT_FOUND, return api_error(status.HTTP_404_NOT_FOUND,
'Draft %s not found.' % pk) 'Draft %s not found.' % pk)
# perm check repo_id = draft.origin_repo_id
repo_id = d.origin_repo_id repo = seafile_api.get_repo(repo_id)
uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(d.origin_file_uuid) if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not uuid: # permission check
return api_error(status.HTTP_404_NOT_FOUND, 'Origin file uuid not found.') origin_file_uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(draft.origin_file_uuid)
if origin_file_uuid and seafile_api.get_dir_id_by_path(repo_id,
origin_file_uuid.parent_path):
permission = check_folder_permission(request, repo_id, origin_file_uuid.parent_path)
else:
permission = check_folder_permission(request, repo_id, '/')
perm = check_folder_permission(request, repo_id, uuid.parent_path) if permission != PERMISSION_READ_WRITE:
if perm != PERMISSION_READ_WRITE:
error_msg = 'Permission denied.' error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg) return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# 1. Overwrite the origin file with the draft file.
# If origin file's parent folder does NOT exist, move draft file to library's root folder.
# get origin file info
origin_file_parent_path = origin_file_uuid.parent_path if origin_file_uuid else ''
# check if origin file's parent folder exists
if not seafile_api.get_dir_id_by_path(repo_id, origin_file_parent_path):
dst_parent_path = '/'
else:
dst_parent_path = origin_file_parent_path
# get draft file info
draft_file_name = os.path.basename(draft.draft_file_path)
draft_file_parent_path = os.path.dirname(draft.draft_file_path)
f = os.path.splitext(draft_file_name)[0][:-7]
file_type = os.path.splitext(draft_file_name)[-1]
dst_file_name = f + file_type
# move draft file
username = request.user.username username = request.user.username
seafile_api.move_file(
repo_id, draft_file_parent_path, draft_file_name,
repo_id, dst_parent_path, dst_file_name,
replace=1, username=username, need_progress=0, synchronous=1
)
try: try:
published_file_path = d.publish(operator=username) # 2. Update draft database info.
send_draft_publish_msg(d, username, published_file_path) dst_file_path = posixpath.join(dst_parent_path, dst_file_name)
return Response({'published_file_path': published_file_path}) dst_file_id = seafile_api.get_file_id_by_path(repo_id, dst_file_path)
except DraftFileConflict: draft.update(dst_file_id)
return api_error(status.HTTP_409_CONFLICT,
'There is a conflict between the draft and the original file') # 3. Send draft file publish msg.
send_draft_publish_msg(draft, username, dst_file_path)
return Response({'published_file_path': dst_file_path})
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'

View File

@ -11,9 +11,9 @@ from seahub.base.fields import LowerCaseCharField
from seahub.base.models import TimestampedModel from seahub.base.models import TimestampedModel
from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email
from seahub.tags.models import FileUUIDMap from seahub.tags.models import FileUUIDMap
from seahub.utils import normalize_file_path, EMPTY_SHA1 from seahub.utils import normalize_file_path
from seahub.utils.timeutils import datetime_to_isoformat_timestr from seahub.utils.timeutils import datetime_to_isoformat_timestr
from .utils import create_user_draft_repo, get_draft_file_name from .utils import get_draft_file_name
class DraftFileExist(Exception): class DraftFileExist(Exception):
@ -53,7 +53,7 @@ class DraftManager(models.Manager):
return drafts return drafts
def list_draft_by_username(self, username, status='open'): def list_draft_by_username(self, username, status='open'):
"""list all user drafts """list all user drafts
If with_reviews is true, return the draft associated review If with_reviews is true, return the draft associated review
""" """
repo_cache = {} repo_cache = {}
@ -70,7 +70,7 @@ class DraftManager(models.Manager):
return repo return repo
data = [] data = []
qs = self.filter(username=username, status='open') qs = self.filter(username=username, status=status)
for d in qs: for d in qs:
# If repo does not exist, no related items are displayed. # If repo does not exist, no related items are displayed.
@ -99,10 +99,6 @@ class DraftManager(models.Manager):
return data return data
def create_exist_file_draft(self, repo, username, file_uuid, file_path): def create_exist_file_draft(self, repo, username, file_uuid, file_path):
# create drafts dir if does not exist
draft_dir_id = seafile_api.get_dir_id_by_path(repo.id, '/Drafts')
if draft_dir_id is None:
seafile_api.post_dir(repo.id, '/', 'Drafts', username)
# check draft file does not exists and copy origin file content to # check draft file does not exists and copy origin file content to
# draft file # draft file
@ -146,10 +142,12 @@ class DraftManager(models.Manager):
return draft_file_path return draft_file_path
def add(self, username, repo, file_path, file_exist=True, file_id=None, org_id=-1, status='open'): def add(self, username, repo, file_path, file_exist=True, file_id=None, org_id=-1, status='open'):
file_path = normalize_file_path(file_path) file_path = normalize_file_path(file_path)
parent_path = os.path.dirname(file_path) parent_path = os.path.dirname(file_path)
filename = os.path.basename(file_path) filename = os.path.basename(file_path)
# origin file uuid # origin file uuid
file_uuid = FileUUIDMap.objects.get_or_create_fileuuidmap( file_uuid = FileUUIDMap.objects.get_or_create_fileuuidmap(
repo.id, parent_path, filename, is_dir=False) repo.id, parent_path, filename, is_dir=False)
@ -186,6 +184,11 @@ class Draft(TimestampedModel):
# class Meta: # class Meta:
# unique_together = (('username', 'draft_repo_id'), ) # unique_together = (('username', 'draft_repo_id'), )
def update(self, publish_file_version, status = 'published'):
self.publish_file_version = publish_file_version
self.status = status
self.save()
def delete(self, operator): def delete(self, operator):
draft_file_name = os.path.basename(self.draft_file_path) draft_file_name = os.path.basename(self.draft_file_path)
draft_file_path = os.path.dirname(self.draft_file_path) draft_file_path = os.path.dirname(self.draft_file_path)
@ -194,66 +197,6 @@ class Draft(TimestampedModel):
super(Draft, self).delete() super(Draft, self).delete()
def publish(self, operator):
# check whether origin file is updated
r_repo = seafile_api.get_repo(self.origin_repo_id)
if not r_repo:
raise DraftFileConflict
file_uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(self.origin_file_uuid)
if not file_uuid:
# TODO update error msg
raise DraftFileConflict
if file_uuid.parent_path == '/':
origin_file_path = file_uuid.parent_path + file_uuid.filename
else:
origin_file_path = file_uuid.parent_path + '/' + file_uuid.filename
file_id = seafile_api.get_file_id_by_path(self.origin_repo_id,
origin_file_path)
draft_file_name = os.path.basename(self.draft_file_path)
draft_file_path = os.path.dirname(self.draft_file_path)
file_name = file_uuid.filename
if file_id:
if file_id != self.origin_file_version and self.draft_file_path != origin_file_path:
raise DraftFileConflict
if self.draft_file_path == origin_file_path:
f = os.path.splitext(draft_file_name)[0][:-7]
file_type = os.path.splitext(draft_file_name)[-1]
file_name = f + file_type
# move draft file to origin file
seafile_api.move_file(
self.origin_repo_id, draft_file_path, draft_file_name,
self.origin_repo_id, file_uuid.parent_path,
file_name, replace=1,
username=operator, need_progress=0, synchronous=1
)
else:
# move draft file to origin file
seafile_api.move_file(
self.origin_repo_id, draft_file_path, draft_file_name,
self.origin_repo_id, file_uuid.parent_path,
file_name, replace=1,
username=operator, need_progress=0, synchronous=1
)
published_file_path = posixpath.join(file_uuid.parent_path, file_name)
# get draft published version
file_id = seafile_api.get_file_id_by_path(self.origin_repo_id, published_file_path)
self.publish_file_version = file_id
self.status = 'published'
self.save()
return published_file_path
def to_dict(self): def to_dict(self):
uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(self.origin_file_uuid) uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(self.origin_file_uuid)
file_path = posixpath.join(uuid.parent_path, uuid.filename) file_path = posixpath.join(uuid.parent_path, uuid.filename)

View File

@ -6,10 +6,9 @@ from django.shortcuts import render, get_object_or_404
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from seaserv import seafile_api from seaserv import seafile_api
from seahub.base.templatetags.seahub_tags import email2nickname
from seahub.auth.decorators import login_required from seahub.auth.decorators import login_required
from seahub.views import check_folder_permission from seahub.views import check_folder_permission
from seahub.utils import render_permission_error, render_error from seahub.utils import render_permission_error
from seahub.drafts.models import Draft from seahub.drafts.models import Draft
from seahub.api2.utils import user_to_dict from seahub.api2.utils import user_to_dict
from seahub.tags.models import FileUUIDMap from seahub.tags.models import FileUUIDMap