Compare commits

...

2 commits

Author SHA1 Message Date
Iris System
3b2c1332c2 fixup! cargo fmt
Some checks failed
Build and push Rust service Docker images / rust docker build (push) Has been cancelled
rust checks / cargo fmt (push) Has been cancelled
2025-08-18 22:33:03 +12:00
Iris System
be218c89cc fixup! working just like it was before :) 2025-08-18 21:57:26 +12:00
14 changed files with 107 additions and 86 deletions

View file

@ -29,7 +29,7 @@ jobs:
- uses: docker/setup-buildx-action@v1
# main docker build
- run: echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
- run: echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" | sed 's|/|-|g' >> $GITHUB_ENV
- uses: docker/build-push-action@v2
with:
# https://github.com/docker/build-push-action/issues/378

1
Cargo.lock generated
View file

@ -2616,6 +2616,7 @@ dependencies = [
"serde",
"serde_json",
"sqlx",
"tracing",
"uuid",
]

View file

@ -19,7 +19,7 @@ reqwest = { version = "0.12.7" , default-features = false, features = ["rustls-t
sentry = { version = "0.36.0", default-features = false, features = ["backtrace", "contexts", "panic", "debug-images", "reqwest", "rustls"] } # replace native-tls with rustls
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.117"
sqlx = { version = "0.8.2", features = ["runtime-tokio", "postgres", "time", "macros", "uuid"] }
sqlx = { version = "0.8.2", features = ["runtime-tokio", "postgres", "time", "chrono", "macros", "uuid"] }
tokio = { version = "1.36.0", features = ["full"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3.16", features = ["env-filter", "json"] }

View file

@ -34,7 +34,13 @@ pub struct AuthState {
}
impl AuthState {
pub fn new(system_id: Option<i32>, app_id: Option<Uuid>, api_key_id: Option<Uuid>, access_level: AccessLevel, internal: bool) -> Self {
pub fn new(
system_id: Option<i32>,
app_id: Option<Uuid>,
api_key_id: Option<Uuid>,
access_level: AccessLevel,
internal: bool,
) -> Self {
Self {
system_id,
app_id,

View file

@ -1,6 +1,6 @@
use crate::{util::json_err, AuthState, ApiContext};
use pluralkit_models::{ApiKeyType, PKApiKey, PKSystem, SystemId};
use crate::{util::json_err, ApiContext, AuthState};
use pk_macros::api_internal_endpoint;
use pluralkit_models::{ApiKeyType, PKApiKey, PKSystem, SystemId};
use axum::{
extract::State,
@ -76,7 +76,8 @@ pub async fn create_api_key_user(
"valid": true,
}))
.expect("should not error"),
).into_response());
)
.into_response());
}
let token: PKApiKey = sqlx::query_as(
@ -110,5 +111,6 @@ pub async fn create_api_key_user(
"token": token,
}))
.expect("should not error"),
).into_response())
)
.into_response())
}

View file

@ -1,6 +1,6 @@
use crate::{util::json_err, ApiContext};
use libpk::config;
use pluralkit_models::{PrivacyLevel, PKApiKey, PKSystem, PKSystemConfig};
use pluralkit_models::{PKApiKey, PKSystem, PKSystemConfig, PrivacyLevel};
use axum::{
extract::{self, State},
@ -201,5 +201,6 @@ pub async fn discord_callback(
"token": token,
}))
.expect("should not error"),
).into_response())
)
.into_response())
}

View file

@ -1,6 +1,9 @@
#![feature(let_chains)]
use auth::{AuthState, INTERNAL_APPID_HEADER, INTERNAL_SYSTEMID_HEADER, INTERNAL_TOKENID_HEADER, INTERNAL_PRIVACYLEVEL_HEADER};
use auth::{
AuthState, INTERNAL_APPID_HEADER, INTERNAL_PRIVACYLEVEL_HEADER, INTERNAL_SYSTEMID_HEADER,
INTERNAL_TOKENID_HEADER,
};
use axum::{
body::Body,
extract::{Request as ExtractRequest, State},
@ -13,9 +16,10 @@ use hyper_util::{
client::legacy::{connect::HttpConnector, Client},
rt::TokioExecutor,
};
use jsonwebtoken::{DecodingKey, EncodingKey};
use tracing::{error, info};
use pk_macros::api_endpoint;
use tracing::{error, info};
mod auth;
mod endpoints;
@ -61,15 +65,24 @@ async fn rproxy(
if let Some(sid) = auth.system_id() {
headers.append(INTERNAL_SYSTEMID_HEADER, sid.into());
headers.append(INTERNAL_PRIVACYLEVEL_HEADER, HeaderValue::from_str(&auth.access_level().privacy_level().to_string())?);
headers.append(
INTERNAL_PRIVACYLEVEL_HEADER,
HeaderValue::from_str(&auth.access_level().privacy_level().to_string())?,
);
}
if let Some(aid) = auth.app_id() {
headers.append(INTERNAL_APPID_HEADER, HeaderValue::from_str(&format!("{}", aid))?);
headers.append(
INTERNAL_APPID_HEADER,
HeaderValue::from_str(&format!("{}", aid))?,
);
}
if let Some(tid) = auth.api_key_id() {
headers.append(INTERNAL_TOKENID_HEADER, HeaderValue::from_str(&format!("{}", tid))?);
headers.append(
INTERNAL_TOKENID_HEADER,
HeaderValue::from_str(&format!("{}", tid))?,
);
}
Ok(ctx.rproxy_client.request(req).await?.into_response())
@ -136,9 +149,9 @@ fn router(ctx: ApiContext) -> Router {
.route("/internal/apikey/user", post(endpoints::internal::create_api_key_user))
.route("/v2/systems/:system_id/oembed.json", get(rproxy))
.route("/v2/members/:member_id/oembed.json", get(rproxy))
.route("/v2/groups/:group_id/oembed.json", get(rproxy))
.route("/v2/systems/{system_id}/oembed.json", get(rproxy))
.route("/v2/members/{member_id}/oembed.json", get(rproxy))
.route("/v2/groups/{group_id}/oembed.json", get(rproxy))
.layer(middleware::ratelimit::ratelimiter(ctx.clone(), middleware::ratelimit::do_request_ratelimited))

View file

@ -1,19 +1,19 @@
use axum::{
extract::{Request, State, MatchedPath},
extract::{MatchedPath, Request, State},
http::StatusCode,
middleware::Next,
response::Response,
};
use uuid::Uuid;
use subtle::ConstantTimeEq;
use uuid::Uuid;
use tracing::error;
use sqlx::Postgres;
use tracing::error;
use pluralkit_models::{ApiKeyType, PKApiKey};
use crate::auth::{AccessLevel, AuthState};
use crate::{util::json_err, ApiContext};
use pluralkit_models::{ApiKeyType, PKApiKey};
pub fn is_part_path<'a, 'b>(part: &'a str, endpoint: &'b str) -> bool {
if !endpoint.starts_with("/v2/") {
@ -133,8 +133,10 @@ pub async fn auth(State(ctx): State<ApiContext>, mut req: Request, next: Next) -
.flatten()
{
if system_auth_header.starts_with("Bearer ")
&& let Some(tid) =
PKApiKey::parse_header_str(system_auth_header[7..].to_string(), &ctx.token_publickey)
&& let Some(tid) = PKApiKey::parse_header_str(
system_auth_header[7..].to_string(),
&ctx.token_publickey,
)
&& let Some(token) =
sqlx::query_as::<Postgres, PKApiKey>("select * from api_keys where id = $1")
.bind(&tid)
@ -142,13 +144,10 @@ pub async fn auth(State(ctx): State<ApiContext>, mut req: Request, next: Next) -
.await
.expect("failed to query apitoken in postgres")
{
authed_system_id = Some(token.system);
authed_api_key_id = Some(tid);
access_level = apikey_can_access(&token, req.method().to_string(), endpoint.clone());
if access_level != AccessLevel::None {
authed_system_id = Some(token.system);
}
}
else if let Some(system_id) =
} else if let Some(system_id) =
match libpk::db::repository::legacy_token_auth(&ctx.db, system_auth_header).await {
Ok(val) => val,
Err(err) => {
@ -201,8 +200,13 @@ pub async fn auth(State(ctx): State<ApiContext>, mut req: Request, next: Next) -
false
};
req.extensions_mut()
.insert(AuthState::new(authed_system_id, authed_app_id, authed_api_key_id, access_level, internal));
req.extensions_mut().insert(AuthState::new(
authed_system_id,
authed_app_id,
authed_api_key_id,
access_level,
internal,
));
next.run(req).await
}

View file

@ -12,9 +12,9 @@ use sqlx::Postgres;
use tracing::{debug, error, info, warn};
use crate::{
ApiContext,
auth::AuthState,
util::{header_or_unknown, json_err},
ApiContext,
};
use pluralkit_models::PKExternalApp;

View file

@ -60,13 +60,8 @@ pub struct ApiConfig {
pub remote_url: String,
#[serde(default)]
pub temp_token2: Option<String>,
pub token_privatekey: String,
pub token_publickey: String,
pub internal_request_secret: String,
}
#[derive(Deserialize, Clone, Debug)]

View file

@ -11,7 +11,6 @@ jsonwebtoken = { workspace = true }
sea-query = "0.32.1"
serde = { workspace = true }
serde_json = { workspace = true, features = ["preserve_order"] }
# in theory we want to default-features = false for sqlx
# but cargo doesn't seem to support this
sqlx = { workspace = true, features = ["chrono"] }
sqlx = { workspace = true }
uuid = { workspace = true }
tracing = { workspace = true }