mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-01 23:20:51 +00:00
user reset repo password (#2913)
* user reset encrypted repo's password * update * send email when user reset encrypted repo's password * resetEncryptedRepoPassword -> resetAndSendEncryptedRepoPassword * update message * update message * bold email when show success msg
This commit is contained in:
@@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import toaster from '../../components/toast';
|
||||||
|
import { Button, Form, FormGroup, Label, Input, Modal, ModalHeader, ModalBody, ModalFooter, Alert } from 'reactstrap';
|
||||||
|
import { gettext, contactEmail } from '../../utils/constants';
|
||||||
|
import { Utils } from '../../utils/utils';
|
||||||
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
repoID: PropTypes.string.isRequired,
|
||||||
|
toggleDialog: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResetEncryptedRepoPasswordDialog extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
errMessage: '',
|
||||||
|
showLoading: true,
|
||||||
|
showSuccess: false,
|
||||||
|
showError: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
seafileAPI.resetAndSendEncryptedRepoPassword(this.props.repoID).then((res) => {
|
||||||
|
this.setState({showLoading: false});
|
||||||
|
this.setState({showSuccess: true});
|
||||||
|
}).catch((error) => {
|
||||||
|
if (error.response) {
|
||||||
|
this.setState({
|
||||||
|
errMessage: error.response.data.error_msg
|
||||||
|
});
|
||||||
|
this.setState({showLoading: false});
|
||||||
|
this.setState({showError: true});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
let user_email = '<strong>' + contactEmail + '</strong>';
|
||||||
|
let message = gettext('New password has been sent to your email {mail}. Please check your mailbox. If you don’t receive the password, please check if your email address is properly configured.').replace('{mail}', user_email);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={true} centered={true}>
|
||||||
|
<ModalHeader toggle={this.props.toggleDialog}>
|
||||||
|
{gettext('Reset library password')}
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalBody>
|
||||||
|
{this.state.showLoading && (
|
||||||
|
<span>{gettext('Sending new password...')}</span>
|
||||||
|
)}
|
||||||
|
{this.state.showSuccess && (
|
||||||
|
<div dangerouslySetInnerHTML={{__html:message}} />
|
||||||
|
)}
|
||||||
|
{this.state.showError && (
|
||||||
|
<span className="err-message">{this.state.errMessage}</span>
|
||||||
|
)}
|
||||||
|
</ModalBody>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetEncryptedRepoPasswordDialog.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default ResetEncryptedRepoPasswordDialog;
|
@@ -6,6 +6,7 @@ import TableBody from './table-body';
|
|||||||
import ModalPortal from '../../components/modal-portal';
|
import ModalPortal from '../../components/modal-portal';
|
||||||
import LibHistorySetting from '../../components/dialog/lib-history-setting-dialog';
|
import LibHistorySetting from '../../components/dialog/lib-history-setting-dialog';
|
||||||
import TransferDialog from '../../components/dialog/transfer-dialog';
|
import TransferDialog from '../../components/dialog/transfer-dialog';
|
||||||
|
import ResetEncryptedRepoPasswordDialog from '../../components/dialog/reset-encrypted-repo-password-dialog';
|
||||||
import DeleteRepoDialog from '../../components/dialog/delete-repo-dialog';
|
import DeleteRepoDialog from '../../components/dialog/delete-repo-dialog';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
@@ -29,6 +30,7 @@ class Content extends Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
deleteItemPopupOpen: false,
|
deleteItemPopupOpen: false,
|
||||||
showTransfer: false,
|
showTransfer: false,
|
||||||
|
showResetEncryptedRepoPassword: false,
|
||||||
itemName: '',
|
itemName: '',
|
||||||
showHistorySetting: false,
|
showHistorySetting: false,
|
||||||
showDetails: false,
|
showDetails: false,
|
||||||
@@ -67,6 +69,14 @@ class Content extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onResetEncryptedRepoPassword = (itemName, itemID) => {
|
||||||
|
this.setState({
|
||||||
|
showResetEncryptedRepoPassword: !this.state.showResetEncryptedRepoPassword,
|
||||||
|
itemName: itemName,
|
||||||
|
libID: itemID
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
sortByName = (e) => {
|
sortByName = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const sortBy = 'name';
|
const sortBy = 'name';
|
||||||
@@ -143,6 +153,7 @@ class Content extends Component {
|
|||||||
onTransfer={this.onTransfer}
|
onTransfer={this.onTransfer}
|
||||||
showDeleteItemPopup={this.showDeleteItemPopup}
|
showDeleteItemPopup={this.showDeleteItemPopup}
|
||||||
onHistorySetting={this.onHistorySetting}
|
onHistorySetting={this.onHistorySetting}
|
||||||
|
onResetEncryptedRepoPassword={this.onResetEncryptedRepoPassword}
|
||||||
/>
|
/>
|
||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
@@ -177,6 +188,14 @@ class Content extends Component {
|
|||||||
/>
|
/>
|
||||||
</ModalPortal>
|
</ModalPortal>
|
||||||
}
|
}
|
||||||
|
{this.state.showResetEncryptedRepoPassword &&
|
||||||
|
<ModalPortal>
|
||||||
|
<ResetEncryptedRepoPasswordDialog
|
||||||
|
repoID={this.state.libID}
|
||||||
|
toggleDialog={this.onResetEncryptedRepoPassword}
|
||||||
|
/>
|
||||||
|
</ModalPortal>
|
||||||
|
}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Link } from '@reach/router';
|
import { Link } from '@reach/router';
|
||||||
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
|
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
|
||||||
import { gettext, siteRoot, storages, folderPermEnabled, enableRepoSnapshotLabel } from '../../utils/constants';
|
import { gettext, siteRoot, storages, folderPermEnabled, enableResetEncryptedRepoPassword, isEmailConfigured, enableRepoSnapshotLabel } from '../../utils/constants';
|
||||||
import { Utils } from '../../utils/utils';
|
import { Utils } from '../../utils/utils';
|
||||||
import { seafileAPI } from '../../utils/seafile-api';
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
import Rename from '../../components/rename';
|
import Rename from '../../components/rename';
|
||||||
@@ -20,6 +20,7 @@ const propTypes = {
|
|||||||
onTransfer: PropTypes.func.isRequired,
|
onTransfer: PropTypes.func.isRequired,
|
||||||
showDeleteItemPopup: PropTypes.func.isRequired,
|
showDeleteItemPopup: PropTypes.func.isRequired,
|
||||||
onHistorySetting: PropTypes.func.isRequired,
|
onHistorySetting: PropTypes.func.isRequired,
|
||||||
|
onResetEncryptedRepoPassword: PropTypes.func.isRequired,
|
||||||
onRepoDetails: PropTypes.func.isRequired,
|
onRepoDetails: PropTypes.func.isRequired,
|
||||||
onItemClick: PropTypes.func.isRequired
|
onItemClick: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
@@ -150,6 +151,12 @@ class Item extends Component {
|
|||||||
this.setState({isChangeRepoPasswordDialogOpen: !this.state.isChangeRepoPasswordDialogOpen});
|
this.setState({isChangeRepoPasswordDialogOpen: !this.state.isChangeRepoPasswordDialogOpen});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetEncryptedRepoPassword = () => {
|
||||||
|
const repoName = this.props.data.repo_name;
|
||||||
|
const repoID = this.props.data.repo_id;
|
||||||
|
this.props.onResetEncryptedRepoPassword(repoName, repoID);
|
||||||
|
}
|
||||||
|
|
||||||
folderPerm = () => {
|
folderPerm = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +178,8 @@ class Item extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const data = this.props.data;
|
const data = this.props.data;
|
||||||
|
const showResetPasswordMenuItem = data.encrypted && enableResetEncryptedRepoPassword && isEmailConfigured;
|
||||||
|
|
||||||
data.icon_url = Utils.getLibIconUrl(data);
|
data.icon_url = Utils.getLibIconUrl(data);
|
||||||
data.icon_title = Utils.getLibIconTitle(data);
|
data.icon_title = Utils.getLibIconTitle(data);
|
||||||
data.url = `${siteRoot}library/${data.repo_id}/${Utils.encodePath(data.repo_name)}/`;
|
data.url = `${siteRoot}library/${data.repo_id}/${Utils.encodePath(data.repo_name)}/`;
|
||||||
@@ -200,6 +208,7 @@ class Item extends Component {
|
|||||||
<DropdownItem onClick={this.transfer}>{gettext('Transfer')}</DropdownItem>
|
<DropdownItem onClick={this.transfer}>{gettext('Transfer')}</DropdownItem>
|
||||||
<DropdownItem onClick={this.historySetting}>{gettext('History Setting')}</DropdownItem>
|
<DropdownItem onClick={this.historySetting}>{gettext('History Setting')}</DropdownItem>
|
||||||
{data.encrypted ? <DropdownItem onClick={this.changePassword}>{gettext('Change Password')}</DropdownItem> : ''}
|
{data.encrypted ? <DropdownItem onClick={this.changePassword}>{gettext('Change Password')}</DropdownItem> : ''}
|
||||||
|
{showResetPasswordMenuItem ? <DropdownItem onClick={this.resetEncryptedRepoPassword}>{gettext('Reset Password')}</DropdownItem> : ''}
|
||||||
{folderPermEnabled ? <DropdownItem onClick={this.folderPerm}>{gettext('Folder Permission')}</DropdownItem> : ''}
|
{folderPermEnabled ? <DropdownItem onClick={this.folderPerm}>{gettext('Folder Permission')}</DropdownItem> : ''}
|
||||||
<DropdownItem onClick={this.showDetails}>{gettext('Details')}</DropdownItem>
|
<DropdownItem onClick={this.showDetails}>{gettext('Details')}</DropdownItem>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@@ -7,6 +7,7 @@ const propTypes = {
|
|||||||
onRenameRepo: PropTypes.func.isRequired,
|
onRenameRepo: PropTypes.func.isRequired,
|
||||||
onDeleteRepo: PropTypes.func.isRequired,
|
onDeleteRepo: PropTypes.func.isRequired,
|
||||||
onTransfer: PropTypes.func.isRequired,
|
onTransfer: PropTypes.func.isRequired,
|
||||||
|
onResetEncryptedRepoPassword: PropTypes.func.isRequired,
|
||||||
showDeleteItemPopup: PropTypes.func.isRequired,
|
showDeleteItemPopup: PropTypes.func.isRequired,
|
||||||
onHistorySetting: PropTypes.func.isRequired,
|
onHistorySetting: PropTypes.func.isRequired,
|
||||||
onRepoDetails: PropTypes.func.isRequired,
|
onRepoDetails: PropTypes.func.isRequired,
|
||||||
@@ -37,6 +38,7 @@ class TableBody extends Component {
|
|||||||
onRenameRepo={this.props.onRenameRepo}
|
onRenameRepo={this.props.onRenameRepo}
|
||||||
onDeleteRepo={this.props.onDeleteRepo}
|
onDeleteRepo={this.props.onDeleteRepo}
|
||||||
onTransfer={this.props.onTransfer}
|
onTransfer={this.props.onTransfer}
|
||||||
|
onResetEncryptedRepoPassword={this.props.onResetEncryptedRepoPassword}
|
||||||
showDeleteItemPopup={this.props.showDeleteItemPopup}
|
showDeleteItemPopup={this.props.showDeleteItemPopup}
|
||||||
onHistorySetting={this.props.onHistorySetting}
|
onHistorySetting={this.props.onHistorySetting}
|
||||||
onRepoDetails={this.props.onRepoDetails}
|
onRepoDetails={this.props.onRepoDetails}
|
||||||
|
@@ -27,6 +27,8 @@ export const canViewOrg = window.app.pageOptions.canViewOrg === 'True';
|
|||||||
export const fileAuditEnabled = window.app.pageOptions.fileAuditEnabled ? true : false;
|
export const fileAuditEnabled = window.app.pageOptions.fileAuditEnabled ? true : false;
|
||||||
export const enableFileComment = window.app.pageOptions.enableFileComment ? true : false;
|
export const enableFileComment = window.app.pageOptions.enableFileComment ? true : false;
|
||||||
export const folderPermEnabled = window.app.pageOptions.folderPermEnabled === 'True';
|
export const folderPermEnabled = window.app.pageOptions.folderPermEnabled === 'True';
|
||||||
|
export const enableResetEncryptedRepoPassword = window.app.pageOptions.enableResetEncryptedRepoPassword === 'True';
|
||||||
|
export const isEmailConfigured = window.app.pageOptions.isEmailConfigured === 'True';
|
||||||
export const enableUploadFolder = window.app.pageOptions.enableUploadFolder === 'True';
|
export const enableUploadFolder = window.app.pageOptions.enableUploadFolder === 'True';
|
||||||
export const enableResumableFileUpload = window.app.pageOptions.enableResumableFileUpload === 'True';
|
export const enableResumableFileUpload = window.app.pageOptions.enableResumableFileUpload === 'True';
|
||||||
export const storages = window.app.pageOptions.storages; // storage backends
|
export const storages = window.app.pageOptions.storages; // storage backends
|
||||||
|
80
seahub/api2/endpoints/repo_send_new_password.py
Normal file
80
seahub/api2/endpoints/repo_send_new_password.py
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from rest_framework.authentication import SessionAuthentication
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework import status
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.utils.crypto import get_random_string
|
||||||
|
|
||||||
|
from seaserv import seafile_api
|
||||||
|
|
||||||
|
from seahub.api2.authentication import TokenAuthentication
|
||||||
|
from seahub.api2.throttling import UserRateThrottle
|
||||||
|
from seahub.api2.utils import api_error
|
||||||
|
from seahub.api2.views import HTTP_520_OPERATION_FAILED
|
||||||
|
|
||||||
|
from seahub.utils import IS_EMAIL_CONFIGURED, send_html_email
|
||||||
|
from seahub.utils.repo import is_repo_owner
|
||||||
|
from seahub.base.models import RepoSecretKey
|
||||||
|
from seahub.base.templatetags.seahub_tags import email2contact_email
|
||||||
|
|
||||||
|
from seahub.settings import ENABLE_RESET_ENCRYPTED_REPO_PASSWORD
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class RepoSendNewPassword(APIView):
|
||||||
|
|
||||||
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
throttle_classes = (UserRateThrottle,)
|
||||||
|
|
||||||
|
def post(self, request, repo_id):
|
||||||
|
""" Only used for reset encrypted repo's password, and then send new
|
||||||
|
password to user's mainbox.
|
||||||
|
|
||||||
|
Permission checking:
|
||||||
|
1. repo owner.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not ENABLE_RESET_ENCRYPTED_REPO_PASSWORD or \
|
||||||
|
not IS_EMAIL_CONFIGURED:
|
||||||
|
error_msg = _(u'Feature disabled.')
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
# resource check
|
||||||
|
repo = seafile_api.get_repo(repo_id)
|
||||||
|
if not repo:
|
||||||
|
error_msg = 'Library %s not found.' % repo_id
|
||||||
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
|
if not repo.encrypted:
|
||||||
|
error_msg = 'Library %s is not encrypted.' % repo_id
|
||||||
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
# permission check
|
||||||
|
username = request.user.username
|
||||||
|
if not is_repo_owner(request, repo_id, username):
|
||||||
|
error_msg = 'Permission denied.'
|
||||||
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
|
secret_key = RepoSecretKey.objects.get_secret_key(repo_id)
|
||||||
|
if not secret_key:
|
||||||
|
error_msg = _(u"Can not reset this library's password.")
|
||||||
|
return api_error(HTTP_520_OPERATION_FAILED, error_msg)
|
||||||
|
|
||||||
|
new_password = get_random_string(10)
|
||||||
|
try:
|
||||||
|
seafile_api.reset_repo_passwd(repo_id, username, secret_key, new_password)
|
||||||
|
content = {'repo_name': repo.name, 'password': new_password,}
|
||||||
|
send_html_email(_(u'New password of library %s') % repo.name,
|
||||||
|
'snippets/reset_repo_password.html', content,
|
||||||
|
None, [email2contact_email(username)])
|
||||||
|
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})
|
@@ -157,7 +157,7 @@ class RepoSetPassword(APIView):
|
|||||||
|
|
||||||
secret_key = RepoSecretKey.objects.get_secret_key(repo_id)
|
secret_key = RepoSecretKey.objects.get_secret_key(repo_id)
|
||||||
if not secret_key:
|
if not secret_key:
|
||||||
error_msg = 'repo_id invalid.'
|
error_msg = _(u"Can not reset this library's password.")
|
||||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@@ -50,6 +50,8 @@
|
|||||||
fileAuditEnabled: '{{ file_audit_enabled }}',
|
fileAuditEnabled: '{{ file_audit_enabled }}',
|
||||||
enableFileComment: '{{ enable_file_comment }}',
|
enableFileComment: '{{ enable_file_comment }}',
|
||||||
folderPermEnabled: '{{ folder_perm_enabled }}',
|
folderPermEnabled: '{{ folder_perm_enabled }}',
|
||||||
|
enableResetEncryptedRepoPassword: '{{ enable_reset_encrypted_repo_password }}',
|
||||||
|
isEmailConfigured: '{{ is_email_configured }}',
|
||||||
enableUploadFolder: '{{ enable_upload_folder }}',
|
enableUploadFolder: '{{ enable_upload_folder }}',
|
||||||
enableResumableFileUpload: '{{ enable_resumable_fileupload }}',
|
enableResumableFileUpload: '{{ enable_resumable_fileupload }}',
|
||||||
// storage backends
|
// storage backends
|
||||||
|
14
seahub/templates/snippets/reset_repo_password.html
Normal file
14
seahub/templates/snippets/reset_repo_password.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{% extends 'email_base.html' %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block email_con %}
|
||||||
|
|
||||||
|
<p style="color:#121214;font-size:14px;">{% trans "Hi," %}</p>
|
||||||
|
|
||||||
|
<p style="font-size:14px;color:#434144;">
|
||||||
|
{% blocktrans %}The new password of library {{repo_name}} is {{password}}. Please change it as soon as possible.{% endblocktrans %}
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
@@ -54,6 +54,7 @@ from seahub.api2.endpoints.repo_trash import RepoTrash
|
|||||||
from seahub.api2.endpoints.deleted_repos import DeletedRepos
|
from seahub.api2.endpoints.deleted_repos import DeletedRepos
|
||||||
from seahub.api2.endpoints.repo_history import RepoHistory
|
from seahub.api2.endpoints.repo_history import RepoHistory
|
||||||
from seahub.api2.endpoints.repo_set_password import RepoSetPassword
|
from seahub.api2.endpoints.repo_set_password import RepoSetPassword
|
||||||
|
from seahub.api2.endpoints.repo_send_new_password import RepoSendNewPassword
|
||||||
from seahub.api2.endpoints.zip_task import ZipTaskView
|
from seahub.api2.endpoints.zip_task import ZipTaskView
|
||||||
from seahub.api2.endpoints.share_link_zip_task import ShareLinkZipTaskView
|
from seahub.api2.endpoints.share_link_zip_task import ShareLinkZipTaskView
|
||||||
from seahub.api2.endpoints.query_zip_progress import QueryZipProgressView
|
from seahub.api2.endpoints.query_zip_progress import QueryZipProgressView
|
||||||
@@ -317,6 +318,7 @@ urlpatterns = [
|
|||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/trash/$', RepoTrash.as_view(), name='api-v2.1-repo-trash'),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/trash/$', RepoTrash.as_view(), name='api-v2.1-repo-trash'),
|
||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/history/$', RepoHistory.as_view(), name='api-v2.1-repo-history'),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/history/$', RepoHistory.as_view(), name='api-v2.1-repo-history'),
|
||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/set-password/$', RepoSetPassword.as_view(), name="api-v2.1-repo-set-password"),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/set-password/$', RepoSetPassword.as_view(), name="api-v2.1-repo-set-password"),
|
||||||
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/send-new-password/$', RepoSendNewPassword.as_view(), name="api-v2.1-repo-send-new-password"),
|
||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/repo-tags/$', RepoTagsView.as_view(), name='api-v2.1-repo-tags'),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/repo-tags/$', RepoTagsView.as_view(), name='api-v2.1-repo-tags'),
|
||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/repo-tags/(?P<repo_tag_id>\d+)/$', RepoTagView.as_view(), name='api-v2.1-repo-tag'),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/repo-tags/(?P<repo_tag_id>\d+)/$', RepoTagView.as_view(), name='api-v2.1-repo-tag'),
|
||||||
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/file-tags/$', RepoFileTagsView.as_view(), name='api-v2.1-file-tags'),
|
url(r'^api/v2.1/repos/(?P<repo_id>[-0-9a-f]{36})/file-tags/$', RepoFileTagsView.as_view(), name='api-v2.1-file-tags'),
|
||||||
|
@@ -43,7 +43,7 @@ from seahub.utils import render_permission_error, render_error, \
|
|||||||
get_user_repos, EMPTY_SHA1, gen_file_get_url, \
|
get_user_repos, EMPTY_SHA1, gen_file_get_url, \
|
||||||
new_merge_with_no_conflict, get_max_upload_file_size, \
|
new_merge_with_no_conflict, get_max_upload_file_size, \
|
||||||
is_pro_version, FILE_AUDIT_ENABLED, is_valid_dirent_name, \
|
is_pro_version, FILE_AUDIT_ENABLED, is_valid_dirent_name, \
|
||||||
is_windows_operating_system, get_service_url, seafevents_api
|
is_windows_operating_system, seafevents_api, IS_EMAIL_CONFIGURED
|
||||||
from seahub.utils.star import get_dir_starred_files
|
from seahub.utils.star import get_dir_starred_files
|
||||||
from seahub.utils.repo import get_library_storages, parse_repo_perm
|
from seahub.utils.repo import get_library_storages, parse_repo_perm
|
||||||
from seahub.utils.file_op import check_file_lock
|
from seahub.utils.file_op import check_file_lock
|
||||||
@@ -55,7 +55,8 @@ import seahub.settings as settings
|
|||||||
from seahub.settings import AVATAR_FILE_STORAGE, \
|
from seahub.settings import AVATAR_FILE_STORAGE, \
|
||||||
ENABLE_SUB_LIBRARY, ENABLE_FOLDER_PERM, ENABLE_REPO_SNAPSHOT_LABEL, \
|
ENABLE_SUB_LIBRARY, ENABLE_FOLDER_PERM, ENABLE_REPO_SNAPSHOT_LABEL, \
|
||||||
UNREAD_NOTIFICATIONS_REQUEST_INTERVAL, SHARE_LINK_EXPIRE_DAYS_MIN, \
|
UNREAD_NOTIFICATIONS_REQUEST_INTERVAL, SHARE_LINK_EXPIRE_DAYS_MIN, \
|
||||||
SHARE_LINK_EXPIRE_DAYS_MAX, SHARE_LINK_EXPIRE_DAYS_DEFAULT, SEAFILE_COLLAB_SERVER
|
SHARE_LINK_EXPIRE_DAYS_MAX, SHARE_LINK_EXPIRE_DAYS_DEFAULT, \
|
||||||
|
SEAFILE_COLLAB_SERVER, ENABLE_RESET_ENCRYPTED_REPO_PASSWORD
|
||||||
|
|
||||||
from seahub.wopi.settings import ENABLE_OFFICE_WEB_APP
|
from seahub.wopi.settings import ENABLE_OFFICE_WEB_APP
|
||||||
from seahub.onlyoffice.settings import ENABLE_ONLYOFFICE
|
from seahub.onlyoffice.settings import ENABLE_ONLYOFFICE
|
||||||
@@ -1225,6 +1226,8 @@ def react_fake_view(request, **kwargs):
|
|||||||
'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX,
|
'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX,
|
||||||
'enable_encrypted_library': config.ENABLE_ENCRYPTED_LIBRARY,
|
'enable_encrypted_library': config.ENABLE_ENCRYPTED_LIBRARY,
|
||||||
'enable_repo_history_setting': config.ENABLE_REPO_HISTORY_SETTING,
|
'enable_repo_history_setting': config.ENABLE_REPO_HISTORY_SETTING,
|
||||||
|
'enable_reset_encrypted_repo_password': ENABLE_RESET_ENCRYPTED_REPO_PASSWORD,
|
||||||
|
'is_email_configured': IS_EMAIL_CONFIGURED,
|
||||||
})
|
})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
Reference in New Issue
Block a user