patx/gitman

fix star/unstar redirect

Commit 003ab59 · patx · 2026-05-10T21:17:26Z

Changeset
003ab593f6c0909a00913da287e0d054fd474c38
Parents
3488e067b91cc5a2cd5b9f4e1470ac9982ae3fc3

View source at this commit

Comments

No comments yet.

Log in to comment

Diff

diff --git a/app.py b/app.py
index 50c1e77..01bcaa2 100644
--- a/app.py
+++ b/app.py
@@ -904,6 +904,8 @@ def render(template_name, **context):
     context.setdefault("render_repo_description", render_repo_description)
     context.setdefault("format_ref_label", format_ref_label)
     context.setdefault("url_with_ref", url_with_ref)
+    context.setdefault("login_url", login_url)
+    context.setdefault("current_url", current_url)
     context.setdefault("current_url_with_ref", current_url_with_ref)
     context.setdefault("current_url_with_page", current_url_with_page)
     context.setdefault("current_url_with_params", current_url_with_params)
@@ -935,10 +937,18 @@ def require_login():
     redirect("/login?next=" + quote(next_url, safe="/?=&"))
 
 
-def safe_next_url(value):
+def safe_next_url(value, default="/"):
     if value and value.startswith("/") and not value.startswith("//"):
         return value
-    return "/"
+    return default
+
+
+def current_url():
+    return request.path + (f"?{request.query_string}" if request.query_string else "")
+
+
+def login_url(next_url=None):
+    return "/login?" + urlencode({"next": safe_next_url(next_url or current_url())})
 
 
 def parse_bounded_int(value, default, minimum=1, maximum=None):
@@ -4758,7 +4768,7 @@ def repo_star(owner, repo_name):
         unstar_repo(user, repo)
     else:
         star_repo(user, repo)
-    redirect(f"/{owner}/{repo_name}")
+    redirect(safe_next_url(request.forms.get("next"), f"/{owner}/{repo_name}"))
 
 
 @app.route("/<owner>/<repo_name>/fork", method=["GET", "POST"])
diff --git a/templates/repo_nav.tpl b/templates/repo_nav.tpl
index b4946fd..640cf05 100644
--- a/templates/repo_nav.tpl
+++ b/templates/repo_nav.tpl
@@ -9,6 +9,7 @@
   % if user:
     <form class="inline-form" method="post" action="/{{repo['owner_username']}}/{{repo['name']}}/star">
       {{!csrf_field()}}
+      <input type="hidden" name="next" value="{{current_url()}}">
       % if is_starred:
         <input type="hidden" name="action" value="unstar">
         <button class="button-link" type="submit">Unstar ({{star_count}})</button>
@@ -18,7 +19,7 @@
       % end
     </form>
   % else:
-    <a class="button-link" href="/login?next=/{{repo['owner_username']}}/{{repo['name']}}">Star ({{star_count}})</a>
+    <a class="button-link" href="{{login_url(current_url())}}">Star ({{star_count}})</a>
   % end
   % if user and not is_owner and not has_fork:
     <form class="inline-form" method="post" action="/{{repo['owner_username']}}/{{repo['name']}}/fork">
diff --git a/tests/test_app.py b/tests/test_app.py
index e8864d1..982fbfa 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -2161,11 +2161,27 @@ def test_bottle_profile_star_fork_and_repo_settings_flows(isolated_app):
     create_repo_with_refs(owner)
 
     bob_client = WsgiClient(isolated_app.app)
+    source_url = "/alice/demo/src?ref_type=branch&ref=feature"
+    guest_source_response = bob_client.get(source_url)
+    assert guest_source_response.status_code == 200
+    expected_login_href = (
+        'href="/login?next=%2Falice%2Fdemo%2Fsrc%3Fref_type%3Dbranch%26ref%3Dfeature"'
+    )
+    assert expected_login_href in guest_source_response.text
+
     response = login_client(bob_client, "bob")
     assert response.status_code == 303
 
-    response = bob_client.post("/alice/demo/star", {"action": "star"})
+    source_response = bob_client.get(source_url)
+    assert source_response.status_code == 200
+    assert 'name="next" value="/alice/demo/src?ref_type=branch&amp;ref=feature"' in source_response.text
+
+    response = bob_client.post(
+        "/alice/demo/star",
+        {"action": "star", "next": "/alice/demo/src?ref_type=branch&ref=feature"},
+    )
     assert response.status_code == 303
+    assert response.location_path == "/alice/demo/src?ref_type=branch&ref=feature"
     assert isolated_app.repo_star_count(isolated_app.get_repo("alice", "demo")["id"]) == 1
 
     response = bob_client.post("/alice/demo/fork", {"name": "demo", "description": "Forked"})