Fix CSRF issues
GET routes are not protected against CSRF. This commit changes the needed URLs to POST and replace simple links with forms. Thanks @fdb-hiroshima for noticing it!
This commit is contained in:
parent
eb24ba1774
commit
d8ca1d70b7
17
po/gl.po
17
po/gl.po
@ -325,7 +325,8 @@ msgstr[1] "{{ count }} autoras en este blog: "
|
|||||||
|
|
||||||
msgid "Login or use your Fediverse account to interact with this article"
|
msgid "Login or use your Fediverse account to interact with this article"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Conéctese ou utilice a súa conta no fediverso para interactuar con este artigo"
|
"Conéctese ou utilice a súa conta no fediverso para interactuar con este "
|
||||||
|
"artigo"
|
||||||
|
|
||||||
msgid "Optional"
|
msgid "Optional"
|
||||||
msgstr "Opcional"
|
msgstr "Opcional"
|
||||||
@ -486,7 +487,6 @@ msgstr "Descrición"
|
|||||||
msgid "Content warning"
|
msgid "Content warning"
|
||||||
msgstr "Aviso sobre o contido"
|
msgstr "Aviso sobre o contido"
|
||||||
|
|
||||||
|
|
||||||
msgid "File"
|
msgid "File"
|
||||||
msgstr "Ficheiro"
|
msgstr "Ficheiro"
|
||||||
|
|
||||||
@ -496,7 +496,8 @@ msgstr "Enviar"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Sorry, but registrations are closed on this instance. Try to find another one"
|
"Sorry, but registrations are closed on this instance. Try to find another one"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Lamentámolo, pero o rexistro está pechado en esta instancia. Intente atopar outra"
|
"Lamentámolo, pero o rexistro está pechado en esta instancia. Intente atopar "
|
||||||
|
"outra"
|
||||||
|
|
||||||
msgid "Subtitle"
|
msgid "Subtitle"
|
||||||
msgstr "Subtítulo"
|
msgstr "Subtítulo"
|
||||||
@ -553,7 +554,8 @@ msgid ""
|
|||||||
"Something is wrong with your CSRF token. Make sure cookies are enabled in "
|
"Something is wrong with your CSRF token. Make sure cookies are enabled in "
|
||||||
"you browser, and try reloading this page. If you continue to see this error "
|
"you browser, and try reloading this page. If you continue to see this error "
|
||||||
"message, please report it."
|
"message, please report it."
|
||||||
msgstr "Hai un problema co seu testemuño CSRF. Asegúrese de ter as cookies activadas "
|
msgstr ""
|
||||||
|
"Hai un problema co seu testemuño CSRF. Asegúrese de ter as cookies activadas "
|
||||||
"no navegador, e recargue a páxina. Si persiste o aviso de este fallo, "
|
"no navegador, e recargue a páxina. Si persiste o aviso de este fallo, "
|
||||||
"informe por favor."
|
"informe por favor."
|
||||||
|
|
||||||
@ -600,7 +602,12 @@ msgid "Delete your account"
|
|||||||
msgstr "Eliminar a súa conta"
|
msgstr "Eliminar a súa conta"
|
||||||
|
|
||||||
msgid "Sorry, but as an admin, you can't leave your instance."
|
msgid "Sorry, but as an admin, you can't leave your instance."
|
||||||
msgstr "Lamentámolo, pero como administradora, non pode deixar a súa instancia."
|
msgstr ""
|
||||||
|
"Lamentámolo, pero como administradora, non pode deixar a súa instancia."
|
||||||
|
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr "Usuarias"
|
msgstr "Usuarias"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
msgid "This post isn't published yet."
|
||||||
|
msgstr "Esto é un borrador, non publicar por agora."
|
||||||
|
@ -156,7 +156,7 @@ fn admin_instances_paginated(admin: Admin, conn: DbConn, page: Page) -> Template
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/admin/instances/<id>/block")]
|
#[post("/admin/instances/<id>/block")]
|
||||||
fn toggle_block(_admin: Admin, conn: DbConn, id: i32) -> Redirect {
|
fn toggle_block(_admin: Admin, conn: DbConn, id: i32) -> Redirect {
|
||||||
if let Some(inst) = Instance::get(&*conn, id) {
|
if let Some(inst) = Instance::get(&*conn, id) {
|
||||||
inst.toggle_block(&*conn);
|
inst.toggle_block(&*conn);
|
||||||
@ -183,7 +183,7 @@ fn admin_users_paginated(admin: Admin, conn: DbConn, page: Page) -> Template {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/admin/users/<id>/ban")]
|
#[post("/admin/users/<id>/ban")]
|
||||||
fn ban(_admin: Admin, conn: DbConn, id: i32) -> Redirect {
|
fn ban(_admin: Admin, conn: DbConn, id: i32) -> Redirect {
|
||||||
User::get(&*conn, id).map(|u| u.delete(&*conn));
|
User::get(&*conn, id).map(|u| u.delete(&*conn));
|
||||||
Redirect::to(uri!(admin_users))
|
Redirect::to(uri!(admin_users))
|
||||||
|
@ -97,14 +97,14 @@ fn details(id: i32, user: User, conn: DbConn) -> Template {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/medias/<id>/delete")]
|
#[post("/medias/<id>/delete")]
|
||||||
fn delete(id: i32, _user: User, conn: DbConn) -> Redirect {
|
fn delete(id: i32, _user: User, conn: DbConn) -> Redirect {
|
||||||
let media = Media::get(&*conn, id).expect("Media to delete not found");
|
let media = Media::get(&*conn, id).expect("Media to delete not found");
|
||||||
media.delete(&*conn);
|
media.delete(&*conn);
|
||||||
Redirect::to(uri!(list))
|
Redirect::to(uri!(list))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/medias/<id>/avatar")]
|
#[post("/medias/<id>/avatar")]
|
||||||
fn set_avatar(id: i32, user: User, conn: DbConn) -> Redirect {
|
fn set_avatar(id: i32, user: User, conn: DbConn) -> Redirect {
|
||||||
let media = Media::get(&*conn, id).expect("Media to delete not found");
|
let media = Media::get(&*conn, id).expect("Media to delete not found");
|
||||||
user.set_avatar(&*conn, media.id);
|
user.set_avatar(&*conn, media.id);
|
||||||
|
@ -338,7 +338,7 @@ fn create(blog_name: String, data: LenientForm<NewPostForm>, user: User, conn: D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/~/<blog_name>/<slug>/delete")]
|
#[post("/~/<blog_name>/<slug>/delete")]
|
||||||
fn delete(blog_name: String, slug: String, conn: DbConn, user: User, worker: State<Pool<ThunkWorker<()>>>) -> Redirect {
|
fn delete(blog_name: String, slug: String, conn: DbConn, user: User, worker: State<Pool<ThunkWorker<()>>>) -> Redirect {
|
||||||
let post = Blog::find_by_fqn(&*conn, blog_name.clone())
|
let post = Blog::find_by_fqn(&*conn, blog_name.clone())
|
||||||
.and_then(|blog| Post::find_by_slug(&*conn, slug.clone(), blog.id));
|
.and_then(|blog| Post::find_by_slug(&*conn, slug.clone(), blog.id));
|
||||||
|
@ -118,7 +118,7 @@ fn dashboard_auth() -> Flash<Redirect> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/@/<name>/follow")]
|
#[post("/@/<name>/follow")]
|
||||||
fn follow(name: String, conn: DbConn, user: User, worker: Worker) -> Redirect {
|
fn follow(name: String, conn: DbConn, user: User, worker: Worker) -> Redirect {
|
||||||
let target = User::find_by_fqn(&*conn, name.clone()).unwrap();
|
let target = User::find_by_fqn(&*conn, name.clone()).unwrap();
|
||||||
if let Some(follow) = follows::Follow::find(&*conn, user.id, target.id) {
|
if let Some(follow) = follows::Follow::find(&*conn, user.id, target.id) {
|
||||||
@ -138,7 +138,7 @@ fn follow(name: String, conn: DbConn, user: User, worker: Worker) -> Redirect {
|
|||||||
Redirect::to(uri!(details: name = name))
|
Redirect::to(uri!(details: name = name))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/@/<name>/follow", rank = 2)]
|
#[post("/@/<name>/follow", rank = 2)]
|
||||||
fn follow_auth(name: String) -> Flash<Redirect> {
|
fn follow_auth(name: String) -> Flash<Redirect> {
|
||||||
utils::requires_login(
|
utils::requires_login(
|
||||||
"You need to be logged in order to follow someone",
|
"You need to be logged in order to follow someone",
|
||||||
@ -225,7 +225,7 @@ fn update(_name: String, conn: DbConn, user: User, data: LenientForm<UpdateUserF
|
|||||||
Redirect::to(uri!(me))
|
Redirect::to(uri!(me))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/@/<name>/delete")]
|
#[post("/@/<name>/delete")]
|
||||||
fn delete(name: String, conn: DbConn, user: User, mut cookies: Cookies) -> Redirect {
|
fn delete(name: String, conn: DbConn, user: User, mut cookies: Cookies) -> Redirect {
|
||||||
let account = User::find_by_fqn(&*conn, name.clone()).unwrap();
|
let account = User::find_by_fqn(&*conn, name.clone()).unwrap();
|
||||||
if user.id == account.id {
|
if user.id == account.id {
|
||||||
|
@ -472,6 +472,33 @@ main .article-meta .tags li a {
|
|||||||
width: initial;
|
width: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Inline forms (containing only CSRF token and a <submit>, for protected links) **/
|
||||||
|
|
||||||
|
form.inline {
|
||||||
|
display: inline;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.inline input[type="submit"] {
|
||||||
|
display: inline-block;
|
||||||
|
color: #7765E3;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1em;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.inline input[type="submit"]:not(.button) {
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.inline input[type="submit"]:not(.button) {
|
||||||
|
background: transparent;
|
||||||
|
color: #7765E3;
|
||||||
|
}
|
||||||
|
|
||||||
/* Button & Submit */
|
/* Button & Submit */
|
||||||
|
|
||||||
.button, input[type="submit"], button {
|
.button, input[type="submit"], button {
|
||||||
|
@ -18,13 +18,13 @@
|
|||||||
<small>{{ instance.public_domain }}</small>
|
<small>{{ instance.public_domain }}</small>
|
||||||
</p>
|
</p>
|
||||||
{% if not instance.local %}
|
{% if not instance.local %}
|
||||||
<a href="/admin/instances/{{ instance.id }}/block">
|
<form class="inline" method="post" action="/admin/instances/{{ instance.id }}/block">
|
||||||
{% if instance.blocked %}
|
{% if instance.blocked %}
|
||||||
{{ "Unblock" | _ }}
|
<input type="submit" value="{{ 'Unblock' | _ }}">
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ "Block" | _ }}
|
<input type="submit" value="{{ 'Block' | _ }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
<small>@{{ user.username }}</small>
|
<small>@{{ user.username }}</small>
|
||||||
</p>
|
</p>
|
||||||
{% if not user.is_admin %}
|
{% if not user.is_admin %}
|
||||||
<a href="/admin/users/{{ user.id }}/ban">
|
<form class="inline" method="post" href="/admin/users/{{ user.id }}/ban">
|
||||||
{{ "Ban" | _ }}
|
<input type="submit" value="{{ 'Ban' | _ }}">
|
||||||
</a>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -24,8 +24,12 @@
|
|||||||
<code>{{ media.md }}</code>
|
<code>{{ media.md }}</code>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a href="/medias/{{ media.id }}/avatar" class="button inline-block">{{ "Use as avatar" | _ }}</a>
|
<form class="inline" method="post" action="/medias/{{ media.id }}/avatar">
|
||||||
<a href="/medias/{{ media.id }}/delete" class="button inline-block">{{ "Delete" | _ }}</a>
|
<input class="button" type="submit" value="{{ 'Use as avatar' | _ }}">
|
||||||
|
</form>
|
||||||
|
<form class="inline" method="post" action="/medias/{{ media.id }}/delete">
|
||||||
|
<input class="button" type="submit" value="{{ 'Delete' | _ }}">
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h1 class="article">{{ article.post.title }}</h1>
|
<h1 class="article">{{ article.post.title }}</h1>
|
||||||
<h2 class="article">{{ article.post.subtitle }}</h2>
|
<h2 class="article">{{ article.post.subtitle }}</h2>
|
||||||
<p class="article-info">
|
<div class="article-info">
|
||||||
<span class="author">{{ "Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}" | _(
|
<span class="author">{{ "Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}" | _(
|
||||||
link_1='<a href="/@/',
|
link_1='<a href="/@/',
|
||||||
url=author.fqn,
|
url=author.fqn,
|
||||||
@ -20,19 +20,21 @@
|
|||||||
name=author.name,
|
name=author.name,
|
||||||
link_3="</a>"
|
link_3="</a>"
|
||||||
)
|
)
|
||||||
}}</a></span>
|
}}</span>
|
||||||
—
|
—
|
||||||
<span class="date">{{ date | date(format="%B %e, %Y") }}</span>
|
<span class="date">{{ date | date(format="%B %e, %Y") }}</span>
|
||||||
{% if is_author %}
|
{% if is_author %}
|
||||||
—
|
—
|
||||||
<a href="{{ article.url}}edit">{{ "Edit" | _ }}</a>
|
<a href="{{ article.url}}edit">{{ "Edit" | _ }}</a>
|
||||||
—
|
—
|
||||||
<a href="{{ article.url}}delete" onclick="return confirm('Are you sure you?')">{{ "Delete this article" | _ }}</a>
|
<form class="inline" method="post" action="{{ article.url}}delete">
|
||||||
|
<input onclick="return confirm('Are you sure you?')" type="submit" value="{{ 'Delete this article' | _ }}">
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not article.post.published %}
|
{% if not article.post.published %}
|
||||||
<span class="badge">{{ "Draft" }}</span>
|
<span class="badge">{{ "Draft" }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</div>
|
||||||
<article>
|
<article>
|
||||||
{{ article.post.content | safe }}
|
{{ article.post.content | safe }}
|
||||||
</article>
|
</article>
|
||||||
|
@ -25,7 +25,9 @@
|
|||||||
<h2>{{ "Danger zone" | _ }}</h2>
|
<h2>{{ "Danger zone" | _ }}</h2>
|
||||||
<p>{{ "Be very careful, any action taken here can't be cancelled." | _ }}
|
<p>{{ "Be very careful, any action taken here can't be cancelled." | _ }}
|
||||||
{% if not account.is_admin %}
|
{% if not account.is_admin %}
|
||||||
<p><a class="inline-block button destructive" href="/@/{{ account.fqn }}/delete">{{ "Delete your account" | _ }}</a></p>
|
<form method="post" action="/@/{{ account.fqn }}/delete">
|
||||||
|
<input type="submit" class="inline-block button destructive" value="{{ 'Delete your account' | _ }}">
|
||||||
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>{{ "Sorry, but as an admin, you can't leave your instance." | _ }}</p>
|
<p>{{ "Sorry, but as an admin, you can't leave your instance." | _ }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -23,16 +23,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if is_remote %}
|
{% if is_remote %}
|
||||||
<a class="inline-block button" href="{{ user.ap_url }}" target="_blank">{{ "Open on {{ instance_url }}" | _(instance_url=instance_url) }}</a>
|
<a class="inline-block" href="{{ user.ap_url }}" target="_blank">{{ "Open on {{ instance_url }}" | _(instance_url=instance_url) }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% set not_self = not is_self %}
|
{% set not_self = not is_self %}
|
||||||
{% if not_self and (account is defined) %}
|
{% if not_self and (account is defined) %}
|
||||||
|
<form class="inline" method="post" action="/@/{{ user.fqn }}/follow/">
|
||||||
{% if follows %}
|
{% if follows %}
|
||||||
<a href="/@/{{ user.fqn }}/follow/" class="inline-block button">{{ "Unfollow" | _ }}</a>
|
<input type="submit" value="{{ 'Unfollow' | _ }}">
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="/@/{{ user.fqn }}/follow/" class="inline-block button">{{ "Follow" | _ }}</a>
|
<input type="submit" value="{{ 'Follow' | _ }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user