diff --git a/README.md b/README.md index 0b0f855..7d69dfd 100644 --- a/README.md +++ b/README.md @@ -67,3 +67,8 @@ App packagers should *not* manually set their apps' level. The levels of all the Applications with no recent activity and no active sign from maintainer may be flagged in `apps.toml` with the `package-not-maintained` antifeature tag to signify that the app is inactive and may slowly become outdated with respect to the upstream, or with respect to good packaging practices. It does **not** mean that the app is not working anymore. Feel free to contact the app group if you feel like taking over the maintenance of a currently unmaintained app! + +### `graveyard.toml` + +This file is for apps that are long-term not-working and unlikely to be ever revived + diff --git a/store/app.py b/store/app.py index ac1fb8c..f0863b9 100644 --- a/store/app.py +++ b/store/app.py @@ -31,6 +31,8 @@ from utils import ( get_wishlist, get_stars, get_app_md_and_screenshots, + save_wishlist_submit_for_ratelimit, + check_wishlist_submit_ratelimit, ) app = Flask(__name__, static_url_path="/assets", static_folder="assets") @@ -147,7 +149,7 @@ def star_app(app_id, action): if app_id not in get_catalog()["apps"] and app_id not in get_wishlist(): return _("App %(app_id) not found", app_id=app_id), 404 if not session.get("user", {}): - return _("You must be logged in to be able to star an app"), 401 + return _("You must be logged in to be able to star an app") + "

" + _("Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.

'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts."), 401 app_star_folder = os.path.join(".stars", app_id) app_star_for_this_user = os.path.join( @@ -190,7 +192,7 @@ def add_to_wishlist(): if request.method == "POST": user = session.get("user", {}) if not user: - errormsg = _("You must be logged in to submit an app to the wishlist") + errormsg = _("You must be logged in to submit an app to the wishlist") + "

" + _("Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.

'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts.") return render_template( "wishlist_add.html", locale=get_locale(), @@ -199,7 +201,6 @@ def add_to_wishlist(): successmsg=None, errormsg=errormsg, ) - csrf_token = request.form["csrf_token"] if csrf_token != session.get("csrf_token"): @@ -217,8 +218,15 @@ def add_to_wishlist(): description = request.form["description"].strip().replace("\n", "") upstream = request.form["upstream"].strip().replace("\n", "") website = request.form["website"].strip().replace("\n", "") + license = request.form["license"].strip().replace("\n", "") + + boring_keywords_to_check_for_people_not_reading_the_instructions = ["free", "open source", "open-source", "self-hosted", "simple", "lightweight", "light-weight", "best", "most", "fast", "flexible", "puissante", "powerful", "secure"] checks = [ + ( + check_wishlist_submit_ratelimit(session['user']['username']) is True, + _("Proposing wishlist additions is limited to once every 15 days per user.") + ), (len(name) >= 3, _("App name should be at least 3 characters")), (len(name) <= 30, _("App name should be less than 30 characters")), ( @@ -237,11 +245,27 @@ def add_to_wishlist(): len(upstream) <= 150, _("Upstream code repo URL should be less than 150 characters"), ), + ( + len(license) >= 10, + _("License URL should be at least 10 characters"), + ), + ( + len(license) <= 250, + _("License URL should be less than 250 characters"), + ), (len(website) <= 150, _("Website URL should be less than 150 characters")), ( re.match(r"^[\w\.\-\(\)\ ]+$", name), _("App name contains special characters"), ), + ( + all(keyword not in description.lower() for keyword in boring_keywords_to_check_for_people_not_reading_the_instructions), + _("Please focus on what the app does, without using marketing, fuzzy terms, or repeating that the app is 'free' and 'self-hostable'.") + ), + ( + description.lower().split()[0] != name and (len(description.split()) == 1 or description.lower().split()[1] not in ["is", "est"]), + _("No need to repeat '{app} is'. Focus on what the app does.") + ) ] for check, errormsg in checks: @@ -328,6 +352,7 @@ Proposed by **{session['user']['username']}** Website: {website} Upstream repo: {upstream} +License: {license} Description: {description} - [ ] Confirm app is self-hostable and generally makes sense to possibly integrate in YunoHost @@ -349,6 +374,9 @@ Description: {description} "Your proposed app has succesfully been submitted. It must now be validated by the YunoHost team. You can track progress here: %(url)s", url=url, ) + + save_wishlist_submit_for_ratelimit(session['user']['username']) + return render_template( "wishlist_add.html", locale=get_locale(), @@ -414,6 +442,9 @@ def sso_login_callback(): uri_to_redirect_to_after_login = session.get("uri_to_redirect_to_after_login") + if "trust_level_1" not in user_data['groups'][0].split(','): + return _("Unfortunately, login was denied.") + "

" + _("Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.

'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts."), 403 + session.clear() session["user"] = { "id": user_data["external_id"][0], diff --git a/store/templates/wishlist_add.html b/store/templates/wishlist_add.html index df02d59..29e6d54 100644 --- a/store/templates/wishlist_add.html +++ b/store/templates/wishlist_add.html @@ -27,20 +27,24 @@

{{ _("You must first login to be allowed to submit an app to the wishlist") }} +

+

+

+ {{ _("Note that, due to various abuses, we restricted login on the app store to 'trust level 1' users.

'Trust level 1' is obtained after interacting a minimum with the forum, and more specifically: entering at least 5 topics, reading at least 30 posts, and spending at least 10 minutes reading posts.") }} +

+ + {% else %} + {% endif %} - - {% if errormsg %}