mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-04 04:56:49 +00:00
most of a dash views api impl
This commit is contained in:
parent
832f07675f
commit
2e3390b27c
5 changed files with 176 additions and 5 deletions
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::ApiContext;
|
use crate::{ApiContext, auth::AuthState, error::fail};
|
||||||
use axum::{extract::State, response::Json};
|
use axum::{Extension, extract::State, response::Json};
|
||||||
use fred::interfaces::*;
|
use fred::interfaces::*;
|
||||||
use libpk::state::ShardState;
|
use libpk::state::ShardState;
|
||||||
use pk_macros::api_endpoint;
|
use pk_macros::api_endpoint;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
|
use sqlx::Postgres;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -53,7 +54,7 @@ use axum::{
|
||||||
};
|
};
|
||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
use libpk::config;
|
use libpk::config;
|
||||||
use pluralkit_models::{PKSystem, PKSystemConfig, PrivacyLevel};
|
use pluralkit_models::{PKDashView, PKSystem, PKSystemConfig, PrivacyLevel};
|
||||||
use reqwest::ClientBuilder;
|
use reqwest::ClientBuilder;
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
#[derive(serde::Deserialize, Debug)]
|
||||||
|
|
@ -187,3 +188,109 @@ pub async fn discord_callback(
|
||||||
)
|
)
|
||||||
.into_response()
|
.into_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, Debug)]
|
||||||
|
#[serde(tag = "action", rename_all = "snake_case")]
|
||||||
|
pub enum DashViewRequest {
|
||||||
|
Add {
|
||||||
|
name: String,
|
||||||
|
value: String,
|
||||||
|
},
|
||||||
|
Patch {
|
||||||
|
id: String,
|
||||||
|
name: Option<String>,
|
||||||
|
value: Option<String>,
|
||||||
|
},
|
||||||
|
Remove { id: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[api_endpoint]
|
||||||
|
pub async fn dash_views(
|
||||||
|
Extension(auth): Extension<AuthState>,
|
||||||
|
State(ctx): State<ApiContext>,
|
||||||
|
extract::Json(body): extract::Json<DashViewRequest>,
|
||||||
|
) -> Json<Value> {
|
||||||
|
let Some(system_id) = auth.system_id() else {
|
||||||
|
return Err(crate::error::GENERIC_AUTH_ERROR);
|
||||||
|
};
|
||||||
|
|
||||||
|
match body {
|
||||||
|
DashViewRequest::Add { name, value } => {
|
||||||
|
match sqlx::query_as::<Postgres, PKDashView>(
|
||||||
|
"select * from dash_views where name = $1 and system = $2",
|
||||||
|
)
|
||||||
|
.bind(&name)
|
||||||
|
.bind(system_id)
|
||||||
|
.fetch_optional(&ctx.db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(val) => {
|
||||||
|
if val.is_some() {
|
||||||
|
return Err(crate::error::GENERIC_BAD_REQUEST);
|
||||||
|
};
|
||||||
|
|
||||||
|
match sqlx::query_as::<Postgres, PKDashView>(
|
||||||
|
"insert into dash_views (system, name, value) values ($1, $2, $3) returning *",
|
||||||
|
)
|
||||||
|
.bind(system_id)
|
||||||
|
.bind(name)
|
||||||
|
.bind(value)
|
||||||
|
.fetch_one(&ctx.db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(res) => Ok(Json(res.to_json())),
|
||||||
|
Err(err) => fail!(?err, "failed to insert dash views"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => fail!(?err, "failed to query dash views"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DashViewRequest::Patch { id, name, value } => {
|
||||||
|
match sqlx::query_as::<Postgres, PKDashView>(
|
||||||
|
"select * from dash_views where id = $1 and system = $2",
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.bind(system_id)
|
||||||
|
.fetch_optional(&ctx.db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(val) => {
|
||||||
|
let Some(val) = val else {
|
||||||
|
return Err(crate::error::GENERIC_BAD_REQUEST);
|
||||||
|
};
|
||||||
|
// update
|
||||||
|
Ok(Json(Value::Null))
|
||||||
|
}
|
||||||
|
Err(err) => fail!(?err, "failed to query dash views"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DashViewRequest::Remove { id } => {
|
||||||
|
match sqlx::query_as::<Postgres, PKDashView>(
|
||||||
|
"select * from dash_views where id = $1 and system = $2",
|
||||||
|
)
|
||||||
|
.bind(id)
|
||||||
|
.bind(system_id)
|
||||||
|
.fetch_optional(&ctx.db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(val) => {
|
||||||
|
let Some(val) = val else {
|
||||||
|
return Err(crate::error::GENERIC_BAD_REQUEST);
|
||||||
|
};
|
||||||
|
match sqlx::query::<Postgres>(
|
||||||
|
"delete from dash_views where id = $1 and system = $2 returning *",
|
||||||
|
)
|
||||||
|
.bind(val.id)
|
||||||
|
.bind(system_id)
|
||||||
|
.fetch_one(&ctx.db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => Ok(Json(Value::Null)),
|
||||||
|
Err(err) => fail!(?err, "failed to remove dash views"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => fail!(?err, "failed to query dash views"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use pk_macros::api_endpoint;
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
use sqlx::Postgres;
|
use sqlx::Postgres;
|
||||||
|
|
||||||
use pluralkit_models::{PKSystem, PKSystemConfig, PrivacyLevel};
|
use pluralkit_models::{PKDashView, PKSystem, PKSystemConfig, PrivacyLevel};
|
||||||
|
|
||||||
use crate::{ApiContext, auth::AuthState, error::fail};
|
use crate::{ApiContext, auth::AuthState, error::fail};
|
||||||
|
|
||||||
|
|
@ -36,7 +36,32 @@ pub async fn get_system_settings(
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Json(match access_level {
|
Ok(Json(match access_level {
|
||||||
PrivacyLevel::Private => config.to_json(),
|
PrivacyLevel::Private => {
|
||||||
|
let mut config_json = config.clone().to_json();
|
||||||
|
|
||||||
|
match sqlx::query_as::<Postgres, PKDashView>(
|
||||||
|
"select * from dash_views where system = $1",
|
||||||
|
)
|
||||||
|
.bind(system.id)
|
||||||
|
.fetch_all(&ctx.db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(val) => {
|
||||||
|
config_json.as_object_mut().unwrap().insert(
|
||||||
|
"dash_views".to_string(),
|
||||||
|
serde_json::to_value(
|
||||||
|
&val.iter()
|
||||||
|
.map(|v| v.clone().to_json())
|
||||||
|
.collect::<Vec<serde_json::Value>>(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(err) => fail!(?err, "failed to query dash views"),
|
||||||
|
};
|
||||||
|
|
||||||
|
config_json
|
||||||
|
}
|
||||||
PrivacyLevel::Public => json!({
|
PrivacyLevel::Public => json!({
|
||||||
"pings_enabled": config.pings_enabled,
|
"pings_enabled": config.pings_enabled,
|
||||||
"latch_timeout": config.latch_timeout,
|
"latch_timeout": config.latch_timeout,
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ fn router(ctx: ApiContext) -> Router {
|
||||||
.route("/private/discord/callback", post(rproxy))
|
.route("/private/discord/callback", post(rproxy))
|
||||||
.route("/private/discord/callback2", post(endpoints::private::discord_callback))
|
.route("/private/discord/callback2", post(endpoints::private::discord_callback))
|
||||||
.route("/private/discord/shard_state", get(endpoints::private::discord_state))
|
.route("/private/discord/shard_state", get(endpoints::private::discord_state))
|
||||||
|
.route("/private/dash_views", post(endpoints::private::dash_views))
|
||||||
.route("/private/stats", get(endpoints::private::meta))
|
.route("/private/stats", get(endpoints::private::meta))
|
||||||
|
|
||||||
.route("/v2/systems/{system_id}/oembed.json", get(rproxy))
|
.route("/v2/systems/{system_id}/oembed.json", get(rproxy))
|
||||||
|
|
|
||||||
27
crates/migrate/data/migrations/55.sql
Normal file
27
crates/migrate/data/migrations/55.sql
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
-- database version 55
|
||||||
|
-- dashboard views
|
||||||
|
|
||||||
|
create function generate_dash_view_id_inner() returns char(10) as $$
|
||||||
|
select string_agg(substr('aieu234567890', ceil(random() * 13)::integer, 1), '') from generate_series(1, 10)
|
||||||
|
$$ language sql volatile;
|
||||||
|
|
||||||
|
|
||||||
|
create function generate_dash_view_id() returns char(10) as $$
|
||||||
|
declare newid char(10);
|
||||||
|
begin
|
||||||
|
loop
|
||||||
|
newid := generate_dash_view_id_inner();
|
||||||
|
if not exists (select 1 from dash_views where id = newid) then return newid; end if;
|
||||||
|
end loop;
|
||||||
|
end
|
||||||
|
$$ language plpgsql volatile;
|
||||||
|
|
||||||
|
create table dash_views (
|
||||||
|
id text not null primary key default generate_dash_view_id(),
|
||||||
|
system int references systems(id) on delete cascade,
|
||||||
|
name text not null,
|
||||||
|
value text not null,
|
||||||
|
unique (system, name)
|
||||||
|
);
|
||||||
|
|
||||||
|
update info set schema_version = 55;
|
||||||
|
|
@ -93,3 +93,14 @@ struct SystemConfig {
|
||||||
#[json = "premium_lifetime"]
|
#[json = "premium_lifetime"]
|
||||||
premium_lifetime: bool
|
premium_lifetime: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[pk_model]
|
||||||
|
struct DashView {
|
||||||
|
#[json = "id"]
|
||||||
|
id: String,
|
||||||
|
system: SystemId,
|
||||||
|
#[json = "name"]
|
||||||
|
name: String,
|
||||||
|
#[json = "value"]
|
||||||
|
value: String
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue