1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-21 11:27:18 +00:00
Files
seahub/seahub/views/sysadmin.py

2247 lines
75 KiB
Python
Raw Normal View History

# encoding: utf-8
2013-05-25 11:40:40 +08:00
import os
from types import FunctionType
import logging
import json
2014-02-26 18:24:34 +08:00
import re
import datetime
2015-10-20 16:35:54 +08:00
import stat
2014-05-09 17:12:25 +08:00
import csv, chardet, StringIO
import time
2015-09-21 11:48:07 +08:00
from constance import config
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.http import HttpResponse, Http404, HttpResponseRedirect, HttpResponseNotAllowed
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils import timezone
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext as _
2015-10-24 17:18:07 +08:00
import seaserv
from seaserv import ccnet_threaded_rpc, seafserv_threaded_rpc, \
2015-04-25 10:57:14 +08:00
CALC_SHARE_USAGE, seafile_api, get_group, get_group_members
from pysearpc import SearpcError
from seahub.base.accounts import User
2013-11-21 15:05:08 +08:00
from seahub.base.models import UserLastLogin
2015-09-02 11:14:54 +08:00
from seahub.base.decorators import sys_staff_required, require_POST
from seahub.base.sudo_mode import update_sudo_mode_ts
from seahub.base.templatetags.seahub_tags import tsstr_sec, email2nickname, \
translate_seahub_time_str
from seahub.auth import authenticate
from seahub.auth.decorators import login_required, login_required_ajax
2014-07-14 17:48:05 +08:00
from seahub.constants import GUEST_USER, DEFAULT_USER
2015-09-21 11:48:07 +08:00
2014-12-25 14:48:02 +08:00
from seahub.utils import IS_EMAIL_CONFIGURED, string2list, is_valid_username, \
2015-09-21 11:48:07 +08:00
is_pro_version, send_html_email, get_user_traffic_list, get_server_id, \
clear_token, gen_file_get_url, is_org_context, handle_virus_record, \
get_virus_record_by_id, get_virus_record
2015-09-21 11:48:07 +08:00
from seahub.utils.rpc import mute_seafile_api
2015-05-08 15:21:54 +08:00
from seahub.utils.licenseparse import parse_license
2015-09-21 11:48:07 +08:00
from seahub.utils.sysinfo import get_platform_name
from seahub.utils.mail import send_html_email_with_dj_template
from seahub.utils.ms_excel import write_xls
2015-09-25 16:03:51 +08:00
from seahub.views.ajax import (get_related_users_by_org_repo,
get_related_users_by_repo)
2015-10-20 16:35:54 +08:00
from seahub.views import get_system_default_repo_id, gen_path_link
2014-05-16 17:43:36 +08:00
from seahub.forms import SetUserQuotaForm, AddUserForm, BatchAddUserForm
from seahub.options.models import UserOptions
2013-12-18 13:56:20 +08:00
from seahub.profile.models import Profile, DetailedProfile
2015-09-25 16:03:51 +08:00
from seahub.signals import repo_deleted
2014-04-29 11:05:36 +08:00
from seahub.share.models import FileShare, UploadLinkShare
import seahub.settings as settings
from seahub.settings import INIT_PASSWD, SITE_NAME, SITE_ROOT, \
2015-10-20 16:35:54 +08:00
SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER, SEND_EMAIL_ON_RESETTING_USER_PASSWD, \
ENABLE_SYS_ADMIN_VIEW_REPO
2015-01-08 16:23:18 +08:00
try:
from seahub.settings import ENABLE_TRIAL_ACCOUNT
2015-01-08 16:23:18 +08:00
except:
ENABLE_TRIAL_ACCOUNT = False
if ENABLE_TRIAL_ACCOUNT:
from seahub_extra.trialaccount.models import TrialAccount
2015-05-08 15:21:54 +08:00
try:
from seahub.settings import MULTI_TENANCY
except ImportError:
MULTI_TENANCY = False
2014-12-04 10:47:22 +08:00
logger = logging.getLogger(__name__)
2015-05-08 15:21:54 +08:00
@login_required
@sys_staff_required
def sys_info(request):
"""System info(members, pro, ..) page.
Arguments:
- `request`:
"""
# count repos
repos_count = mute_seafile_api.count_repos()
# count groups
try:
groups_count = len(ccnet_threaded_rpc.get_all_groups(-1, -1))
except Exception as e:
logger.error(e)
groups_count = 0
# count orgs
2015-05-08 15:21:54 +08:00
if MULTI_TENANCY:
try:
org_count = ccnet_threaded_rpc.count_orgs()
except Exception as e:
logger.error(e)
org_count = 0
2015-05-08 15:21:54 +08:00
else:
org_count = -1
# count users
try:
active_db_users = ccnet_threaded_rpc.count_emailusers('DB')
except Exception as e:
logger.error(e)
active_db_users = 0
try:
active_ldap_users = ccnet_threaded_rpc.count_emailusers('LDAP')
except Exception as e:
logger.error(e)
active_ldap_users = 0
try:
inactive_db_users = ccnet_threaded_rpc.count_inactive_emailusers('DB')
except Exception as e:
logger.error(e)
inactive_db_users = 0
try:
inactive_ldap_users = ccnet_threaded_rpc.count_inactive_emailusers('LDAP')
except Exception as e:
logger.error(e)
inactive_ldap_users = 0
active_users = active_db_users + active_ldap_users if active_ldap_users > 0 \
else active_db_users
inactive_users = inactive_db_users + inactive_ldap_users if inactive_ldap_users > 0 \
else inactive_db_users
2015-05-08 15:21:54 +08:00
is_pro = is_pro_version()
if is_pro:
license_file = os.path.join(settings.PROJECT_ROOT, '../../seafile-license.txt')
license_dict = parse_license(license_file)
2015-05-08 15:21:54 +08:00
else:
license_dict = {}
2015-05-08 15:21:54 +08:00
return render_to_response('sysadmin/sys_info.html', {
'users_count': active_users + inactive_users,
'active_users_count': active_users,
2015-05-08 15:21:54 +08:00
'repos_count': repos_count,
'groups_count': groups_count,
'org_count': org_count,
'is_pro': is_pro,
'license_dict': license_dict,
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_repo_admin(request):
# 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', '25'))
except ValueError:
current_page = 1
per_page = 25
repos_all = seafile_api.get_repo_list(per_page * (current_page -1),
per_page + 1)
repos = repos_all[:per_page]
if len(repos_all) == per_page + 1:
page_next = True
else:
page_next = False
2015-10-20 16:35:54 +08:00
default_repo_id = get_system_default_repo_id()
for repo in repos:
2015-10-20 16:35:54 +08:00
repo.is_default_repo = True if repo.id == default_repo_id else False
try:
repo.owner = seafile_api.get_repo_owner(repo.id)
except:
repo.owner = "failed to get"
return render_to_response(
'sysadmin/sys_repo_admin.html', {
2015-10-20 16:35:54 +08:00
'enable_sys_admin_view_repo': ENABLE_SYS_ADMIN_VIEW_REPO,
'is_pro_version': is_pro_version(),
'repos': repos,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
},
context_instance=RequestContext(request))
2015-10-20 16:35:54 +08:00
@login_required
@sys_staff_required
def sys_admin_repo_download_file(request, repo_id):
"""
"""
repo = seafile_api.get_repo(repo_id)
2015-10-20 16:35:54 +08:00
path = request.GET.get('p', '')
obj_id = seafile_api.get_file_id_by_path(repo_id, path)
next = request.META.get('HTTP_REFERER', None)
if not next:
next = reverse('sys_admin_repo')
if not repo or repo.encrypted or not is_pro_version() \
or not ENABLE_SYS_ADMIN_VIEW_REPO or not obj_id:
messages.error(request, _(u'Unable to download file'))
return HttpResponseRedirect(next)
try:
token = seafile_api.get_fileserver_access_token(repo_id, obj_id,
'download', request.user.username)
except SearpcError as e:
logger.error(e)
messages.error(request, _(u'Unable to view library'))
return HttpResponseRedirect(next)
file_name = os.path.basename(path.rstrip('/'))
redirect_url = gen_file_get_url(token, file_name)
return HttpResponseRedirect(redirect_url)
@login_required
@sys_staff_required
def sys_admin_repo(request, repo_id):
next = request.META.get('HTTP_REFERER', None)
if not next:
next = reverse('sys_repo_admin')
if not is_pro_version() or not ENABLE_SYS_ADMIN_VIEW_REPO:
messages.error(request, _(u'Unable to view library, this feature is not enabled.'))
return HttpResponseRedirect(next)
repo = seafile_api.get_repo(repo_id)
2015-10-20 16:35:54 +08:00
if not repo:
messages.error(request, _(u'Library does not exist'))
return HttpResponseRedirect(next)
if repo.encrypted:
messages.error(request, _(u'Library is encrypted'))
return HttpResponseRedirect(next)
path = request.GET.get('p', '/')
if path[-1] != '/':
path = path + '/'
dir_id = seafile_api.get_dir_id_by_path(repo_id, path)
if not dir_id:
messages.error(request, _(u'Unable to view library, wrong folder path.'))
return HttpResponseRedirect(next)
if is_org_context(request):
repo_owner = seafile_api.get_org_repo_owner(repo_id)
else:
repo_owner = seafile_api.get_repo_owner(repo_id)
try:
dirs = seafserv_threaded_rpc.list_dir_with_perm(repo_id, path,
dir_id, repo_owner,
-1, -1)
except SearpcError as e:
logger.error(e)
messages.error(request, _(u'Unable to view library'))
return HttpResponseRedirect(next)
file_list, dir_list = [], []
for dirent in dirs:
dirent.last_modified = dirent.mtime
if stat.S_ISDIR(dirent.props.mode):
dir_list.append(dirent)
else:
if repo.version == 0:
dirent.file_size = seafile_api.get_file_size(repo.store_id,
repo.version,
dirent.obj_id)
2015-10-20 16:35:54 +08:00
else:
dirent.file_size = dirent.size
file_list.append(dirent)
zipped = gen_path_link(path, repo.name)
return render_to_response('sysadmin/admin_repo_view.html', {
'repo': repo,
'repo_owner': repo_owner,
'dir_list': dir_list,
'file_list': file_list,
'path': path,
'zipped': zipped,
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_list_system(request):
"""List system repos.
"""
repos = []
sys_repo = seafile_api.get_repo(get_system_default_repo_id())
repos.append(sys_repo)
return render_to_response('sysadmin/sys_list_system.html', {
'repos': repos,
}, context_instance=RequestContext(request))
2015-03-23 17:59:33 +08:00
@login_required
@sys_staff_required
def sys_repo_trash(request):
""" List deleted repos (by owner) """
search_owner = request.GET.get('name', '')
if search_owner:
if is_valid_username(search_owner):
repos = seafserv_threaded_rpc.get_trash_repos_by_owner(search_owner)
return render_to_response(
'sysadmin/sys_repo_trash.html', {
'repos': repos,
'search_owner': search_owner,
}, context_instance=RequestContext(request))
else:
messages.error(request, _(u'Invalid username'))
return HttpResponseRedirect(reverse('sys_repo_trash'))
try:
current_page = int(request.GET.get('page', '1'))
per_page = int(request.GET.get('per_page', '25'))
except ValueError:
current_page = 1
per_page = 25
repos_all = seafserv_threaded_rpc.get_trash_repo_list(per_page * (current_page -1),
per_page + 1)
repos = repos_all[:per_page]
if len(repos_all) == per_page + 1:
page_next = True
else:
page_next = False
return render_to_response(
'sysadmin/sys_repo_trash.html', {
'repos': repos,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
@require_POST
2015-03-23 17:59:33 +08:00
def sys_repo_trash_restore(request, repo_id):
"""Restore deleted repo by id"""
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_repo_trash') if referer is None else referer
try:
seafserv_threaded_rpc.restore_repo_from_trash(repo_id)
messages.success(request, _(u'Success'))
except SearpcError, e:
logger.error(e)
messages.error(request, _(u'Failed'))
return HttpResponseRedirect(next)
@login_required
@sys_staff_required
@require_POST
2015-03-23 17:59:33 +08:00
def sys_repo_trash_remove(request, repo_id):
"""Remove deleted repo by id"""
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_repo_trash') if referer is None else referer
try:
seafserv_threaded_rpc.del_repo_from_trash(repo_id)
messages.success(request, _(u'Success'))
except SearpcError, e:
logger.error(e)
messages.error(request, _(u'Failed'))
return HttpResponseRedirect(next)
@login_required
@sys_staff_required
@require_POST
2015-03-23 17:59:33 +08:00
def sys_repo_trash_clear(request):
"""Clear repo trash (by owner)"""
next = reverse('sys_repo_trash')
owner = request.POST.get('owner', '')
2015-03-23 17:59:33 +08:00
try:
if owner:
if is_valid_username(owner):
seafserv_threaded_rpc.empty_repo_trash_by_owner(owner)
else:
messages.error(request, _(u'Invalid username'))
return HttpResponseRedirect(next)
else:
seafserv_threaded_rpc.empty_repo_trash()
except SearpcError, e:
logger.error(e)
messages.error(request, _(u'Failed'))
messages.success(request, _(u'Success'))
return HttpResponseRedirect(next)
2013-09-23 15:57:54 +08:00
def list_repos_by_name_and_owner(repo_name, owner):
repos = []
owned_repos = seafile_api.get_owned_repo_list(owner)
for repo in owned_repos:
if not repo.name:
continue
2013-09-28 16:50:34 +08:00
if repo_name in repo.name:
2013-09-23 15:57:54 +08:00
repo.owner = owner
repos.append(repo)
return repos
def list_repos_by_name(repo_name):
repos = []
repos_all = seafile_api.get_repo_list(-1, -1)
for repo in repos_all:
if not repo.name:
continue
2013-09-28 16:50:34 +08:00
if repo_name in repo.name:
2013-09-23 15:57:54 +08:00
try:
repo.owner = seafile_api.get_repo_owner(repo.id)
except SearpcError:
repo.owner = "failed to get"
repos.append(repo)
return repos
def list_repos_by_owner(owner):
repos = seafile_api.get_owned_repo_list(owner)
for e in repos:
e.owner = owner
return repos
2014-12-25 17:17:29 +08:00
2013-09-23 15:57:54 +08:00
@login_required
@sys_staff_required
def sys_repo_search(request):
"""Search a repo.
"""
repo_name = request.GET.get('name', '')
owner = request.GET.get('owner', '')
2014-12-25 17:17:29 +08:00
repos = []
2013-09-23 15:57:54 +08:00
2013-09-28 16:50:34 +08:00
if repo_name and owner : # search by name and owner
repos = list_repos_by_name_and_owner(repo_name, owner)
elif repo_name: # search by name
repos = list_repos_by_name(repo_name)
elif owner: # search by owner
repos = list_repos_by_owner(owner)
2013-09-23 15:57:54 +08:00
return render_to_response('sysadmin/sys_repo_search.html', {
'repos': repos,
'name': repo_name,
'owner': owner,
2015-10-20 16:35:54 +08:00
'enable_sys_admin_view_repo': ENABLE_SYS_ADMIN_VIEW_REPO,
2013-09-23 15:57:54 +08:00
}, context_instance=RequestContext(request))
def _populate_user_quota_usage(user):
"""Populate space/share quota to user.
Arguments:
- `user`:
"""
orgs = ccnet_threaded_rpc.get_orgs_by_user(user.email)
try:
if orgs:
user.org = orgs[0]
org_id = user.org.org_id
user.space_usage = seafserv_threaded_rpc.get_org_user_quota_usage(org_id, user.email)
user.space_quota = seafserv_threaded_rpc.get_org_user_quota(org_id, user.email)
user.share_usage = user.share_quota = 0
else:
user.space_usage = seafile_api.get_user_self_usage(user.email)
user.space_quota = seafile_api.get_user_quota(user.email)
if CALC_SHARE_USAGE:
user.share_quota = seafile_api.get_user_share_quota(user.email)
user.share_usage = seafile_api.get_user_share_usage(user.email)
else:
user.share_usage = user.share_quota = 0
except SearpcError as e:
logger.error(e)
user.space_usage = user.space_quota = user.share_usage = user.share_quota = -1
@login_required
@sys_staff_required
def sys_user_admin(request):
"""List all users from database.
"""
2015-09-16 18:40:14 +08:00
try:
from seahub_extra.plan.models import UserPlan
enable_user_plan = True
except ImportError:
enable_user_plan = False
if enable_user_plan and request.GET.get('filter', '') == 'paid':
# show paid users
users = []
ups = UserPlan.objects.all()
for up in ups:
try:
u = User.objects.get(up.username)
except User.DoesNotExist:
continue
2015-09-16 18:40:14 +08:00
_populate_user_quota_usage(u)
users.append(u)
last_logins = UserLastLogin.objects.filter(username__in=[x.username for x in users])
for u in users:
for e in last_logins:
if e.username == u.username:
u.last_login = e.last_login
return render_to_response('sysadmin/sys_useradmin_paid.html', {
'users': users,
'enable_user_plan': enable_user_plan,
}, context_instance=RequestContext(request))
### List all users
# 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', '25'))
except ValueError:
current_page = 1
per_page = 25
2015-10-24 17:18:07 +08:00
users_plus_one = seaserv.get_emailusers('DB', per_page * (current_page - 1),
per_page + 1)
if len(users_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
users = users_plus_one[:per_page]
2013-11-21 15:05:08 +08:00
last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users])
if ENABLE_TRIAL_ACCOUNT:
2015-01-10 12:07:33 +08:00
trial_users = TrialAccount.objects.filter(user_or_org__in=[x.email for x in users])
2015-01-08 16:23:18 +08:00
else:
trial_users = []
for user in users:
2015-06-26 14:05:39 +08:00
if user.email == request.user.email:
user.is_self = True
_populate_user_quota_usage(user)
2014-07-14 17:48:05 +08:00
# check user's role
if user.role == GUEST_USER:
user.is_guest = True
else:
user.is_guest = False
2015-01-08 16:23:18 +08:00
2013-11-21 15:05:08 +08:00
# populate user last login time
user.last_login = None
for last_login in last_logins:
if last_login.username == user.email:
user.last_login = last_login.last_login
2015-01-08 16:23:18 +08:00
user.trial_info = None
for trial_user in trial_users:
2015-01-10 12:07:33 +08:00
if trial_user.user_or_org == user.email:
2015-01-08 16:23:18 +08:00
user.trial_info = {'expire_date': trial_user.expire_date}
2015-10-24 17:18:07 +08:00
have_ldap = True if len(seaserv.get_emailusers('LDAP', 0, 1)) > 0 else False
platform = get_platform_name()
2014-04-18 12:13:43 +08:00
server_id = get_server_id()
2014-12-25 14:48:02 +08:00
pro_server = 1 if is_pro_version() else 0
return render_to_response(
'sysadmin/sys_useradmin.html', {
'users': users,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
'CALC_SHARE_USAGE': CALC_SHARE_USAGE,
'have_ldap': have_ldap,
'platform': platform,
2014-04-18 14:19:58 +08:00
'server_id': server_id[:8],
2014-07-14 17:48:05 +08:00
'default_user': DEFAULT_USER,
'guest_user': GUEST_USER,
'is_pro': is_pro_version(),
2014-12-25 14:48:02 +08:00
'pro_server': pro_server,
2015-09-16 18:40:14 +08:00
'enable_user_plan': enable_user_plan,
2014-07-14 17:48:05 +08:00
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_useradmin_export_excel(request):
""" Export all users from database to excel
"""
next = request.META.get('HTTP_REFERER', None)
if not next:
next = SITE_ROOT
try:
users = seaserv.get_emailusers('DB', -1, -1) + \
seaserv.get_emailusers('LDAPImport', -1, -1)
except Exception as e:
logger.error(e)
2015-12-03 17:56:28 +08:00
messages.error(request, _(u'Failed to export Excel'))
return HttpResponseRedirect(next)
if is_pro_version():
is_pro = True
else:
is_pro = False
if is_pro:
2015-11-24 13:19:58 +08:00
head = [_("Email"), _("Status"), _("Role"), _("Create At"),
_("Last Login"), _("Admin"), _("LDAP(imported)"),]
else:
2015-11-24 13:19:58 +08:00
head = [_("Email"), _("Status"), _("Create At"),
_("Last Login"), _("Admin"), _("LDAP(imported)"),]
data_list = []
last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users])
for user in users:
# populate user last login time
user.last_login = None
for last_login in last_logins:
if last_login.username == user.email:
user.last_login = last_login.last_login
if user.is_active:
status = _('Active')
else:
status = _('Inactive')
2015-11-24 13:19:58 +08:00
create_at = tsstr_sec(user.ctime) if user.ctime else ''
last_login = user.last_login.strftime("%Y-%m-%d %H:%M:%S") if \
user.last_login else ''
is_admin = _('Yes') if user.is_staff else ''
ldap_import = _('Yes') if user.source == 'LDAPImport' else ''
if is_pro:
if user.role == GUEST_USER:
role = _('Guest')
else:
role = _('Default')
2015-11-24 13:19:58 +08:00
row = [user.email, status, role, create_at,
last_login, is_admin, ldap_import]
else:
2015-11-24 13:19:58 +08:00
row = [user.email, status, create_at, last_login,
is_admin, ldap_import]
data_list.append(row)
2015-12-03 17:56:28 +08:00
wb = write_xls('users', head, data_list)
if not wb:
2015-12-03 17:56:28 +08:00
messages.error(request, _(u'Failed to export Excel'))
return HttpResponseRedirect(next)
response = HttpResponse(content_type='application/ms-excel')
2015-11-24 13:19:58 +08:00
response['Content-Disposition'] = 'attachment; filename=users.xlsx'
wb.save(response)
return response
2015-06-26 14:05:39 +08:00
@login_required
@sys_staff_required
def sys_user_admin_ldap_imported(request):
"""List all users from LDAP imported.
"""
# 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', '25'))
except ValueError:
current_page = 1
per_page = 25
2015-10-24 17:18:07 +08:00
users_plus_one = seaserv.get_emailusers('LDAPImport',
per_page * (current_page - 1),
per_page + 1)
2015-06-26 14:05:39 +08:00
if len(users_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
users = users_plus_one[:per_page]
last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users])
for user in users:
if user.email == request.user.email:
user.is_self = True
_populate_user_quota_usage(user)
# populate user last login time
user.last_login = None
for last_login in last_logins:
if last_login.username == user.email:
user.last_login = last_login.last_login
return render_to_response(
'sysadmin/sys_user_admin_ldap_imported.html', {
'users': users,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
'CALC_SHARE_USAGE': CALC_SHARE_USAGE,
'is_pro': is_pro_version(),
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
2014-04-16 17:39:23 +08:00
def sys_user_admin_ldap(request):
"""List all users from LDAP.
"""
# 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', '25'))
except ValueError:
current_page = 1
per_page = 25
2015-10-24 17:18:07 +08:00
users_plus_one = seaserv.get_emailusers('LDAP',
per_page * (current_page - 1),
per_page + 1)
if len(users_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
users = users_plus_one[:per_page]
2013-11-21 15:05:08 +08:00
last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users])
for user in users:
2015-06-26 14:05:39 +08:00
if user.email == request.user.email:
user.is_self = True
_populate_user_quota_usage(user)
2013-11-21 15:05:08 +08:00
# populate user last login time
user.last_login = None
for last_login in last_logins:
if last_login.username == user.email:
user.last_login = last_login.last_login
2014-12-25 17:17:29 +08:00
return render_to_response(
2014-04-16 17:39:23 +08:00
'sysadmin/sys_useradmin_ldap.html', {
'users': users,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
'is_pro': is_pro_version(),
'CALC_SHARE_USAGE': CALC_SHARE_USAGE,
},
context_instance=RequestContext(request))
2014-04-16 17:39:23 +08:00
@login_required
@sys_staff_required
def sys_user_admin_admins(request):
2015-06-26 14:05:39 +08:00
"""List all admins from database and ldap imported
2014-04-16 17:39:23 +08:00
"""
2015-10-24 17:18:07 +08:00
db_users = seaserv.get_emailusers('DB', -1, -1)
ldpa_imported_users = seaserv.get_emailusers('LDAPImport', -1, -1)
2014-04-16 17:39:23 +08:00
admin_users = []
not_admin_users = []
2015-06-26 14:05:39 +08:00
for user in db_users + ldpa_imported_users:
2014-04-16 17:39:23 +08:00
if user.is_staff is True:
admin_users.append(user)
else:
not_admin_users.append(user)
last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in admin_users])
for user in admin_users:
2015-06-26 14:05:39 +08:00
if user.email == request.user.email:
2014-04-16 17:39:23 +08:00
user.is_self = True
_populate_user_quota_usage(user)
2015-06-26 14:05:39 +08:00
# check db user's role
if user.source == "DB":
if user.role == GUEST_USER:
user.is_guest = True
else:
user.is_guest = False
2014-04-16 17:39:23 +08:00
# populate user last login time
user.last_login = None
for last_login in last_logins:
if last_login.username == user.email:
user.last_login = last_login.last_login
2015-10-24 17:18:07 +08:00
have_ldap = True if len(seaserv.get_emailusers('LDAP', 0, 1)) > 0 else False
2014-04-16 17:39:23 +08:00
return render_to_response(
'sysadmin/sys_useradmin_admins.html', {
2015-06-26 14:05:39 +08:00
'users': admin_users,
2014-04-16 17:39:23 +08:00
'not_admin_users': not_admin_users,
'CALC_SHARE_USAGE': CALC_SHARE_USAGE,
'have_ldap': have_ldap,
2014-07-14 17:48:05 +08:00
'default_user': DEFAULT_USER,
'guest_user': GUEST_USER,
'is_pro': is_pro_version(),
}, context_instance=RequestContext(request))
2014-04-16 17:39:23 +08:00
@login_required
@sys_staff_required
def user_info(request, email):
org_name = None
space_quota = space_usage = 0
share_quota = share_usage = 0
org = ccnet_threaded_rpc.get_orgs_by_user(email)
if not org:
2016-01-19 16:35:12 +08:00
owned_repos = mute_seafile_api.get_owned_repo_list(email,
ret_corrupted=True)
in_repos = mute_seafile_api.get_share_in_repo_list(email, -1, -1)
space_usage = mute_seafile_api.get_user_self_usage(email)
space_quota = mute_seafile_api.get_user_quota(email)
if CALC_SHARE_USAGE:
share_usage = mute_seafile_api.get_user_share_usage(email)
share_quota = mute_seafile_api.get_user_share_quota(email)
else:
org_id = org[0].org_id
2014-10-22 10:10:58 +08:00
org_name = org[0].org_name
space_usage = seafserv_threaded_rpc.get_org_user_quota_usage(org_id,
email)
space_quota = seafserv_threaded_rpc.get_org_user_quota(org_id, email)
2016-01-19 16:35:12 +08:00
owned_repos = seafile_api.get_org_owned_repo_list(org_id, email,
ret_corrupted=True)
in_repos = seafile_api.get_org_share_in_repo_list(org_id, email, -1, -1)
2013-12-18 13:56:20 +08:00
# get user profile
profile = Profile.objects.get_profile_by_user(email)
d_profile = DetailedProfile.objects.get_detailed_profile_by_user(email)
2014-04-29 11:05:36 +08:00
user_shared_links = []
# download links
p_fileshares = []
fileshares = list(FileShare.objects.filter(username=email))
2014-04-29 11:05:36 +08:00
for fs in fileshares:
try:
r = seafile_api.get_repo(fs.repo_id)
if not r:
2014-04-29 11:05:36 +08:00
fs.delete()
continue
if fs.is_file_share_link():
if seafile_api.get_file_id_by_path(r.id, fs.path) is None:
fs.delete()
continue
fs.filename = os.path.basename(fs.path)
path = fs.path.rstrip('/') # Normalize file path
obj_id = seafile_api.get_file_id_by_path(r.id, path)
fs.file_size = seafile_api.get_file_size(r.store_id,
r.version, obj_id)
else:
if seafile_api.get_dir_id_by_path(r.id, fs.path) is None:
fs.delete()
continue
if fs.path == '/':
fs.filename = '/'
else:
fs.filename = os.path.basename(fs.path.rstrip('/'))
path = fs.path
if path[-1] != '/': # Normalize dir path
path += '/'
# get dir size
dir_id = seafile_api.get_dir_id_by_commit_and_path(r.id, r.head_cmmt_id, path)
fs.dir_size = seafile_api.get_dir_size(r.store_id, r.version, dir_id)
fs.is_download = True
p_fileshares.append(fs)
except SearpcError as e:
logger.error(e)
continue
p_fileshares.sort(key=lambda x: x.view_cnt, reverse=True)
user_shared_links += p_fileshares
2014-04-29 11:05:36 +08:00
# upload links
uploadlinks = list(UploadLinkShare.objects.filter(username=email))
p_uploadlinks = []
2014-04-29 11:05:36 +08:00
for link in uploadlinks:
try:
r = seafile_api.get_repo(link.repo_id)
if not r:
link.delete()
continue
if seafile_api.get_dir_id_by_path(r.id, link.path) is None:
link.delete()
continue
if link.path == '/':
link.dir_name = '/'
else:
link.dir_name = os.path.basename(link.path.rstrip('/'))
link.is_upload = True
p_uploadlinks.append(link)
except SearpcError as e:
logger.error(e)
2014-04-29 11:05:36 +08:00
continue
p_uploadlinks.sort(key=lambda x: x.view_cnt, reverse=True)
user_shared_links += p_uploadlinks
2014-04-29 11:05:36 +08:00
try:
personal_groups = seaserv.get_personal_groups_by_user(email)
except SearpcError as e:
logger.error(e)
personal_groups = []
for g in personal_groups:
try:
is_group_staff = seaserv.check_group_staff(g.id, email)
except SearpcError as e:
logger.error(e)
is_group_staff = False
if email == g.creator_name:
g.role = _('Owner')
elif is_group_staff:
g.role = _('Admin')
else:
g.role = _('Member')
return render_to_response(
'sysadmin/userinfo.html', {
'owned_repos': owned_repos,
'space_quota': space_quota,
'space_usage': space_usage,
'share_quota': share_quota,
'share_usage': share_usage,
'CALC_SHARE_USAGE': CALC_SHARE_USAGE,
'in_repos': in_repos,
'email': email,
2013-12-18 13:56:20 +08:00
'profile': profile,
'd_profile': d_profile,
2014-10-22 10:10:58 +08:00
'org_name': org_name,
2014-12-25 17:17:29 +08:00
'user_shared_links': user_shared_links,
2015-10-20 16:35:54 +08:00
'enable_sys_admin_view_repo': ENABLE_SYS_ADMIN_VIEW_REPO,
'personal_groups': personal_groups,
}, context_instance=RequestContext(request))
@login_required_ajax
@sys_staff_required
def user_set_quota(request, email):
if request.method != 'POST':
raise Http404
content_type = 'application/json; charset=utf-8'
result = {}
f = SetUserQuotaForm(request.POST)
if f.is_valid():
email = f.cleaned_data['email']
2014-12-25 17:17:29 +08:00
space_quota_mb = f.cleaned_data['space_quota']
space_quota = space_quota_mb * (1 << 20)
share_quota_mb = f.cleaned_data['share_quota']
share_quota = None
if share_quota_mb is not None:
share_quota = share_quota_mb * (1 << 20)
org = ccnet_threaded_rpc.get_orgs_by_user(email)
try:
if not org:
2014-12-25 17:17:29 +08:00
seafile_api.set_user_quota(email, space_quota)
if share_quota is not None:
seafile_api.set_user_share_quota(email, share_quota)
else:
org_id = org[0].org_id
2014-10-22 10:10:58 +08:00
org_quota_mb = seafserv_threaded_rpc.get_org_quota(org_id) / (1 << 20)
2014-12-25 17:17:29 +08:00
if space_quota_mb > org_quota_mb:
2014-10-22 10:10:58 +08:00
result['error'] = _(u'Failed to set quota: maximum quota is %d MB' % \
org_quota_mb)
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
else:
2014-12-25 17:17:29 +08:00
seafserv_threaded_rpc.set_org_user_quota(org_id, email, space_quota)
except:
result['error'] = _(u'Failed to set quota: internal server error')
return HttpResponse(json.dumps(result), status=500, content_type=content_type)
result['success'] = True
return HttpResponse(json.dumps(result), content_type=content_type)
else:
result['error'] = str(f.errors.values()[0])
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
2014-09-26 14:02:19 +08:00
@login_required_ajax
@sys_staff_required
def sys_org_set_quota(request, org_id):
if request.method != 'POST':
raise Http404
content_type = 'application/json; charset=utf-8'
result = {}
org_id = int(org_id)
quota_mb = int(request.POST.get('quota', 0))
quota = quota_mb * (1 << 20)
try:
seafserv_threaded_rpc.set_org_quota(org_id, quota)
except SearpcError as e:
logger.error(e)
result['error'] = _(u'Failed to set quota: internal server error')
return HttpResponse(json.dumps(result), status=500, content_type=content_type)
result['success'] = True
return HttpResponse(json.dumps(result), content_type=content_type)
@login_required
@sys_staff_required
2015-09-02 11:14:54 +08:00
@require_POST
2015-06-26 14:05:39 +08:00
def user_remove(request, email):
"""Remove user"""
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_useradmin') if referer is None else referer
try:
2015-06-26 14:05:39 +08:00
user = User.objects.get(email=email)
org = ccnet_threaded_rpc.get_orgs_by_user(user.email)
if org:
if org[0].creator == user.email:
messages.error(request, _(u'Failed to delete: the user is an organization creator'))
return HttpResponseRedirect(next)
org_id = org[0].org_id
2014-10-22 10:10:58 +08:00
org_user_repos = seafile_api.get_org_owned_repo_list(org_id, user.email)
for repo in org_user_repos:
seafile_api.remove_repo(repo.id)
user.delete()
messages.success(request, _(u'Successfully deleted %s') % user.username)
except User.DoesNotExist:
messages.error(request, _(u'Failed to delete: the user does not exist'))
return HttpResponseRedirect(next)
2015-01-08 16:23:18 +08:00
@login_required
@sys_staff_required
@require_POST
2015-01-10 12:07:33 +08:00
def remove_trial(request, user_or_org):
"""Remove trial account.
2015-01-08 16:23:18 +08:00
Arguments:
- `request`:
"""
if not ENABLE_TRIAL_ACCOUNT:
raise Http404
2015-01-08 16:23:18 +08:00
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_useradmin') if referer is None else referer
2015-01-10 12:07:33 +08:00
TrialAccount.objects.filter(user_or_org=user_or_org).delete()
2015-01-08 16:23:18 +08:00
2015-01-10 12:07:33 +08:00
messages.success(request, _('Successfully remove trial for: %s') % user_or_org)
2015-01-08 16:23:18 +08:00
return HttpResponseRedirect(next)
# @login_required
# @sys_staff_required
# def user_make_admin(request, user_id):
# """Set user as system admin."""
# try:
# user = User.objects.get(id=int(user_id))
# user.is_staff = True
# user.save()
# messages.success(request, _(u'Successfully set %s as admin') % user.username)
# except User.DoesNotExist:
# messages.error(request, _(u'Failed to set admin: the user does not exist'))
# referer = request.META.get('HTTP_REFERER', None)
# next = reverse('sys_useradmin') if referer is None else referer
# return HttpResponseRedirect(next)
@login_required
@sys_staff_required
2015-09-02 11:14:54 +08:00
@require_POST
2015-06-26 14:05:39 +08:00
def user_remove_admin(request, email):
"""Unset user admin."""
try:
2015-06-26 14:05:39 +08:00
user = User.objects.get(email=email)
user.is_staff = False
user.save()
messages.success(request, _(u'Successfully revoke the admin permission of %s') % user.username)
except User.DoesNotExist:
messages.error(request, _(u'Failed to revoke admin: the user does not exist'))
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_useradmin') if referer is None else referer
2014-12-25 17:17:29 +08:00
return HttpResponseRedirect(next)
# @login_required
# @sys_staff_required
# def user_activate(request, user_id):
# try:
# user = User.objects.get(id=int(user_id))
# user.is_active = True
# user.save()
# messages.success(request, _(u'Successfully activated "%s".') % user.email)
# except User.DoesNotExist:
# messages.success(request, _(u'Failed to activate: user does not exist.'))
# next = request.META.get('HTTP_REFERER', None)
# if not next:
# next = reverse('sys_useradmin')
# return HttpResponseRedirect(next)
# @login_required
# @sys_staff_required
# def user_deactivate(request, user_id):
# try:
# user = User.objects.get(id=int(user_id))
# user.is_active = False
# user.save()
# messages.success(request, _(u'Successfully deactivated "%s".') % user.email)
# except User.DoesNotExist:
# messages.success(request, _(u'Failed to deactivate: user does not exist.'))
# next = request.META.get('HTTP_REFERER', None)
# if not next:
# next = reverse('sys_useradmin')
# return HttpResponseRedirect(next)
def email_user_on_activation(user):
"""Send an email to user when admin activate his/her account.
"""
c = {
'username': user.email,
}
send_html_email(_(u'Your account on %s is activated') % SITE_NAME,
'sysadmin/user_activation_email.html', c, None, [user.email])
2014-07-18 11:52:59 +08:00
@login_required_ajax
@sys_staff_required
@require_POST
2014-07-18 11:52:59 +08:00
def user_toggle_status(request, email):
content_type = 'application/json; charset=utf-8'
2014-07-18 11:52:59 +08:00
if not is_valid_username(email):
return HttpResponse(json.dumps({'success': False}), status=400,
content_type=content_type)
try:
user_status = int(request.POST.get('s', 0))
except ValueError:
user_status = 0
try:
2014-07-18 11:52:59 +08:00
user = User.objects.get(email)
user.is_active = bool(user_status)
result_code = user.save()
if result_code == -1:
return HttpResponse(json.dumps({'success': False}), status=403,
content_type=content_type)
if user.is_active is True:
try:
email_user_on_activation(user)
email_sent = True
except Exception as e:
logger.error(e)
email_sent = False
return HttpResponse(json.dumps({'success': True,
'email_sent': email_sent,
}), content_type=content_type)
else:
clear_token(user.email)
return HttpResponse(json.dumps({'success': True}),
content_type=content_type)
except User.DoesNotExist:
return HttpResponse(json.dumps({'success': False}), status=500,
content_type=content_type)
@login_required_ajax
@sys_staff_required
@require_POST
2014-07-14 17:48:05 +08:00
def user_toggle_role(request, email):
content_type = 'application/json; charset=utf-8'
2014-07-14 17:48:05 +08:00
if not is_valid_username(email):
return HttpResponse(json.dumps({'success': False}), status=400,
content_type=content_type)
if not is_pro_version():
2014-07-14 17:48:05 +08:00
return HttpResponse(json.dumps({'success': False}), status=403,
content_type=content_type)
try:
user_role = request.POST.get('r', DEFAULT_USER)
except ValueError:
user_role = DEFAULT_USER
try:
2014-07-14 17:48:05 +08:00
user = User.objects.get(email)
User.objects.update_role(user.email, user_role)
return HttpResponse(json.dumps({'success': True}),
content_type=content_type)
except User.DoesNotExist:
return HttpResponse(json.dumps({'success': False}), status=500,
content_type=content_type)
def send_user_reset_email(request, email, password):
"""
Send email when reset user password.
"""
c = {
'email': email,
'password': password,
}
send_html_email(_(u'Password has been reset on %s') % SITE_NAME,
'sysadmin/user_reset_email.html', c, None, [email])
2014-12-25 17:17:29 +08:00
@login_required
@sys_staff_required
2015-09-02 11:14:54 +08:00
@require_POST
2015-06-26 14:05:39 +08:00
def user_reset(request, email):
"""Reset password for user."""
try:
2015-06-26 14:05:39 +08:00
user = User.objects.get(email=email)
if isinstance(INIT_PASSWD, FunctionType):
new_password = INIT_PASSWD()
else:
new_password = INIT_PASSWD
user.set_password(new_password)
user.save()
2015-04-29 10:24:29 +08:00
clear_token(user.username)
UserOptions.objects.set_force_passwd_change(user.username)
if IS_EMAIL_CONFIGURED:
if SEND_EMAIL_ON_RESETTING_USER_PASSWD:
try:
send_user_reset_email(request, user.email, new_password)
msg = _('Successfully reset password to %(passwd)s, an email has been sent to %(user)s.') % \
{'passwd': new_password, 'user': user.email}
messages.success(request, msg)
except Exception, e:
logger.error(str(e))
msg = _('Successfully reset password to %(passwd)s, but failed to send email to %(user)s, please check your email configuration.') % \
{'passwd':new_password, 'user': user.email}
messages.success(request, msg)
else:
messages.success(request, _(u'Successfully reset password to %(passwd)s for user %(user)s.') % \
{'passwd':new_password,'user': user.email})
else:
messages.success(request, _(u'Successfully reset password to %(passwd)s for user %(user)s. But email notification can not be sent, because Email service is not properly configured.') % \
{'passwd':new_password,'user': user.email})
except User.DoesNotExist:
msg = _(u'Failed to reset password: user does not exist')
messages.error(request, msg)
2014-03-01 13:49:22 +08:00
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_useradmin') if referer is None else referer
2014-12-25 17:17:29 +08:00
2014-03-01 13:49:22 +08:00
return HttpResponseRedirect(next)
2014-12-25 17:17:29 +08:00
def send_user_add_mail(request, email, password):
"""Send email when add new user."""
c = {
'user': request.user.username,
'org': request.user.org,
'email': email,
'password': password,
}
send_html_email(_(u'You are invited to join %s') % SITE_NAME,
'sysadmin/user_add_email.html', c, None, [email])
@login_required_ajax
def user_add(request):
"""Add a user"""
if not request.user.is_staff or request.method != 'POST':
raise Http404
content_type = 'application/json; charset=utf-8'
post_values = request.POST.copy()
post_email = request.POST.get('email', '')
post_role = request.POST.get('role', DEFAULT_USER)
post_values.update({
'email': post_email.lower(),
'role': post_role,
})
form = AddUserForm(post_values)
if form.is_valid():
email = form.cleaned_data['email']
role = form.cleaned_data['role']
password = form.cleaned_data['password1']
try:
user = User.objects.create_user(email, password, is_staff=False,
is_active=True)
except User.DoesNotExist as e:
logger.error(e)
err_msg = _(u'Fail to add user %s.') % email
return HttpResponse(json.dumps({'error': err_msg}), status=403, content_type=content_type)
if user:
User.objects.update_role(email, role)
UserOptions.objects.set_force_passwd_change(email)
if request.user.org:
org_id = request.user.org.org_id
url_prefix = request.user.org.url_prefix
ccnet_threaded_rpc.add_org_user(org_id, email, 0)
if IS_EMAIL_CONFIGURED:
try:
send_user_add_mail(request, email, password)
messages.success(request, _(u'Successfully added user %s. An email notification has been sent.') % email)
except Exception, e:
logger.error(str(e))
messages.success(request, _(u'Successfully added user %s. An error accurs when sending email notification, please check your email configuration.') % email)
else:
messages.success(request, _(u'Successfully added user %s.') % email)
return HttpResponse(json.dumps({'success': True}), content_type=content_type)
else:
if IS_EMAIL_CONFIGURED:
if SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER:
try:
send_user_add_mail(request, email, password)
messages.success(request, _(u'Successfully added user %s. An email notification has been sent.') % email)
except Exception, e:
logger.error(str(e))
messages.success(request, _(u'Successfully added user %s. An error accurs when sending email notification, please check your email configuration.') % email)
else:
messages.success(request, _(u'Successfully added user %s.') % email)
else:
messages.success(request, _(u'Successfully added user %s. But email notification can not be sent, because Email service is not properly configured.') % email)
return HttpResponse(json.dumps({'success': True}), content_type=content_type)
else:
2014-07-09 17:51:07 +08:00
return HttpResponse(json.dumps({'error': str(form.errors.values()[0])}), status=400, content_type=content_type)
@login_required
@sys_staff_required
def sys_group_admin(request):
# 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', '25'))
except ValueError:
current_page = 1
per_page = 25
groups_plus_one = ccnet_threaded_rpc.get_all_groups(per_page * (current_page -1),
per_page +1)
2014-10-22 10:10:58 +08:00
groups = groups_plus_one[:per_page]
2014-10-22 10:10:58 +08:00
for grp in groups:
org_id = ccnet_threaded_rpc.get_org_id_by_group(int(grp.id))
if org_id > 0:
grp.org_id = org_id
grp.org_name = ccnet_threaded_rpc.get_org_by_id(int(org_id)).org_name
if len(groups_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
return render_to_response('sysadmin/sys_group_admin.html', {
'groups': groups,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_group_admin_export_excel(request):
""" Export all groups to excel
"""
next = request.META.get('HTTP_REFERER', None)
if not next:
next = SITE_ROOT
try:
groups = ccnet_threaded_rpc.get_all_groups(-1, -1)
except Exception as e:
logger.error(e)
2015-12-03 18:05:20 +08:00
messages.error(request, _(u'Failed to export Excel'))
return HttpResponseRedirect(next)
head = [_("Name"), _("Creator"), _("Create At")]
data_list = []
for grp in groups:
2015-11-24 13:19:58 +08:00
create_at = tsstr_sec(grp.timestamp) if grp.timestamp else ''
row = [grp.group_name, grp.creator_name, create_at]
data_list.append(row)
2015-12-03 17:56:28 +08:00
wb = write_xls('groups', head, data_list)
if not wb:
2015-12-03 18:05:20 +08:00
messages.error(request, _(u'Failed to export Excel'))
return HttpResponseRedirect(next)
response = HttpResponse(content_type='application/ms-excel')
2015-11-24 13:19:58 +08:00
response['Content-Disposition'] = 'attachment; filename=groups.xlsx'
wb.save(response)
return response
2015-04-25 10:57:14 +08:00
@login_required
@sys_staff_required
def sys_admin_group_info(request, group_id):
group_id = int(group_id)
group = get_group(group_id)
org_id = request.GET.get('org_id', None)
if org_id:
repos = seafile_api.get_org_group_repos(org_id, group_id)
else:
repos = seafile_api.get_repos_by_group(group_id)
2015-04-25 10:57:14 +08:00
members = get_group_members(group_id)
return render_to_response('sysadmin/sys_admin_group_info.html', {
'group': group,
'repos': repos,
'members': members,
2015-10-20 16:35:54 +08:00
'enable_sys_admin_view_repo': ENABLE_SYS_ADMIN_VIEW_REPO,
2015-04-25 10:57:14 +08:00
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_org_admin(request):
2014-08-27 17:14:35 +08:00
# 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', '25'))
except ValueError:
current_page = 1
per_page = 25
2015-09-16 18:40:14 +08:00
try:
from seahub_extra.plan.models import OrgPlan
enable_org_plan = True
except ImportError:
enable_org_plan = False
if enable_org_plan and request.GET.get('filter', '') == 'paid':
orgs = []
ops = OrgPlan.objects.all()
for e in ops:
o = ccnet_threaded_rpc.get_org_by_id(e.org_id)
if not o:
continue
2015-09-16 18:40:14 +08:00
o.quota_usage = seafserv_threaded_rpc.get_org_quota_usage(o.org_id)
o.total_quota = seafserv_threaded_rpc.get_org_quota(o.org_id)
o.expiration = e.expire_date
o.is_expired = True if e.expire_date < timezone.now() else False
orgs.append(o)
return render_to_response('sysadmin/sys_org_admin.html', {
'orgs': orgs,
'enable_org_plan': enable_org_plan,
'hide_paginator': True,
'paid_page': True,
}, context_instance=RequestContext(request))
2014-08-27 17:14:35 +08:00
orgs_plus_one = ccnet_threaded_rpc.get_all_orgs(per_page * (current_page - 1),
per_page + 1)
2015-09-16 18:40:14 +08:00
if len(orgs_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
2014-08-27 17:14:35 +08:00
orgs = orgs_plus_one[:per_page]
2015-01-10 12:07:33 +08:00
if ENABLE_TRIAL_ACCOUNT:
2015-01-10 12:07:33 +08:00
trial_orgs = TrialAccount.objects.filter(user_or_org__in=[x.org_id for x in orgs])
else:
trial_orgs = []
2015-09-16 18:40:14 +08:00
2014-09-26 14:02:19 +08:00
for org in orgs:
org.quota_usage = seafserv_threaded_rpc.get_org_quota_usage(org.org_id)
org.total_quota = seafserv_threaded_rpc.get_org_quota(org.org_id)
2014-08-27 17:14:35 +08:00
from seahub_extra.organizations.settings import ORG_TRIAL_DAYS
if ORG_TRIAL_DAYS > 0:
from datetime import timedelta
org.expiration = datetime.datetime.fromtimestamp(org.ctime / 1e6) + timedelta(days=ORG_TRIAL_DAYS)
2015-01-10 12:07:33 +08:00
org.trial_info = None
for trial_org in trial_orgs:
if trial_org.user_or_org == str(org.org_id):
org.trial_info = {'expire_date': trial_org.expire_date}
if trial_org.expire_date:
org.expiration = trial_org.expire_date
2015-01-10 12:07:33 +08:00
if org.expiration:
org.is_expired = True if org.expiration < timezone.now() else False
else:
org.is_expired = False
return render_to_response('sysadmin/sys_org_admin.html', {
'orgs': orgs,
2014-08-27 17:14:35 +08:00
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
2015-09-16 18:40:14 +08:00
'enable_org_plan': enable_org_plan,
'all_page': True,
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_org_search(request):
org_name = request.GET.get('name', '').lower()
creator = request.GET.get('creator', '').lower()
if not org_name and not creator:
return HttpResponseRedirect(reverse('sys_org_admin'))
orgs = []
orgs_all = ccnet_threaded_rpc.get_all_orgs(-1, -1)
if org_name and creator:
for o in orgs_all:
if org_name in o.org_name.lower() and creator in o.creator.lower():
orgs.append(o)
else:
if org_name:
for o in orgs_all:
if org_name in o.org_name.lower():
orgs.append(o)
if creator:
for o in orgs_all:
if creator in o.creator.lower():
orgs.append(o)
return render_to_response(
'sysadmin/sys_org_search.html', {
'orgs': orgs,
'name': org_name,
'creator': creator,
}, context_instance=RequestContext(request))
@login_required
@sys_staff_required
2014-10-22 10:10:58 +08:00
def sys_org_rename(request, org_id):
if request.method != 'POST':
raise Http404
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_org_admin') if referer is None else referer
new_name = request.POST.get('new_name', None)
if new_name:
try:
ccnet_threaded_rpc.set_org_name(int(org_id), new_name)
messages.success(request, _(u'Success'))
except Exception as e:
logger.error(e)
messages.error(request, _(u'Failed to rename organization'))
return HttpResponseRedirect(next)
2015-09-17 16:14:09 +08:00
@login_required
@require_POST
@sys_staff_required
def sys_org_remove(request, org_id):
"""Remove an org and all members/repos/groups.
Arguments:
- `request`:
- `org_id`:
"""
org_id = int(org_id)
org = ccnet_threaded_rpc.get_org_by_id(org_id)
users = ccnet_threaded_rpc.get_org_emailusers(org.url_prefix, -1, -1)
for u in users:
ccnet_threaded_rpc.remove_org_user(org_id, u.email)
groups = ccnet_threaded_rpc.get_org_groups(org.org_id, -1, -1)
for g in groups:
ccnet_threaded_rpc.remove_org_group(org_id, g.gid)
# remove org repos
seafserv_threaded_rpc.remove_org_repo_by_org_id(org_id)
# remove org
ccnet_threaded_rpc.remove_org(org_id)
messages.success(request, _(u'Successfully deleted.'))
referer = request.META.get('HTTP_REFERER', None)
next = reverse('sys_org_admin') if referer is None else referer
return HttpResponseRedirect(next)
2015-09-17 16:14:09 +08:00
@login_required_ajax
@sys_staff_required
def sys_org_set_member_quota(request, org_id):
if request.method != 'POST':
raise Http404
content_type = 'application/json; charset=utf-8'
try:
member_quota = int(request.POST.get('member_quota', '0'))
except ValueError:
return HttpResponse(json.dumps({ 'error': _('Input should be a number')}),
status=400, content_type=content_type)
2014-12-04 10:47:22 +08:00
if member_quota > 0:
from seahub_extra.organizations.models import OrgMemberQuota
OrgMemberQuota.objects.set_quota(org_id, member_quota)
messages.success(request, _(u'Success'))
return HttpResponse(json.dumps({'success': True}), status=200,
content_type=content_type)
else:
return HttpResponse(json.dumps({ 'error': _('Input number should be greater than 0')}),
status=400, content_type=content_type)
2014-10-22 10:10:58 +08:00
def sys_get_org_base_info(org_id):
org = ccnet_threaded_rpc.get_org_by_id(org_id)
2014-10-22 10:10:58 +08:00
# users
users = ccnet_threaded_rpc.get_org_emailusers(org.url_prefix, -1, -1)
users_count = len(users)
2014-10-22 10:10:58 +08:00
# groups
groups = ccnet_threaded_rpc.get_org_groups(org_id, -1, -1)
groups_count = len(groups)
# quota
total_quota = seafserv_threaded_rpc.get_org_quota(org_id)
quota_usage = seafserv_threaded_rpc.get_org_quota_usage(org_id)
2014-10-22 10:10:58 +08:00
return {
"org": org,
"users": users,
"users_count": users_count,
"groups": groups,
"groups_count": groups_count,
"total_quota": total_quota,
"quota_usage": quota_usage,
}
@login_required
@sys_staff_required
def sys_org_info_user(request, org_id):
org_id = int(org_id)
org_basic_info = sys_get_org_base_info(org_id)
users = org_basic_info["users"]
last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users])
for user in users:
2015-06-26 14:05:39 +08:00
if user.email == request.user.email:
user.is_self = True
try:
user.self_usage =seafserv_threaded_rpc. \
get_org_user_quota_usage(org_id, user.email)
2014-10-22 10:10:58 +08:00
user.share_usage = 0
user.quota = seafserv_threaded_rpc. \
get_org_user_quota(org_id, user.email)
except SearpcError as e:
logger.error(e)
user.self_usage = -1
user.share_usage = -1
user.quota = -1
# populate user last login time
user.last_login = None
for last_login in last_logins:
if last_login.username == user.email:
user.last_login = last_login.last_login
2014-10-22 10:10:58 +08:00
return render_to_response('sysadmin/sys_org_info_user.html',
org_basic_info, context_instance=RequestContext(request))
2014-10-22 10:10:58 +08:00
@login_required
@sys_staff_required
def sys_org_info_group(request, org_id):
org_id = int(org_id)
org_basic_info = sys_get_org_base_info(org_id)
return render_to_response('sysadmin/sys_org_info_group.html',
org_basic_info, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_org_info_library(request, org_id):
org_id = int(org_id)
org_basic_info = sys_get_org_base_info(org_id)
# library
org_repos = seafserv_threaded_rpc.get_org_repo_list(org_id, -1, -1)
for repo in org_repos:
try:
repo.owner = seafserv_threaded_rpc.get_org_repo_owner(repo.id)
except:
repo.owner = None
org_basic_info["org_repos"] = org_repos
return render_to_response('sysadmin/sys_org_info_library.html',
org_basic_info, context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_org_info_setting(request, org_id):
org_id = int(org_id)
org_basic_info = sys_get_org_base_info(org_id)
2014-12-04 10:47:22 +08:00
if getattr(settings, 'ORG_MEMBER_QUOTA_ENABLED', False):
from seahub_extra.organizations.models import OrgMemberQuota
org_basic_info['org_member_quota'] = OrgMemberQuota.objects.get_quota(org_id)
else:
org_basic_info['org_member_quota'] = None
2014-10-22 10:10:58 +08:00
return render_to_response('sysadmin/sys_org_info_setting.html',
2014-12-04 10:47:22 +08:00
org_basic_info,
context_instance=RequestContext(request))
2013-05-25 11:40:40 +08:00
@login_required
@sys_staff_required
def sys_publink_admin(request):
# 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', '100'))
except ValueError:
current_page = 1
per_page = 100
2013-08-14 11:45:41 +08:00
offset = per_page * (current_page -1)
limit = per_page + 1
publinks = FileShare.objects.all()[offset:offset+limit]
2013-08-09 17:35:08 +08:00
if len(publinks) == per_page + 1:
page_next = True
else:
page_next = False
2013-05-25 11:40:40 +08:00
for l in publinks:
if l.is_file_share_link():
2013-05-25 11:40:40 +08:00
l.name = os.path.basename(l.path)
else:
l.name = os.path.dirname(l.path)
return render_to_response(
'sysadmin/sys_publink_admin.html', {
'publinks': publinks,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
2013-08-09 17:35:08 +08:00
'page_next': page_next,
2013-05-25 11:40:40 +08:00
},
context_instance=RequestContext(request))
2013-09-07 11:44:21 +08:00
@login_required_ajax
@sys_staff_required
@require_POST
def sys_publink_remove(request):
"""Remove share links.
"""
content_type = 'application/json; charset=utf-8'
result = {}
token = request.POST.get('t')
if not token:
result = {'error': _(u"Argument missing")}
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
FileShare.objects.filter(token=token).delete()
result = {'success': True}
return HttpResponse(json.dumps(result), content_type=content_type)
@login_required_ajax
@sys_staff_required
@require_POST
def sys_upload_link_remove(request):
"""Remove shared upload links.
"""
content_type = 'application/json; charset=utf-8'
result = {}
token = request.POST.get('t')
if not token:
result = {'error': _(u"Argument missing")}
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
UploadLinkShare.objects.filter(token=token).delete()
result = {'success': True}
return HttpResponse(json.dumps(result), content_type=content_type)
2013-09-07 11:44:21 +08:00
@login_required
@sys_staff_required
def user_search(request):
"""Search a user.
"""
email = request.GET.get('email', '')
2014-10-10 15:35:47 +08:00
2015-06-16 10:39:49 +08:00
users = ccnet_threaded_rpc.search_emailusers('DB', email, -1, -1)
ldap_users = ccnet_threaded_rpc.search_emailusers('LDAP', email, -1, -1)
users.extend(ldap_users)
2013-11-21 15:05:08 +08:00
last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users])
if ENABLE_TRIAL_ACCOUNT:
2015-01-10 12:07:33 +08:00
trial_users = TrialAccount.objects.filter(user_or_org__in=[x.email for x in users])
2015-01-08 16:23:18 +08:00
else:
trial_users = []
2013-11-21 15:05:08 +08:00
for user in users:
_populate_user_quota_usage(user)
# check user's role
if user.role == GUEST_USER:
user.is_guest = True
else:
user.is_guest = False
2013-11-21 15:05:08 +08:00
# populate user last login time
user.last_login = None
for last_login in last_logins:
if last_login.username == user.email:
user.last_login = last_login.last_login
2013-09-07 11:44:21 +08:00
2015-01-08 16:23:18 +08:00
user.trial_info = None
for trial_user in trial_users:
2015-01-10 12:07:33 +08:00
if trial_user.user_or_org == user.email:
2015-01-08 16:23:18 +08:00
user.trial_info = {'expire_date': trial_user.expire_date}
2013-09-07 11:44:21 +08:00
return render_to_response('sysadmin/user_search.html', {
'users': users,
'email': email,
'default_user': DEFAULT_USER,
'guest_user': GUEST_USER,
'is_pro': is_pro_version(),
2013-09-07 11:44:21 +08:00
}, context_instance=RequestContext(request))
2013-09-23 16:58:33 +08:00
@login_required
@sys_staff_required
2015-09-02 11:14:54 +08:00
@require_POST
2013-09-23 16:58:33 +08:00
def sys_repo_transfer(request):
"""Transfer a repo to others.
"""
repo_id = request.POST.get('repo_id', None)
new_owner = request.POST.get('email', None)
next = request.META.get('HTTP_REFERER', None)
if not next:
next = reverse(sys_repo_admin)
if not (repo_id and new_owner):
messages.error(request, _(u'Failed to transfer, invalid arguments.'))
return HttpResponseRedirect(next)
repo = seafile_api.get_repo(repo_id)
if not repo:
messages.error(request, _(u'Library does not exist'))
return HttpResponseRedirect(next)
try:
User.objects.get(email=new_owner)
except User.DoesNotExist:
messages.error(request, _(u'Failed to transfer, user %s not found') % new_owner)
return HttpResponseRedirect(next)
try:
if seafserv_threaded_rpc.get_org_id_by_repo_id(repo_id) > 0:
messages.error(request, _(u'Can not transfer organization library'))
return HttpResponseRedirect(next)
if ccnet_threaded_rpc.get_orgs_by_user(new_owner):
messages.error(request, _(u'Can not transfer library to organization user %s') % new_owner)
return HttpResponseRedirect(next)
except SearpcError: # XXX: ignore rpc not found error
pass
seafile_api.set_repo_owner(repo_id, new_owner)
2015-09-25 16:03:51 +08:00
messages.success(request, _(u'Successfully transfered.'))
return HttpResponseRedirect(next)
2014-12-25 17:17:29 +08:00
2015-09-25 16:03:51 +08:00
@login_required
@sys_staff_required
@require_POST
def sys_repo_delete(request, repo_id):
"""Delete a repo.
"""
next = request.META.get('HTTP_REFERER', None)
if not next:
next = reverse(sys_repo_admin)
if get_system_default_repo_id() == repo_id:
messages.error(request, _('System library can not be deleted.'))
return HttpResponseRedirect(next)
repo = seafile_api.get_repo(repo_id)
if repo: # Handle the case that repo is `None`.
repo_name = repo.name
else:
repo_name = ''
2015-09-25 16:03:51 +08:00
2015-09-28 15:08:35 +08:00
if MULTI_TENANCY:
org_id = seafserv_threaded_rpc.get_org_id_by_repo_id(repo_id)
2015-09-25 16:03:51 +08:00
usernames = get_related_users_by_org_repo(org_id, repo_id)
repo_owner = seafile_api.get_org_repo_owner(repo_id)
else:
2015-09-28 15:08:35 +08:00
org_id = -1
2015-09-25 16:03:51 +08:00
usernames = get_related_users_by_repo(repo_id)
repo_owner = seafile_api.get_repo_owner(repo_id)
seafile_api.remove_repo(repo_id)
repo_deleted.send(sender=None, org_id=org_id, usernames=usernames,
repo_owner=repo_owner, repo_id=repo_id,
repo_name=repo_name)
messages.success(request, _(u'Successfully deleted.'))
return HttpResponseRedirect(next)
2014-02-26 18:24:34 +08:00
@login_required
@sys_staff_required
def sys_traffic_admin(request):
"""List all users from database.
"""
try:
current_page = int(request.GET.get('page', '1'))
per_page = int(request.GET.get('per_page', '25'))
except ValueError:
current_page = 1
per_page = 25
month = request.GET.get('month', '')
if not re.match(r'[\d]{6}', month):
month = datetime.datetime.now().strftime('%Y%m')
start = per_page * (current_page -1)
limit = per_page + 1
traffic_info_list = get_user_traffic_list(month, start, limit)
page_next = len(traffic_info_list) == limit
for info in traffic_info_list:
info['total'] = info['file_view'] + info['file_download'] + info['dir_download']
return render_to_response(
'sysadmin/sys_trafficadmin.html', {
'traffic_info_list': traffic_info_list,
'month': month,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
},
context_instance=RequestContext(request))
2014-04-03 15:19:09 +08:00
2015-08-17 11:20:00 +08:00
@login_required
@sys_staff_required
def sys_virus_scan_records(request):
"""List virus scan records.
"""
try:
current_page = int(request.GET.get('page', '1'))
per_page = int(request.GET.get('per_page', '100'))
except ValueError:
current_page = 1
per_page = 100
records_all = get_virus_record(start=per_page * (current_page - 1),
limit=per_page + 1)
if len(records_all) == per_page + 1:
page_next = True
else:
page_next = False
records = []
for r in records_all[:per_page]:
try:
2015-11-18 10:18:34 +08:00
repo = seafile_api.get_repo(r.repo_id)
except SearpcError as e:
logger.error(e)
continue
if not repo:
2015-08-17 11:20:00 +08:00
continue
2015-11-18 10:18:34 +08:00
r.repo = repo
2015-08-17 11:20:00 +08:00
r.repo.owner = seafile_api.get_repo_owner(r.repo.repo_id)
records.append(r)
return render_to_response(
'sysadmin/sys_virus_scan_records.html', {
'records': records,
'current_page': current_page,
'prev_page': current_page - 1,
'next_page': current_page + 1,
'per_page': per_page,
'page_next': page_next,
}, context_instance=RequestContext(request))
2015-10-22 15:40:15 +08:00
@login_required
2015-08-17 11:20:00 +08:00
@sys_staff_required
@require_POST
2015-08-17 11:20:00 +08:00
def sys_delete_virus_scan_records(request, vid):
r = get_virus_record_by_id(vid)
parent_dir = os.path.dirname(r.file_path)
dirent_name = os.path.basename(r.file_path)
try:
seafile_api.del_file(r.repo_id, parent_dir, dirent_name,
request.user.username)
handle_virus_record(vid)
2015-10-22 15:40:15 +08:00
messages.success(request, _('Successfully deleted.'))
2015-08-17 11:20:00 +08:00
except SearpcError as e:
logger.error(e)
2015-10-22 15:40:15 +08:00
messages.error(request, _('Failed to delete, please try again later.'))
return HttpResponseRedirect(reverse('sys_virus_scan_records'))
2015-08-17 11:20:00 +08:00
@login_required_ajax
2014-04-03 15:19:09 +08:00
@sys_staff_required
def batch_user_make_admin(request):
2014-04-16 17:39:23 +08:00
"""Batch make users as admins.
"""
if request.method != 'POST':
2014-04-16 11:47:53 +08:00
raise Http404
2014-04-03 15:19:09 +08:00
content_type = 'application/json; charset=utf-8'
set_admin_emails = request.POST.get('set_admin_emails')
set_admin_emails = string2list(set_admin_emails)
2014-04-03 17:31:43 +08:00
success = []
failed = []
for email in set_admin_emails:
try:
2014-04-03 15:19:09 +08:00
user = User.objects.get(email=email)
2014-04-03 17:31:43 +08:00
except User.DoesNotExist:
failed.append(email)
continue
2015-06-26 14:05:39 +08:00
user.is_staff = True
user.save()
success.append(email)
for item in success:
2014-04-16 17:39:23 +08:00
messages.success(request, _(u'Successfully set %s as admin.') % item)
2014-04-03 17:31:43 +08:00
for item in failed:
2014-04-16 17:39:23 +08:00
messages.error(request, _(u'Failed to set %s as admin: user does not exist.') % item)
2014-04-03 17:31:43 +08:00
return HttpResponse(json.dumps({'success': True,}), content_type=content_type)
2014-05-09 17:12:25 +08:00
@login_required
@sys_staff_required
def batch_add_user(request):
2014-05-16 17:43:36 +08:00
"""Batch add users. Import users from CSV file.
"""
2014-05-09 17:12:25 +08:00
if request.method != 'POST':
raise Http404
2014-05-16 17:43:36 +08:00
form = BatchAddUserForm(request.POST, request.FILES)
if form.is_valid():
content = request.FILES['file'].read()
2014-05-09 17:12:25 +08:00
encoding = chardet.detect(content)['encoding']
if encoding != 'utf-8':
content = content.decode(encoding, 'replace').encode('utf-8')
filestream = StringIO.StringIO(content)
2014-05-16 17:43:36 +08:00
reader = csv.reader(filestream)
2014-05-09 17:12:25 +08:00
2014-05-16 17:43:36 +08:00
for row in reader:
if not row:
continue
2014-05-09 17:12:25 +08:00
2014-05-16 17:43:36 +08:00
username = row[0].strip()
password = row[1].strip()
2014-05-09 17:12:25 +08:00
2014-05-16 17:43:36 +08:00
if not is_valid_username(username):
continue
2014-05-09 17:12:25 +08:00
2014-05-16 17:43:36 +08:00
if password == '':
continue
2014-05-09 17:12:25 +08:00
2014-05-16 17:43:36 +08:00
try:
User.objects.get(email=username)
continue
except User.DoesNotExist:
User.objects.create_user(username, password, is_staff=False,
is_active=True)
send_html_email_with_dj_template(
username, dj_template='sysadmin/user_batch_add_email.html',
subject=_(u'You are invited to join %s') % SITE_NAME,
context={
'user': email2nickname(request.user.username),
'email': username,
'password': password,
})
2014-06-17 17:08:43 +08:00
messages.success(request, _('Import succeeded'))
2014-05-09 17:12:25 +08:00
else:
messages.error(request, _(u'Please select a csv file first.'))
2014-05-16 17:43:36 +08:00
next = request.META.get('HTTP_REFERER', reverse(sys_user_admin))
2014-05-09 17:12:25 +08:00
return HttpResponseRedirect(next)
@login_required
def sys_sudo_mode(request):
if request.method not in ('GET', 'POST'):
return HttpResponseNotAllowed
# here we can't use @sys_staff_required
if not request.user.is_staff:
2015-10-19 18:01:55 +08:00
raise Http404
password_error = False
if request.method == 'POST':
password = request.POST.get('password')
if password:
user = authenticate(username=request.user.username, password=password)
2015-05-05 13:34:03 +08:00
if user:
update_sudo_mode_ts(request)
return HttpResponseRedirect(
request.GET.get('next', reverse('sys_useradmin')))
password_error = True
2015-05-05 13:34:03 +08:00
enable_shib_login = getattr(settings, 'ENABLE_SHIB_LOGIN', False)
return render_to_response(
'sysadmin/sudo_mode.html', {
2015-05-05 13:34:03 +08:00
'password_error': password_error,
'enable_shib_login': enable_shib_login,
},
context_instance=RequestContext(request))
@login_required
@sys_staff_required
def sys_settings(request):
"""List and change seahub settings in admin panel.
"""
2015-09-21 11:48:07 +08:00
DIGIT_WEB_SETTINGS = ('DISABLE_SYNC_WITH_ANY_FOLDER', 'ENABLE_SIGNUP',
'ACTIVATE_AFTER_REGISTRATION', 'REGISTRATION_SEND_MAIL',
'LOGIN_REMEMBER_DAYS', 'REPO_PASSWORD_MIN_LENGTH',
'ENABLE_REPO_HISTORY_SETTING', 'USER_STRONG_PASSWORD_REQUIRED',
'ENABLE_ENCRYPTED_LIBRARY', 'USER_PASSWORD_MIN_LENGTH',
'USER_PASSWORD_STRENGTH_LEVEL', 'SHARE_LINK_PASSWORD_MIN_LENGTH')
2015-09-21 11:48:07 +08:00
STRING_WEB_SETTINGS = ('SERVICE_URL', 'FILE_SERVER_ROOT',)
if request.is_ajax() and request.method == "POST":
content_type = 'application/json; charset=utf-8'
result = {}
2015-09-21 11:48:07 +08:00
key = request.POST.get('key', None)
value = request.POST.get('value', None)
if key not in dir(config) or value is None:
result['error'] = _(u'Invalid setting')
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
if value.isdigit():
if key in DIGIT_WEB_SETTINGS:
value = int(value)
else:
result['error'] = _(u'Invalid value')
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
if key == 'USER_PASSWORD_STRENGTH_LEVEL' and value not in (1,2,3,4):
result['error'] = _(u'Invalid value')
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
2015-09-21 11:48:07 +08:00
else:
if key not in STRING_WEB_SETTINGS:
result['error'] = _(u'Invalid value')
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
try:
setattr(config, key, value)
result['success'] = True
return HttpResponse(json.dumps(result), content_type=content_type)
except AttributeError as e:
logger.error(e)
result['error'] = _(u'Internal server error')
return HttpResponse(json.dumps(result), status=500, content_type=content_type)
config_dict = {}
2015-09-21 11:48:07 +08:00
for key in dir(config):
value = getattr(config, key)
config_dict[key] = value
return render_to_response('sysadmin/settings.html', {
'config_dict': config_dict,
}, context_instance=RequestContext(request))
@login_required_ajax
@sys_staff_required
def sys_check_license(request):
"""Check seafile license expiration.
"""
if not is_pro_version():
raise Http404
content_type = 'application/json; charset=utf-8'
result = {}
license_file = os.path.join(settings.PROJECT_ROOT, '../../seafile-license.txt')
license_dict = parse_license(license_file)
if license_dict:
try:
expiration = license_dict['Expiration']
except KeyError as e:
logger.error(e)
result['error'] = str(e)
return HttpResponse(json.dumps(result), status=500, content_type=content_type)
struct_time = datetime.datetime.strptime(expiration, "%Y-%m-%d")
expiration_timestamp = time.mktime(struct_time.timetuple())
if time.time() > expiration_timestamp:
# already expired
result['already_expired'] = True
elif time.time() + 30 * 24 * 60 * 60 > expiration_timestamp:
# will be expired in 30 days
result['to_be_expired'] = True
result['expiration_date'] = expiration
return HttpResponse(json.dumps(result), content_type=content_type)