diff --git a/seahub/api2/endpoints/admin/users.py b/seahub/api2/endpoints/admin/users.py index 7cb8fe1d14b..6291ad2403c 100644 --- a/seahub/api2/endpoints/admin/users.py +++ b/seahub/api2/endpoints/admin/users.py @@ -22,9 +22,12 @@ from seaserv import seafile_api, ccnet_api from seahub.api2.authentication import TokenAuthentication +from seahub.api2.endpoints.utils import is_org_user from seahub.api2.throttling import UserRateThrottle from seahub.api2.utils import api_error, to_python_boolean, get_user_common_info from seahub.api2.models import TokenV2 +from seahub.organizations.models import OrgSettings +from seahub.organizations.views import gen_org_url_prefix from seahub.utils.ccnet_db import get_ccnet_db_name import seahub.settings as settings from seahub.settings import SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER, INIT_PASSWD, \ @@ -40,13 +43,14 @@ is_pro_version, normalize_cache_key, is_valid_email, \ IS_EMAIL_CONFIGURED, send_html_email, get_site_name, \ gen_shared_link, gen_shared_upload_link +from seahub.utils.db_api import SeafileDB from seahub.utils.file_size import get_file_size_unit, byte_to_kb from seahub.utils.timeutils import timestamp_to_isoformat_timestr, \ datetime_to_isoformat_timestr from seahub.utils.user_permissions import get_user_role from seahub.utils.repo import normalize_repo_status_code -from seahub.constants import DEFAULT_ADMIN +from seahub.constants import DEFAULT_ADMIN, DEFAULT_ORG from seahub.role_permissions.models import AdminRole from seahub.role_permissions.utils import get_available_roles from seahub.utils.licenseparse import user_number_over_limit @@ -2121,3 +2125,61 @@ def post(self, request): user_list.append(user_info) return Response({'user_list': user_list}) + + +class AdminUserConvertToTeamView(APIView): + authentication_classes = (TokenAuthentication, SessionAuthentication) + permission_classes = (IsAdminUser,) + throttle_classes = (UserRateThrottle,) + + def post(self, request): + username = request.data.get('email') + if not username: + return api_error(status.HTTP_400_BAD_REQUEST, 'email invalid.') + + # resource check + try: + user = User.objects.get(email=username) + except User.DoesNotExist: + error_msg = 'User %s not found.' % username + return api_error(status.HTTP_404_NOT_FOUND, error_msg) + + if is_org_user(username): + error_msg = 'User is already in team.' + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + org_role = DEFAULT_ORG + + url_prefix = gen_org_url_prefix(3) + if url_prefix is None: + error_msg = 'Internal Server Error' + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + # Use the nickname as the org_name, but the org_name does not support emoji + nickname = email2nickname(username) + nickname_characters = [] + for character in nickname: + if len(character.encode('utf-8')) > 3: + nickname_characters.append('_') + else: + nickname_characters.append(character) + org_name = ''.join(nickname_characters) + + try: + # 1. Create a new org, and add the user(username) to org as a team admin + # by ccnet_api.create_org + org_id = ccnet_api.create_org(org_name, url_prefix, username) + # 2. Update org-settings + new_org = ccnet_api.get_org_by_id(org_id) + OrgSettings.objects.add_or_update(new_org, org_role) + # 3. Add user's repo to OrgRepo + owned_repos = seafile_api.get_owned_repo_list(username, ret_corrupted=True) + owned_repo_ids = [item.repo_id for item in owned_repos] + seafile_db = SeafileDB() + seafile_db.add_repos_to_org_user(org_id, username, owned_repo_ids) + except Exception as e: + logger.error(e) + error_msg = 'Internal Server Error' + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + return Response({'success': True}) diff --git a/seahub/api2/endpoints/user.py b/seahub/api2/endpoints/user.py index ba97df96025..24bedba1fee 100644 --- a/seahub/api2/endpoints/user.py +++ b/seahub/api2/endpoints/user.py @@ -8,6 +8,10 @@ from rest_framework.views import APIView from django.utils.translation import gettext as _ +from seahub.constants import DEFAULT_ORG +from seahub.organizations.models import OrgSettings +from seahub.organizations.settings import ORG_AUTO_URL_PREFIX +from seahub.organizations.views import gen_org_url_prefix from seahub.utils import is_valid_email from seahub.api2.authentication import TokenAuthentication from seahub.api2.throttling import UserRateThrottle @@ -15,7 +19,12 @@ from seahub.base.templatetags.seahub_tags import email2nickname, \ email2contact_email from seahub.profile.models import Profile, DetailedProfile -from seahub.settings import ENABLE_UPDATE_USER_INFO, ENABLE_USER_SET_CONTACT_EMAIL +from seahub.settings import ENABLE_UPDATE_USER_INFO, ENABLE_USER_SET_CONTACT_EMAIL, ENABLE_CONVERT_TO_TEAM_ACCOUNT + +import seaserv +from seaserv import ccnet_api, seafile_api + +from seahub.utils.db_api import SeafileDB logger = logging.getLogger(__name__) json_content_type = 'application/json; charset=utf-8' @@ -138,3 +147,54 @@ def put(self, request): # get user info and return info = self._get_user_info(email) return Response(info) + +class UserConvertToTeamView(APIView): + authentication_classes = (TokenAuthentication, SessionAuthentication) + permission_classes = (IsAuthenticated,) + throttle_classes = (UserRateThrottle,) + + def post(self, request): + if not ENABLE_CONVERT_TO_TEAM_ACCOUNT: + error_msg = 'Feature is not enabled.' + return api_error(status.HTTP_403_FORBIDDEN, error_msg) + + org_role = DEFAULT_ORG + + if request.user.org: + error_msg = 'User is already in team.' + return api_error(status.HTTP_400_BAD_REQUEST, error_msg) + + url_prefix = gen_org_url_prefix(3) + if url_prefix is None: + error_msg = 'Internal Server Error' + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + username = request.user.username + # Use the nickname as the org_name, but the org_name does not support emoji + nickname = email2nickname(username) + nickname_characters = [] + for character in nickname: + if len(character.encode('utf-8')) > 3: + nickname_characters.append('_') + else: + nickname_characters.append(character) + org_name = ''.join(nickname_characters) + + try: + # 1. Create a new org, and add the current to org as a team admin + # by ccnet_api.create_org + org_id = ccnet_api.create_org(org_name, url_prefix, username) + # 2. Update org-settings + new_org = ccnet_api.get_org_by_id(org_id) + OrgSettings.objects.add_or_update(new_org, org_role) + # 3. Add user's repo to OrgRepo + owned_repos = seafile_api.get_owned_repo_list(username, ret_corrupted=True) + owned_repo_ids = [item.repo_id for item in owned_repos] + seafile_db = SeafileDB() + seafile_db.add_repos_to_org_user(org_id, username, owned_repo_ids) + except Exception as e: + logger.error(e) + error_msg = 'Internal Server Error' + return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + + return Response({'success': True}) diff --git a/seahub/settings.py b/seahub/settings.py index 815d4a568d2..a36b38d5603 100644 --- a/seahub/settings.py +++ b/seahub/settings.py @@ -486,6 +486,8 @@ # enable integration seatbale ENABLE_SEATABLE_INTEGRATION = False +ENABLE_CONVERT_TO_TEAM_ACCOUNT = False + # File preview FILE_PREVIEW_MAX_SIZE = 30 * 1024 * 1024 FILE_ENCODING_LIST = ['auto', 'utf-8', 'gbk', 'ISO-8859-1', 'ISO-8859-5'] diff --git a/seahub/urls.py b/seahub/urls.py index 065416746bb..c6c348cb392 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -93,7 +93,7 @@ from seahub.api2.endpoints.activities import ActivitiesView from seahub.api2.endpoints.wiki_pages import WikiPagesDirView, WikiPageContentView from seahub.api2.endpoints.revision_tag import TaggedItemsView, TagNamesView -from seahub.api2.endpoints.user import User +from seahub.api2.endpoints.user import User, UserConvertToTeamView from seahub.api2.endpoints.auth_token_by_session import AuthTokenBySession from seahub.api2.endpoints.repo_tags import RepoTagsView, RepoTagView from seahub.api2.endpoints.file_tag import RepoFileTagsView, RepoFileTagView @@ -141,7 +141,7 @@ from seahub.api2.endpoints.admin.device_errors import AdminDeviceErrors from seahub.api2.endpoints.admin.users import AdminUsers, AdminUser, AdminUserResetPassword, AdminAdminUsers, \ AdminUserGroups, AdminUserShareLinks, AdminUserUploadLinks, AdminUserBeSharedRepos, \ - AdminLDAPUsers, AdminSearchUser, AdminUpdateUserCcnetEmail, AdminUserList + AdminLDAPUsers, AdminSearchUser, AdminUpdateUserCcnetEmail, AdminUserList, AdminUserConvertToTeamView from seahub.api2.endpoints.admin.device_trusted_ip import AdminDeviceTrustedIP from seahub.api2.endpoints.admin.libraries import AdminLibraries, AdminLibrary, \ AdminSearchLibrary @@ -310,6 +310,9 @@ ## user re_path(r'^api/v2.1/user/$', User.as_view(), name="api-v2.1-user"), + + # user:convert to team account + re_path(r'^api/v2.1/user/convert-to-team/$', UserConvertToTeamView.as_view(), name="api-v2.1-user-convert-to-team"), ## obtain auth token by login session re_path(r'^api/v2.1/auth-token-by-session/$', AuthTokenBySession.as_view(), name="api-v2.1-auth-token-by-session"), @@ -583,6 +586,7 @@ re_path(r'^api/v2.1/admin/search-user/$', AdminSearchUser.as_view(), name='api-v2.1-admin-search-user'), re_path(r'^api/v2.1/admin/update-user-ccnet-email/$', AdminUpdateUserCcnetEmail.as_view(), name='api-v2.1-admin-update-user-ccnet-email'), re_path(r'^api/v2.1/admin/user-list/$', AdminUserList.as_view(), name='api-v2.1-admin-user-list'), + re_path(r'^api/v2.1/admin/user-convert-to-team/$', AdminUserConvertToTeamView.as_view(), name='api-v2.1-admin-user-list'), # [^...] Matches any single character not in brackets # + Matches between one and unlimited times, as many times as possible diff --git a/seahub/utils/db_api.py b/seahub/utils/db_api.py index 437a7df86e9..d373b93a841 100644 --- a/seahub/utils/db_api.py +++ b/seahub/utils/db_api.py @@ -348,3 +348,12 @@ def del_repo_trash(cursor,repo_ids): repo_ids.append(repo_id) del_repo_trash(cursor, repo_ids) cursor.close() + + def add_repos_to_org_user(self, org_id, username, repo_ids): + for repo_id in repo_ids: + sql = f""" + INSERT INTO `{self.db_name}`.`OrgRepo` (org_id, repo_id, user) + VALUES ({org_id}, "{repo_id}", "{username}"); + """ + with connection.cursor() as cursor: + cursor.execute(sql)