def notify_admins_on_register_complete(reg_email): ctx_dict = { "site_name": settings.SITE_NAME, "user_search_link": "%s%s?query=%s" % (get_site_scheme_and_netloc(), reverse("sys_search_users"), urlquote(reg_email)), "reg_email": reg_email, } subject = render_to_string( 'registration/register_complete_email_subject.html', ctx_dict) # Email subject *must not* contain newlines subject = ''.join(subject.splitlines()) message = render_to_string('registration/register_complete_email.html', ctx_dict) admins = User.objects.get_superusers() for admin in admins: try: admin.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) except Exception as e: logger.error(e)
def send_html_email_with_dj_template(recipients, subject, dj_template, context={}, sender=None, template=None, message='', headers=None, priority=None, backend=''): """ Arguments: - `recipients`: - `subject`: - `sender`: - `template`: - `context`: """ # get logo path logo_path = LOGO_PATH custom_logo_file = os.path.join(MEDIA_ROOT, CUSTOM_LOGO_PATH) if os.path.exists(custom_logo_file): logo_path = CUSTOM_LOGO_PATH base_context = { 'url_base': get_site_scheme_and_netloc(), 'site_name': get_site_name(), 'media_url': MEDIA_URL, 'logo_path': logo_path, } context.update(base_context) t = loader.get_template(dj_template) html_message = t.render(context) return mail.send(recipients, sender=sender, template=template, context=context, subject=subject, message=message, html_message=html_message, headers=headers, priority=priority, backend=backend)
def send_html_email_with_dj_template(recipients, subject, dj_template, context={}, sender=None, template=None, message='', headers=None, priority=None, backend=''): """ Arguments: - `recipients`: - `subject`: - `sender`: - `template`: - `context`: """ base_context = { 'url_base': get_site_scheme_and_netloc(), 'site_name': SITE_NAME, 'media_url': MEDIA_URL, 'logo_path': LOGO_PATH, } context.update(base_context) t = loader.get_template(dj_template) html_message = t.render(Context(context)) mail.send(recipients, sender=sender, template=template, context=context, subject=subject, message=message, html_message=html_message, headers=headers, priority=priority, backend=backend)
def work_weixin_oauth_login(request): if not work_weixin_oauth_check(): return render_error(request, _('Feature is not enabled.')) if request.user.is_authenticated(): return HttpResponseRedirect( request.GET.get(auth.REDIRECT_FIELD_NAME, redirect_to)) state = str(uuid.uuid4()) request.session['work_weixin_oauth_state'] = state request.session['work_weixin_oauth_redirect'] = request.GET.get( auth.REDIRECT_FIELD_NAME, redirect_to) data = { 'appid': WORK_WEIXIN_CORP_ID, 'agentid': WORK_WEIXIN_AGENT_ID, 'redirect_uri': get_site_scheme_and_netloc() + reverse('work_weixin_oauth_callback'), 'state': state, } authorization_url = WORK_WEIXIN_AUTHORIZATION_URL + '?' + urllib.parse.urlencode( data) return HttpResponseRedirect(authorization_url)
def get_default_avatar(self, default_size=32): # user default avatar img_tag = """<img src="%s" width="%s" height="%s" class="avatar" alt="" />""" % \ (get_default_avatar_url(), default_size, default_size) pattern = r'src="(.*)"' repl = r'src="%s\1"' % get_site_scheme_and_netloc() return re.sub(pattern, repl, img_tag)
def abs_reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None): return get_site_scheme_and_netloc().rstrip('/') + reverse( viewname, urlconf, args, kwargs, current_app)
def dingtalk_connect(request): if not ENABLE_DINGTALK: return render_error(request, _('Error, please contact administrator.')) state = str(uuid.uuid4()) request.session['dingtalk_connect_state'] = state request.session['dingtalk_connect_redirect'] = request.GET.get( auth.REDIRECT_FIELD_NAME, '/') data = { 'appid': DINGTALK_QR_CONNECT_APP_ID, 'response_type': DINGTALK_QR_CONNECT_RESPONSE_TYPE, 'scope': DINGTALK_QR_CONNECT_SCOPE, 'redirect_uri': get_site_scheme_and_netloc() + reverse('dingtalk_connect_callback'), 'state': state, } url = DINGTALK_QR_CONNECT_AUTHORIZATION_URL + '?' + urllib.parse.urlencode( data) return HttpResponseRedirect(url)
def work_weixin_oauth_login(request): if not work_weixin_oauth_check(): return render_error(request, _('Feature is not enabled.')) state = str(uuid.uuid4()) request.session['work_weixin_oauth_state'] = state request.session['work_weixin_oauth_redirect'] = request.GET.get( auth.REDIRECT_FIELD_NAME, '/') data = { 'appid': WORK_WEIXIN_CORP_ID, 'agentid': WORK_WEIXIN_AGENT_ID, 'redirect_uri': get_site_scheme_and_netloc() + reverse('work_weixin_oauth_callback'), 'state': state, } if 'micromessenger' in request.META.get('HTTP_USER_AGENT').lower(): data['response_type'] = 'code' data['scope'] = 'snsapi_base' authorization_url = MP_WORK_WEIXIN_AUTHORIZATION_URL + '?' + urllib.parse.urlencode( data) + '#wechat_redirect' else: authorization_url = WORK_WEIXIN_AUTHORIZATION_URL + '?' + urllib.parse.urlencode( data) return HttpResponseRedirect(authorization_url)
def email_admin_on_registration(sender, **kwargs): """Send an email notification to admin when a newly registered user need activate. This email will be sent when both ``ACTIVATE_AFTER_REGISTRATION`` and ``REGISTRATION_SEND_MAIL`` are set to False. """ if settings.ACTIVATE_AFTER_REGISTRATION is False and \ settings.REGISTRATION_SEND_MAIL is False: reg_email = kwargs['user'].email ctx_dict = { "site_name": settings.SITE_NAME, "user_search_link": "%s%s?email=%s" % (get_site_scheme_and_netloc(), reverse("user_search"), urlquote(reg_email)), } subject = render_to_string( 'registration/activate_request_email_subject.txt', ctx_dict) # Email subject *must not* contain newlines subject = ''.join(subject.splitlines()) message = render_to_string('registration/activate_request_email.txt', ctx_dict) admins = User.objects.get_superusers() for admin in admins: try: admin.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) except Exception as e: logger.error(e)
def get_or_create_invitation_link(org_id): """Invitation link for an org. Users will be redirected to WeChat QR page. """ if not weixin_check(): return None org_id = int(org_id) expires = 3 * 24 * 60 * 60 def get_token_by_org_id(org_id): return cache.get('org_associate_%d' % org_id, None) def set_token_by_org_id(org_id, token): cache.set('org_associate_%d' % org_id, token, expires) def get_org_id_by_token(token): return cache.get('org_associate_%s' % token, -1) def set_org_id_by_token(token, org_id): cache.set('org_associate_%s' % token, org_id, expires) token = get_token_by_org_id(org_id) cached_org_id = get_org_id_by_token(token) if not token or org_id != cached_org_id: token = gen_token(32) set_token_by_org_id(org_id, token) set_org_id_by_token(token, org_id) link = get_site_scheme_and_netloc() + reverse('weixin_oauth_login') \ + '?org_token=' + token return link
def email_admin_on_registration(sender, **kwargs): """Send an email notification to admin when a newly registered user need activate. This email will be sent when both ``ACTIVATE_AFTER_REGISTRATION`` and ``REGISTRATION_SEND_MAIL`` are set to False. """ if config.ACTIVATE_AFTER_REGISTRATION is False and \ config.REGISTRATION_SEND_MAIL is False: reg_email = kwargs['user'].email ctx_dict = { "site_name": settings.SITE_NAME, "user_search_link": "%s%s?email=%s" % ( get_site_scheme_and_netloc(), reverse("user_search"), urlquote(reg_email)), } subject = render_to_string('registration/activate_request_email_subject.txt', ctx_dict) # Email subject *must not* contain newlines subject = ''.join(subject.splitlines()) message = render_to_string('registration/activate_request_email.txt', ctx_dict) admins = User.objects.get_superusers() for admin in admins: try: admin.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) except Exception as e: logger.error(e)
def process_request(self, request): """Returns an HTTP redirect response for requests including non-"www" subdomains. """ if getattr(settings, 'MULTI_TENANCY', False) is False: return None if ORG_REDIRECT is False: return None path = request.get_full_path() domain = request.META.get('HTTP_HOST') or request.META.get( 'SERVER_NAME') if request.user.is_anonymous: return None if request.user.org is None: # personal user sub_domain = get_subdomain(domain) if sub_domain is not None: return HttpResponseRedirect(get_site_scheme_and_netloc() + path) else: return None else: # org user url_prefix = request.user.org.url_prefix sub_domain = get_subdomain(domain) if sub_domain is None or sub_domain != url_prefix: return HttpResponseRedirect(construct_org_url( url_prefix, path)) else: return None
def get_onlyoffice_dict(username, repo_id, file_path, file_id='', can_edit=False, can_download=True): repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) # for view history/trash/snapshot file if not file_id: file_id = seafile_api.get_file_id_by_path(origin_repo_id, origin_file_path) else: origin_repo_id = repo_id origin_file_path = file_path if not file_id: file_id = seafile_api.get_file_id_by_path(repo_id, file_path) dl_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=True) if not dl_token: return None filetype, fileext = get_file_type_and_ext(file_path) if fileext in ('xls', 'xlsx', 'ods', 'fods', 'csv'): document_type = 'spreadsheet' elif fileext in ('pptx', 'ppt', 'odp', 'fodp', 'ppsx', 'pps'): document_type = 'presentation' else: document_type = 'text' doc_info = json.dumps({'repo_id': repo_id, 'file_path': file_path, 'username': username}) doc_key = hashlib.md5(force_bytes(origin_repo_id + origin_file_path + file_id)).hexdigest()[:20] cache.set("ONLYOFFICE_%s" % doc_key, doc_info, None) file_name = os.path.basename(file_path.rstrip('/')) doc_url = gen_file_get_url(dl_token, file_name) base_url = get_site_scheme_and_netloc() onlyoffice_editor_callback_url = reverse('onlyoffice_editor_callback') calllback_url = urlparse.urljoin(base_url, onlyoffice_editor_callback_url) return_dict = { 'repo_id': repo_id, 'path': file_path, 'ONLYOFFICE_APIJS_URL': ONLYOFFICE_APIJS_URL, 'file_type': fileext, 'doc_key': doc_key, 'doc_title': file_name, 'doc_url': doc_url, 'document_type': document_type, 'callback_url': calllback_url, 'can_edit': can_edit, 'can_download': can_download, 'username': username, 'enable_watermark': ENABLE_WATERMARK and not can_edit, } return return_dict
def get_wiki_page_object(wiki_object, page_name): page_name = clean_page_name(page_name) filepath = "/" + page_name + ".md" repo_id = wiki_object.repo_id try: dirent = seafile_api.get_dirent_by_path(repo_id, filepath) if dirent: latest_contributor, last_modified = dirent.modifier, dirent.mtime else: latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 try: repo = seafile_api.get_repo(wiki_object.repo_id) except SearpcError as e: logger.error(e) file_url = get_inner_file_url(repo, dirent.obj_id, dirent.obj_name) edit_url = get_site_scheme_and_netloc().rstrip('/') + "%s?p=%s" % ( reverse('file_edit', args=[repo_id]), urlquote(filepath.encode('utf-8'))) slug = wiki_object.slug page_url = get_site_scheme_and_netloc().rstrip('/') + reverse('wiki:slug', args=[slug, page_name]) # FIX ME: move to top after wiki code refactor from seahub.base.templatetags.seahub_tags import email2nickname, \ email2contact_email return {"name": page_name, "link": page_url, "file_link": file_url, "file_edit_link": edit_url, "updated_at": timestamp_to_isoformat_timestr(last_modified), "last_modifier": latest_contributor, "last_modifier_contact_email": email2contact_email(latest_contributor), "last_modifier_name": email2nickname(latest_contributor), }
def get_wiki_page_object(wiki_object, page_name): page_name = clean_page_name(page_name) filepath = "/" + page_name + ".md" repo_id = wiki_object.repo_id try: dirent = seafile_api.get_dirent_by_path(repo_id, filepath) if dirent: latest_contributor, last_modified = dirent.modifier, dirent.mtime else: latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 try: repo = seafile_api.get_repo(wiki_object.repo_id) except SearpcError as e: logger.error(e) file_url = get_inner_file_url(repo, dirent.obj_id, dirent.obj_name) edit_url = get_site_scheme_and_netloc().rstrip('/') + "%s?p=%s" % (reverse( 'file_edit', args=[repo_id]), urlquote(filepath.encode('utf-8'))) slug = wiki_object.slug page_url = get_site_scheme_and_netloc().rstrip('/') + reverse( 'wiki:slug', args=[slug, page_name]) # FIX ME: move to top after wiki code refactor from seahub.base.templatetags.seahub_tags import email2nickname, \ email2contact_email return { "name": page_name, "link": page_url, "file_link": file_url, "file_edit_link": edit_url, "updated_at": timestamp_to_isoformat_timestr(last_modified), "last_modifier": latest_contributor, "last_modifier_contact_email": email2contact_email(latest_contributor), "last_modifier_name": email2nickname(latest_contributor), }
def user_to_dict(email, request=None, avatar_size=AVATAR_DEFAULT_SIZE): d = get_user_common_info(email, avatar_size) if request is None: avatar_url = '%s%s' % (get_site_scheme_and_netloc(), d['avatar_url']) else: avatar_url = request.build_absolute_uri(d['avatar_url']) return { 'user_name': d['name'], 'user_email': d['email'], 'user_login_id': d['login_id'], 'avatar_url': avatar_url, }
def weixin_oauth_connect(request): if not weixin_check(): return render_error(request, _('Feature is not enabled.')) # mobile weixin user_agent = request.META.get('HTTP_USER_AGENT', '').lower() if 'mobile' in user_agent and 'micromessenger' not in user_agent: return render_error(request, '请在微信客户端打开链接') if 'micromessenger' in user_agent: if not mp_weixin_check(): return render_error(request, '微信客户端登录功能未启用,请联系管理员') is_mobile_weixin = True scope = 'snsapi_userinfo' weixin_authorization_url = MP_WEIXIN_AUTHORIZATION_URL appid = MP_WEIXIN_APP_ID else: is_mobile_weixin = False scope = 'snsapi_login' weixin_authorization_url = WEIXIN_AUTHORIZATION_URL appid = WEIXIN_APP_ID state = str(uuid.uuid4()) request.session['weixin_oauth_connect_state'] = state request.session['weixin_oauth_connect_redirect'] = request.GET.get( auth.REDIRECT_FIELD_NAME, redirect_to) request.session['weixin_oauth_connect_is_mobile_weixin'] = is_mobile_weixin response_type = 'code' # from weixn official document wechat_redirect = '#wechat_redirect' data = { 'appid': appid, 'redirect_uri': get_site_scheme_and_netloc() + reverse('weixin_oauth_connect_callback'), 'response_type': response_type, 'scope': scope, 'state': state, } authorization_url = weixin_authorization_url + '?' + urllib.parse.urlencode( data) + wechat_redirect return HttpResponseRedirect(authorization_url)
def send_html_email_with_dj_template(recipients, subject, dj_template, context={}, sender=None, template=None, message='', headers=None, priority=None, backend=''): """ Arguments: - `recipients`: - `subject`: - `sender`: - `template`: - `context`: """ # get logo path logo_path = LOGO_PATH custom_logo_file = os.path.join(MEDIA_ROOT, CUSTOM_LOGO_PATH) if os.path.exists(custom_logo_file): logo_path = CUSTOM_LOGO_PATH base_context = { 'url_base': get_site_scheme_and_netloc(), 'site_name': SITE_NAME, 'media_url': MEDIA_URL, 'logo_path': logo_path, } context.update(base_context) t = loader.get_template(dj_template) html_message = t.render(context) mail.send(recipients, sender=sender, template=template, context=context, subject=subject, message=message, html_message=html_message, headers=headers, priority=priority, backend=backend)
def post(self, request): favicon_file = request.FILES.get('favicon', None) if not favicon_file: error_msg = 'Favicon can not be found.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_type, ext = get_file_type_and_ext(favicon_file.name) if file_type != IMAGE: error_msg = file_type_error_msg(ext, PREVIEW_FILEEXT.get(IMAGE)) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if favicon_file.size > 1024 * 1024 * 20: # 20mb error_msg = file_size_error_msg(favicon_file.size, 20*1024*1024) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not os.path.exists(SEAHUB_DATA_ROOT): os.makedirs(SEAHUB_DATA_ROOT) custom_dir = os.path.join(SEAHUB_DATA_ROOT, os.path.dirname(CUSTOM_FAVICON_PATH)) if not os.path.exists(custom_dir): os.makedirs(custom_dir) try: custom_favicon_file = os.path.join(SEAHUB_DATA_ROOT, CUSTOM_FAVICON_PATH) # save favicon file to custom dir with open(custom_favicon_file, 'wb') as fd: fd.write(favicon_file.read()) custom_symlink = os.path.join(MEDIA_ROOT, os.path.dirname(CUSTOM_FAVICON_PATH)) # create symlink for custom dir if not os.path.exists(custom_symlink): os.symlink(custom_dir, custom_symlink) 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({'favicon_path': get_site_scheme_and_netloc() + MEDIA_URL + CUSTOM_FAVICON_PATH})
def email_user_on_activation(user): """Send an email to user when admin activate his/her account. """ ctx_dict = { "site_name": settings.SITE_NAME, "login_url": "%s%s" % (get_site_scheme_and_netloc(), reverse('auth_login')), "username": user.email, } subject = render_to_string('sysadmin/user_activation_email_subject.txt', ctx_dict) # Email subject *must not* contain newlines subject = ''.join(subject.splitlines()) message = render_to_string('sysadmin/user_activation_email.txt', ctx_dict) user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
def post(self, request): logo_file = request.FILES.get('logo', None) if not logo_file: error_msg = 'Logo can not be found.' logger.error(error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_type, ext = get_file_type_and_ext(logo_file.name) if file_type != IMAGE: error_msg = file_type_error_msg(ext, PREVIEW_FILEEXT.get(IMAGE)) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if logo_file.size > 1024 * 1024 * 20: # 20mb error_msg = file_size_error_msg(logo_file.size, 20 * 1024 * 1024) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not os.path.exists(SEAHUB_DATA_ROOT): os.makedirs(SEAHUB_DATA_ROOT) custom_dir = os.path.join(SEAHUB_DATA_ROOT, os.path.dirname(CUSTOM_LOGO_PATH)) if not os.path.exists(custom_dir): os.makedirs(custom_dir) try: # save logo file to custom dir custom_logo_file = os.path.join(SEAHUB_DATA_ROOT, CUSTOM_LOGO_PATH) image = Image.open(logo_file) image.save(custom_logo_file) # create symlink for custom dir custom_symlink = os.path.join(MEDIA_ROOT, os.path.dirname(CUSTOM_LOGO_PATH)) if not os.path.exists(custom_symlink): os.symlink(custom_dir, custom_symlink) 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({ 'logo_path': get_site_scheme_and_netloc() + MEDIA_URL + CUSTOM_LOGO_PATH })
def weixin_oauth_login(request): if not ENABLE_WEIXIN: return render_error(request, _('Error, please contact administrator.')) state = str(uuid.uuid4()) request.session['weixin_oauth_login_state'] = state request.session['weixin_oauth_login_redirect'] = request.GET.get(auth.REDIRECT_FIELD_NAME, '/') data = { 'appid': WEIXIN_OAUTH_APP_ID, 'redirect_uri': get_site_scheme_and_netloc() + reverse('weixin_oauth_callback'), 'response_type': WEIXIN_OAUTH_RESPONSE_TYPE, 'scope': WEIXIN_OAUTH_SCOPE, 'state': state, } url = WEIXIN_OAUTH_QR_CONNECT_URL + '?' + urllib.parse.urlencode(data) return HttpResponseRedirect(url)
def post(self, request): image_file = request.FILES.get('login_bg_image', None) if not image_file: error_msg = 'Image can not be found.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not os.path.exists(SEAHUB_DATA_ROOT): os.makedirs(SEAHUB_DATA_ROOT) file_type, ext = get_file_type_and_ext(image_file.name) if file_type != IMAGE: error_msg = file_type_error_msg(ext, PREVIEW_FILEEXT.get('Image')) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if image_file.size > 1024 * 1024 * 20: # 20mb error_msg = file_size_error_msg(image_file.size, 20*1024*1024) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) custom_login_bg_image_path = get_custom_login_bg_image_path() custom_dir = os.path.join(SEAHUB_DATA_ROOT, os.path.dirname(custom_login_bg_image_path)) if not os.path.exists(custom_dir): os.makedirs(custom_dir) try: custom_login_bg_image_file = os.path.join(SEAHUB_DATA_ROOT, custom_login_bg_image_path) # save login background image file to custom dir with open(custom_login_bg_image_file, 'wb') as fd: fd.write(image_file.read()) custom_symlink = os.path.join(MEDIA_ROOT, os.path.dirname(custom_login_bg_image_path)) # create symlink for custom dir if not os.path.exists(custom_symlink): os.symlink(custom_dir, custom_symlink) 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({'login_bg_image_path': get_site_scheme_and_netloc() + MEDIA_URL + CUSTOM_LOGIN_BG_PATH})
def get_bisheng_dict(username, repo_id, file_path): doc_id = hashlib.md5(force_bytes(repo_id + file_path)).hexdigest() base_url = get_site_scheme_and_netloc() bisheng_url = urlparse.urljoin(base_url, reverse('api-v2.1-bisheng-office')) bisheng_url += '?doc_id=%s' % doc_id call_url = base64.b64encode(bisheng_url) sign = get_hmac_hexdigest(BISHENG_OFFICE_API_KEY, call_url) info = { 'username': username, 'repo_id': repo_id, 'file_path': file_path, 'doc_id': doc_id, 'call_url': call_url, 'sign': sign, } return info
def send_html_email_with_dj_template(recipients, subject, dj_template, context={}): """ Arguments: - `recipients`: - `subject`: - `dj_template`: - `context`: """ # get logo path logo_path = LOGO_PATH custom_logo_file = os.path.join(MEDIA_ROOT, CUSTOM_LOGO_PATH) if os.path.exists(custom_logo_file): logo_path = CUSTOM_LOGO_PATH base_context = { 'url_base': get_site_scheme_and_netloc(), 'site_name': get_site_name(), 'media_url': MEDIA_URL, 'logo_path': logo_path, } context.update(base_context) t = loader.get_template(dj_template) html_message = t.render(context) mail = EmailMessage(subject=subject, body=html_message, to=[recipients]) mail.content_subtype = "html" try: mail.send() return True except Exception as e: logger.error(e) return False
def notify_admins_on_activate_request(reg_email): ctx_dict = { "site_name": settings.SITE_NAME, "user_search_link": "%s%s?email=%s" % ( get_site_scheme_and_netloc(), reverse("user_search"), urlquote(reg_email)), } subject = render_to_string('registration/activate_request_email_subject.txt', ctx_dict) # Email subject *must not* contain newlines subject = ''.join(subject.splitlines()) message = render_to_string('registration/activate_request_email.txt', ctx_dict) admins = User.objects.get_superusers() for admin in admins: try: admin.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) except Exception as e: logger.error(e)
def get_wopi_dict(request_user, repo_id, file_path, action_name='view', can_download=True, language_code='en', obj_id=''): """ Prepare dict data for WOPI host page """ if action_name not in ('view', 'edit'): return None file_name = os.path.basename(file_path) file_ext = os.path.splitext(file_name)[1][1:].lower() if OFFICE_SERVER_TYPE.lower() == 'collaboraoffice': if file_ext == 'doc': file_ext = 'docx' if file_ext == 'ppt': file_ext = 'pptx' if file_ext == 'xls': file_ext = 'xlsx' wopi_key = generate_discovery_cache_key(action_name, file_ext) action_url = cache.get(wopi_key) if not action_url: # can not get action_url from cache try: if OFFICE_WEB_APP_CLIENT_CERT and OFFICE_WEB_APP_CLIENT_KEY: xml = requests.get(OFFICE_WEB_APP_BASE_URL, cert=(OFFICE_WEB_APP_CLIENT_CERT, OFFICE_WEB_APP_CLIENT_KEY), verify=OFFICE_WEB_APP_SERVER_CA) elif OFFICE_WEB_APP_CLIENT_PEM: xml = requests.get(OFFICE_WEB_APP_BASE_URL, cert=OFFICE_WEB_APP_CLIENT_PEM, verify=OFFICE_WEB_APP_SERVER_CA) else: xml = requests.get(OFFICE_WEB_APP_BASE_URL, verify=OFFICE_WEB_APP_SERVER_CA) except Exception as e: logger.error(e) return None try: root = ET.fromstring(xml.content) except Exception as e: logger.error(e) return None for action in root.getiterator('action'): attr = action.attrib ext = attr.get('ext') name = attr.get('name') urlsrc = attr.get('urlsrc') if ext and name and urlsrc: tmp_action_url = re.sub(r'<.*>', '', urlsrc) tmp_wopi_key = generate_discovery_cache_key(name, ext) cache.set(tmp_wopi_key, tmp_action_url, OFFICE_WEB_APP_DISCOVERY_EXPIRATION) if wopi_key == tmp_wopi_key: action_url = tmp_action_url else: continue if not action_url: # can not get action_url from hosting discovery page return None # generate full action url repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) repo_path_info = '_'.join([origin_repo_id, origin_file_path]) else: repo_path_info = '_'.join([repo_id, file_path]) fake_file_id = hashlib.sha1(repo_path_info.encode('utf8')).hexdigest() base_url = get_site_scheme_and_netloc() check_file_info_endpoint = reverse('WOPIFilesView', args=[fake_file_id]) WOPISrc = urlparse.urljoin(base_url, check_file_info_endpoint) query_dict = {'WOPISrc': WOPISrc} if action_url[-1] in ('?', '&'): full_action_url = action_url + urllib.urlencode(query_dict) elif '?' in action_url: full_action_url = action_url + '&' + urllib.urlencode(query_dict) else: full_action_url = action_url + '?' + urllib.urlencode(query_dict) # key, collected from seahub/settings.py # value, collected from https://wopi.readthedocs.io/en/latest/faq/languages.html#languages lang_dict = { "ar": "ar-SA", "ca": "ca-ES", "cs": "cs-CZ", "de": "de-DE", "el": "el-GR", "en": "en-US", "es": "es-ES", "es-ar": "es-ES", "es-mx": "es-ES", "fi": "fi-FI", "fr": "fr-FR", "he": "he-IL", "hu": "hu-HU", "is": "is-IS", "it": "it-IT", "ja": "ja-JP", "ko": "ko-KR", "lv": "lv-LV", "nl": "nl-NL", "pl": "pl-PL", "pt-br": "pt-BR", "ru": "ru-Ru", "sl": "sl-SI", "sv": "sv-SE", "th": "th-TH", "tr": "tr-TR", "uk": "uk-UA", "vi": "vi-VN", "zh-cn": "zh-CN", "zh-tw": "zh-TW", } WOPI_UI_LLCC = lang_dict[language_code] full_action_url += '&ui=%s&rs=%s' % (WOPI_UI_LLCC, WOPI_UI_LLCC) # generate access token user_repo_path_info = { 'request_user': request_user, 'repo_id': repo_id, 'file_path': file_path, 'obj_id': obj_id, 'can_edit': action_name == 'edit', 'can_download': can_download, } # collobora office only allowed alphanumeric and _ uid = uuid.uuid4() access_token = uid.hex key = generate_access_token_cache_key(access_token) cache.set(key, user_repo_path_info, WOPI_ACCESS_TOKEN_EXPIRATION) # access_token_ttl property tells office web app # when access token expires utc_timestamp = time.time() access_token_ttl = int((utc_timestamp + WOPI_ACCESS_TOKEN_EXPIRATION) * 1000) wopi_dict = {} wopi_dict['repo_id'] = repo_id wopi_dict['path'] = file_path wopi_dict['can_edit'] = action_name == 'edit' wopi_dict['action_url'] = full_action_url wopi_dict['access_token'] = access_token wopi_dict['access_token_ttl'] = access_token_ttl wopi_dict['doc_title'] = file_name wopi_dict['enable_watermark'] = ENABLE_WATERMARK and action_name == 'view' return wopi_dict
def do_action(self): now = datetime.now() today = datetime.now().replace(hour=0).replace(minute=0).replace( second=0).replace(microsecond=0) # 1. get all users who are connected wechat work socials = UserSocialAuth.objects.filter(provider='weixin-work') users = [(x.username, x.uid) for x in socials] if not users: return user_uid_map = {} for username, uid in users: user_uid_map[username] = uid # 2. get previous time that command last runs try: cmd_last_check = CommandsLastCheck.objects.get(command_type=self.label) self.log_debug('Last check time is %s' % cmd_last_check.last_check) last_check_dt = cmd_last_check.last_check cmd_last_check.last_check = now cmd_last_check.save() except CommandsLastCheck.DoesNotExist: last_check_dt = today self.log_debug('Create new last check time: %s' % now) CommandsLastCheck(command_type=self.label, last_check=now).save() # 3. get all unseen notices for those users qs = UserNotification.objects.filter( timestamp__gt=last_check_dt ).filter(seen=False).filter( to_user__in=user_uid_map.keys() ) user_notices = {} for q in qs: if q.to_user not in user_notices: user_notices[q.to_user] = [q] else: user_notices[q.to_user].append(q) # 4. send msg to users url = get_site_scheme_and_netloc().rstrip('/') + reverse('user_notification_list') for username, uid in users: notices = user_notices.get(username, []) count = len(notices) if count == 0: continue # save current language cur_language = translation.get_language() # get and active user language user_language = self.get_user_language(username) translation.activate(user_language) self.log_debug('Set language code to %s for user: %s' % ( user_language, username)) title = ungettext( "\n" "You've got 1 new notice on %(site_name)s:\n", "\n" "You've got %(num)s new notices on %(site_name)s:\n", count ) % { 'num': count, 'site_name': get_site_name(), } content = ''.join([wrap_div(x.format_msg()) for x in notices]) self.send_wx_msg(uid, title, content, url) translation.activate(cur_language)
def dir_url(repo_id, repo_name, dir_path): p = reverse('lib_view', args=[repo_id, repo_name, dir_path.strip('/')]) return get_site_scheme_and_netloc() + p
def link(self): return get_site_scheme_and_netloc().rstrip('/') + reverse('wiki:slug', args=[self.slug])
def get_wopi_dict(request_user, repo_id, file_path, action_name='view', can_download=True, language_code='en', obj_id=''): """ Prepare dict data for WOPI host page """ if action_name not in ('view', 'edit'): return None file_name = os.path.basename(file_path) file_ext = os.path.splitext(file_name)[1][1:].lower() if OFFICE_SERVER_TYPE.lower() == 'collaboraoffice': if file_ext == 'doc': file_ext = 'docx' if file_ext == 'ppt': file_ext = 'pptx' if file_ext == 'xls': file_ext = 'xlsx' wopi_key = generate_discovery_cache_key(action_name, file_ext) action_url = cache.get(wopi_key) if not action_url: # can not get action_url from cache try: if OFFICE_WEB_APP_CLIENT_CERT and OFFICE_WEB_APP_CLIENT_KEY: xml = requests.get(OFFICE_WEB_APP_BASE_URL, cert=(OFFICE_WEB_APP_CLIENT_CERT, OFFICE_WEB_APP_CLIENT_KEY), verify=OFFICE_WEB_APP_SERVER_CA) elif OFFICE_WEB_APP_CLIENT_PEM: xml = requests.get(OFFICE_WEB_APP_BASE_URL, cert=OFFICE_WEB_APP_CLIENT_PEM, verify=OFFICE_WEB_APP_SERVER_CA) else: xml = requests.get(OFFICE_WEB_APP_BASE_URL, verify=OFFICE_WEB_APP_SERVER_CA) except Exception as e: logger.error(e) return None try: root = ET.fromstring(xml.content) except Exception as e: logger.error(e) return None for action in root.iter('action'): attr = action.attrib ext = attr.get('ext') name = attr.get('name') urlsrc = attr.get('urlsrc') if ext and name and urlsrc: tmp_action_url = re.sub(r'<.*>', '', urlsrc) tmp_wopi_key = generate_discovery_cache_key(name, ext) cache.set(tmp_wopi_key, tmp_action_url, OFFICE_WEB_APP_DISCOVERY_EXPIRATION) if wopi_key == tmp_wopi_key: action_url = tmp_action_url else: continue if not action_url: # can not get action_url from hosting discovery page return None # generate full action url repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) repo_path_info = '_'.join([origin_repo_id, origin_file_path]) else: repo_path_info = '_'.join([repo_id, file_path]) fake_file_id = hashlib.sha1(repo_path_info.encode('utf8')).hexdigest() base_url = get_site_scheme_and_netloc() check_file_info_endpoint = reverse('WOPIFilesView', args=[fake_file_id]) WOPISrc = urllib.parse.urljoin(base_url, check_file_info_endpoint) query_dict = {'WOPISrc': WOPISrc} if action_url[-1] in ('?', '&'): full_action_url = action_url + urllib.parse.urlencode(query_dict) elif '?' in action_url: full_action_url = action_url + '&' + urllib.parse.urlencode(query_dict) else: full_action_url = action_url + '?' + urllib.parse.urlencode(query_dict) # key, collected from seahub/settings.py # value, collected from https://wopi.readthedocs.io/en/latest/faq/languages.html#languages lang_dict = { "ar": "ar-SA", "ca": "ca-ES", "cs": "cs-CZ", "de": "de-DE", "el": "el-GR", "en": "en-US", "es": "es-ES", "es-ar": "es-ES", "es-mx": "es-ES", "fi": "fi-FI", "fr": "fr-FR", "he": "he-IL", "hu": "hu-HU", "is": "is-IS", "it": "it-IT", "ja": "ja-JP", "ko": "ko-KR", "lv": "lv-LV", "nl": "nl-NL", "pl": "pl-PL", "pt-br": "pt-BR", "ru": "ru-Ru", "sl": "sl-SI", "sv": "sv-SE", "th": "th-TH", "tr": "tr-TR", "uk": "uk-UA", "vi": "vi-VN", "zh-cn": "zh-CN", "zh-tw": "zh-TW", } WOPI_UI_LLCC = lang_dict[language_code] full_action_url += '&ui=%s&rs=%s' % (WOPI_UI_LLCC, WOPI_UI_LLCC) # generate access token user_repo_path_info = { 'request_user': request_user, 'repo_id': repo_id, 'file_path': file_path, 'obj_id': obj_id, 'can_edit': action_name == 'edit', 'can_download': can_download, } # collobora office only allowed alphanumeric and _ uid = uuid.uuid4() access_token = uid.hex key = generate_access_token_cache_key(access_token) cache.set(key, user_repo_path_info, WOPI_ACCESS_TOKEN_EXPIRATION) # access_token_ttl property tells office web app # when access token expires utc_timestamp = time.time() access_token_ttl = int( (utc_timestamp + WOPI_ACCESS_TOKEN_EXPIRATION) * 1000) wopi_dict = {} wopi_dict['repo_id'] = repo_id wopi_dict['path'] = file_path wopi_dict['can_edit'] = action_name == 'edit' wopi_dict['action_url'] = full_action_url wopi_dict['access_token'] = access_token wopi_dict['access_token_ttl'] = access_token_ttl wopi_dict['doc_title'] = file_name wopi_dict['enable_watermark'] = ENABLE_WATERMARK and action_name == 'view' return wopi_dict
def user_info_url(username): p = reverse('user_profile', args=[username]) return get_site_scheme_and_netloc() + p
def file_url(repo_id, file_path): p = reverse('view_lib_file', args=[repo_id, file_path]) return get_site_scheme_and_netloc() + p
def repo_url(repo_id, repo_name): p = reverse('lib_view', args=[repo_id, repo_name, '']) return get_site_scheme_and_netloc() + p
def get_avatar_url(self, username, default_size=20): img_tag = avatar(username, default_size) pattern = r'src="(.*)"' repl = r'src="%s\1"' % get_site_scheme_and_netloc() return re.sub(pattern, repl, img_tag)
def get_avatar(self, username, default_size=32): img_tag = avatar(username, default_size) pattern = r'src="(.*)"' repl = r'src="%s\1"' % get_site_scheme_and_netloc() return re.sub(pattern, repl, img_tag)
def get_wopi_dict(request_user, repo_id, file_path, action_name='view'): """ Prepare dict data for WOPI host page """ if action_name not in ('view', 'edit'): return None file_name = os.path.basename(file_path) file_ext = os.path.splitext(file_name)[1][1:].lower() if OFFICE_SERVER_TYPE.lower() == 'collaboraoffice': if file_ext == 'doc': file_ext = 'docx' if file_ext == 'ppt': file_ext = 'pptx' if file_ext == 'xls': file_ext = 'xlsx' wopi_key = generate_discovery_cache_key(action_name, file_ext) action_url = cache.get(wopi_key) if not action_url: # can not get action_url from cache try: if OFFICE_WEB_APP_CLIENT_CERT and OFFICE_WEB_APP_CLIENT_KEY: xml = requests.get(OFFICE_WEB_APP_BASE_URL, cert=(OFFICE_WEB_APP_CLIENT_CERT, OFFICE_WEB_APP_CLIENT_KEY), verify=OFFICE_WEB_APP_SERVER_CA) elif OFFICE_WEB_APP_CLIENT_PEM: xml = requests.get(OFFICE_WEB_APP_BASE_URL, cert=OFFICE_WEB_APP_CLIENT_PEM, verify=OFFICE_WEB_APP_SERVER_CA) else: xml = requests.get(OFFICE_WEB_APP_BASE_URL, verify=OFFICE_WEB_APP_SERVER_CA) except Exception as e: logger.error(e) return None try: root = ET.fromstring(xml.content) except Exception as e: logger.error(e) return None for action in root.getiterator('action'): attr = action.attrib ext = attr.get('ext') name = attr.get('name') urlsrc = attr.get('urlsrc') if ext and name and urlsrc: tmp_action_url = re.sub(r'<.*>', '', urlsrc) tmp_wopi_key = generate_discovery_cache_key(name, ext) cache.set(tmp_wopi_key, tmp_action_url, OFFICE_WEB_APP_DISCOVERY_EXPIRATION) if wopi_key == tmp_wopi_key: action_url = tmp_action_url else: continue if not action_url: # can not get action_url from hosting discovery page return None # generate full action url repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) repo_path_info = '_'.join([origin_repo_id, origin_file_path]) else: repo_path_info = '_'.join([repo_id, file_path]) fake_file_id = hashlib.sha1(repo_path_info.encode('utf8')).hexdigest() base_url = get_site_scheme_and_netloc() check_file_info_endpoint = reverse('WOPIFilesView', args=[fake_file_id]) WOPISrc = urlparse.urljoin(base_url, check_file_info_endpoint) query_dict = {'WOPISrc': WOPISrc} if action_url[-1] in ('?', '&'): full_action_url = action_url + urllib.urlencode(query_dict) elif '?' in action_url: full_action_url = action_url + '&' + urllib.urlencode(query_dict) else: full_action_url = action_url + '?' + urllib.urlencode(query_dict) lang_code = Profile.objects.get_user_language(request_user) if lang_code.lower() == 'zh-cn': full_action_url += '&ui=zh-CN&rs=zh-CN' # generate access token user_repo_path_info = (request_user, repo_id, file_path) # collobora office only allowed alphanumeric and _ uid = uuid.uuid4() access_token = uid.hex key = generate_access_token_cache_key(access_token) cache.set(key, user_repo_path_info, WOPI_ACCESS_TOKEN_EXPIRATION) # access_token_ttl property tells office web app # when access token expires utc_timestamp = time.time() access_token_ttl = int( (utc_timestamp + WOPI_ACCESS_TOKEN_EXPIRATION) * 1000) wopi_dict = {} wopi_dict['action_url'] = full_action_url wopi_dict['access_token'] = access_token wopi_dict['access_token_ttl'] = access_token_ttl return wopi_dict