Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update #6931

Open
wants to merge 3 commits into
base: 11.0
Choose a base branch
from
Open

update #6931

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions seahub/base/management/commands/repo_transfer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
import logging
from datetime import datetime

from django.core.management.base import BaseCommand
from seaserv import seafile_api, ccnet_api

from seahub.base.accounts import User
from seahub.share.models import UploadLinkShare, FileShare
from seahub.utils.db_api import SeafileDB

logger = logging.getLogger(__name__)


class Command(BaseCommand):
help = 'Transfer a repo to a new owner'
label = "repo_transfer"

def add_arguments(self, parser):
parser.add_argument('-r', '--repo_id', help='Repo ID')
parser.add_argument('-o', '--new_owner', help='New owner of the repo')

def handle(self, *args, **options):
repo_id = options.get('repo_id')
new_owner = options.get('new_owner')
if not repo_id:
self._pring_msg('repo_id is required', 'error')
return
if not new_owner:
self._pring_msg('new_owner is required', 'error')
return

logger.debug('Start transfer_repos.')
self.stdout.write('[%s] Start transfer repos.' % datetime.now())
self.transfer_repo(repo_id, new_owner)
self.stdout.write('[%s] Finish transfer repos.\n' % datetime.now())
logger.debug('Finish transfer repos.\n')

def _pring_msg(self, msg, msg_type='info'):
self.stdout.write('[%s][%s] %s' % (datetime.now(),msg_type.upper(), msg))

def _get_repo_owner(self, repo_id, org_id):
if org_id:
repo_owner = seafile_api.get_org_repo_owner(repo_id)
else:
repo_owner = seafile_api.get_repo_owner(repo_id)

return repo_owner

def is_dept(self, group):
return group.creator_name == 'system admin'


def transfer_repo(self, repo_id, new_owner, org_id=None):

try:
int(new_owner)
new_owner = '%s@seafile_group' % new_owner
except:
pass

# 1. check repo_owner
repo_owner = self._get_repo_owner(repo_id, org_id)
if repo_owner == new_owner:
error_msg = 'Cannot transfer repo to its owner'
self._pring_msg(error_msg, 'error')
return

group_id = None
if '@seafile_group' in new_owner:
group_id = int(new_owner.split('@')[0])

# 2. transfer repo
seafile_db_api = SeafileDB()
if group_id:
group = ccnet_api.get_group(int(group_id))

if not group:
error_msg = 'Group %s not found' % group_id
self._pring_msg(error_msg, 'error')
return

if not self.is_dept(group):
error_msg = 'Group %s is not a department' % group_id
self._pring_msg(error_msg, 'error')
return

seafile_db_api.set_repo_group_owner(repo_id, group_id, org_id)
else:
try:
User.objects.get(email=new_owner)
except User.DoesNotExist:
error_msg = 'User %s not found.' % new_owner
self._pring_msg(error_msg, 'error')
return

seafile_db_api.set_repo_owner(repo_id, new_owner, org_id)

# 3. update the share relations
try:
seafile_db_api.update_repo_user_shares(repo_id, new_owner, org_id)
seafile_db_api.update_repo_group_shares(repo_id, new_owner, org_id)
seafile_db_api.delete_repo_user_token(repo_id, repo_owner)

UploadLinkShare.objects.filter(repo_id=repo_id).update(username=new_owner)
FileShare.objects.filter(repo_id=repo_id).update(username=new_owner)
except Exception as error_msg:
self._pring_msg(error_msg, 'error')
83 changes: 83 additions & 0 deletions seahub/utils/db_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,86 @@ def add_repos_to_org_user(self, org_id, username, repo_ids):
"""
with connection.cursor() as cursor:
cursor.execute(sql)


def get_repo_ids_in_repo(self, repo_id):
repo_ids_sql = f"""
SELECT repo_id from `{self.db_name}`.`VirtualRepo` where origin_repo="{repo_id}"
"""
repo_ids = [repo_id, ]
with connection.cursor() as cursor:
cursor.execute(repo_ids_sql)
for item in cursor.fetchall():
repo_id = item[0]
repo_ids.append(repo_id)

return repo_ids

def set_repo_owner(self, repo_id, new_owner, org_id=None):
# transfert repo to user
repo_ids = self.get_repo_ids_in_repo(repo_id)
repo_ids_str = ','.join(["'%s'" % str(rid) for rid in repo_ids])
if org_id:
sql = f"""
UPDATE `{self.db_name}`.`OrgRepo` SET user="{new_owner}" WHERE org_id ={org_id} AND repo_id IN ({repo_ids_str})
"""
else:
sql = f"""
UPDATE `{self.db_name}`.`RepoOwner` SET owner_id="{new_owner}" WHERE repo_id IN ({repo_ids_str})
"""
with connection.cursor() as cursor:
cursor.execute(sql)

def set_repo_group_owner(self, repo_id, group_id, org_id=None):
# transfer repo to department
group_username = "%s@seafile_group" % group_id
if org_id:
sql = f"""
INSERT INTO `{self.db_name}`.`OrgGroupRepo` (org_id, repo_id, group_id, owner, permission) VALUES ({org_id}, "{repo_id}", {group_id}, "{group_username}", "rw")
ON DUPLICATE KEY UPDATE owner="{group_username}"
"""
else:
sql = f"""
INSERT INTO `{self.db_name}`.`RepoGroup` (repo_id, group_id, user_name, permission) VALUES ("{repo_id}", {group_id}, "{group_username}", "rw")
ON DUPLICATE KEY UPDATE user_name="{group_username}"
"""
with connection.cursor() as cursor:
cursor.execute(sql)

self.set_repo_owner(repo_id, group_username, org_id)

def update_repo_user_shares(self, repo_id, new_owner, org_id=None):
repo_ids = self.get_repo_ids_in_repo(repo_id)
repo_ids_str = ','.join(["'%s'" % str(rid) for rid in repo_ids])
if org_id:
sql = f"""
UPDATE `{self.db_name}`.`OrgSharedRepo` SET from_email="{new_owner}" WHERE org_id={org_id} AND repo_id IN ({repo_ids_str})
"""
else:
sql = f"""
UPDATE `{self.db_name}`.`SharedRepo` SET from_email="{new_owner}" WHERE repo_id IN ({repo_ids_str})
"""
with connection.cursor() as cursor:
cursor.execute(sql)

def update_repo_group_shares(self, repo_id, new_owner, org_id=None):
repo_ids = self.get_repo_ids_in_repo(repo_id)
repo_ids_str = ','.join(["'%s'" % str(rid) for rid in repo_ids])
if org_id:
sql = f"""
UPDATE `{self.db_name}`.`OrgGroupRepo` SET owner="{new_owner}" WHERE org_id={org_id} AND repo_id IN ({repo_ids_str})
"""
else:
sql = f"""
UPDATE `{self.db_name}`.`RepoGroup` SET user_name="{new_owner}" WHERE repo_id IN ({repo_ids_str})
"""
with connection.cursor() as cursor:
cursor.execute(sql)

def delete_repo_user_token(self, repo_id, owner):
sql = f"""
DELETE FROM `{self.db_name}`.`RepoUserToken` where repo_id="{repo_id}" AND email="{owner}"
"""
with connection.cursor() as cursor:
cursor.execute(sql)

Loading