mirror of
https://git.anonymousland.org/anonymousland/synapse-product.git
synced 2024-09-09 13:12:00 +00:00
Synapse 1.21.0rc2 (2020-10-02)
============================== Features -------- - Convert additional templates from inline HTML to Jinja2 templates. ([\#8444](https://github.com/matrix-org/synapse/issues/8444)) Bugfixes -------- - Fix a regression in v1.21.0rc1 which broke thumbnails of remote media. ([\#8438](https://github.com/matrix-org/synapse/issues/8438)) - Do not expose the experimental `uk.half-shot.msc2778.login.application_service` flow in the login API, which caused a compatibility problem with Element iOS. ([\#8440](https://github.com/matrix-org/synapse/issues/8440)) - Fix malformed log line in new federation "catch up" logic. ([\#8442](https://github.com/matrix-org/synapse/issues/8442)) - Fix DB query on startup for negative streams which caused long start up times. Introduced in [\#8374](https://github.com/matrix-org/synapse/issues/8374). ([\#8447](https://github.com/matrix-org/synapse/issues/8447)) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEv27Axt/F4vrTL/8QOSor00I9eP8FAl93FccACgkQOSor00I9 eP9/Egf7B4YOF6tniyAXxZvmvFOwV1WNw4sbFmF+czUKHBTAwS/Ij9MbutulD4OB +yqHAvu15qUCQR/G+KGjyHBDtESEUtn5SRy8znLYlR2n3qfEdEpd5y6LJSq4s7sr NjFVNVI1g5L8PmbvvWCINfpPm2JSm8zyOdyxy4KZifex1B+8YgPILeQOB59sWL/H 1maFbHCgepqO3jotsA8PUXQZx5oScABmqYYe92b4sLna00uFBq2NWp0NA654dRqK VRFlGzId1fZNWTy1jzfOY2sJKpBCy4cMrtfGJ/eqMtryHqbnBFT6hgB8FyTNg0h0 oew+BLV/mcJLcvB0ALRMFS7xZHdoxQ== =+3N3 -----END PGP SIGNATURE----- Merge tag 'v1.21.0rc2' into develop Synapse 1.21.0rc2 (2020-10-02) ============================== Features -------- - Convert additional templates from inline HTML to Jinja2 templates. ([\#8444](https://github.com/matrix-org/synapse/issues/8444)) Bugfixes -------- - Fix a regression in v1.21.0rc1 which broke thumbnails of remote media. ([\#8438](https://github.com/matrix-org/synapse/issues/8438)) - Do not expose the experimental `uk.half-shot.msc2778.login.application_service` flow in the login API, which caused a compatibility problem with Element iOS. ([\#8440](https://github.com/matrix-org/synapse/issues/8440)) - Fix malformed log line in new federation "catch up" logic. ([\#8442](https://github.com/matrix-org/synapse/issues/8442)) - Fix DB query on startup for negative streams which caused long start up times. Introduced in [\#8374](https://github.com/matrix-org/synapse/issues/8374). ([\#8447](https://github.com/matrix-org/synapse/issues/8447))
This commit is contained in:
commit
462e681c79
17
CHANGES.md
17
CHANGES.md
@ -1,3 +1,20 @@
|
|||||||
|
Synapse 1.21.0rc2 (2020-10-02)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Convert additional templates from inline HTML to Jinja2 templates. ([\#8444](https://github.com/matrix-org/synapse/issues/8444))
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Fix a regression in v1.21.0rc1 which broke thumbnails of remote media. ([\#8438](https://github.com/matrix-org/synapse/issues/8438))
|
||||||
|
- Do not expose the experimental `uk.half-shot.msc2778.login.application_service` flow in the login API, which caused a compatibility problem with Element iOS. ([\#8440](https://github.com/matrix-org/synapse/issues/8440))
|
||||||
|
- Fix malformed log line in new federation "catch up" logic. ([\#8442](https://github.com/matrix-org/synapse/issues/8442))
|
||||||
|
- Fix DB query on startup for negative streams which caused long start up times. Introduced in [\#8374](https://github.com/matrix-org/synapse/issues/8374). ([\#8447](https://github.com/matrix-org/synapse/issues/8447))
|
||||||
|
|
||||||
|
|
||||||
Synapse 1.21.0rc1 (2020-10-01)
|
Synapse 1.21.0rc1 (2020-10-01)
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
__version__ = "1.21.0rc1"
|
__version__ = "1.21.0rc2"
|
||||||
|
|
||||||
if bool(os.environ.get("SYNAPSE_TEST_PATCH_LOG_CONTEXTS", False)):
|
if bool(os.environ.get("SYNAPSE_TEST_PATCH_LOG_CONTEXTS", False)):
|
||||||
# We import here so that we don't have to install a bunch of deps when
|
# We import here so that we don't have to install a bunch of deps when
|
||||||
|
@ -242,11 +242,10 @@ class Config:
|
|||||||
env = jinja2.Environment(loader=loader, autoescape=autoescape)
|
env = jinja2.Environment(loader=loader, autoescape=autoescape)
|
||||||
|
|
||||||
# Update the environment with our custom filters
|
# Update the environment with our custom filters
|
||||||
|
env.filters.update({"format_ts": _format_ts_filter})
|
||||||
|
if self.public_baseurl:
|
||||||
env.filters.update(
|
env.filters.update(
|
||||||
{
|
{"mxc_to_http": _create_mxc_to_http_filter(self.public_baseurl)}
|
||||||
"format_ts": _format_ts_filter,
|
|
||||||
"mxc_to_http": _create_mxc_to_http_filter(self.public_baseurl),
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
|
@ -28,6 +28,9 @@ class CaptchaConfig(Config):
|
|||||||
"recaptcha_siteverify_api",
|
"recaptcha_siteverify_api",
|
||||||
"https://www.recaptcha.net/recaptcha/api/siteverify",
|
"https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||||
)
|
)
|
||||||
|
self.recaptcha_template = self.read_templates(
|
||||||
|
["recaptcha.html"], autoescape=True
|
||||||
|
)[0]
|
||||||
|
|
||||||
def generate_config_section(self, **kwargs):
|
def generate_config_section(self, **kwargs):
|
||||||
return """\
|
return """\
|
||||||
|
@ -89,6 +89,8 @@ class ConsentConfig(Config):
|
|||||||
|
|
||||||
def read_config(self, config, **kwargs):
|
def read_config(self, config, **kwargs):
|
||||||
consent_config = config.get("user_consent")
|
consent_config = config.get("user_consent")
|
||||||
|
self.terms_template = self.read_templates(["terms.html"], autoescape=True)[0]
|
||||||
|
|
||||||
if consent_config is None:
|
if consent_config is None:
|
||||||
return
|
return
|
||||||
self.user_consent_version = str(consent_config["version"])
|
self.user_consent_version = str(consent_config["version"])
|
||||||
|
@ -187,6 +187,11 @@ class RegistrationConfig(Config):
|
|||||||
session_lifetime = self.parse_duration(session_lifetime)
|
session_lifetime = self.parse_duration(session_lifetime)
|
||||||
self.session_lifetime = session_lifetime
|
self.session_lifetime = session_lifetime
|
||||||
|
|
||||||
|
# The success template used during fallback auth.
|
||||||
|
self.fallback_success_template = self.read_templates(
|
||||||
|
["auth_success.html"], autoescape=True
|
||||||
|
)[0]
|
||||||
|
|
||||||
def generate_config_section(self, generate_secrets=False, **kwargs):
|
def generate_config_section(self, generate_secrets=False, **kwargs):
|
||||||
if generate_secrets:
|
if generate_secrets:
|
||||||
registration_shared_secret = 'registration_shared_secret: "%s"' % (
|
registration_shared_secret = 'registration_shared_secret: "%s"' % (
|
||||||
|
@ -490,7 +490,7 @@ class PerDestinationQueue:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if logger.isEnabledFor(logging.INFO):
|
if logger.isEnabledFor(logging.INFO):
|
||||||
rooms = (p.room_id for p in catchup_pdus)
|
rooms = [p.room_id for p in catchup_pdus]
|
||||||
logger.info("Catching up rooms to %s: %r", self._destination, rooms)
|
logger.info("Catching up rooms to %s: %r", self._destination, rooms)
|
||||||
|
|
||||||
success = await self._transaction_manager.send_new_transaction(
|
success = await self._transaction_manager.send_new_transaction(
|
||||||
|
21
synapse/res/templates/auth_success.html
Normal file
21
synapse/res/templates/auth_success.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Success!</title>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1,
|
||||||
|
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
||||||
|
<link rel="stylesheet" href="/_matrix/static/client/register/style.css">
|
||||||
|
<script>
|
||||||
|
if (window.onAuthDone) {
|
||||||
|
window.onAuthDone();
|
||||||
|
} else if (window.opener && window.opener.postMessage) {
|
||||||
|
window.opener.postMessage("authDone", "*");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p>Thank you</p>
|
||||||
|
<p>You may now close this window and return to the application</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
38
synapse/res/templates/recaptcha.html
Normal file
38
synapse/res/templates/recaptcha.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Authentication</title>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1,
|
||||||
|
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
||||||
|
<script src="https://www.recaptcha.net/recaptcha/api.js"
|
||||||
|
async defer></script>
|
||||||
|
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="/_matrix/static/client/register/style.css">
|
||||||
|
<script>
|
||||||
|
function captchaDone() {
|
||||||
|
$('#registrationForm').submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form id="registrationForm" method="post" action="{{ myurl }}">
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Hello! We need to prevent computer programs and other automated
|
||||||
|
things from creating accounts on this server.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please verify that you're not a robot.
|
||||||
|
</p>
|
||||||
|
<input type="hidden" name="session" value="{{ session }}" />
|
||||||
|
<div class="g-recaptcha"
|
||||||
|
data-sitekey="{{ sitekey }}"
|
||||||
|
data-callback="captchaDone">
|
||||||
|
</div>
|
||||||
|
<noscript>
|
||||||
|
<input type="submit" value="All Done" />
|
||||||
|
</noscript>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
20
synapse/res/templates/terms.html
Normal file
20
synapse/res/templates/terms.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Authentication</title>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1,
|
||||||
|
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
||||||
|
<link rel="stylesheet" href="/_matrix/static/client/register/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form id="registrationForm" method="post" action="{{ myurl }}">
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Please click the button below if you agree to the
|
||||||
|
<a href="{{ terms_url }}">privacy policy of this homeserver.</a>
|
||||||
|
</p>
|
||||||
|
<input type="hidden" name="session" value="{{ session }}" />
|
||||||
|
<input type="submit" value="Agree" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -111,8 +111,6 @@ class LoginRestServlet(RestServlet):
|
|||||||
({"type": t} for t in self.auth_handler.get_supported_login_types())
|
({"type": t} for t in self.auth_handler.get_supported_login_types())
|
||||||
)
|
)
|
||||||
|
|
||||||
flows.append({"type": LoginRestServlet.APPSERVICE_TYPE})
|
|
||||||
|
|
||||||
return 200, {"flows": flows}
|
return 200, {"flows": flows}
|
||||||
|
|
||||||
def on_OPTIONS(self, request: SynapseRequest):
|
def on_OPTIONS(self, request: SynapseRequest):
|
||||||
|
@ -25,94 +25,6 @@ from ._base import client_patterns
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
RECAPTCHA_TEMPLATE = """
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Authentication</title>
|
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1,
|
|
||||||
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
|
||||||
<script src="https://www.recaptcha.net/recaptcha/api.js"
|
|
||||||
async defer></script>
|
|
||||||
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
|
|
||||||
<link rel="stylesheet" href="/_matrix/static/client/register/style.css">
|
|
||||||
<script>
|
|
||||||
function captchaDone() {
|
|
||||||
$('#registrationForm').submit();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form id="registrationForm" method="post" action="%(myurl)s">
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
Hello! We need to prevent computer programs and other automated
|
|
||||||
things from creating accounts on this server.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Please verify that you're not a robot.
|
|
||||||
</p>
|
|
||||||
<input type="hidden" name="session" value="%(session)s" />
|
|
||||||
<div class="g-recaptcha"
|
|
||||||
data-sitekey="%(sitekey)s"
|
|
||||||
data-callback="captchaDone">
|
|
||||||
</div>
|
|
||||||
<noscript>
|
|
||||||
<input type="submit" value="All Done" />
|
|
||||||
</noscript>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
|
|
||||||
TERMS_TEMPLATE = """
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Authentication</title>
|
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1,
|
|
||||||
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
|
||||||
<link rel="stylesheet" href="/_matrix/static/client/register/style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<form id="registrationForm" method="post" action="%(myurl)s">
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
Please click the button below if you agree to the
|
|
||||||
<a href="%(terms_url)s">privacy policy of this homeserver.</a>
|
|
||||||
</p>
|
|
||||||
<input type="hidden" name="session" value="%(session)s" />
|
|
||||||
<input type="submit" value="Agree" />
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
|
|
||||||
SUCCESS_TEMPLATE = """
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Success!</title>
|
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1,
|
|
||||||
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0'>
|
|
||||||
<link rel="stylesheet" href="/_matrix/static/client/register/style.css">
|
|
||||||
<script>
|
|
||||||
if (window.onAuthDone) {
|
|
||||||
window.onAuthDone();
|
|
||||||
} else if (window.opener && window.opener.postMessage) {
|
|
||||||
window.opener.postMessage("authDone", "*");
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div>
|
|
||||||
<p>Thank you</p>
|
|
||||||
<p>You may now close this window and return to the application</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class AuthRestServlet(RestServlet):
|
class AuthRestServlet(RestServlet):
|
||||||
"""
|
"""
|
||||||
@ -145,26 +57,30 @@ class AuthRestServlet(RestServlet):
|
|||||||
self._cas_server_url = hs.config.cas_server_url
|
self._cas_server_url = hs.config.cas_server_url
|
||||||
self._cas_service_url = hs.config.cas_service_url
|
self._cas_service_url = hs.config.cas_service_url
|
||||||
|
|
||||||
|
self.recaptcha_template = hs.config.recaptcha_template
|
||||||
|
self.terms_template = hs.config.terms_template
|
||||||
|
self.success_template = hs.config.fallback_success_template
|
||||||
|
|
||||||
async def on_GET(self, request, stagetype):
|
async def on_GET(self, request, stagetype):
|
||||||
session = parse_string(request, "session")
|
session = parse_string(request, "session")
|
||||||
if not session:
|
if not session:
|
||||||
raise SynapseError(400, "No session supplied")
|
raise SynapseError(400, "No session supplied")
|
||||||
|
|
||||||
if stagetype == LoginType.RECAPTCHA:
|
if stagetype == LoginType.RECAPTCHA:
|
||||||
html = RECAPTCHA_TEMPLATE % {
|
html = self.recaptcha_template.render(
|
||||||
"session": session,
|
session=session,
|
||||||
"myurl": "%s/r0/auth/%s/fallback/web"
|
myurl="%s/r0/auth/%s/fallback/web"
|
||||||
% (CLIENT_API_PREFIX, LoginType.RECAPTCHA),
|
% (CLIENT_API_PREFIX, LoginType.RECAPTCHA),
|
||||||
"sitekey": self.hs.config.recaptcha_public_key,
|
sitekey=self.hs.config.recaptcha_public_key,
|
||||||
}
|
)
|
||||||
elif stagetype == LoginType.TERMS:
|
elif stagetype == LoginType.TERMS:
|
||||||
html = TERMS_TEMPLATE % {
|
html = self.terms_template.render(
|
||||||
"session": session,
|
session=session,
|
||||||
"terms_url": "%s_matrix/consent?v=%s"
|
terms_url="%s_matrix/consent?v=%s"
|
||||||
% (self.hs.config.public_baseurl, self.hs.config.user_consent_version),
|
% (self.hs.config.public_baseurl, self.hs.config.user_consent_version),
|
||||||
"myurl": "%s/r0/auth/%s/fallback/web"
|
myurl="%s/r0/auth/%s/fallback/web"
|
||||||
% (CLIENT_API_PREFIX, LoginType.TERMS),
|
% (CLIENT_API_PREFIX, LoginType.TERMS),
|
||||||
}
|
)
|
||||||
|
|
||||||
elif stagetype == LoginType.SSO:
|
elif stagetype == LoginType.SSO:
|
||||||
# Display a confirmation page which prompts the user to
|
# Display a confirmation page which prompts the user to
|
||||||
@ -222,14 +138,14 @@ class AuthRestServlet(RestServlet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
html = SUCCESS_TEMPLATE
|
html = self.success_template.render()
|
||||||
else:
|
else:
|
||||||
html = RECAPTCHA_TEMPLATE % {
|
html = self.recaptcha_template.render(
|
||||||
"session": session,
|
session=session,
|
||||||
"myurl": "%s/r0/auth/%s/fallback/web"
|
myurl="%s/r0/auth/%s/fallback/web"
|
||||||
% (CLIENT_API_PREFIX, LoginType.RECAPTCHA),
|
% (CLIENT_API_PREFIX, LoginType.RECAPTCHA),
|
||||||
"sitekey": self.hs.config.recaptcha_public_key,
|
sitekey=self.hs.config.recaptcha_public_key,
|
||||||
}
|
)
|
||||||
elif stagetype == LoginType.TERMS:
|
elif stagetype == LoginType.TERMS:
|
||||||
authdict = {"session": session}
|
authdict = {"session": session}
|
||||||
|
|
||||||
@ -238,18 +154,18 @@ class AuthRestServlet(RestServlet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
html = SUCCESS_TEMPLATE
|
html = self.success_template.render()
|
||||||
else:
|
else:
|
||||||
html = TERMS_TEMPLATE % {
|
html = self.terms_template.render(
|
||||||
"session": session,
|
session=session,
|
||||||
"terms_url": "%s_matrix/consent?v=%s"
|
terms_url="%s_matrix/consent?v=%s"
|
||||||
% (
|
% (
|
||||||
self.hs.config.public_baseurl,
|
self.hs.config.public_baseurl,
|
||||||
self.hs.config.user_consent_version,
|
self.hs.config.user_consent_version,
|
||||||
),
|
),
|
||||||
"myurl": "%s/r0/auth/%s/fallback/web"
|
myurl="%s/r0/auth/%s/fallback/web"
|
||||||
% (CLIENT_API_PREFIX, LoginType.TERMS),
|
% (CLIENT_API_PREFIX, LoginType.TERMS),
|
||||||
}
|
)
|
||||||
elif stagetype == LoginType.SSO:
|
elif stagetype == LoginType.SSO:
|
||||||
# The SSO fallback workflow should not post here,
|
# The SSO fallback workflow should not post here,
|
||||||
raise SynapseError(404, "Fallback SSO auth does not support POST requests.")
|
raise SynapseError(404, "Fallback SSO auth does not support POST requests.")
|
||||||
|
@ -141,31 +141,34 @@ class MediaStorage:
|
|||||||
Returns:
|
Returns:
|
||||||
Returns a Responder if the file was found, otherwise None.
|
Returns a Responder if the file was found, otherwise None.
|
||||||
"""
|
"""
|
||||||
|
paths = [self._file_info_to_path(file_info)]
|
||||||
|
|
||||||
path = self._file_info_to_path(file_info)
|
# fallback for remote thumbnails with no method in the filename
|
||||||
local_path = os.path.join(self.local_media_directory, path)
|
|
||||||
if os.path.exists(local_path):
|
|
||||||
return FileResponder(open(local_path, "rb"))
|
|
||||||
|
|
||||||
# Fallback for paths without method names
|
|
||||||
# Should be removed in the future
|
|
||||||
if file_info.thumbnail and file_info.server_name:
|
if file_info.thumbnail and file_info.server_name:
|
||||||
legacy_path = self.filepaths.remote_media_thumbnail_rel_legacy(
|
paths.append(
|
||||||
|
self.filepaths.remote_media_thumbnail_rel_legacy(
|
||||||
server_name=file_info.server_name,
|
server_name=file_info.server_name,
|
||||||
file_id=file_info.file_id,
|
file_id=file_info.file_id,
|
||||||
width=file_info.thumbnail_width,
|
width=file_info.thumbnail_width,
|
||||||
height=file_info.thumbnail_height,
|
height=file_info.thumbnail_height,
|
||||||
content_type=file_info.thumbnail_type,
|
content_type=file_info.thumbnail_type,
|
||||||
)
|
)
|
||||||
legacy_local_path = os.path.join(self.local_media_directory, legacy_path)
|
)
|
||||||
if os.path.exists(legacy_local_path):
|
|
||||||
return FileResponder(open(legacy_local_path, "rb"))
|
for path in paths:
|
||||||
|
local_path = os.path.join(self.local_media_directory, path)
|
||||||
|
if os.path.exists(local_path):
|
||||||
|
logger.debug("responding with local file %s", local_path)
|
||||||
|
return FileResponder(open(local_path, "rb"))
|
||||||
|
logger.debug("local file %s did not exist", local_path)
|
||||||
|
|
||||||
for provider in self.storage_providers:
|
for provider in self.storage_providers:
|
||||||
|
for path in paths:
|
||||||
res = await provider.fetch(path, file_info) # type: Any
|
res = await provider.fetch(path, file_info) # type: Any
|
||||||
if res:
|
if res:
|
||||||
logger.debug("Streaming %s from %s", path, provider)
|
logger.debug("Streaming %s from %s", path, provider)
|
||||||
return res
|
return res
|
||||||
|
logger.debug("%s not found on %s", path, provider)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ class MultiWriterIdGenerator:
|
|||||||
"cmp": "<=" if self._positive else ">=",
|
"cmp": "<=" if self._positive else ">=",
|
||||||
}
|
}
|
||||||
sql = self._db.engine.convert_param_style(sql)
|
sql = self._db.engine.convert_param_style(sql)
|
||||||
cur.execute(sql, (min_stream_id,))
|
cur.execute(sql, (min_stream_id * self._return_factor,))
|
||||||
|
|
||||||
self._persisted_upto_position = min_stream_id
|
self._persisted_upto_position = min_stream_id
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user