feat: follow-by-handle form on following and users pages
This commit is contained in:
@@ -4,6 +4,12 @@
|
|||||||
{% if let Some(err) = error %}
|
{% if let Some(err) = error %}
|
||||||
<p class="error">{{ err }}</p>
|
<p class="error">{{ err }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<form method="POST" action="/users/{{ user_id }}/follow" class="follow-form">
|
||||||
|
<input type="hidden" name="_csrf" value="{{ ctx.csrf_token }}">
|
||||||
|
<input type="hidden" name="redirect_after" value="/social/following">
|
||||||
|
<input type="text" name="handle" placeholder="@user@instance.tld" required>
|
||||||
|
<button type="submit">Follow</button>
|
||||||
|
</form>
|
||||||
{% if actors.is_empty() %}
|
{% if actors.is_empty() %}
|
||||||
<p>Not following anyone yet. Follow remote users from your <a href="/users/{{ user_id }}">profile page</a>.</p>
|
<p>Not following anyone yet. Follow remote users from your <a href="/users/{{ user_id }}">profile page</a>.</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@@ -2,6 +2,14 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="users-list">
|
<div class="users-list">
|
||||||
<h2 class="page-title">Members</h2>
|
<h2 class="page-title">Members</h2>
|
||||||
|
{% if let Some(viewer_id) = ctx.user_id %}
|
||||||
|
<form method="POST" action="/users/{{ viewer_id }}/follow" class="follow-form">
|
||||||
|
<input type="hidden" name="_csrf" value="{{ ctx.csrf_token }}">
|
||||||
|
<input type="hidden" name="redirect_after" value="/users">
|
||||||
|
<input type="text" name="handle" placeholder="@user@instance.tld" required>
|
||||||
|
<button type="submit">Follow</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
{% for user in users %}
|
{% for user in users %}
|
||||||
<div class="user-row">
|
<div class="user-row">
|
||||||
<div class="user-avatar">{{ user.initial }}</div>
|
<div class="user-avatar">{{ user.initial }}</div>
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ pub struct FollowForm {
|
|||||||
pub handle: String,
|
pub handle: String,
|
||||||
#[serde(rename = "_csrf", default)]
|
#[serde(rename = "_csrf", default)]
|
||||||
pub csrf_token: String,
|
pub csrf_token: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub redirect_after: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|||||||
@@ -718,12 +718,20 @@ pub async fn follow_remote_user(
|
|||||||
if crate::csrf::mismatch(&csrf, &form.csrf_token) {
|
if crate::csrf::mismatch(&csrf, &form.csrf_token) {
|
||||||
return StatusCode::FORBIDDEN.into_response();
|
return StatusCode::FORBIDDEN.into_response();
|
||||||
}
|
}
|
||||||
|
let redirect_base = form
|
||||||
|
.redirect_after
|
||||||
|
.as_deref()
|
||||||
|
.filter(|u| u.starts_with('/') && !u.starts_with("//"))
|
||||||
|
.unwrap_or(&format!("/users/{}", profile_user_uuid))
|
||||||
|
.to_string();
|
||||||
|
|
||||||
match state.ap_service.follow(user_id.value(), &form.handle).await {
|
match state.ap_service.follow(user_id.value(), &form.handle).await {
|
||||||
Ok(()) => Redirect::to(&format!("/users/{}", profile_user_uuid)).into_response(),
|
Ok(()) => Redirect::to(&redirect_base).into_response(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("follow error: {:?}", e);
|
tracing::error!("follow error: {:?}", e);
|
||||||
let msg = encode_error(&e.to_string());
|
let msg = encode_error(&e.to_string());
|
||||||
Redirect::to(&format!("/users/{}?error={}", profile_user_uuid, msg)).into_response()
|
let sep = if redirect_base.contains('?') { '&' } else { '?' };
|
||||||
|
Redirect::to(&format!("{}{}error={}", redirect_base, sep, msg)).into_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user