Exemple #1
0
    def publisher_details(publisher):
        """
        A view to display the publisher details page for specific publisher.
        """

        publisher_content_path = flask.current_app.config["CONTENT_DIRECTORY"][
            "PUBLISHER_PAGES"
        ]

        context = helpers.get_yaml(
            publisher_content_path + publisher + ".yaml", typ="safe"
        )

        if not context:
            flask.abort(404)

        popular_snaps = helpers.get_yaml(
            publisher_content_path + publisher + "-snaps.yaml",
            typ="safe",
        )

        context["popular_snaps"] = (
            popular_snaps["snaps"] if popular_snaps else []
        )

        if "publishers" in context:
            context["snaps"] = []
            for publisher in context["publishers"]:
                snaps_results = []
                try:
                    snaps_results = api.get_publisher_items(
                        publisher, size=500, page=1
                    )["results"]
                except StoreApiError:
                    pass

                context["snaps"].extend(
                    [snap for snap in snaps_results if snap["apps"]]
                )

        featured_snaps = [
            snap["package_name"] for snap in context["featured_snaps"]
        ]

        context["snaps"] = [
            snap
            for snap in context["snaps"]
            if snap["package_name"] not in featured_snaps
        ]

        context["snaps_count"] = len(snaps_results)

        return flask.render_template("store/publisher-details.html", **context)
Exemple #2
0
def get_livestreams():
    """
    Get available livestreams and decide whether they should be shown
    :returns: Dictionary of livestream details
    """
    livestream_to_show = None
    livestreams = helpers.get_yaml("snapcraft/content/snapcraft_live.yaml",
                                   typ="safe")

    if livestreams:
        now = datetime.now()
        lead_time = 4  # 4 days
        cooldown_time = 2  # 2 days

        for livestream in livestreams:
            instance_lead_time = lead_time
            if "lead_time" in livestream:
                instance_lead_time = livestream["lead_time"]

            instance_cooldown_time = cooldown_time
            if "cooldown_time" in livestream:
                instance_cooldown_time = livestream["cooldown_time"]

            show_from = livestream["time"] - timedelta(days=instance_lead_time)
            show_until = livestream["time"] + timedelta(
                days=instance_cooldown_time)

            if show_from < now and show_until > now:
                livestream_to_show = livestream

    return livestream_to_show
Exemple #3
0
    def snap_distro_install(snap_name, distro):
        filename = f"store/content/distros/{distro}.yaml"
        distro_data = helpers.get_yaml(filename)

        if not distro_data:
            flask.abort(404)

        context = _get_context_snap_details(snap_name)
        context.update({
            "distro": distro,
            "distro_name": distro_data["name"],
            "distro_logo": distro_data["logo"],
            "distro_logo_mono": distro_data["logo-mono"],
            "distro_color_1": distro_data["color-1"],
            "distro_color_2": distro_data["color-2"],
            "distro_install_steps": distro_data["install"],
        })

        try:
            featured_snaps_results = api.get_searched_snaps(
                snap_searched="", category="featured", size=12, page=1)
        except ApiError:
            featured_snaps_results = []

        featured_snaps = logic.get_searched_snaps(featured_snaps_results)

        context.update({"featured_snaps": featured_snaps})
        return flask.render_template("store/snap-distro-install.html",
                                     **context)
Exemple #4
0
def get_language_snapcraft_yaml(language):
    filename = f"first_snap/content/{language}/package.yaml"
    snapcraft_yaml_filename = f"first_snap/content/{language}/snapcraft.yaml"
    snap_name_cookie = f"fsf_snap_name_{language}"
    steps = helpers.get_yaml(filename, typ="rt")

    if not steps:
        return flask.abort(404)

    snap_name = steps["name"]

    if snap_name_cookie in flask.request.cookies:
        snap_name = flask.request.cookies.get(snap_name_cookie)

    snapcraft_yaml = helpers.get_file(
        snapcraft_yaml_filename, {"${name}": snap_name}
    )

    if not snapcraft_yaml:
        return flask.abort(404)

    return flask.Response(
        snapcraft_yaml,
        mimetype="text/yaml",
        headers={"Content-Disposition": "attachment;filename=snapcraft.yaml"},
    )
Exemple #5
0
def get_build(language, operating_system):
    filename = f"first_snap/content/{language}/build.yaml"
    snap_name_cookie = f"fsf_snap_name_{language}"
    steps = helpers.get_yaml(filename, typ="rt")
    operating_system_parts = operating_system.split("-")

    operating_system_only = operating_system_parts[0]
    install_type = (operating_system_parts[1]
                    if len(operating_system_parts) == 2 else "auto")

    if ((not steps) or (operating_system_only not in steps)
            or (install_type not in steps[operating_system_only])):
        return flask.abort(404)

    snap_name = steps["name"]

    if flask.session.get("openid"):
        user_name = flask.session["openid"]["nickname"]
        snap_name = snap_name.replace("{name}", user_name)

    if snap_name_cookie in flask.request.cookies:
        snap_name = flask.request.cookies.get(snap_name_cookie)

    context = {
        "language": language,
        "os": operating_system,
        "steps": steps[operating_system_only][install_type],
        "snap_name": snap_name,
    }

    return flask.render_template("first-snap/build.html", **context)
Exemple #6
0
def get_build(language, operating_system):
    build_filename = f"first_snap/content/{language}/build.yaml"
    test_filename = f"first_snap/content/{language}/test.yaml"
    snap_name_cookie = f"fsf_snap_name_{language}"
    build_steps = helpers.get_yaml(build_filename, typ="rt")
    test_steps = helpers.get_yaml(test_filename, typ="rt")
    operating_system_parts = operating_system.split("-")

    operating_system_only = operating_system_parts[0]
    install_type = (
        operating_system_parts[1]
        if len(operating_system_parts) == 2
        else "auto"
    )

    if (
        (not (build_steps and test_steps))
        or (
            (operating_system_only not in build_steps)
            and (operating_system_only not in test_steps)
        )
        or (install_type not in build_steps[operating_system_only])
    ):
        return flask.abort(404)

    snap_name = build_steps["name"]

    if "publisher" in flask.session:
        user_name = flask.session["publisher"]["nickname"]
        snap_name = snap_name.replace("{name}", user_name)

    if snap_name_cookie in flask.request.cookies:
        snap_name = flask.request.cookies.get(snap_name_cookie)

    context = {
        "language": language,
        "os": operating_system,
        "build_steps": build_steps[operating_system_only][install_type],
        "test_steps": test_steps[operating_system_only],
        "snap_name": snap_name,
        "fsf_flow": FSF_FLOW,
    }

    return flask.render_template("first-snap/build-and-test.html", **context)
Exemple #7
0
def get_package(language, operating_system):
    filename = f"first_snap/content/{language}/package.yaml"
    snapcraft_yaml_filename = f"first_snap/content/{language}/snapcraft.yaml"
    annotations_filename = "first_snap/content/snapcraft_yaml_annotations.yaml"

    snap_name_cookie = f"fsf_snap_name_{language}"
    steps = helpers.get_yaml(filename, typ="rt")

    if not steps:
        return flask.abort(404)

    snap_name = steps["name"]
    has_user_chosen_name = False

    if "publisher" in flask.session:
        user_name = flask.session["publisher"]["nickname"]
        snap_name = snap_name.replace("{name}", user_name)

    if snap_name_cookie in flask.request.cookies:
        snap_name = flask.request.cookies.get(snap_name_cookie)
        has_user_chosen_name = True

    context = {
        "language": language,
        "os": operating_system,
        "steps": steps,
        "snap_name": snap_name,
        "has_user_chosen_name": has_user_chosen_name,
        "fsf_flow": FSF_FLOW,
    }

    snapcraft_yaml = helpers.get_yaml(
        snapcraft_yaml_filename, typ="rt", replaces={"${name}": snap_name}
    )
    annotations = helpers.get_yaml(annotations_filename, typ="rt")

    if snapcraft_yaml:
        context["snapcraft_yaml"] = transform_snapcraft_yaml(snapcraft_yaml)
        context["annotations"] = annotations
        return flask.render_template("first-snap/package.html", **context)
    else:
        return flask.abort(404)
Exemple #8
0
    def publisher_details(publisher):
        """
        A view to display the publisher details page for specific publisher.
        """

        publisher_content_path = flask.current_app.config["CONTENT_DIRECTORY"][
            "PUBLISHER_PAGES"]

        context = helpers.get_yaml(publisher_content_path + publisher +
                                   ".yaml",
                                   typ="safe")

        if not context:
            flask.abort(404)

        return flask.render_template("store/publisher-details.html", **context)
Exemple #9
0
def get_snap_developer(snap_name):
    """Is this a special snap published by Canonical?
    Show some developer information

    :param snap_name: The name of a snap

    :returns: a list of [display_name, url]

    """
    filename = "store/content/developers/snaps.yaml"
    snaps = helpers.get_yaml(filename, typ="rt")

    if snaps and snap_name in snaps:
        return snaps[snap_name]

    return None
Exemple #10
0
    def snap_distro_install(snap_name, distro):
        filename = f"store/content/distros/{distro}.yaml"
        distro_data = helpers.get_yaml(filename)

        if not distro_data:
            flask.abort(404)

        context = _get_context_snap_details(snap_name)

        if distro == "raspbian":
            if (
                "armhf" not in context["channel_map"]
                and "arm64" not in context["channel_map"]
            ):
                return flask.render_template("404.html"), 404

        context.update(
            {
                "distro": distro,
                "distro_name": distro_data["name"],
                "distro_logo": distro_data["logo"],
                "distro_logo_mono": distro_data["logo-mono"],
                "distro_color_1": distro_data["color-1"],
                "distro_color_2": distro_data["color-2"],
                "distro_install_steps": distro_data["install"],
            }
        )

        try:
            featured_snaps_results = api.get_featured_items(size=13, page=1)
        except StoreApiError:
            featured_snaps_results = []

        featured_snaps = [
            snap
            for snap in logic.get_searched_snaps(featured_snaps_results)
            if snap["package_name"] != snap_name
        ][:12]

        context.update({"featured_snaps": featured_snaps})
        return flask.render_template(
            "store/snap-distro-install.html", **context
        )
Exemple #11
0
def get_upload(language, operating_system):
    filename = f"first_snap/content/{language}/package.yaml"
    snap_name_cookie = f"fsf_snap_name_{language}"

    data = helpers.get_yaml(filename, typ="rt")

    if not data:
        return flask.abort(404)

    snap_name = data["name"]
    has_user_chosen_name = False

    if "publisher" in flask.session:
        user_name = flask.session["publisher"]["nickname"]
        snap_name = snap_name.replace("{name}", user_name)

    if snap_name_cookie in flask.request.cookies:
        snap_name = flask.request.cookies.get(snap_name_cookie)
        has_user_chosen_name = True

    flask_user = flask.session.get("publisher", {})

    if "nickname" in flask_user:
        user = {
            "image": flask_user["image"],
            "username": flask_user["nickname"],
            "display_name": flask_user["fullname"],
            "email": flask_user["email"],
        }
    else:
        user = None

    context = {
        "language": language,
        "os": operating_system,
        "user": user,
        "snap_name": snap_name,
        "has_user_chosen_name": has_user_chosen_name,
        "fsf_flow": FSF_FLOW,
    }

    return flask.render_template("first-snap/upload.html", **context)
Exemple #12
0
def get_test(language, operating_system):
    filename = f"first_snap/content/{language}/test.yaml"
    snap_name_cookie = f"fsf_snap_name_{language}"
    steps = helpers.get_yaml(filename, typ="rt")

    operating_system_only = operating_system.split("-")[0]

    if not steps or operating_system_only not in steps:
        return flask.abort(404)

    snap_name = steps["name"]

    if flask.session.get("openid"):
        user_name = flask.session["openid"]["nickname"]
        snap_name = snap_name.replace("{name}", user_name)

    if snap_name_cookie in flask.request.cookies:
        snap_name = flask.request.cookies.get(snap_name_cookie)

    converted_steps = []

    for step in steps[operating_system_only]:
        action = logic.convert_md(step["action"])
        converted_steps.append({
            "action":
            action,
            "warning":
            step["warning"] if "warning" in step else None,
            "command":
            step["command"] if "command" in step else None,
        })

    context = {
        "language": language,
        "os": operating_system,
        "steps": converted_steps,
        "snap_name": snap_name,
    }

    return flask.render_template("first-snap/test.html", **context)
Exemple #13
0
def get_listing_snap(snap_name):
    try:
        snap_details = api.get_snap_info(snap_name, flask.session)
    except ApiResponseErrorList as api_response_error_list:
        if api_response_error_list.status_code == 404:
            return flask.abort(404, "No snap named {}".format(snap_name))
        else:
            return _handle_error_list(api_response_error_list.errors)
    except ApiError as api_error:
        return _handle_error(api_error)

    details_metrics_enabled = snap_details["public_metrics_enabled"]
    details_blacklist = snap_details["public_metrics_blacklist"]

    is_on_stable = logic.is_snap_on_stable(snap_details["channel_maps_list"])

    # Filter icon & screenshot urls from the media set.
    icon_urls, screenshot_urls, banner_urls = logic.categorise_media(
        snap_details["media"])

    licenses = []
    for license in get_licenses():
        licenses.append({"key": license["licenseId"], "name": license["name"]})

    license = snap_details["license"]
    license_type = "custom"

    if " AND " not in license.upper() and " WITH " not in license.upper():
        license_type = "simple"

    referrer = None

    if flask.request.args.get("from"):
        referrer = flask.request.args.get("from")

    try:
        categories_results = store_api.get_categories()
    except StoreApiError:
        categories_results = []

    categories = sorted(
        get_categories(categories_results),
        key=lambda category: category["slug"],
    )

    snap_categories = logic.replace_reserved_categories_key(
        snap_details["categories"])

    snap_categories = logic.filter_categories(snap_categories)

    snap_categories["categories"] = [
        category["name"] for category in snap_categories["categories"]
    ]

    filename = f"publisher/content/listing_tour.yaml"
    tour_steps = helpers.get_yaml(filename, typ="rt")

    context = {
        "snap_id": snap_details["snap_id"],
        "snap_name": snap_details["snap_name"],
        "snap_title": snap_details["title"],
        "snap_categories": snap_categories,
        "summary": snap_details["summary"],
        "description": snap_details["description"],
        "icon_url": icon_urls[0] if icon_urls else None,
        "publisher_name": snap_details["publisher"]["display-name"],
        "username": snap_details["publisher"]["username"],
        "screenshot_urls": screenshot_urls,
        "banner_urls": banner_urls,
        "contact": snap_details["contact"],
        "private": snap_details["private"],
        "website": snap_details["website"] or "",
        "public_metrics_enabled": details_metrics_enabled,
        "public_metrics_blacklist": details_blacklist,
        "license": license,
        "license_type": license_type,
        "licenses": licenses,
        "video_urls": snap_details["video_urls"],
        "is_on_stable": is_on_stable,
        "from": referrer,
        "categories": categories,
        "tour_steps": tour_steps,
    }

    return flask.render_template("publisher/listing.html", **context)
    def _get_context_snap_details(snap_name):
        try:
            details = api.get_item_details(snap_name, api_version=2)
        except StoreApiTimeoutError as api_timeout_error:
            flask.abort(504, str(api_timeout_error))
        except StoreApiResponseDecodeError as api_response_decode_error:
            flask.abort(502, str(api_response_decode_error))
        except StoreApiResponseErrorList as api_response_error_list:
            if api_response_error_list.status_code == 404:
                flask.abort(404, "No snap named {}".format(snap_name))
            else:
                if api_response_error_list.errors:
                    error_messages = ", ".join(
                        api_response_error_list.errors.key())
                else:
                    error_messages = "An error occurred."
                flask.abort(502, error_messages)
        except StoreApiResponseError as api_response_error:
            flask.abort(502, str(api_response_error))
        except StoreApiCircuitBreaker:
            flask.abort(503)
        except (StoreApiError, ApiError) as api_error:
            flask.abort(502, str(api_error))

        # When removing all the channel maps of an existing snap the API,
        # responds that the snaps still exists with data.
        # Return a 404 if not channel maps, to avoid having a error.
        # For example: mir-kiosk-browser
        if not details.get("channel-map"):
            flask.abort(404, "No snap named {}".format(snap_name))

        clean_description = bleach.clean(details["snap"]["description"],
                                         tags=[])
        formatted_description = parse_markdown_description(clean_description)

        channel_maps_list = logic.convert_channel_maps(
            details.get("channel-map"))

        latest_channel = logic.get_last_updated_version(
            details.get("channel-map"))

        last_updated = latest_channel["created-at"]
        last_version = latest_channel["version"]
        binary_filesize = latest_channel["download"]["size"]

        # filter out banner and banner-icon images from screenshots
        screenshots = logic.filter_screenshots(details["snap"]["media"])

        icons = logic.get_icon(details["snap"]["media"])

        publisher_info = helpers.get_yaml(
            "{}{}.yaml".format(
                flask.current_app.config["CONTENT_DIRECTORY"]
                ["PUBLISHER_PAGES"],
                details["snap"]["publisher"]["username"],
            ),
            typ="safe",
        )

        publisher_snaps = helpers.get_yaml(
            "{}{}-snaps.yaml".format(
                flask.current_app.config["CONTENT_DIRECTORY"]
                ["PUBLISHER_PAGES"],
                details["snap"]["publisher"]["username"],
            ),
            typ="safe",
        )

        publisher_featured_snaps = None

        if publisher_info:
            publisher_featured_snaps = publisher_info.get("featured_snaps")
            publisher_snaps = logic.get_n_random_snaps(
                publisher_snaps["snaps"], 4)

        videos = logic.get_videos(details["snap"]["media"])

        # until default tracks are supported by the API we special case node
        # to use 10, rather then latest
        default_track = helpers.get_default_track(details["name"])
        if not default_track:
            default_track = (details.get("default-track")
                             if details.get("default-track") else "latest")

        lowest_risk_available = logic.get_lowest_available_risk(
            channel_maps_list, default_track)

        confinement = logic.get_confinement(channel_maps_list, default_track,
                                            lowest_risk_available)

        last_version = logic.get_version(channel_maps_list, default_track,
                                         lowest_risk_available)

        is_users_snap = False
        if authentication.is_authenticated(flask.session):
            if (flask.session.get("openid").get("nickname")
                    == details["snap"]["publisher"]["username"]
                ) or ("user_shared_snaps" in flask.session
                      and snap_name in flask.session.get("user_shared_snaps")):
                is_users_snap = True

        # build list of categories of a snap
        categories = logic.get_snap_categories(details["snap"]["categories"])

        developer = logic.get_snap_developer(details["name"])

        context = {
            "snap-id": details.get("snap-id"),
            # Data direct from details API
            "snap_title": details["snap"]["title"],
            "package_name": details["name"],
            "categories": categories,
            "icon_url": icons[0] if icons else None,
            "version": last_version,
            "license": details["snap"]["license"],
            "publisher": details["snap"]["publisher"]["display-name"],
            "username": details["snap"]["publisher"]["username"],
            "screenshots": screenshots,
            "videos": videos,
            "publisher_snaps": publisher_snaps,
            "publisher_featured_snaps": publisher_featured_snaps,
            "has_publisher_page": publisher_info is not None,
            "prices": details["snap"]["prices"],
            "contact": details["snap"].get("contact"),
            "website": details["snap"].get("website"),
            "summary": details["snap"]["summary"],
            "description": formatted_description,
            "channel_map": channel_maps_list,
            "has_stable": logic.has_stable(channel_maps_list),
            "developer_validation": details["snap"]["publisher"]["validation"],
            "default_track": default_track,
            "lowest_risk_available": lowest_risk_available,
            "confinement": confinement,
            "trending": details["snap"]["trending"],
            # Transformed API data
            "filesize": humanize.naturalsize(binary_filesize),
            "last_updated": logic.convert_date(last_updated),
            "last_updated_raw": last_updated,
            "is_users_snap": is_users_snap,
            "unlisted": details["snap"]["unlisted"],
            "developer": developer,
            # TODO: This is horrible and hacky
            "appliances": {
                "adguard-home": "adguard",
                "mosquitto": "mosquitto",
                "nextcloud": "nextcloud",
                "plexmediaserver": "plex",
                "openhab": "openhab",
            },
        }

        return context
Exemple #15
0
    def snap_posts(snap):
        try:
            blog_tags = blog_api.get_tag_by_name(f"sc:snap:{snap}")
        except NotFoundError:
            blog_tags = None

        blog_articles = None
        articles = []

        third_party_blogs = get_yaml("blog/content/blog-posts.yaml")

        if third_party_blogs and snap in third_party_blogs:
            post = third_party_blogs[snap]
            cdn_image = "/".join(
                [
                    "https://res.cloudinary.com",
                    "canonical",
                    "image",
                    "fetch",
                    "f_auto,q_auto,fl_sanitize,w_346,h_231,c_fill",
                    post["image"],
                ]
            )
            brand_image = "https://assets.ubuntu.com/v1/aae0f33a-omgubuntu.svg"
            image_element = "".join(
                [
                    f'<img src="{cdn_image}" ',
                    'style="display:block">',
                    f'<img src="{brand_image}" ',
                    'class="p-blog-post__source" />',
                ]
            )
            articles.append(
                {
                    "slug": post["uri"],
                    "title": post["title"],
                    "image": image_element,
                }
            )

        if blog_tags:
            snapcraft_tag = blog_api.get_tag_by_name("snapcraft.io")

            try:
                blog_articles, total_pages = blog_api.get_articles(
                    tags=blog_tags["id"],
                    tags_exclude=[3184, 3265, 3408],
                    per_page=3 - len(articles),
                )
            except RequestException:
                blog_articles = []

            for article in blog_articles:
                if article["image"]:
                    featured_media = image_template(
                        url=article["image"]["source_url"],
                        alt="",
                        width="346",
                        height="231",
                        fill=True,
                        hi_def=True,
                        loading="auto",
                    )
                else:
                    featured_media = None

                url = f"/blog/{article['slug']}"

                if snapcraft_tag["id"] not in article["tags"]:
                    url = f"https://ubuntu.com{url}"

                articles.append(
                    {
                        "slug": url,
                        "title": article["title"]["rendered"],
                        "image": featured_media,
                    }
                )

        return flask.jsonify(articles)
Exemple #16
0
def post_listing_snap(snap_name):
    changes = None
    changed_fields = flask.request.form.get("changes")

    if changed_fields:
        changes = loads(changed_fields)

    if changes:
        snap_id = flask.request.form.get("snap_id")
        error_list = []

        if "images" in changes:
            # Add existing screenshots
            try:
                current_screenshots = api.snap_screenshots(
                    snap_id, flask.session)
            except ApiResponseErrorList as api_response_error_list:
                if api_response_error_list.status_code == 404:
                    return flask.abort(404,
                                       "No snap named {}".format(snap_name))
                else:
                    return _handle_error_list(api_response_error_list.errors)
            except ApiError as api_error:
                return _handle_error(api_error)

            images_json, images_files = logic.build_changed_images(
                changes["images"],
                current_screenshots,
                flask.request.files.get("icon"),
                flask.request.files.getlist("screenshots"),
                flask.request.files.get("banner-image"),
            )

            try:
                api.snap_screenshots(snap_id, flask.session, images_json,
                                     images_files)
            except ApiResponseErrorList as api_response_error_list:
                if api_response_error_list.status_code == 404:
                    return flask.abort(404,
                                       "No snap named {}".format(snap_name))
                else:
                    error_list = error_list + api_response_error_list.errors
            except ApiError as api_error:
                return _handle_error(api_error)

        body_json = logic.filter_changes_data(changes)

        if body_json:
            if "description" in body_json:
                body_json["description"] = logic.remove_invalid_characters(
                    body_json["description"])

            try:
                api.snap_metadata(snap_id, flask.session, body_json)
            except ApiResponseErrorList as api_response_error_list:
                if api_response_error_list.status_code == 404:
                    return flask.abort(404,
                                       "No snap named {}".format(snap_name))
                else:
                    error_list = error_list + api_response_error_list.errors
            except ApiError as api_error:
                return _handle_error(api_error)

        if error_list:
            try:
                snap_details = api.get_snap_info(snap_name, flask.session)
            except ApiResponseErrorList as api_response_error_list:
                if api_response_error_list.status_code == 404:
                    return flask.abort(404,
                                       "No snap named {}".format(snap_name))
                else:
                    error_list = error_list + api_response_error_list.errors
            except ApiError as api_error:
                return _handle_error(api_error)

            field_errors, other_errors = logic.invalid_field_errors(error_list)

            details_metrics_enabled = snap_details["public_metrics_enabled"]
            details_blacklist = snap_details["public_metrics_blacklist"]

            is_on_stable = logic.is_snap_on_stable(
                snap_details["channel_maps_list"])

            # Filter icon & screenshot urls from the media set.
            icon_urls, screenshot_urls, banner_urls = logic.categorise_media(
                snap_details["media"])

            licenses = []
            for license in get_licenses():
                licenses.append({
                    "key": license["licenseId"],
                    "name": license["name"]
                })

            license = snap_details["license"]
            license_type = "custom"

            if (" AND " not in license.upper()
                    and " WITH " not in license.upper()):
                license_type = "simple"

            try:
                categories_results = store_api.get_categories()
            except StoreApiError:
                categories_results = []

            categories = get_categories(categories_results)

            snap_categories = logic.replace_reserved_categories_key(
                snap_details["categories"])

            snap_categories = logic.filter_categories(snap_categories)

            filename = f"publisher/content/listing_tour.yaml"
            tour_steps = helpers.get_yaml(filename, typ="rt")

            context = {
                # read-only values from details API
                "snap_id":
                snap_details["snap_id"],
                "snap_name":
                snap_details["snap_name"],
                "snap_categories":
                snap_categories,
                "icon_url":
                icon_urls[0] if icon_urls else None,
                "publisher_name":
                snap_details["publisher"]["display-name"],
                "username":
                snap_details["publisher"]["username"],
                "screenshot_urls":
                screenshot_urls,
                "banner_urls":
                banner_urls,
                "display_title":
                snap_details["title"],
                # values posted by user
                "snap_title": (changes["title"] if "title" in changes else
                               snap_details["title"] or ""),
                "summary": (changes["summary"] if "summary" in changes else
                            snap_details["summary"] or ""),
                "description":
                (changes["description"] if "description" in changes else
                 snap_details["description"] or ""),
                "contact": (changes["contact"] if "contact" in changes else
                            snap_details["contact"] or ""),
                "private":
                snap_details["private"],
                "website": (changes["website"] if "website" in changes else
                            snap_details["website"] or ""),
                "public_metrics_enabled":
                details_metrics_enabled,
                "video_urls": ([changes["video_urls"]] if "video_urls"
                               in changes else snap_details["video_urls"]),
                "public_metrics_blacklist":
                details_blacklist,
                "license":
                license,
                "license_type":
                license_type,
                "licenses":
                licenses,
                "is_on_stable":
                is_on_stable,
                "categories":
                categories,
                # errors
                "error_list":
                error_list,
                "field_errors":
                field_errors,
                "other_errors":
                other_errors,
                "tour_steps":
                tour_steps,
            }

            return flask.render_template("publisher/listing.html", **context)

        flask.flash("Changes applied successfully.", "positive")
    else:
        flask.flash("No changes to save.", "information")

    return flask.redirect(
        flask.url_for(".get_listing_snap", snap_name=snap_name))
Exemple #17
0
 def test_get_yaml_error(self, mock_open_file):
     yaml_read = helpers.get_yaml("filename.yaml", typ="rt")
     self.assertEqual(yaml_read, None)
     mock_open_file.assert_called_with(
         os.path.join(self.app.root_path, "filename.yaml"), "r")
Exemple #18
0
    def snap_posts(snap):
        try:
            blog_tags = wordpress_api.get_tag_by_name(f"sc:snap:{snap}")
        except Exception:
            blog_tags = None

        blog_articles = None
        articles = []

        third_party_blogs = get_yaml("blog/content/blog-posts.yaml")

        if snap in third_party_blogs:
            post = third_party_blogs[snap]
            cdn_image = "/".join([
                "https://res.cloudinary.com",
                "canonical",
                "image",
                "fetch",
                "f_auto,q_auto,fl_sanitize,w_346,h_231,c_fill",
                post["image"],
            ])
            brand_image = "https://assets.ubuntu.com/v1/aae0f33a-omgubuntu.svg"
            image_element = "".join([
                f'<img src="{cdn_image}" ',
                'style="display:block">',
                f'<img src="{brand_image}" ',
                'class="p-blog-post__source" />',
            ])
            articles.append({
                "slug": post["uri"],
                "title": post["title"],
                "image": image_element,
            })

        if blog_tags:
            try:
                blog_articles, total_pages = wordpress_api.get_articles(
                    blog_tags["id"], 3 - len(articles))
            except Exception:
                blog_articles = []

            for article in blog_articles:
                try:
                    featured_media = wordpress_api.get_media(
                        article["featured_media"])["source_url"]
                    featured_media = image_template(
                        url=featured_media,
                        alt="",
                        width="346",
                        height="231",
                        hi_def=True,
                        loading="auto",
                    )
                except Exception:
                    featured_media = None

                transformed_article = logic.transform_article(
                    article, featured_image=featured_media, author=None)

                articles.append({
                    "slug":
                    "/blog/" + transformed_article["slug"],
                    "title":
                    transformed_article["title"]["rendered"],
                    "image":
                    transformed_article["image"],
                })

        return flask.jsonify(articles)