mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-02 23:48:47 +00:00
show share/upload link password
This commit is contained in:
@@ -400,6 +400,14 @@ class GenerateShareLink extends React.Component {
|
|||||||
</dd>
|
</dd>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
|
{sharedLinkInfo.password && (
|
||||||
|
<FormGroup className="mb-0">
|
||||||
|
<dt className="text-secondary font-weight-normal">{gettext('Password:')}</dt>
|
||||||
|
<dd className="d-flex">
|
||||||
|
<span>{sharedLinkInfo.password}</span>
|
||||||
|
</dd>
|
||||||
|
</FormGroup>
|
||||||
|
)}
|
||||||
{sharedLinkInfo.expire_date && (
|
{sharedLinkInfo.expire_date && (
|
||||||
<FormGroup className="mb-0">
|
<FormGroup className="mb-0">
|
||||||
<dt className="text-secondary font-weight-normal">{gettext('Expiration Date:')}</dt>
|
<dt className="text-secondary font-weight-normal">{gettext('Expiration Date:')}</dt>
|
||||||
|
@@ -16,6 +16,7 @@ class ShareLink {
|
|||||||
this.link = object.link;
|
this.link = object.link;
|
||||||
this.view_cnt = object.view_cnt;
|
this.view_cnt = object.view_cnt;
|
||||||
this.ctime = object.ctime;
|
this.ctime = object.ctime;
|
||||||
|
this.password = object.password;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ from django.utils.translation import ugettext as _
|
|||||||
from seahub.api2.authentication import TokenAuthentication
|
from seahub.api2.authentication import TokenAuthentication
|
||||||
from seahub.api2.throttling import UserRateThrottle
|
from seahub.api2.throttling import UserRateThrottle
|
||||||
from seahub.api2.utils import api_error
|
from seahub.api2.utils import api_error
|
||||||
from seahub.utils import IS_EMAIL_CONFIGURED, is_valid_username, \
|
from seahub.utils import IS_EMAIL_CONFIGURED, \
|
||||||
is_valid_email, string2list, gen_shared_link, send_html_email, \
|
is_valid_email, string2list, gen_shared_link, send_html_email, \
|
||||||
get_site_name
|
get_site_name
|
||||||
from seahub.share.models import FileShare
|
from seahub.share.models import FileShare
|
||||||
@@ -21,6 +21,7 @@ from seahub.profile.models import Profile
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SendShareLinkView(APIView):
|
class SendShareLinkView(APIView):
|
||||||
|
|
||||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
@@ -80,6 +81,7 @@ class SendShareLinkView(APIView):
|
|||||||
'email': username,
|
'email': username,
|
||||||
'to_email': to_email,
|
'to_email': to_email,
|
||||||
'extra_msg': extra_msg,
|
'extra_msg': extra_msg,
|
||||||
|
'password': link.get_password(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if REPLACE_FROM_EMAIL:
|
if REPLACE_FROM_EMAIL:
|
||||||
|
@@ -11,7 +11,7 @@ from django.utils.translation import ugettext as _
|
|||||||
from seahub.api2.authentication import TokenAuthentication
|
from seahub.api2.authentication import TokenAuthentication
|
||||||
from seahub.api2.throttling import UserRateThrottle
|
from seahub.api2.throttling import UserRateThrottle
|
||||||
from seahub.api2.utils import api_error
|
from seahub.api2.utils import api_error
|
||||||
from seahub.utils import IS_EMAIL_CONFIGURED, is_valid_username, \
|
from seahub.utils import IS_EMAIL_CONFIGURED, \
|
||||||
is_valid_email, string2list, gen_shared_upload_link, send_html_email, \
|
is_valid_email, string2list, gen_shared_upload_link, send_html_email, \
|
||||||
get_site_name
|
get_site_name
|
||||||
from seahub.share.models import UploadLinkShare
|
from seahub.share.models import UploadLinkShare
|
||||||
@@ -20,6 +20,7 @@ from seahub.profile.models import Profile
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SendUploadLinkView(APIView):
|
class SendUploadLinkView(APIView):
|
||||||
|
|
||||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
@@ -79,6 +80,7 @@ class SendUploadLinkView(APIView):
|
|||||||
'email': username,
|
'email': username,
|
||||||
'to_email': to_email,
|
'to_email': to_email,
|
||||||
'extra_msg': extra_msg,
|
'extra_msg': extra_msg,
|
||||||
|
'password': link.get_password(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if REPLACE_FROM_EMAIL:
|
if REPLACE_FROM_EMAIL:
|
||||||
@@ -106,4 +108,3 @@ class SendUploadLinkView(APIView):
|
|||||||
result['failed'].append(failed_info)
|
result['failed'].append(failed_info)
|
||||||
|
|
||||||
return Response(result)
|
return Response(result)
|
||||||
|
|
||||||
|
@@ -94,6 +94,7 @@ def get_share_link_info(fileshare):
|
|||||||
data['expire_date'] = expire_date
|
data['expire_date'] = expire_date
|
||||||
data['is_expired'] = fileshare.is_expired()
|
data['is_expired'] = fileshare.is_expired()
|
||||||
data['permissions'] = fileshare.get_permissions()
|
data['permissions'] = fileshare.get_permissions()
|
||||||
|
data['password'] = fileshare.get_password()
|
||||||
|
|
||||||
data['can_edit'] = False
|
data['can_edit'] = False
|
||||||
if repo and path != '/' and not data['is_dir']:
|
if repo and path != '/' and not data['is_dir']:
|
||||||
|
@@ -1,28 +1,37 @@
|
|||||||
# Copyright (c) 2012-2016 Seafile Ltd.
|
# Copyright (c) 2012-2016 Seafile Ltd.
|
||||||
import operator
|
|
||||||
import datetime
|
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
import operator
|
||||||
|
import datetime
|
||||||
|
from functools import reduce
|
||||||
|
from constance import config
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.dispatch import receiver
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.contrib.auth.hashers import make_password, check_password
|
from django.contrib.auth.hashers import check_password
|
||||||
from constance import config
|
|
||||||
|
|
||||||
|
from seahub.signals import repo_deleted
|
||||||
from seahub.base.fields import LowerCaseCharField
|
from seahub.base.fields import LowerCaseCharField
|
||||||
|
from seahub.utils.hasher import AESPasswordHasher
|
||||||
from seahub.utils import normalize_file_path, normalize_dir_path, gen_token,\
|
from seahub.utils import normalize_file_path, normalize_dir_path, gen_token,\
|
||||||
get_service_url
|
get_service_url, is_valid_org_id
|
||||||
from seahub.constants import PERMISSION_READ, PERMISSION_ADMIN
|
from seahub.constants import PERMISSION_READ, PERMISSION_ADMIN
|
||||||
from seahub.utils import is_valid_org_id
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
# Get an instance of a logger
|
# Get an instance of a logger
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def make_password(password):
|
||||||
|
|
||||||
|
aes = AESPasswordHasher()
|
||||||
|
return aes.encode(password)
|
||||||
|
|
||||||
|
|
||||||
class AnonymousShare(models.Model):
|
class AnonymousShare(models.Model):
|
||||||
"""
|
"""
|
||||||
Model used for sharing repo to unregistered email.
|
Model used for sharing repo to unregistered email.
|
||||||
@@ -32,10 +41,12 @@ class AnonymousShare(models.Model):
|
|||||||
anonymous_email = LowerCaseCharField(max_length=255)
|
anonymous_email = LowerCaseCharField(max_length=255)
|
||||||
token = models.CharField(max_length=25, unique=True)
|
token = models.CharField(max_length=25, unique=True)
|
||||||
|
|
||||||
|
|
||||||
def _get_link_key(token, is_upload_link=False):
|
def _get_link_key(token, is_upload_link=False):
|
||||||
return 'visited_ufs_' + token if is_upload_link else \
|
return 'visited_ufs_' + token if is_upload_link else \
|
||||||
'visited_fs_' + token
|
'visited_fs_' + token
|
||||||
|
|
||||||
|
|
||||||
def set_share_link_access(request, token, is_upload_link=False):
|
def set_share_link_access(request, token, is_upload_link=False):
|
||||||
"""Remember which shared download/upload link user can access without
|
"""Remember which shared download/upload link user can access without
|
||||||
providing password.
|
providing password.
|
||||||
@@ -48,6 +59,7 @@ def set_share_link_access(request, token, is_upload_link=False):
|
|||||||
logger.warn('Failed to remember shared link password, request.session'
|
logger.warn('Failed to remember shared link password, request.session'
|
||||||
' is None when set shared link access.')
|
' is None when set shared link access.')
|
||||||
|
|
||||||
|
|
||||||
def check_share_link_access(request, token, is_upload_link=False):
|
def check_share_link_access(request, token, is_upload_link=False):
|
||||||
"""Check whether user can access shared download/upload link without
|
"""Check whether user can access shared download/upload link without
|
||||||
providing password.
|
providing password.
|
||||||
@@ -58,6 +70,7 @@ def check_share_link_access(request, token, is_upload_link=False):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_share_link_common(request, sharelink, is_upload_link=False):
|
def check_share_link_common(request, sharelink, is_upload_link=False):
|
||||||
"""Check if user can view a share link
|
"""Check if user can view a share link
|
||||||
"""
|
"""
|
||||||
@@ -79,17 +92,20 @@ def check_share_link_common(request, sharelink, is_upload_link=False):
|
|||||||
msg = _("Password can\'t be empty")
|
msg = _("Password can\'t be empty")
|
||||||
return (False, msg)
|
return (False, msg)
|
||||||
|
|
||||||
if check_password(password, sharelink.password):
|
if check_password(password, sharelink.password) or password == sharelink.get_password():
|
||||||
set_share_link_access(request, sharelink.token, is_upload_link)
|
set_share_link_access(request, sharelink.token, is_upload_link)
|
||||||
return (True, msg)
|
return (True, msg)
|
||||||
else:
|
else:
|
||||||
msg = _("Please enter a correct password.")
|
msg = _("Please enter a correct password.")
|
||||||
return (False, msg)
|
return (False, msg)
|
||||||
|
|
||||||
|
|
||||||
class FileShareManager(models.Manager):
|
class FileShareManager(models.Manager):
|
||||||
|
|
||||||
def _add_file_share(self, username, repo_id, path, s_type,
|
def _add_file_share(self, username, repo_id, path, s_type,
|
||||||
password=None, expire_date=None,
|
password=None, expire_date=None,
|
||||||
permission='view_download', org_id=None):
|
permission='view_download', org_id=None):
|
||||||
|
|
||||||
if password is not None:
|
if password is not None:
|
||||||
password_enc = make_password(password)
|
password_enc = make_password(password)
|
||||||
else:
|
else:
|
||||||
@@ -131,7 +147,7 @@ class FileShareManager(models.Manager):
|
|||||||
else:
|
else:
|
||||||
return fs
|
return fs
|
||||||
|
|
||||||
########## public methods ##########
|
# public methods
|
||||||
def create_file_link(self, username, repo_id, path, password=None,
|
def create_file_link(self, username, repo_id, path, password=None,
|
||||||
expire_date=None, permission='view_download',
|
expire_date=None, permission='view_download',
|
||||||
org_id=None):
|
org_id=None):
|
||||||
@@ -231,6 +247,7 @@ class ExtraSharePermissionManager(models.Manager):
|
|||||||
|
|
||||||
|
|
||||||
class ExtraGroupsSharePermissionManager(models.Manager):
|
class ExtraGroupsSharePermissionManager(models.Manager):
|
||||||
|
|
||||||
def get_group_permission(self, repo_id, gid):
|
def get_group_permission(self, repo_id, gid):
|
||||||
record_list = super(ExtraGroupsSharePermissionManager, self).filter(
|
record_list = super(ExtraGroupsSharePermissionManager, self).filter(
|
||||||
repo_id=repo_id, group_id=gid
|
repo_id=repo_id, group_id=gid
|
||||||
@@ -240,7 +257,6 @@ class ExtraGroupsSharePermissionManager(models.Manager):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_repos_with_admin_permission(self, gid):
|
def get_repos_with_admin_permission(self, gid):
|
||||||
""" return admin repo in specific group
|
""" return admin repo in specific group
|
||||||
e.g: ['repo_id1', 'repo_id2']
|
e.g: ['repo_id1', 'repo_id2']
|
||||||
@@ -384,6 +400,18 @@ class FileShare(models.Model):
|
|||||||
return '/' if self.path == '/' else os.path.basename(self.path.rstrip('/'))
|
return '/' if self.path == '/' else os.path.basename(self.path.rstrip('/'))
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
def get_password(self):
|
||||||
|
|
||||||
|
if self.password:
|
||||||
|
try:
|
||||||
|
aes = AESPasswordHasher()
|
||||||
|
return aes.decode(self.password)
|
||||||
|
except Exception:
|
||||||
|
logger.error('Error occurred when get share link password')
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class OrgFileShareManager(models.Manager):
|
class OrgFileShareManager(models.Manager):
|
||||||
def set_org_file_share(self, org_id, file_share):
|
def set_org_file_share(self, org_id, file_share):
|
||||||
@@ -397,6 +425,7 @@ class OrgFileShareManager(models.Manager):
|
|||||||
ofs.save(using=self._db)
|
ofs.save(using=self._db)
|
||||||
return ofs
|
return ofs
|
||||||
|
|
||||||
|
|
||||||
class OrgFileShare(models.Model):
|
class OrgFileShare(models.Model):
|
||||||
"""
|
"""
|
||||||
Model used for organization file or dir shared link.
|
Model used for organization file or dir shared link.
|
||||||
@@ -407,6 +436,7 @@ class OrgFileShare(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class UploadLinkShareManager(models.Manager):
|
class UploadLinkShareManager(models.Manager):
|
||||||
|
|
||||||
def _get_upload_link_by_path(self, username, repo_id, path):
|
def _get_upload_link_by_path(self, username, repo_id, path):
|
||||||
ufs = list(super(UploadLinkShareManager, self).filter(repo_id=repo_id).filter(
|
ufs = list(super(UploadLinkShareManager, self).filter(repo_id=repo_id).filter(
|
||||||
username=username).filter(path=path))
|
username=username).filter(path=path))
|
||||||
@@ -449,6 +479,7 @@ class UploadLinkShareManager(models.Manager):
|
|||||||
else:
|
else:
|
||||||
return fs
|
return fs
|
||||||
|
|
||||||
|
|
||||||
class UploadLinkShare(models.Model):
|
class UploadLinkShare(models.Model):
|
||||||
"""
|
"""
|
||||||
Model used for shared upload link.
|
Model used for shared upload link.
|
||||||
@@ -475,7 +506,9 @@ class UploadLinkShare(models.Model):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PrivateFileDirShareManager(models.Manager):
|
class PrivateFileDirShareManager(models.Manager):
|
||||||
|
|
||||||
def add_private_file_share(self, from_user, to_user, repo_id, path, perm):
|
def add_private_file_share(self, from_user, to_user, repo_id, path, perm):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
@@ -550,6 +583,7 @@ class PrivateFileDirShareManager(models.Manager):
|
|||||||
return super(PrivateFileDirShareManager, self).filter(
|
return super(PrivateFileDirShareManager, self).filter(
|
||||||
to_user=to_user, repo_id=repo_id, s_type='d')
|
to_user=to_user, repo_id=repo_id, s_type='d')
|
||||||
|
|
||||||
|
|
||||||
class PrivateFileDirShare(models.Model):
|
class PrivateFileDirShare(models.Model):
|
||||||
from_user = LowerCaseCharField(max_length=255, db_index=True)
|
from_user = LowerCaseCharField(max_length=255, db_index=True)
|
||||||
to_user = LowerCaseCharField(max_length=255, db_index=True)
|
to_user = LowerCaseCharField(max_length=255, db_index=True)
|
||||||
@@ -597,9 +631,7 @@ class CustomSharePermissions(models.Model):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
###### signal handlers
|
# signal handlers
|
||||||
from django.dispatch import receiver
|
|
||||||
from seahub.signals import repo_deleted
|
|
||||||
|
|
||||||
@receiver(repo_deleted)
|
@receiver(repo_deleted)
|
||||||
def remove_share_info(sender, **kwargs):
|
def remove_share_info(sender, **kwargs):
|
||||||
|
@@ -13,6 +13,10 @@
|
|||||||
<a href="{{ file_shared_link }}">{{ file_shared_link }}</a>
|
<a href="{{ file_shared_link }}">{{ file_shared_link }}</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{% if password %}
|
||||||
|
<p>{% trans "Password:"%} {{ password }}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if extra_msg %}
|
{% if extra_msg %}
|
||||||
<p>" {{ extra_msg }} "</p>
|
<p>" {{ extra_msg }} "</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -16,6 +16,10 @@
|
|||||||
<a href="{{ shared_upload_link }}">{{ shared_upload_link }}</a>
|
<a href="{{ shared_upload_link }}">{{ shared_upload_link }}</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{% if password %}
|
||||||
|
<p>{% trans "Password:"%} {{ password }}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if extra_msg %}
|
{% if extra_msg %}
|
||||||
<p>" {{ extra_msg }} "</p>
|
<p>" {{ extra_msg }} "</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Reference in New Issue
Block a user