def test_get_spec_apps(self):
        apps = _db_get_spec_apps("http://justatest.com")
        assert len(apps) == 1

        # Add a second spec (which should NOT be retrieved) for further testing.
        app2 = api.create_app("UTApp (1)", "translate", "http://different.com", "{'spec':'http://different.com'}")
        apps = _db_get_spec_apps("http://justatest.com")
        # Should still be 1. The new app is of a different spec.
        assert len(apps) == 1

        # Add a second spec (which should be retrieved) for further testing.
        app2 = api.create_app("UTApp2", "translate", "http://justatest.com", "{'spec':'http://justatest.com'}")
        apps = _db_get_spec_apps("http://justatest.com")
        # Should now be 2.
        assert len(apps) == 2
def transfer_ownership():

    # No matter if we are handling a GET or POST, we require these parameters.
    appid = request.values.get("appid")

    # Retrieve the application we want to view or edit.
    app = get_app(appid)
    if app is None:
        return render_template("composers/errors.html", message=gettext("App not found")), 404

    # Make sure the logged in user owns the app.
    user = current_user()
    if app.owner != user:
        return render_template("composers/errors.html", message=gettext("Not Authorized: User does not own app")), 403

    # Get the XMLSPEC
    bm = BundleManager.create_from_existing_app(app.data)
    spec = bm.get_gadget_spec()

    # Get the language
    lang = request.values.get("lang")
    if lang is None:
        return render_template("composers/errors.html", message=gettext("Lang not specified")), 400

    # Verify that we are the owners of the language we are trying to transfer.
    owner_app = _db_get_lang_owner_app(spec, lang)
    if owner_app != app:
        return render_template("composers/errors.html", message=gettext("Not Authorized: App does not own language")), 403

    # Get the possible apps to which we can concede ownership.
    apps = _db_get_spec_apps(spec)
    apps = [a for a in apps if a != app]

    # We received a POST request. We need to transfer the ownership.
    if request.method == "POST":

        # Protect against CSRF attacks.
        if not verify_csrf(request):
            return render_template("composers/errors.html",
                                   message=gettext("Request does not seem to come from the right source (csrf check)")), 400

        # Verify that we were passed the target app.
        targetapp = get_app(request.values.get("transfer"))
        if targetapp is None:
            return render_template("composers/errors.html", message=gettext("Target app not specified")), 400

        # Verify that the target app is of the same spec.
        targetappdata = json.loads(targetapp.data)
        targetspec = targetappdata["spec"]
        if targetspec != spec:
            return render_template("composers/errors.html", message=gettext("Target app does not have the same spec")), 400

        # Carry out the transfer.
        _db_transfer_ownership(lang, app, targetapp)

        # Redirect to selectlang.
        return redirect(url_for("translate.translate_selectlang", appid=app.unique_id))

    # For GET
    return render_template("composers/translate/transfer_ownership.html", app=app, apps=apps, xmlspec=spec, lang=lang)
 def test_get_spec_apps_empty(self):
     """
     Calling test_get_spec_apps on a non-existing spec gets an empty list.
     :return:
     """
     apps = _db_get_spec_apps("http://doesnt-exist.com")
     assert len(apps) == 0
def adapt_type_selection():
    """
    adapt_type_selection()
    Loads the page that lets the user choose the adaptation type, and that lets the user view or duplicate
    an existing adaptation instead. This method DOES NOT REQUIRE LOGIN but will display a different view when
    not logged in.
    """

    # Check if we are logged in.
    logged_in = current_user() is not None

    # If we are not logged in disallow POST.
    if not logged_in and request.method == "POST":
        return render_template("composers/errors.html", message=gettext("Cannot POST to this URL if not logged in")), 403

    # We require the appurl parameter.
    appurl = request.values.get("appurl")
    if appurl is None:
        return render_template("composers/errors.html", message=gettext("appurl parameter not specified"))

    # Obtain a list of every adaptation that exists in the database for the specified appurl.
    # TODO: Move db_helpers somewhere else. Makes no sense to use translator files in the adaptor.
    apps_list = _db_get_spec_apps(appurl)
    apps = []
    for app in apps_list:
        if app.composer != "adapt":
            continue
        apps.append({
            "name": app.name,
            "desc": app.description,
            "owner": app.owner.name,
            "type": "adapt",  # TO-DO: Specify the specific adaptor sub-type.
            "app_id": app.unique_id
        })

    # We will only get here if we are logged in
    if request.method == "POST":

        # Protect against CSRF attacks.
        if not verify_csrf(request):
            return render_template("composers/errors.html",
                                   message="Request does not seem to come from the right source (csrf check)"), 400

        adaptor_type = request.form["adaptor_type"]

        if adaptor_type and adaptor_type in ADAPTORS:
            # In order to show the list of apps we redirect to other url
            return redirect(url_for("adapt.adapt_create", adaptor_type=adaptor_type))
        else:
            # An adaptor_type is required.
            flash("Invalid adaptor type", "error")

    if logged_in:
        return render_template("composers/adapt/type.html", adaptors=ADAPTORS, apps=apps)

    # Version for the public
    else:
        return render_template("composers/adapt/public_type.html", adaptors=ADAPTORS, apps=apps)
示例#5
0
def translate_delete():
    """
    Handles the translate app delete endpoint. Only the user who owns the App can delete it.
    This is ensured at the appstorage level. A 401 code is returned if an attempt to delete
    other user's App is made.
    """

    appid = request.values.get("appid")
    if not appid:
        return "appid not provided", 400
    app = get_app(appid)
    if app is None:
        return "App not found", 404

    # Get our spec.
    spec = db.session.query(AppVar.value).filter_by(app=app, name="spec").first()[0]

    # Find out which languages we own.
    ownerships = _db_get_app_ownerships(app)

    # Find out which apps we can transfer to.
    transfer_apps = _db_get_spec_apps(spec)
    transfer_apps = [a for a in transfer_apps if a != app]

    # If GET we display the confirmation screen and do not actually delete it.
    if request.method == "GET":
        return render_template("composers/translate/delete.html", app=app, ownerships=ownerships,
                               transfer_apps=transfer_apps)

    # If POST we consider whether the user clicked Delete or Cancel in the confirmation screen.
    elif request.method == "POST":

        # Protect against CSRF attacks.
        if not verify_csrf(request):
            return render_template("composers/errors.html",
                                   message=gettext("Request does not seem to come from the right source (csrf check)")), 400

        # If the user didn't click delete he probably clicked cancel.
        # We return to the Apps View page.
        if not "delete" in request.form:
            return redirect(url_for("user.apps.index"))

        try:

            # If we have ownerships and we have someone to transfer them to,
            # then we need to do it.
            if len(ownerships) > 0 and len(transfer_apps) > 0:
                transfer_app_id = request.values.get("transfer")
                if transfer_app_id is None:
                    return render_template("composers/errors.html", message=gettext("transfer parameter missing")), 400
                transfer_app = get_app(transfer_app_id)
                if transfer_app is None:
                    return render_template("composers/errors.html", message=gettext("could not retrieve app")), 400

                # Transfer all ownerships to the selected app.
                for o in ownerships:
                    o.app = transfer_app
                    db.session.add(o)
                db.session.commit()

                transfer_app = get_app(transfer_app_id)

            delete_app(app)

            flash(gettext("App successfully deleted."), "success")

        except NotAuthorizedException:
            return render_template("composers/errors.html", message=gettext("Not Authorized")), 401

        return redirect(url_for("user.apps.index"))
def adapt_type_selection():
    """
    adapt_type_selection()
    Loads the page that lets the user choose the adaptation type, and that lets the user view or duplicate
    an existing adaptation instead. This method DOES NOT REQUIRE LOGIN but will display a different view when
    not logged in.
    """

    # Check if we are logged in.
    logged_in = current_user() is not None

    # If we are not logged in disallow POST.
    if not logged_in and request.method == "POST":
        return render_template(
            "composers/errors.html",
            message=gettext("Cannot POST to this URL if not logged in")), 403

    # We require the appurl parameter.
    appurl = request.values.get("appurl")
    if appurl is None:
        return render_template(
            "composers/errors.html",
            message=gettext("appurl parameter not specified"))

    # Obtain a list of every adaptation that exists in the database for the specified appurl.
    # TODO: Move db_helpers somewhere else. Makes no sense to use translator files in the adaptor.
    apps_list = _db_get_spec_apps(appurl)
    apps = []
    for app in apps_list:
        if app.composer != "adapt":
            continue
        apps.append({
            "name": app.name,
            "desc": app.description,
            "owner": app.owner.name,
            "type": "adapt",  # TO-DO: Specify the specific adaptor sub-type.
            "app_id": app.unique_id
        })

    # We will only get here if we are logged in
    if request.method == "POST":

        # Protect against CSRF attacks.
        if not verify_csrf(request):
            return render_template(
                "composers/errors.html",
                message=
                "Request does not seem to come from the right source (csrf check)"
            ), 400

        adaptor_type = request.form["adaptor_type"]

        if adaptor_type and adaptor_type in ADAPTORS:
            # In order to show the list of apps we redirect to other url
            return redirect(
                url_for("adapt.adapt_create", adaptor_type=adaptor_type))
        else:
            # An adaptor_type is required.
            flash("Invalid adaptor type", "error")

    if logged_in:
        return render_template("composers/adapt/type.html",
                               adaptors=ADAPTORS,
                               apps=apps)

    # Version for the public
    else:
        return render_template("composers/adapt/public_type.html",
                               adaptors=ADAPTORS,
                               apps=apps)