Merge pull request #1556 from YunoHost/applogos

Yoloimplementation of app logo support (require change in app catalog build)
This commit is contained in:
Alexandre Aubin 2023-01-03 16:34:02 +01:00 committed by GitHub
commit eacb1dc0e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 0 deletions

View file

@ -19,6 +19,10 @@ location /yunohost/admin/ {
more_set_headers "Cache-Control: no-store, no-cache, must-revalidate";
}
location /yunohost/admin/applogos/ {
alias /usr/share/yunohost/applogos/;
}
more_set_headers "Content-Security-Policy: upgrade-insecure-requests; default-src 'self'; connect-src 'self' https://paste.yunohost.org wss://$host; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-eval'; object-src 'none'; img-src 'self' data:;";
more_set_headers "Content-Security-Policy-Report-Only:";
}

View file

@ -71,6 +71,7 @@ from yunohost.app_catalog import ( # noqa
app_catalog,
app_search,
_load_apps_catalog,
APPS_CATALOG_LOGOS,
)
logger = getActionLogger("yunohost.app")
@ -151,6 +152,9 @@ def app_info(app, full=False, upgradable=False):
absolute_app_name, _ = _parse_app_instance_name(app)
from_catalog = _load_apps_catalog()["apps"].get(absolute_app_name, {})
# Check if $app.png exists in the app logo folder, this is a trick to be able to easily customize the logo
# of an app just by creating $app.png (instead of the hash.png) in the corresponding folder
ret["logo"] = app if os.path.exists(f"{APPS_CATALOG_LOGOS}/{app}.png") else from_catalog.get("logo_hash")
ret["upgradable"] = _app_upgradable({**ret, "from_catalog": from_catalog})
if ret["upgradable"] == "yes":

View file

@ -18,6 +18,7 @@
#
import os
import re
import hashlib
from moulinette import m18n
from moulinette.utils.log import getActionLogger
@ -36,6 +37,7 @@ from yunohost.utils.error import YunohostError
logger = getActionLogger("yunohost.app_catalog")
APPS_CATALOG_CACHE = "/var/cache/yunohost/repo"
APPS_CATALOG_LOGOS = "/usr/share/yunohost/applogos"
APPS_CATALOG_CONF = "/etc/yunohost/apps_catalog.yml"
APPS_CATALOG_API_VERSION = 3
APPS_CATALOG_DEFAULT_URL = "https://app.yunohost.org/default"
@ -182,6 +184,9 @@ def _update_apps_catalog():
logger.debug("Initialize folder for apps catalog cache")
mkdir(APPS_CATALOG_CACHE, mode=0o750, parents=True, uid="root")
if not os.path.exists(APPS_CATALOG_LOGOS):
mkdir(APPS_CATALOG_LOGOS, mode=0o755, parents=True, uid="root")
for apps_catalog in apps_catalog_list:
if apps_catalog["url"] is None:
continue
@ -212,6 +217,37 @@ def _update_apps_catalog():
raw_msg=True,
)
# Download missing app logos
logos_to_download = []
for app, infos in apps_catalog_content["apps"].items():
logo_hash = infos.get("logo_hash")
if not logo_hash or os.path.exists(f"{APPS_CATALOG_LOGOS}/{logo_hash}.png"):
continue
logos_to_download.append(logo_hash)
if len(logos_to_download) > 20:
logger.info(f"(Will fetch {len(logos_to_download)} logos, this may take a couple minutes)")
import requests
from multiprocessing.pool import ThreadPool
def fetch_logo(logo_hash):
try:
r = requests.get(f"{apps_catalog['url']}/v{APPS_CATALOG_API_VERSION}/logos/{logo_hash}.png", timeout=10)
assert r.status_code == 200, f"Got status code {r.status_code}, expected 200"
if hashlib.sha256(r.content).hexdigest() != logo_hash:
raise Exception(f"Found inconsistent hash while downloading logo {logo_hash}")
open(f"{APPS_CATALOG_LOGOS}/{logo_hash}.png", "wb").write(r.content)
return True
except Exception as e:
logger.debug(f"Failed to download logo {logo_hash} : {e}")
return False
results = ThreadPool(8).imap_unordered(fetch_logo, logos_to_download)
for result in results:
# Is this even needed to iterate on the results ?
pass
logger.success(m18n.n("apps_catalog_update_success"))