mirror of
https://github.com/4cuck/nitter-status.git
synced 2026-10-27 00:57:39 +00:00
add admin mode
This commit is contained in:
1 parent
0ed4c1f45c
commit
7e2b645490
5 files changed
+26
-11
No files matched your search
+2
-2
@@ -43,7 +43,7 @@ ORIGIN_SOURCE_GIT_BRANCH="master"
|
||||
ORIGIN_SOURCE_GIT_URL="https://github.com/zedeus/nitter.git"
|
||||
# session lifetime for host logins
|
||||
SESSION_TTL_SECONDS="2592000"
|
||||
# admin hosts to get full access
|
||||
ADMIN_HOSTS="example.com,foo.net"
|
||||
# admin instance domains
|
||||
ADMIN_DOMAINS="example.com,foo.net"
|
||||
# token name used for logging in - has to be a valid DNS TXT key
|
||||
LOGIN_TOKEN_NAME="localhost"
|
||||
+17
-8
@@ -43,6 +43,7 @@ use crate::LOGIN_URL;
|
||||
pub struct ActiveLogin {
|
||||
/// Hosts this session has access to.
|
||||
hosts: HashSet<i32>,
|
||||
admin: bool,
|
||||
}
|
||||
const LOGIN_KEY: &'static str = "LOGIN";
|
||||
|
||||
@@ -85,8 +86,9 @@ pub async fn login(
|
||||
Form(input): Form<LoginInput>,
|
||||
) -> Result<axum::response::Response> {
|
||||
tracing::debug!(login=?input);
|
||||
let domain = input.domain.trim();
|
||||
let host = host::Entity::find()
|
||||
.filter(host::Column::Domain.eq(input.domain.trim()))
|
||||
.filter(host::Column::Domain.eq(domain))
|
||||
.one(db)
|
||||
.await?;
|
||||
|
||||
@@ -113,7 +115,7 @@ pub async fn login(
|
||||
Err(_) => {
|
||||
let mut ids = HashSet::with_capacity(1);
|
||||
ids.insert(host.id);
|
||||
ActiveLogin { hosts: ids }
|
||||
ActiveLogin { hosts: ids, admin: config.admin_domains.iter().any(|e| e == domain) }
|
||||
}
|
||||
};
|
||||
session.insert(LOGIN_KEY, session_value)?;
|
||||
@@ -273,7 +275,7 @@ pub async fn overview(
|
||||
) -> Result<axum::response::Response> {
|
||||
tracing::info!(?session);
|
||||
|
||||
let hosts = get_all_login_hosts(&session, db).await?;
|
||||
let (login,hosts) = get_all_login_hosts(&session, db).await?;
|
||||
|
||||
let mut context = tera::Context::new();
|
||||
let res = {
|
||||
@@ -284,6 +286,7 @@ pub async fn overview(
|
||||
let time = guard.last_update.format("%Y.%m.%d %H:%M").to_string();
|
||||
context.insert("last_updated", &time);
|
||||
context.insert("instances", &hosts);
|
||||
context.insert("is_admin", &login.admin);
|
||||
|
||||
let res = Html(template.render("admin.html.j2", &context)?).into_response();
|
||||
drop(guard);
|
||||
@@ -377,14 +380,20 @@ pub async fn errors_view(
|
||||
async fn get_all_login_hosts(
|
||||
session: &Session,
|
||||
db: &DatabaseConnection,
|
||||
) -> Result<Vec<host::Model>> {
|
||||
) -> Result<(ActiveLogin, Vec<host::Model>)> {
|
||||
let login = get_session_login(&session)?;
|
||||
|
||||
let host_res = host::Entity::find()
|
||||
let host_res = match login.admin {
|
||||
true => host::Entity::find()
|
||||
.filter(host::Column::Enabled.eq(true))
|
||||
.all(db)
|
||||
.await?,
|
||||
false => host::Entity::find()
|
||||
.filter(host::Column::Id.is_in(login.hosts.iter().map(|v| *v)))
|
||||
.all(db)
|
||||
.await?;
|
||||
Ok(host_res)
|
||||
.await?,
|
||||
};
|
||||
Ok((login,host_res))
|
||||
}
|
||||
|
||||
/// Get wanted [host::Model] for current [Session] if valid for this user
|
||||
@@ -395,7 +404,7 @@ async fn get_specific_login_host(
|
||||
) -> Result<host::Model> {
|
||||
let login = get_session_login(&session)?;
|
||||
|
||||
if !login.hosts.contains(&wanted_host_id) {
|
||||
if !login.hosts.contains(&wanted_host_id) && !login.admin {
|
||||
return Err(ServerError::MissingPermission);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ pub struct Config {
|
||||
pub max_age: usize,
|
||||
pub session_ttl_seconds: u64,
|
||||
pub login_token_name: String,
|
||||
pub admin_domains: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, axum::extract::FromRef)]
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
<h1>Admin Interface</h1>
|
||||
<p><a href="/admin/logout">Logout</a> <a href="/admin/login">Add more instances</a></p>
|
||||
|
||||
<p><h4>Instances</h4> you are logged in for.</p>
|
||||
<h4>Instances</h4>
|
||||
{% if is_admin %}<p class="text-danger-emphasis">Admin mode.</p>{% endif %}
|
||||
<div class="table-responsive">
|
||||
<table id="status-tbl" class="table sortable table-hover table-sm">
|
||||
<thead>
|
||||
@@ -24,9 +25,11 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for instance in instances -%}
|
||||
<tr>
|
||||
<td>{{instance.domain}}</td>
|
||||
{# <td><a href="/admin/history/{{instance.id}}">History</a></td> #}
|
||||
<td><a href="/admin/errors/{{instance.id}}">Errors</a></td>
|
||||
</tr>
|
||||
{%- endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -166,12 +166,14 @@ fn read_server_config(instance_ping_interval: usize) -> miette::Result<server::C
|
||||
.parse()
|
||||
.expect("SESSION_TTL_SECONDS must be a positive number");
|
||||
let login_token_name = require_env_str("LOGIN_TOKEN_NAME")?;
|
||||
let admin_domains = require_env_str("ADMIN_DOMAINS")?.split(",").map(|v|v.trim().to_string()).collect();
|
||||
|
||||
Ok(server::Config {
|
||||
site_url,
|
||||
max_age: instance_ping_interval,
|
||||
session_ttl_seconds,
|
||||
login_token_name,
|
||||
admin_domains,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user