Skip to content
Clone

refactor: rename identity and auth modules for improved organization

ZhenYi committed
parent f2e745a commit e870254 Browse files

185 files changed

+1453 −1523

File tree 185
Modified app/src/main.rs View app/src/main.rs
@@ -47,9 +47,9 @@
4747 let identity = match identity_config()? {
4848 Some(identity_config) => {
4949 let db =
50 identity::db::DbConn::new(database.primary().clone(), database.replicas().to_vec());
50 auth::db::DbConn::new(database.primary().clone(), database.replicas().to_vec());
5151 Some(
52 identity::oauth::start(&identity_config, db)
52 auth::oauth::start(&identity_config, db)
5353 .await
5454 .context("starting identity service")?,
5555 )
@@ -144,7 +144,7 @@
144144 app.wrap(webapi::build_cors(&state.config.web))
145145 .wrap(from_fn(export::middleware::trace_request))
146146 .wrap(from_fn(export::telemetry::http_telemetry))
147 .wrap(from_fn(auth::oauth::revalidate::revalidate))
147 .wrap(from_fn(webapi::auth::oauth::revalidate::revalidate))
148148 .service(web::resource("/api/docs").route(web::get().to(|| async {
149149 actix_web::HttpResponse::Found()
150150 .insert_header((actix_web::http::header::LOCATION, "/api/docs/"))
@@ -229,8 +229,8 @@
229229 info!("running schema migration");
230230 sync_schema(&db).await.context("running schema sync")?;
231231 if let Some(identity) = identity_config()? {
232 let identity_db = identity::db::DbConn::new(db.clone(), Vec::new());
233 identity::auth::migrate::sync_schema(&identity_db)
232 let identity_db = auth::db::DbConn::new(db.clone(), Vec::new());
233 auth::server::migrate::sync_schema(&identity_db)
234234 .await
235235 .context("synchronizing identity schema")?;
236236 drop(identity);
@@ -289,7 +289,7 @@
289289 Ok(())
290290}
291291
292fn identity_config() -> anyhow::Result<Option<identity::config::Config>> {
292fn identity_config() -> anyhow::Result<Option<auth::config::Config>> {
293293 let figment = config::loader::figment();
294294 let enabled = figment
295295 .extract_inner::<bool>("identity.enabled")
@@ -300,13 +300,13 @@
300300 let value: serde_json::Value = figment
301301 .extract_inner("identity")
302302 .context("loading [identity] configuration")?;
303 Ok(Some(identity::config::Config::from_value(value)))
303 Ok(Some(auth::config::Config::from_value(value)))
304304}
305305
306306fn identity_openapi() -> anyhow::Result<()> {
307307 use utoipa_identity::OpenApi;
308 let doc = identity::auth::openapi::ApiDoc::openapi();
309 let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../lib/identity/OpenApi.Auth.json");
308 let doc = auth::server::openapi::ApiDoc::openapi();
309 let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../lib/auth/OpenApi.Auth.json");
310310 std::fs::write(&path, doc.to_pretty_json()?).context("writing identity OpenAPI")?;
311311 println!("wrote {}", path.display());
312312 Ok(())
Modified app/Cargo.toml View app/Cargo.toml
@@ -7,7 +7,6 @@
77[dependencies]
88kenauth = { workspace = true }
99serde_json = { workspace = true }
10identity = { workspace = true }
1110anyhow = { workspace = true }
1211auth = { workspace = true }
1312actix-web = { workspace = true }
Renamed lib/identity/src/client/error.rs → lib/auth/src/client/error.rs View lib/auth/src/client/error.rs

No content changes.

Renamed lib/identity/src/client/local.rs → lib/auth/src/client/local.rs View lib/auth/src/client/local.rs
@@ -1,10 +1,10 @@
1use crate::auth::AuthSvc;
2use crate::auth::grpc::context::RequestMeta;
1use crate::server::AuthSvc;
2use crate::server::grpc::context::RequestMeta;
33use tonic::{Request, Response, Status};
44use uuid::Uuid;
55
6use crate::auth::grpc::identity::IdentityApi;
76use crate::protos::auth::v1::identity_service_server::IdentityService;
7use crate::server::grpc::identity::IdentityApi;
88
99pub struct IdentityClient {
1010 api: IdentityApi,
@@ -88,8 +88,8 @@
8888 }
8989}
9090
91use crate::auth::grpc::authority::AuthorityApi;
9291use crate::protos::auth::internal::v1::authority_service_server::AuthorityService;
92use crate::server::grpc::authority::AuthorityApi;
9393
9494pub struct AuthorityClient {
9595 api: AuthorityApi,
@@ -205,8 +205,8 @@
205205 }
206206}
207207
208use crate::auth::grpc::email::EmailApi;
209208use crate::protos::auth::internal::v1::email_service_server::EmailService;
209use crate::server::grpc::email::EmailApi;
210210
211211pub struct EmailClient {
212212 api: EmailApi,
@@ -260,8 +260,8 @@
260260 }
261261}
262262
263use crate::auth::grpc::session::SessionApi;
264263use crate::protos::auth::v1::session_service_server::SessionService;
264use crate::server::grpc::session::SessionApi;
265265
266266pub struct SessionClient {
267267 api: SessionApi,
@@ -315,8 +315,8 @@
315315 }
316316}
317317
318use crate::auth::grpc::organization::OrganizationApi;
319318use crate::protos::auth::v1::organization_service_server::OrganizationService;
319use crate::server::grpc::organization::OrganizationApi;
320320
321321pub struct OrganizationClient {
322322 api: OrganizationApi,
@@ -820,8 +820,8 @@
820820 }
821821}
822822
823use crate::auth::grpc::token::TokenApi;
824823use crate::protos::auth::v1::token_service_server::TokenService;
824use crate::server::grpc::token::TokenApi;
825825
826826pub struct TokenClient {
827827 api: TokenApi,
@@ -865,8 +865,8 @@
865865 }
866866}
867867
868use crate::auth::grpc::authorization::AuthorizationApi;
869868use crate::protos::auth::v1::authorization_service_server::AuthorizationService;
869use crate::server::grpc::authorization::AuthorizationApi;
870870
871871pub struct AuthorizationClient {
872872 api: AuthorizationApi,
@@ -920,8 +920,8 @@
920920 }
921921}
922922
923use crate::auth::grpc::access_key::AccessKeyApi;
924923use crate::protos::auth::v1::access_key_service_server::AccessKeyService;
924use crate::server::grpc::access_key::AccessKeyApi;
925925
926926pub struct AccessKeyClient {
927927 api: AccessKeyApi,
@@ -985,8 +985,8 @@
985985 }
986986}
987987
988use crate::auth::grpc::ssh_key::SshKeyApi;
989988use crate::protos::auth::v1::ssh_key_service_server::SshKeyService;
989use crate::server::grpc::ssh_key::SshKeyApi;
990990
991991pub struct SshKeyClient {
992992 api: SshKeyApi,
@@ -1040,8 +1040,8 @@
10401040 }
10411041}
10421042
1043use crate::auth::grpc::mfa::MfaApi;
10441043use crate::protos::auth::v1::mfa_service_server::MfaService;
1044use crate::server::grpc::mfa::MfaApi;
10451045
10461046pub struct MfaClient {
10471047 api: MfaApi,
@@ -1125,8 +1125,8 @@
11251125 }
11261126}
11271127
1128use crate::auth::grpc::agreement::AgreementApi;
11291128use crate::protos::auth::v1::agreement_service_server::AgreementService;
1129use crate::server::grpc::agreement::AgreementApi;
11301130
11311131pub struct AgreementClient {
11321132 api: AgreementApi,
Renamed lib/identity/src/client/mod.rs → lib/auth/src/client/mod.rs View lib/auth/src/client/mod.rs
@@ -4,7 +4,7 @@
44use std::collections::HashMap;
55use std::time::Duration;
66
7use crate::auth::AuthSvc;
7use crate::server::AuthSvc;
88use tonic::Request;
99use uuid::Uuid;
1010
Renamed lib/identity/src/oauth/assets.rs → lib/auth/src/oauth/assets.rs View lib/auth/src/oauth/assets.rs
@@ -69,7 +69,7 @@
6969}
7070
7171fn api_not_found() -> HttpResponse {
72 HttpResponse::NotFound().json(crate::auth::errors::ErrorBody {
72 HttpResponse::NotFound().json(crate::server::errors::ErrorBody {
7373 code: "not_found".to_owned(),
7474 message: "unknown api route".to_owned(),
7575 })
Modified lib/auth/src/oauth/mod.rs View lib/auth/src/oauth/mod.rs
@@ -1,11 +1,262 @@
1pub mod callback;
2pub mod login;
3pub mod logout;
4pub mod project;
5pub mod refresh;
6pub mod revalidate;
7pub mod state;
1mod assets;
2
3use crate::cache::Cache;
4use crate::config::Config;
5use crate::config::app::AppRegistry;
6use crate::config::auth::AuthConfig;
7use crate::config::jwt::JwtConfig;
8use crate::config::pow::PowConfig;
9use crate::config::redis::RedisConfig;
10use crate::config::rocketmq::RocketMqConfig;
11use crate::config::server::ServerConfig;
12use crate::config::session::SessionConfig;
13use crate::config::web::WebConfig;
14use crate::db::DbConn;
15use crate::email::EmailServiceBuilder;
16use crate::events::EventHandler;
17use crate::queue::RocketMqConn;
18use crate::server::AuthSvc;
19use crate::session::{RedisStore, SessionMiddleware};
20use actix_web::{App, HttpServer, web};
21use anyhow::{Context, Result};
22use std::net::{IpAddr, SocketAddr};
23
24const APP: &str = "oauth";
25/// 邮件订阅者排空时的宽限时间。
26const EMAIL_SHUTDOWN_GRACE: std::time::Duration = std::time::Duration::from_secs(10);
27const GRPC_SHUTDOWN_GRACE_SECS: u64 = 10;
28
29#[derive(Clone)]
30struct AppState {
31 service: AuthSvc,
32 session: SessionConfig,
33 store: RedisStore,
34}
835
9mod flow;
36/// host 网络部署下绑非回环地址即把单密钥门禁的 gRPC 面暴露公网;
37/// 显式设 KENOAUTH_ALLOW_PUBLIC_BIND=1 才放行。
38fn ensure_public_bind_allowed(addr: SocketAddr, label: &str) -> Result<SocketAddr> {
39 let loopback = match addr.ip() {
40 IpAddr::V4(ip) => ip.is_loopback(),
41 IpAddr::V6(ip) => ip.is_loopback(),
42 };
43 if loopback || std::env::var("KENOAUTH_ALLOW_PUBLIC_BIND").as_deref() == Ok("1") {
44 return Ok(addr);
45 }
46 Err(anyhow::anyhow!(
47 "{label} binds a non-loopback address ({addr}); the grpc plane is guarded by a single \
48 shared rpc_key. Set KENOAUTH_ALLOW_PUBLIC_BIND=1 to confirm public exposure."
49 ))
50}
1051
11pub use flow::*;
52pub async fn start(config: &Config, db: DbConn) -> Result<Runtime> {
53 let server: ServerConfig = config.section()?;
54 crate::jwt::service::install(config.section()?).context("loading service identity")?;
55 let auth_config: AuthConfig = config.section()?;
56 let jwt_config: JwtConfig = config.section()?;
57 let pow_config: PowConfig = config.section()?;
58 let apps: AppRegistry = config.section_or_default()?;
59 let redis: RedisConfig = config.section()?;
60 let session_config: SessionConfig = config.section()?;
61 let rocketmq: RocketMqConfig = config.section()?;
62 let web: WebConfig = config.section_or_default()?;
63 let email_pool: crate::config::email::EmailPoolConfig = config.section_or_default()?;
64
65 auth_config
66 .validate()
67 .map_err(anyhow::Error::msg)
68 .context("invalid auth configuration")?;
69 pow_config
70 .validate()
71 .map_err(anyhow::Error::msg)
72 .context("invalid pow configuration")?;
73 apps.validate()
74 .map_err(anyhow::Error::msg)
75 .context("invalid apps configuration")?;
76 redis
77 .validate()
78 .map_err(anyhow::Error::msg)
79 .context("invalid redis configuration")?;
80 rocketmq
81 .validate()
82 .map_err(anyhow::Error::msg)
83 .context("invalid rocketmq configuration")?;
84 email_pool
85 .is_valid()
86 .map_err(anyhow::Error::msg)
87 .context("invalid email configuration")?;
88 web.is_valid()
89 .map_err(anyhow::Error::msg)
90 .context("invalid web configuration")?;
91 crate::config::session::ensure_secure_cookie(
92 session_config.secure,
93 server.http_addr,
94 std::env::var("KENOAUTH_ALLOW_INSECURE_COOKIE").as_deref() == Ok("1"),
95 )
96 .map_err(anyhow::Error::msg)
97 .context("invalid session configuration")?;
98 let cors = crate::envelope::Cors::new(&web);
99
100 let cache = Cache::connect(&redis)
101 .await
102 .context("connecting to redis")?;
103 let mq = RocketMqConn::init(&rocketmq)
104 .await
105 .context("connecting to rocketmq")?;
106 let events = EventHandler::new(mq);
107
108 let mut email_builder = EmailServiceBuilder::new(email_pool)
109 .with_events(events.clone())
110 .with_database(db.clone());
111 if config.has("smtp") {
112 let smtp: crate::config::smtp::SmtpConfig = config.section()?;
113 email_builder = email_builder.with_transport(smtp);
114 }
115 let email_service = email_builder
116 .register_default_templates()
117 .await
118 .build()
119 .await
120 .context("building the email service")?;
121 let email_enabled = email_service.enabled();
122 let email_queue_depth = email_service.depth();
123 let email = Some(email_service);
124
125 let session_max_age_secs = session_config.max_age.max(1) as u64;
126 let service = AuthSvc::new(
127 db,
128 cache.clone(),
129 email,
130 Some(events),
131 auth_config,
132 pow_config,
133 apps,
134 jwt_config,
135 session_max_age_secs,
136 )
137 .await?;
138 let state = AppState {
139 service: service.clone(),
140 session: session_config,
141 store: RedisStore::new(cache),
142 };
143
144 let grpc_addr = ensure_public_bind_allowed(server.grpc_addr, "grpc")?;
145 let grpc_listener = tokio::net::TcpListener::bind(grpc_addr)
146 .await
147 .with_context(|| format!("binding grpc on {grpc_addr}"))?;
148 let grpc = crate::server::grpc::router(service.clone())
149 .await
150 .context("building the grpc router")?;
151
152 let http = HttpServer::new(move || {
153 App::new()
154 .wrap(SessionMiddleware::new(
155 state.session.clone(),
156 state.store.clone(),
157 ))
158 .wrap(crate::oltp::HttpTelemetry::new("oauth"))
159 .wrap(crate::envelope::EnvelopeContext)
160 .wrap(cors.clone())
161 .app_data(web::Data::new(state.service.clone()))
162 .app_data(web::Data::new(web.clone()))
163 .configure(crate::server::router::configure)
164 .default_service(web::to(assets::serve))
165 })
166 .disable_signals()
167 .bind(ensure_public_bind_allowed(server.http_addr, "http")?)
168 .with_context(|| format!("binding http on {}", server.http_addr))?
169 .run();
170
171 let event_forwarding = service.verify_event_forwarding().await;
172 tracing::info!(
173 app = APP,
174 config = %config.path().display(),
175 http = %server.http_addr,
176 grpc = %server.grpc_addr,
177 assets = assets::count(),
178 email = email_enabled,
179 email_queue_depth,
180 event_forwarding,
181 "oauth serving"
182 );
183
184 Ok(Runtime {
185 service,
186 http,
187 grpc,
188 grpc_listener,
189 })
190}
191
192pub struct Runtime {
193 service: AuthSvc,
194 http: actix_web::dev::Server,
195 grpc: crate::server::grpc::GrpcRouter,
196 grpc_listener: tokio::net::TcpListener,
197}
198
199impl Runtime {
200 pub fn service(&self) -> &AuthSvc {
201 &self.service
202 }
203
204 pub async fn serve_until(self, shutdown: tokio_util::sync::CancellationToken) -> Result<()> {
205 let Self {
206 service,
207 http,
208 grpc,
209 grpc_listener,
210 } = self;
211 let handle = http.handle();
212 let grpc_cancel = shutdown.clone();
213 let incoming = tokio_stream::wrappers::TcpListenerStream::new(grpc_listener);
214 let grpc = grpc.serve_with_incoming_shutdown(incoming, async move {
215 grpc_cancel.cancelled().await;
216 });
217 tokio::pin!(http, grpc);
218 let mut grpc_done = false;
219 let mut http_done = false;
220 let result = tokio::select! {
221 result = &mut http => { http_done = true; result.context("identity HTTP server stopped") },
222 result = &mut grpc => { grpc_done = true; result.context("identity gRPC server stopped") },
223 _ = shutdown.cancelled() => Ok(()),
224 };
225 shutdown.cancel();
226 let http_shutdown = async {
227 if !http_done {
228 let stop = handle.stop(true);
229 let (_, result) = tokio::join!(stop, &mut http);
230 if let Err(error) = result {
231 tracing::warn!(%error, "identity HTTP shutdown failed");
232 }
233 }
234 };
235 let grpc_shutdown = async {
236 if !grpc_done {
237 match tokio::time::timeout(
238 std::time::Duration::from_secs(GRPC_SHUTDOWN_GRACE_SECS),
239 &mut grpc,
240 )
241 .await
242 {
243 Ok(Ok(())) => {}
244 Ok(Err(error)) => tracing::warn!(%error, "identity gRPC shutdown failed"),
245 Err(_) => tracing::warn!("identity gRPC shutdown timed out"),
246 }
247 }
248 };
249 tokio::join!(http_shutdown, grpc_shutdown);
250 if let Some(email) = service.email()
251 && let Err(error) = email.shutdown(EMAIL_SHUTDOWN_GRACE).await
252 {
253 tracing::warn!(%error, "draining the email queue failed");
254 }
255 if let Some(events) = service.events()
256 && let Err(error) = events.shutdown().await
257 {
258 tracing::warn!(%error, "shutting down identity producer failed");
259 }
260 result
261 }
262}
Renamed lib/identity/src/auth/access_token/handler.rs → lib/auth/src/server/access_token/handler.rs View lib/auth/src/server/access_token/handler.rs
@@ -2,13 +2,13 @@
22use actix_web::web;
33use uuid::Uuid;
44
5use crate::auth::AuthSvc;
6use crate::auth::access_token::types::{
5use crate::envelope::{Envelope, NoData};
6use crate::server::AuthSvc;
7use crate::server::access_token::types::{
78 AccessTokenCreateRequest, AccessTokenCreateResponse, AccessTokenSummary,
89};
9use crate::auth::errors::AuthError;
10use crate::auth::share::types::ListQuery;
11use crate::envelope::{Envelope, NoData};
10use crate::server::errors::AuthError;
11use crate::server::share::types::ListQuery;
1212
1313#[utoipa::path(
1414 get,
Renamed lib/identity/src/auth/access_token/mod.rs → lib/auth/src/server/access_token/mod.rs View lib/auth/src/server/access_token/mod.rs

No content changes.

Renamed lib/identity/src/auth/access_token/service.rs → lib/auth/src/server/access_token/service.rs View lib/auth/src/server/access_token/service.rs
@@ -11,18 +11,18 @@
1111};
1212use uuid::Uuid;
1313
14use crate::auth::AuthSvc;
15use crate::auth::access_token::types::{
14use crate::jwt::{AppClaims, JwtError};
15use crate::server::AuthSvc;
16use crate::server::access_token::types::{
1617 ALLOWED_APP_SCOPES, AccessTokenAuthRequest, AccessTokenAuthResponse, AccessTokenCreateRequest,
1718 AccessTokenCreateResponse, AccessTokenSummary, LAST_USED_THROTTLE_SECS,
1819 MAX_ACCESS_KEY_DESCRIPTION_LEN, MAX_ACCESS_KEY_EXPIRES_SECS, MAX_ACCESS_KEY_NAME_LEN,
1920 MAX_ACCESS_KEY_SCOPE_ENTRIES, MAX_ACTIVE_ACCESS_KEYS, MIN_ACCESS_KEY_EXPIRES_SECS, TOKEN_BYTES,
2021 TOKEN_FINGERPRINT_LEN, TOKEN_HASH_KEY_ID,
2122};
22use crate::auth::errors::{AuthError, AuthResult};
23use crate::auth::share::crypto::{random_b64url, sha256_hex};
24use crate::auth::share::types::ListQuery;
25use crate::jwt::{AppClaims, JwtError};
23use crate::server::errors::{AuthError, AuthResult};
24use crate::server::share::crypto::{random_b64url, sha256_hex};
25use crate::server::share::types::ListQuery;
2626
2727fn summary(record: user_access_tokens::Model) -> AccessTokenSummary {
2828 AccessTokenSummary {
@@ -182,7 +182,7 @@
182182 .await?;
183183 txn.commit().await?;
184184
185 crate::auth::share::audit::entry(
185 crate::server::share::audit::entry(
186186 self.db(),
187187 user_id,
188188 Some(user_id),
@@ -280,7 +280,7 @@
280280 return Err(AuthError::AccessTokenNotFound);
281281 }
282282
283 crate::auth::share::audit::entry(
283 crate::server::share::audit::entry(
284284 self.db(),
285285 user_id,
286286 Some(user_id),
@@ -375,7 +375,7 @@
375375 return Ok(());
376376 }
377377
378 crate::auth::share::audit::entry(
378 crate::server::share::audit::entry(
379379 self.db(),
380380 user_id,
381381 Some(user_id),
Renamed lib/identity/src/auth/access_token/types.rs → lib/auth/src/server/access_token/types.rs View lib/auth/src/server/access_token/types.rs

No content changes.

Renamed lib/identity/src/auth/app_token/handler.rs → lib/auth/src/server/app_token/handler.rs View lib/auth/src/server/app_token/handler.rs
@@ -1,10 +1,10 @@
11use crate::session::{RequestId, Session};
22use actix_web::web;
33
4use crate::auth::AuthSvc;
5use crate::auth::app_token::types::{AppTokenRequest, AppTokenResponse};
6use crate::auth::errors::AuthError;
74use crate::envelope::{Envelope, NoData};
5use crate::server::AuthSvc;
6use crate::server::app_token::types::{AppTokenRequest, AppTokenResponse};
7use crate::server::errors::AuthError;
88
99#[utoipa::path(
1010 post,
Renamed lib/identity/src/auth/app_token/mod.rs → lib/auth/src/server/app_token/mod.rs View lib/auth/src/server/app_token/mod.rs

No content changes.

Renamed lib/identity/src/auth/app_token/service.rs → lib/auth/src/server/app_token/service.rs View lib/auth/src/server/app_token/service.rs
@@ -1,11 +1,11 @@
11use crate::events::{AuthEvent, Labels, RestOperate, RuntimeEvent};
22
3use crate::auth::AuthSvc;
4use crate::auth::app_token::types::{
3use crate::server::AuthSvc;
4use crate::server::app_token::types::{
55 AppTokenRequest, AppTokenResponse, DEFAULT_TTL_SECS, MAX_TTL_SECS,
66};
7use crate::auth::errors::{AuthError, AuthResult};
8use crate::auth::share::issue;
7use crate::server::errors::{AuthError, AuthResult};
8use crate::server::share::issue;
99
1010impl AuthSvc {
1111 #[tracing::instrument(skip_all, fields(user_id = user_id, request_id = %request_id.unwrap_or_default()))]
Renamed lib/identity/src/auth/app_token/types.rs → lib/auth/src/server/app_token/types.rs View lib/auth/src/server/app_token/types.rs

No content changes.

Renamed lib/identity/src/auth/challenge/handler.rs → lib/auth/src/server/challenge/handler.rs View lib/auth/src/server/challenge/handler.rs
@@ -1,10 +1,10 @@
11use crate::session::{RequestId, Session};
22use actix_web::web;
33
4use crate::auth::AuthSvc;
5use crate::auth::challenge::types::ChallengeResponse;
6use crate::auth::errors::AuthError;
74use crate::envelope::{Envelope, NoData};
5use crate::server::AuthSvc;
6use crate::server::challenge::types::ChallengeResponse;
7use crate::server::errors::AuthError;
88
99#[utoipa::path(
1010 post,
Renamed lib/identity/src/auth/challenge/mod.rs → lib/auth/src/server/challenge/mod.rs View lib/auth/src/server/challenge/mod.rs

No content changes.

Renamed lib/identity/src/auth/challenge/service.rs → lib/auth/src/server/challenge/service.rs View lib/auth/src/server/challenge/service.rs
@@ -1,9 +1,9 @@
11use crate::events::{AuthEvent, Labels, RestOperate, RuntimeEvent};
22use crate::session::Session;
33
4use crate::auth::AuthSvc;
5use crate::auth::challenge::types::{ChallengeResponse, PowProofRequest};
6use crate::auth::errors::AuthResult;
4use crate::server::AuthSvc;
5use crate::server::challenge::types::{ChallengeResponse, PowProofRequest};
6use crate::server::errors::AuthResult;
77
88impl AuthSvc {
99 #[tracing::instrument(skip_all, fields(request_id = %request_id, client_ip = ?session.client_ip().ok().flatten()))]
@@ -12,7 +12,7 @@
1212 session: Session,
1313 request_id: String,
1414 ) -> AuthResult<ChallengeResponse> {
15 let response = crate::auth::pow::store::issue(&session, self.pow()).await?;
15 let response = crate::server::pow::store::issue(&session, self.pow()).await?;
1616 self.emit_labeled(
1717 RuntimeEvent::Auth(AuthEvent::Challenge {
1818 operate: RestOperate::Create,
@@ -35,7 +35,7 @@
3535 expected_payload: &[u8],
3636 request_id: String,
3737 ) -> AuthResult<()> {
38 crate::auth::pow::store::verify(&session, self.cache(), proof, expected_payload).await?;
38 crate::server::pow::store::verify(&session, self.cache(), proof, expected_payload).await?;
3939 self.emit_labeled(
4040 RuntimeEvent::Auth(AuthEvent::Challenge {
4141 operate: RestOperate::Used,
Renamed lib/identity/src/auth/challenge/types.rs → lib/auth/src/server/challenge/types.rs View lib/auth/src/server/challenge/types.rs

No content changes.

Renamed lib/identity/src/auth/client/mod.rs → lib/auth/src/server/client/mod.rs View lib/auth/src/server/client/mod.rs

No content changes.

Renamed lib/identity/src/auth/client/registry.rs → lib/auth/src/server/client/registry.rs View lib/auth/src/server/client/registry.rs
@@ -8,14 +8,14 @@
88use sea_orm::{ActiveModelTrait, EntityTrait, Set};
99use serde_json::{Value, json};
1010
11use crate::auth::errors::{AuthError, AuthResult};
12use crate::auth::share::crypto;
1311use crate::config::auth::{OAuthClient, OAuthConfig};
1412use crate::db::DbConn;
1513use crate::models::users::oauth_clients::{
1614 ActiveModel as ClientActiveModel, ClientKind, ClientSource, Column, Entity as ClientEntity,
1715 Model as ClientModel,
1816};
17use crate::server::errors::{AuthError, AuthResult};
18use crate::server::share::crypto;
1919
2020/// 机密客户端 secret 的最小长度(high-entropy 才能用 sha256 存储)。
2121pub const MIN_SECRET_LEN: usize = 32;
@@ -489,7 +489,7 @@
489489}
490490
491491pub fn is_loopback(host: &str) -> bool {
492 crate::auth::share::net::is_loopback_host(host)
492 crate::server::share::net::is_loopback_host(host)
493493}
494494
495495/// 请求的 URI 是否匹配注册的模式;`wildcard=false` 时退化为精确串比较。
Renamed lib/identity/src/auth/grpc/access_key.rs → lib/auth/src/server/grpc/access_key.rs View lib/auth/src/server/grpc/access_key.rs
@@ -10,10 +10,10 @@
1010use tonic::{Request, Response, Status};
1111use uuid::Uuid;
1212
13use crate::auth::AuthSvc;
14use crate::auth::access_token::types::TOKEN_HASH_KEY_ID;
15use crate::auth::errors::AuthError;
16use crate::auth::grpc::{context, convert, error, store};
13use crate::server::AuthSvc;
14use crate::server::access_token::types::TOKEN_HASH_KEY_ID;
15use crate::server::errors::AuthError;
16use crate::server::grpc::{context, convert, error, store};
1717
1818#[derive(Clone)]
1919pub struct AccessKeyApi {
@@ -230,7 +230,7 @@
230230 .svc
231231 .create_access_token_for_user(
232232 request.user_id,
233 crate::auth::access_token::types::AccessTokenCreateRequest {
233 crate::server::access_token::types::AccessTokenCreateRequest {
234234 name: request.name,
235235 description: Some(request.description).filter(|text| !text.is_empty()),
236236 scope,
Renamed lib/identity/src/auth/grpc/agreement.rs → lib/auth/src/server/grpc/agreement.rs View lib/auth/src/server/grpc/agreement.rs
@@ -8,9 +8,9 @@
88use serde::{Deserialize, Serialize};
99use tonic::{Request, Response, Status};
1010
11use crate::auth::AuthSvc;
12use crate::auth::errors::{AuthError, AuthResult};
13use crate::auth::grpc::{context, convert, error, store};
11use crate::server::AuthSvc;
12use crate::server::errors::{AuthError, AuthResult};
13use crate::server::grpc::{context, convert, error, store};
1414
1515pub const DEFAULT_LOCALE: &str = "zh-CN";
1616pub const SUMMARY_MAX_CHARS: usize = 160;
@@ -43,7 +43,7 @@
4343) -> AuthResult<()> {
4444 let record = Acceptance {
4545 version: version.to_owned(),
46 accepted_at: crate::auth::share::crypto::now_secs(),
46 accepted_at: crate::server::share::crypto::now_secs(),
4747 };
4848 cache
4949 .set_json(&acceptance_key(user_id, key), &record)
Renamed lib/identity/src/auth/grpc/audit.rs → lib/auth/src/server/grpc/audit.rs View lib/auth/src/server/grpc/audit.rs
@@ -9,9 +9,9 @@
99};
1010use tonic::{Request, Response, Status};
1111
12use crate::auth::AuthSvc;
13use crate::auth::errors::AuthError;
14use crate::auth::grpc::{context, convert, error, store};
12use crate::server::AuthSvc;
13use crate::server::errors::AuthError;
14use crate::server::grpc::{context, convert, error, store};
1515
1616const DEFAULT_EXPORT_BATCH: u32 = 500;
1717const MAX_EXPORT_BATCH: u32 = 5_000;
Renamed lib/identity/src/auth/grpc/authority.rs → lib/auth/src/server/grpc/authority.rs View lib/auth/src/server/grpc/authority.rs
@@ -15,8 +15,8 @@
1515use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect};
1616use tonic::{Request, Response, Status};
1717
18use crate::auth::AuthSvc;
19use crate::auth::grpc::{context, convert, error, store};
18use crate::server::AuthSvc;
19use crate::server::grpc::{context, convert, error, store};
2020
2121pub struct AuthorityApi {
2222 svc: AuthSvc,
@@ -368,7 +368,7 @@
368368 if user_ids.is_empty() {
369369 return Ok(Response::new(BatchGetUserResponse { users: Vec::new() }));
370370 }
371 if user_ids.len() > crate::auth::grpc::store::MAX_BATCH_USER_IDS {
371 if user_ids.len() > crate::server::grpc::store::MAX_BATCH_USER_IDS {
372372 return Err(error::invalid_argument(
373373 "too many user ids in one batch",
374374 request_id,
@@ -480,7 +480,7 @@
480480 payload: ListUsersRequest,
481481 ) -> Result<Response<ListUsersResponse>, Status> {
482482 let filter = payload.filter.unwrap_or_default();
483 if filter.user_ids.len() > crate::auth::grpc::store::MAX_BATCH_USER_IDS {
483 if filter.user_ids.len() > crate::server::grpc::store::MAX_BATCH_USER_IDS {
484484 return Err(error::invalid_argument(
485485 "too many user ids in one filter",
486486 request_id,
@@ -502,7 +502,7 @@
502502 .all(self.svc.db().read())
503503 .await
504504 .map_err(|value| {
505 error::status(&crate::auth::errors::AuthError::from(value), request_id)
505 error::status(&crate::server::errors::AuthError::from(value), request_id)
506506 })?;
507507 let next_page_token = if convert::has_more(offset, page_size, rows.len()) {
508508 store::page_token(offset + rows.len() as u64)
@@ -512,7 +512,7 @@
512512 Ok(Response::new(ListUsersResponse {
513513 users: rows
514514 .iter()
515 .map(|row| user(&crate::auth::authority::record(row.clone())))
515 .map(|row| user(&crate::server::authority::record(row.clone())))
516516 .collect(),
517517 page: Some(PageResponse { next_page_token }),
518518 }))
Renamed lib/identity/src/auth/grpc/authorization.rs → lib/auth/src/server/grpc/authorization.rs View lib/auth/src/server/grpc/authorization.rs
@@ -10,10 +10,10 @@
1010use sea_orm::EntityTrait;
1111use tonic::{Request, Response, Status};
1212
13use crate::auth::AuthSvc;
14use crate::auth::access_token::types::ALLOWED_APP_SCOPES;
15use crate::auth::errors::{AuthError, AuthResult};
16use crate::auth::grpc::{agreement, context, error, store};
13use crate::server::AuthSvc;
14use crate::server::access_token::types::ALLOWED_APP_SCOPES;
15use crate::server::errors::{AuthError, AuthResult};
16use crate::server::grpc::{agreement, context, error, store};
1717
1818const MAX_BATCH_CAPABILITIES: usize = 32;
1919const ADMIN_CACHE_TTL_SECS: u64 = 300;
Renamed lib/identity/src/auth/grpc/cache_maintenance.rs → lib/auth/src/server/grpc/cache_maintenance.rs View lib/auth/src/server/grpc/cache_maintenance.rs
@@ -8,10 +8,10 @@
88use crate::protos::auth::internal::v1::*;
99use tonic::{Request, Response, Status};
1010
11use crate::auth::AuthSvc;
12use crate::auth::errors::AuthError;
13use crate::auth::grpc::{context, error, store};
14use crate::auth::me::types::MeResponse;
11use crate::server::AuthSvc;
12use crate::server::errors::AuthError;
13use crate::server::grpc::{context, error, store};
14use crate::server::me::types::MeResponse;
1515
1616const USER_SCOPED_PREFIXES: [&str; 3] = ["auth:me:", "auth:admin:", "auth:rate:mfa:"];
1717
Renamed lib/identity/src/auth/grpc/client.rs → lib/auth/src/server/grpc/client.rs View lib/auth/src/server/grpc/client.rs
@@ -5,10 +5,6 @@
55use sea_orm::EntityTrait;
66use tonic::{Request, Response, Status};
77
8use crate::auth::AuthSvc;
9use crate::auth::client::{ClientRecord, ClientSpec};
10use crate::auth::errors::AuthError;
11use crate::auth::grpc::{context, convert, error};
128use crate::models::users::oauth_clients::{
139 ClientKind as ModelKind, ClientSource as ModelSource, Entity as ClientEntity,
1410};
@@ -16,6 +12,10 @@
1612 ClientService, ClientServiceServer,
1713};
1814use crate::protos::auth::internal::v1::*;
15use crate::server::AuthSvc;
16use crate::server::client::{ClientRecord, ClientSpec};
17use crate::server::errors::AuthError;
18use crate::server::grpc::{context, convert, error};
1919
2020#[derive(Clone)]
2121pub struct ClientApi {
Renamed lib/identity/src/auth/grpc/context.rs → lib/auth/src/server/grpc/context.rs View lib/auth/src/server/grpc/context.rs
@@ -12,7 +12,7 @@
1212use tonic::{Request, Status};
1313use uuid::Uuid;
1414
15use crate::auth::grpc::error;
15use crate::server::grpc::error;
1616
1717pub const RPC_KEY_METADATA: &str = "x-rpc-key";
1818pub const REQUEST_ID_METADATA: &str = "gitdata-request-id";
@@ -106,7 +106,7 @@
106106 ));
107107 }
108108 if presented.is_empty()
109 || !crate::auth::share::crypto::constant_time_eq(
109 || !crate::server::share::crypto::constant_time_eq(
110110 presented.as_bytes(),
111111 self.key.as_bytes(),
112112 )
Renamed lib/identity/src/auth/grpc/convert.rs → lib/auth/src/server/grpc/convert.rs View lib/auth/src/server/grpc/convert.rs
@@ -3,7 +3,7 @@
33use chrono::{DateTime, NaiveDate, TimeZone, Utc};
44use prost_types::Timestamp;
55
6use crate::auth::grpc::store;
6use crate::server::grpc::store;
77
88pub const DEFAULT_PAGE_SIZE: i32 = 20;
99pub const MAX_PAGE_SIZE: i32 = 100;
Renamed lib/identity/src/auth/grpc/email.rs → lib/auth/src/server/grpc/email.rs View lib/auth/src/server/grpc/email.rs
@@ -8,9 +8,6 @@
88use tonic::{Request, Response, Status};
99use uuid::Uuid;
1010
11use crate::auth::AuthSvc;
12use crate::auth::errors::AuthError;
13use crate::auth::grpc::{context, error};
1411use crate::email::events::{
1512 Attachment as ModelAttachment, BatchRecipient as ModelBatchRecipient,
1613 EmailAddress as ModelAddress, RenderAndSendEmailRequest as ModelRenderRequest,
@@ -18,6 +15,9 @@
1815};
1916use crate::protos::auth::internal::v1::email_service_server::{EmailService, EmailServiceServer};
2017use crate::protos::auth::internal::v1::*;
18use crate::server::AuthSvc;
19use crate::server::errors::AuthError;
20use crate::server::grpc::{context, error};
2121
2222#[derive(Clone)]
2323pub struct EmailApi {
Renamed lib/identity/src/auth/grpc/error.rs → lib/auth/src/server/grpc/error.rs View lib/auth/src/server/grpc/error.rs
@@ -4,7 +4,7 @@
44use prost_types::Any;
55use tonic::Status;
66
7use crate::auth::errors::AuthError;
7use crate::server::errors::AuthError;
88
99/// 基础设施故障:调用方必须按可重试错误处理,不能当业务结论报告。
1010pub fn is_infrastructure(error: &AuthError) -> bool {
Renamed lib/identity/src/auth/grpc/identity.rs → lib/auth/src/server/grpc/identity.rs View lib/auth/src/server/grpc/identity.rs
@@ -11,11 +11,11 @@
1111use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};
1212use tonic::{Request, Response, Status};
1313
14use crate::auth::AuthSvc;
15use crate::auth::access_token::types::AccessTokenAuthRequest;
16use crate::auth::errors::{AuthError, AuthResult};
17use crate::auth::grpc::{context, convert, error, service_token, store};
18use crate::auth::ssh_key::service;
14use crate::server::AuthSvc;
15use crate::server::access_token::types::AccessTokenAuthRequest;
16use crate::server::errors::{AuthError, AuthResult};
17use crate::server::grpc::{context, convert, error, service_token, store};
18use crate::server::ssh_key::service;
1919
2020fn ensure_authorized(
2121 principal: &Principal,
@@ -278,7 +278,7 @@
278278}
279279
280280fn bot_public(user: &users::Model) -> crate::protos::auth::common::v1::UserPublic {
281 crate::auth::grpc::store::user_public(user, String::new(), None)
281 crate::server::grpc::store::user_public(user, String::new(), None)
282282}
283283
284284impl IdentityApi {
@@ -296,23 +296,23 @@
296296 return Err(AuthError::InvalidPassword);
297297 }
298298 if !stored.is_empty() {
299 let check = crate::auth::share::password::verify(
299 let check = crate::server::share::password::verify(
300300 request.old_password_hash.clone(),
301301 stored,
302302 request_id,
303303 )
304304 .await?;
305 if check == crate::auth::share::password::PasswordCheck::Mismatch {
305 if check == crate::server::share::password::PasswordCheck::Mismatch {
306306 return Err(AuthError::InvalidPassword);
307307 }
308308 }
309309
310 crate::auth::share::password::validate_new_password(
310 crate::server::share::password::validate_new_password(
311311 &request.new_password_hash,
312312 &self.svc.auth().password_policy,
313313 )?;
314314 let new_hash =
315 crate::auth::share::password::hash(request.new_password_hash.clone(), request_id)
315 crate::server::share::password::hash(request.new_password_hash.clone(), request_id)
316316 .await?;
317317
318318 let now = store::now();
@@ -356,7 +356,7 @@
356356 if let Err(err) = store::drop_user_session_states(self.svc.cache(), user.id, keep).await {
357357 tracing::warn!(%err, user_id = user.id, "failed to drop revoked sessions");
358358 }
359 crate::auth::me::service::invalidate_me_cache(self.svc.cache(), user.id).await;
359 crate::server::me::service::invalidate_me_cache(self.svc.cache(), user.id).await;
360360
361361 store::audit(
362362 db,
@@ -675,7 +675,7 @@
675675 };
676676 let now = Utc::now();
677677 let password_hash =
678 crate::auth::share::password::hash(format!("bot-{lower}-{now}"), request_id)
678 crate::server::share::password::hash(format!("bot-{lower}-{now}"), request_id)
679679 .await
680680 .map_err(|value| error::status(&value, request_id))?;
681681 let inserted = users::ActiveModel {
Renamed lib/identity/src/auth/grpc/key_rotation.rs → lib/auth/src/server/grpc/key_rotation.rs View lib/auth/src/server/grpc/key_rotation.rs
@@ -8,9 +8,9 @@
88use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter};
99use tonic::{Request, Response, Status};
1010
11use crate::auth::AuthSvc;
12use crate::auth::errors::{AuthError, AuthResult};
13use crate::auth::grpc::{context, error, store};
11use crate::server::AuthSvc;
12use crate::server::errors::{AuthError, AuthResult};
13use crate::server::grpc::{context, error, store};
1414
1515const LEDGER_PREFIX: &str = "auth:key-rotation";
1616const DEFAULT_GRACE_SECS: u64 = 86_400;
Renamed lib/identity/src/auth/grpc/mfa.rs → lib/auth/src/server/grpc/mfa.rs View lib/auth/src/server/grpc/mfa.rs
@@ -8,9 +8,9 @@
88use serde_json::json;
99use tonic::{Request, Response, Status};
1010
11use crate::auth::AuthSvc;
12use crate::auth::errors::{AuthError, AuthResult};
13use crate::auth::grpc::{context, convert, error, store};
11use crate::server::AuthSvc;
12use crate::server::errors::{AuthError, AuthResult};
13use crate::server::grpc::{context, convert, error, store};
1414
1515#[derive(Clone)]
1616pub struct MfaApi {
@@ -114,7 +114,7 @@
114114 for _ in 0..count {
115115 let code = recovery_code();
116116 let normalized = normalize_recovery_code(&code);
117 let code_hash = crate::auth::share::crypto::sha256_hex(normalized.as_bytes());
117 let code_hash = crate::server::share::crypto::sha256_hex(normalized.as_bytes());
118118 user_mfa_backup_codes::ActiveModel {
119119 id: Set(uuid::Uuid::new_v4()),
120120 user_id: Set(user_id),
@@ -140,10 +140,13 @@
140140 if stored.is_empty() {
141141 return Err(AuthError::InvalidPassword);
142142 }
143 let check =
144 crate::auth::share::password::verify(client_digest.to_owned(), stored.to_owned(), None)
145 .await?;
146 if check == crate::auth::share::password::PasswordCheck::Mismatch {
143 let check = crate::server::share::password::verify(
144 client_digest.to_owned(),
145 stored.to_owned(),
146 None,
147 )
148 .await?;
149 if check == crate::server::share::password::PasswordCheck::Mismatch {
147150 return Err(AuthError::InvalidPassword);
148151 }
149152 Ok(())
@@ -189,9 +192,9 @@
189192 .await?;
190193 }
191194
192 let secret = crate::auth::share::totp::generate_secret();
193 let ciphertext = crate::auth::share::totp::encrypt_secret(key, &secret)?;
194 let uri = crate::auth::share::totp::otpauth_uri(&secret, &user.username);
195 let secret = crate::server::share::totp::generate_secret();
196 let ciphertext = crate::server::share::totp::encrypt_secret(key, &secret)?;
197 let uri = crate::server::share::totp::otpauth_uri(&secret, &user.username);
195198 let name = request.name.trim();
196199 let name = if name.is_empty() { "TOTP" } else { name };
197200
@@ -262,9 +265,9 @@
262265 .secret_ciphertext
263266 .as_deref()
264267 .ok_or(AuthError::TotpNotConfigured)?;
265 let secret = crate::auth::share::totp::decrypt_secret(key, ciphertext)?;
268 let secret = crate::server::share::totp::decrypt_secret(key, ciphertext)?;
266269 let (step, value) =
267 crate::auth::share::totp::verify_totp_code(&secret, &request.code, None)?;
270 crate::server::share::totp::verify_totp_code(&secret, &request.code, None)?;
268271 let _ = step;
269272
270273 let now = store::now();
@@ -323,12 +326,12 @@
323326
324327 let code = request.code.trim();
325328 let key = self.svc.auth().totp_encryption_key.as_deref();
326 let consumed = crate::auth::share::mfa::consume_totp(db, &factor, key, code, None)
329 let consumed = crate::server::share::mfa::consume_totp(db, &factor, key, code, None)
327330 .await
328331 .is_ok();
329332 let consumed = match consumed {
330333 true => true,
331 false => crate::auth::share::mfa::consume_recovery(db, user.id, code, None)
334 false => crate::server::share::mfa::consume_recovery(db, user.id, code, None)
332335 .await
333336 .is_ok(),
334337 };
@@ -444,7 +447,7 @@
444447 attempt_count: 0,
445448 });
446449 };
447 match crate::auth::share::mfa::consume_totp(
450 match crate::server::share::mfa::consume_totp(
448451 db,
449452 &factor,
450453 self.svc.auth().totp_encryption_key.as_deref(),
@@ -519,7 +522,7 @@
519522 };
520523
521524 let remaining_before = self.remaining_codes(user.id).await?;
522 match crate::auth::share::mfa::consume_recovery(db, user.id, &request.code, request_id)
525 match crate::server::share::mfa::consume_recovery(db, user.id, &request.code, request_id)
523526 .await
524527 {
525528 Ok(()) => {}
@@ -575,8 +578,8 @@
575578}
576579
577580fn recovery_code() -> String {
578 let left = crate::auth::share::crypto::random_alnum(6);
579 let right = crate::auth::share::crypto::random_alnum(6);
581 let left = crate::server::share::crypto::random_alnum(6);
582 let right = crate::server::share::crypto::random_alnum(6);
580583 format!("{left}-{right}")
581584}
582585
Renamed lib/identity/src/auth/grpc/mod.rs → lib/auth/src/server/grpc/mod.rs View lib/auth/src/server/grpc/mod.rs
@@ -28,22 +28,22 @@
2828use tonic_reflection::server::Builder as ReflectionBuilder;
2929use tower::layer::util::{Identity, Stack};
3030
31use crate::auth::AuthSvc;
32use crate::auth::grpc::access_key::AccessKeyApi;
33use crate::auth::grpc::agreement::AgreementApi;
34use crate::auth::grpc::audit::AuditApi;
35use crate::auth::grpc::authority::AuthorityApi;
36use crate::auth::grpc::authorization::AuthorizationApi;
37use crate::auth::grpc::cache_maintenance::CacheMaintenanceApi;
38use crate::auth::grpc::client::ClientApi;
39use crate::auth::grpc::email::EmailApi;
40use crate::auth::grpc::identity::IdentityApi;
41use crate::auth::grpc::key_rotation::KeyRotationApi;
42use crate::auth::grpc::mfa::MfaApi;
43use crate::auth::grpc::organization::{OrganizationAdminApi, OrganizationApi};
44use crate::auth::grpc::session::SessionApi;
45use crate::auth::grpc::ssh_key::SshKeyApi;
46use crate::auth::grpc::token::TokenApi;
31use crate::server::AuthSvc;
32use crate::server::grpc::access_key::AccessKeyApi;
33use crate::server::grpc::agreement::AgreementApi;
34use crate::server::grpc::audit::AuditApi;
35use crate::server::grpc::authority::AuthorityApi;
36use crate::server::grpc::authorization::AuthorizationApi;
37use crate::server::grpc::cache_maintenance::CacheMaintenanceApi;
38use crate::server::grpc::client::ClientApi;
39use crate::server::grpc::email::EmailApi;
40use crate::server::grpc::identity::IdentityApi;
41use crate::server::grpc::key_rotation::KeyRotationApi;
42use crate::server::grpc::mfa::MfaApi;
43use crate::server::grpc::organization::{OrganizationAdminApi, OrganizationApi};
44use crate::server::grpc::session::SessionApi;
45use crate::server::grpc::ssh_key::SshKeyApi;
46use crate::server::grpc::token::TokenApi;
4747
4848pub const DEFAULT_MAX_MESSAGE_SIZE: usize = 4 * 1024 * 1024;
4949pub const HEALTH_SERVICE: &str = "";
Renamed lib/identity/src/auth/grpc/organization.rs → lib/auth/src/server/grpc/organization.rs View lib/auth/src/server/grpc/organization.rs
@@ -7,15 +7,6 @@
77use tonic::{Request, Response, Status};
88use uuid::Uuid;
99
10use crate::auth::AuthSvc;
11use crate::auth::errors::{AuthError, AuthResult};
12use crate::auth::grpc::{context, convert, error, store};
13use crate::auth::organization::types::{
14 AddMemberBody, CreateOrganizationBody, CreateRoleBody, JoinRequestSummary, JoinRuleSummary,
15 MAX_BATCH_PERMISSIONS, PermissionGrant, SetMemberRoleBody, SetRolePermissionsBody,
16 UpdateBanBody, UpdateMemberBody, UpdateOrganizationBody,
17};
18use crate::auth::organization::{member, role, service};
1910use crate::models::space::{
2011 MessageNotifications as DomainNotifications, OrgJoinMethod as DomainJoin,
2112 OrgMemberRole as DomainRole, OrganizationJoinPolicy as DomainJoinPolicy,
@@ -40,6 +31,15 @@
4031 OrganizationJoinMethod as OrgJoinMethodProto, OrganizationMemberRole as OrgMemberRoleProto,
4132 OrganizationStatus as OrganizationStatusProto, PermissionEffect as PermissionEffectProto, *,
4233};
34use crate::server::AuthSvc;
35use crate::server::errors::{AuthError, AuthResult};
36use crate::server::grpc::{context, convert, error, store};
37use crate::server::organization::types::{
38 AddMemberBody, CreateOrganizationBody, CreateRoleBody, JoinRequestSummary, JoinRuleSummary,
39 MAX_BATCH_PERMISSIONS, PermissionGrant, SetMemberRoleBody, SetRolePermissionsBody,
40 UpdateBanBody, UpdateMemberBody, UpdateOrganizationBody,
41};
42use crate::server::organization::{member, role, service};
4343
4444fn uuid_of(value: &str, request_id: Option<&str>) -> Result<Uuid, Status> {
4545 Uuid::parse_str(value.trim())
@@ -98,7 +98,7 @@
9898 }
9999}
100100
101fn org_info(summary: crate::auth::organization::types::OrganizationSummary) -> OrganizationInfo {
101fn org_info(summary: crate::server::organization::types::OrganizationSummary) -> OrganizationInfo {
102102 OrganizationInfo {
103103 id: summary.id.to_string(),
104104 slug: summary.slug,
@@ -124,7 +124,9 @@
124124 }
125125}
126126
127fn member_info(summary: crate::auth::organization::types::MemberSummary) -> OrganizationMemberInfo {
127fn member_info(
128 summary: crate::server::organization::types::MemberSummary,
129) -> OrganizationMemberInfo {
128130 OrganizationMemberInfo {
129131 id: summary.id.to_string(),
130132 organization_id: summary.organization_id.to_string(),
@@ -159,7 +161,7 @@
159161 }
160162}
161163
162fn role_info(summary: crate::auth::organization::types::RoleSummary) -> OrganizationRoleInfo {
164fn role_info(summary: crate::server::organization::types::RoleSummary) -> OrganizationRoleInfo {
163165 OrganizationRoleInfo {
164166 id: summary.id.to_string(),
165167 organization_id: summary.organization_id.to_string(),
@@ -189,7 +191,9 @@
189191 }
190192}
191193
192fn invite_info(summary: crate::auth::organization::types::InviteSummary) -> OrganizationInviteInfo {
194fn invite_info(
195 summary: crate::server::organization::types::InviteSummary,
196) -> OrganizationInviteInfo {
193197 OrganizationInviteInfo {
194198 id: summary.id.to_string(),
195199 organization_id: summary.organization_id.to_string(),
Renamed lib/identity/src/auth/grpc/service_token.rs → lib/auth/src/server/grpc/service_token.rs View lib/auth/src/server/grpc/service_token.rs
@@ -1,8 +1,8 @@
11use crate::protos::auth::common::v1::TokenAudience;
22use serde::{Deserialize, Serialize};
33
4use crate::auth::errors::{AuthError, AuthResult};
5use crate::auth::share::crypto;
4use crate::server::errors::{AuthError, AuthResult};
5use crate::server::share::crypto;
66
77pub const DEFAULT_TTL_SECS: u32 = 900;
88pub const MAX_TTL_SECS: u32 = 3600;
@@ -110,14 +110,14 @@
110110}
111111
112112pub fn issue(
113 signing: &crate::auth::keys::SigningState,
113 signing: &crate::server::keys::SigningState,
114114 claims: &ServiceTokenClaims,
115115) -> AuthResult<String> {
116116 signing.sign(claims)
117117}
118118
119119pub fn issue_claims<T: Serialize>(
120 signing: &crate::auth::keys::SigningState,
120 signing: &crate::server::keys::SigningState,
121121 claims: &T,
122122) -> AuthResult<String> {
123123 signing.sign(claims)
Renamed lib/identity/src/auth/grpc/session.rs → lib/auth/src/server/grpc/session.rs View lib/auth/src/server/grpc/session.rs
@@ -7,9 +7,9 @@
77use tonic::{Request, Response, Status};
88use uuid::Uuid;
99
10use crate::auth::AuthSvc;
11use crate::auth::errors::AuthError;
12use crate::auth::grpc::{context, convert, error, store};
10use crate::server::AuthSvc;
11use crate::server::errors::AuthError;
12use crate::server::grpc::{context, convert, error, store};
1313
1414pub const MAX_LIST_PAGE: u64 = 100;
1515pub const SESSION_LIST_MAX: usize = 200;
@@ -271,7 +271,8 @@
271271 .exec(self.svc.db().write())
272272 .await
273273 .map_err(|err| error::status(&AuthError::from(err), request_id))?;
274 crate::auth::me::service::invalidate_me_cache(self.svc.cache(), request.user_id).await;
274 crate::server::me::service::invalidate_me_cache(self.svc.cache(), request.user_id)
275 .await;
275276 security_version = store::load_user(self.svc.db(), request.user_id)
276277 .await
277278 .map_err(|err| error::status(&err, request_id))?
@@ -326,7 +327,7 @@
326327 revoked_sessions = revoked.rows_affected as u32;
327328 }
328329
329 crate::auth::me::service::invalidate_me_cache(self.svc.cache(), request.user_id).await;
330 crate::server::me::service::invalidate_me_cache(self.svc.cache(), request.user_id).await;
330331 store::audit(
331332 self.svc.db(),
332333 request.user_id,
Renamed lib/identity/src/auth/grpc/ssh_key.rs → lib/auth/src/server/grpc/ssh_key.rs View lib/auth/src/server/grpc/ssh_key.rs
@@ -8,9 +8,9 @@
88use tonic::{Request, Response, Status};
99use uuid::Uuid;
1010
11use crate::auth::AuthSvc;
12use crate::auth::errors::AuthError;
13use crate::auth::grpc::{context, convert, error, store};
11use crate::server::AuthSvc;
12use crate::server::errors::AuthError;
13use crate::server::grpc::{context, convert, error, store};
1414
1515#[derive(Clone)]
1616pub struct SshKeyApi {
@@ -109,7 +109,7 @@
109109 request_id,
110110 ));
111111 }
112 crate::auth::ssh_key::service::parse_public_key(public_key)
112 crate::server::ssh_key::service::parse_public_key(public_key)
113113 .map_err(|err| error::status(&err, request_id))?
114114 .1
115115 } else {
@@ -166,7 +166,7 @@
166166 .svc
167167 .add_ssh_key_for_user(
168168 request.user_id,
169 crate::auth::ssh_key::types::SshKeyAddRequest {
169 crate::server::ssh_key::types::SshKeyAddRequest {
170170 name: request.name,
171171 description: Some(request.description).filter(|text| !text.is_empty()),
172172 public_key: request.public_key,
@@ -313,7 +313,8 @@
313313 .map_err(|err| error::status(&AuthError::from(err), request_id))?;
314314
315315 if request.bump_security_version {
316 crate::auth::me::service::invalidate_me_cache(self.svc.cache(), request.user_id).await;
316 crate::server::me::service::invalidate_me_cache(self.svc.cache(), request.user_id)
317 .await;
317318 }
318319
319320 if let Err(err) = store::audit(
Renamed lib/identity/src/auth/grpc/store.rs → lib/auth/src/server/grpc/store.rs View lib/auth/src/server/grpc/store.rs
@@ -7,11 +7,11 @@
77use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
88use uuid::Uuid;
99
10use crate::auth::access_token::types::ALLOWED_APP_SCOPES;
11use crate::auth::errors::{AuthError, AuthResult};
12use crate::auth::grpc::context::RequestMeta;
13use crate::auth::grpc::convert;
14use crate::auth::share::user as user_store;
10use crate::server::access_token::types::ALLOWED_APP_SCOPES;
11use crate::server::errors::{AuthError, AuthResult};
12use crate::server::grpc::context::RequestMeta;
13use crate::server::grpc::convert;
14use crate::server::share::user as user_store;
1515
1616pub const MAX_BATCH_USER_IDS: usize = 500;
1717
@@ -197,7 +197,7 @@
197197 client_ip: Option<String>,
198198 user_agent: Option<String>,
199199) -> AuthResult<()> {
200 crate::auth::share::audit::entry(
200 crate::server::share::audit::entry(
201201 db,
202202 user_id,
203203 actor_user_id,
@@ -240,7 +240,7 @@
240240}
241241
242242pub fn sha256_digest(value: &str) -> String {
243 crate::auth::share::crypto::sha256_hex(value.as_bytes())
243 crate::server::share::crypto::sha256_hex(value.as_bytes())
244244}
245245
246246pub fn new_id() -> Uuid {
Renamed lib/identity/src/auth/grpc/token.rs → lib/auth/src/server/grpc/token.rs View lib/auth/src/server/grpc/token.rs
@@ -10,11 +10,11 @@
1010use serde::{Deserialize, Serialize};
1111use tonic::{Request, Response, Status};
1212
13use crate::auth::AuthSvc;
14use crate::auth::access_token::types::{ALLOWED_APP_SCOPES, AccessTokenAuthRequest};
15use crate::auth::errors::AuthError;
16use crate::auth::grpc::{context, convert, error, service_token, store};
17use crate::auth::share::crypto;
13use crate::server::AuthSvc;
14use crate::server::access_token::types::{ALLOWED_APP_SCOPES, AccessTokenAuthRequest};
15use crate::server::errors::AuthError;
16use crate::server::grpc::{context, convert, error, service_token, store};
17use crate::server::share::crypto;
1818
1919const REVOKED_PREFIX: &str = "auth:svc-token:revoked:";
2020const META_PREFIX: &str = "auth:svc-token:meta:";
Renamed lib/identity/src/auth/login/handler.rs → lib/auth/src/server/login/handler.rs View lib/auth/src/server/login/handler.rs
@@ -1,11 +1,11 @@
11use crate::session::{RequestId, Session};
22use actix_web::web;
33
4use crate::auth::AuthSvc;
5use crate::auth::errors::AuthError;
64use crate::envelope::{Envelope, NoData};
5use crate::server::AuthSvc;
6use crate::server::errors::AuthError;
77
8use crate::auth::login::types::{
8use crate::server::login::types::{
99 LoginCodeRequest, LoginCodeResponse, LoginCodeVerifyRequest, LoginVerifyRequest,
1010 UserLoginRequest, UserLoginResponse,
1111};
Renamed lib/identity/src/auth/login/mod.rs → lib/auth/src/server/login/mod.rs View lib/auth/src/server/login/mod.rs

No content changes.

Renamed lib/identity/src/auth/login/service.rs → lib/auth/src/server/login/service.rs View lib/auth/src/server/login/service.rs
@@ -6,18 +6,18 @@
66use sea_orm::sea_query::{Expr, ExprTrait, Func};
77use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter};
88
9use crate::auth::AuthSvc;
10use crate::auth::errors::{AuthError, AuthResult};
11use crate::auth::login::types::{
9use crate::server::AuthSvc;
10use crate::server::errors::{AuthError, AuthResult};
11use crate::server::login::types::{
1212 LOGIN_ATTEMPTS_MAX, LOGIN_ATTEMPTS_WINDOW_SECS, LoginCodeRequest, LoginCodeResponse,
1313 LoginCodeVerifyRequest, LoginMfaChallenge, LoginVerifyRequest, MFA_CHALLENGE_TTL_SECS,
1414 SESSION_LOGIN_MFA, UserLoginRequest, UserLoginResponse,
1515};
16use crate::auth::share::codes::{consume_email_code, store_email_code};
17use crate::auth::share::crypto::{now_secs, random_alnum, random_numeric_code};
18use crate::auth::share::password::{self, PasswordCheck};
19use crate::auth::share::rate::{attempts_load, attempts_reset, attempts_track, rate_limit_once};
20use crate::auth::share::validate;
16use crate::server::share::codes::{consume_email_code, store_email_code};
17use crate::server::share::crypto::{now_secs, random_alnum, random_numeric_code};
18use crate::server::share::password::{self, PasswordCheck};
19use crate::server::share::rate::{attempts_load, attempts_reset, attempts_track, rate_limit_once};
20use crate::server::share::validate;
2121
2222pub(crate) fn login_code_key(user_id: i64) -> String {
2323 format!("auth:code:login:{user_id}")
@@ -47,7 +47,7 @@
4747 let ip_key = format!(
4848 "auth:rate:login:ip:{}:{}",
4949 client_ip,
50 &crate::auth::share::crypto::sha256_hex(identity.as_bytes())[..16]
50 &crate::server::share::crypto::sha256_hex(identity.as_bytes())[..16]
5151 );
5252 let ip_allowed = attempts_track(
5353 self.cache(),
@@ -61,7 +61,7 @@
6161 Some(user) => format!("auth:rate:login:attempts:{}", user.id),
6262 None => {
6363 // identity 截断后哈希,防任意长度输入撑大 Redis key。
64 let identity_digest = crate::auth::share::crypto::sha256_hex(identity.as_bytes());
64 let identity_digest = crate::server::share::crypto::sha256_hex(identity.as_bytes());
6565 format!(
6666 "auth:rate:login:attempts:anon:{client_ip}:{}",
6767 &identity_digest[..16]
@@ -404,7 +404,7 @@
404404 .exec(self.db().write())
405405 .await?;
406406
407 crate::auth::me::service::invalidate_me_cache(self.cache(), user.id).await;
407 crate::server::me::service::invalidate_me_cache(self.cache(), user.id).await;
408408 self.audit(
409409 session,
410410 user.id,
@@ -431,7 +431,7 @@
431431 .ok_or(AuthError::MfaRequired)?;
432432
433433 if record.mfa_type == MfaType::Totp && record.secret_ciphertext.is_some() {
434 match crate::auth::share::mfa::consume_totp(
434 match crate::server::share::mfa::consume_totp(
435435 self.db(),
436436 &record,
437437 self.auth().totp_encryption_key.as_deref(),
@@ -450,7 +450,7 @@
450450 }
451451
452452 async fn consume_recovery_code(&self, user_id: i64, code: &str) -> AuthResult<()> {
453 crate::auth::share::mfa::consume_recovery(self.db(), user_id, code, None).await
453 crate::server::share::mfa::consume_recovery(self.db(), user_id, code, None).await
454454 }
455455
456456 async fn enabled_mfa(&self, user_id: i64) -> AuthResult<Option<user_mfa::Model>> {
@@ -532,7 +532,7 @@
532532 details: Option<serde_json::Value>,
533533 request_id: &str,
534534 ) -> AuthResult<()> {
535 crate::auth::share::audit::entry(
535 crate::server::share::audit::entry(
536536 self.db(),
537537 user_id,
538538 actor_user_id,
Renamed lib/identity/src/auth/login/types.rs → lib/auth/src/server/login/types.rs View lib/auth/src/server/login/types.rs
@@ -1,7 +1,7 @@
11use serde::{Deserialize, Serialize};
22use utoipa::ToSchema;
33
4use crate::auth::challenge::types::PowProofRequest;
4use crate::server::challenge::types::PowProofRequest;
55
66pub const SESSION_LOGIN_MFA: &str = "login_mfa";
77pub const HASH_KEY_SHA256_V1: &str = "sha256-v1";
Renamed lib/identity/src/auth/logout/handler.rs → lib/auth/src/server/logout/handler.rs View lib/auth/src/server/logout/handler.rs
@@ -1,10 +1,10 @@
11use crate::session::{RequestId, Session};
22use actix_web::web;
33
4use crate::auth::AuthSvc;
5use crate::auth::errors::AuthError;
6use crate::auth::logout::types::LogoutResponse;
74use crate::envelope::{Envelope, NoData};
5use crate::server::AuthSvc;
6use crate::server::errors::AuthError;
7use crate::server::logout::types::LogoutResponse;
88
99#[utoipa::path(
1010 post,
Renamed lib/identity/src/auth/logout/mod.rs → lib/auth/src/server/logout/mod.rs View lib/auth/src/server/logout/mod.rs

No content changes.

Renamed lib/identity/src/auth/logout/service.rs → lib/auth/src/server/logout/service.rs View lib/auth/src/server/logout/service.rs
@@ -3,9 +3,9 @@
33use crate::session::Session;
44use sea_orm::Set;
55
6use crate::auth::AuthSvc;
7use crate::auth::errors::AuthResult;
8use crate::auth::logout::types::LogoutResponse;
6use crate::server::AuthSvc;
7use crate::server::errors::AuthResult;
8use crate::server::logout::types::LogoutResponse;
99
1010impl AuthSvc {
1111 #[tracing::instrument(skip_all, fields(request_id = %request_id, client_ip = ?session.client_ip().ok().flatten()))]
@@ -53,8 +53,8 @@
5353 }
5454
5555 if let Some(uid) = user_id {
56 crate::auth::me::service::invalidate_me_cache(self.cache(), uid).await;
57 if let Err(error) = crate::auth::share::audit::entry(
56 crate::server::me::service::invalidate_me_cache(self.cache(), uid).await;
57 if let Err(error) = crate::server::share::audit::entry(
5858 self.db(),
5959 uid,
6060 Some(uid),
Renamed lib/identity/src/auth/logout/types.rs → lib/auth/src/server/logout/types.rs View lib/auth/src/server/logout/types.rs

No content changes.

Renamed lib/identity/src/auth/me/handler.rs → lib/auth/src/server/me/handler.rs View lib/auth/src/server/me/handler.rs
@@ -1,10 +1,10 @@
11use crate::session::{RequestId, Session};
22use actix_web::{HttpRequest, web};
33
4use crate::auth::AuthSvc;
5use crate::auth::errors::AuthError;
6use crate::auth::me::types::MeResponse;
74use crate::envelope::{Envelope, NoData};
5use crate::server::AuthSvc;
6use crate::server::errors::AuthError;
7use crate::server::me::types::MeResponse;
88
99/// 鉴权失败一律映射成 401/503:`JwtError::Config`/`Internal` 是服务端/配置故障,
1010/// 直接报 401 会让运维把可用性故障当成用户凭证问题。
Renamed lib/identity/src/auth/me/mod.rs → lib/auth/src/server/me/mod.rs View lib/auth/src/server/me/mod.rs

No content changes.

Renamed lib/identity/src/auth/me/service.rs → lib/auth/src/server/me/service.rs View lib/auth/src/server/me/service.rs
@@ -5,9 +5,9 @@
55use crate::session::Session;
66use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
77
8use crate::auth::AuthSvc;
9use crate::auth::errors::{AuthError, AuthResult};
10use crate::auth::me::types::MeResponse;
8use crate::server::AuthSvc;
9use crate::server::errors::{AuthError, AuthResult};
10use crate::server::me::types::MeResponse;
1111
1212pub const ME_CACHE_TTL_SECS: u64 = 300;
1313const ME_COUNT_TTL_SECS: u64 = 600;
Renamed lib/identity/src/auth/me/types.rs → lib/auth/src/server/me/types.rs View lib/auth/src/server/me/types.rs

No content changes.

Renamed lib/identity/src/auth/oauth/consent.rs → lib/auth/src/server/oauth/consent.rs View lib/auth/src/server/oauth/consent.rs
@@ -9,9 +9,9 @@
99use serde::{Deserialize, Serialize};
1010use utoipa::ToSchema;
1111
12use crate::auth::AuthSvc;
13use crate::auth::errors::AuthResult;
1412use crate::models::users::oauth_consents as consents;
13use crate::server::AuthSvc;
14use crate::server::errors::AuthResult;
1515
1616async fn load(svc: &AuthSvc, user_id: i64, client_id: &str) -> AuthResult<Option<consents::Model>> {
1717 Ok(consents::Entity::find()
@@ -208,7 +208,7 @@
208208 svc: web::Data<AuthSvc>,
209209 session: crate::session::Session,
210210 request_id: crate::session::RequestId,
211 query: Result<web::Query<crate::auth::protocol::AuthorizeRequest>, actix_web::Error>,
211 query: Result<web::Query<crate::server::protocol::AuthorizeRequest>, actix_web::Error>,
212212) -> HttpResponse {
213213 let Ok(query) = query else {
214214 return bad_request("invalid_request");
@@ -269,7 +269,7 @@
269269 session: crate::session::Session,
270270 req: actix_web::HttpRequest,
271271 request_id: crate::session::RequestId,
272 query: Result<web::Query<crate::auth::protocol::AuthorizeRequest>, actix_web::Error>,
272 query: Result<web::Query<crate::server::protocol::AuthorizeRequest>, actix_web::Error>,
273273 form: Result<web::Form<ConsentForm>, actix_web::Error>,
274274) -> HttpResponse {
275275 let (Ok(query), Ok(form)) = (query, form) else {
Renamed lib/identity/src/auth/oauth/id_token.rs → lib/auth/src/server/oauth/id_token.rs View lib/auth/src/server/oauth/id_token.rs
@@ -5,7 +5,7 @@
55use serde::Serialize;
66use sha2::{Digest, Sha512};
77
8use crate::auth::{AuthResult, AuthSvc};
8use crate::server::{AuthResult, AuthSvc};
99
1010/// EdDSA 底层是 SHA-512:`at_hash` 取哈希左半再 base64url 无填充(OIDC Core 3.1.3.6)。
1111pub fn at_hash(access_token: &str) -> String {
Renamed lib/identity/src/auth/oauth/logout.rs → lib/auth/src/server/oauth/logout.rs View lib/auth/src/server/oauth/logout.rs
@@ -13,7 +13,7 @@
1313use serde::{Deserialize, Serialize};
1414use uuid::Uuid;
1515
16use crate::auth::AuthSvc;
16use crate::server::AuthSvc;
1717use crate::session::{RequestId, Session};
1818
1919/// 反向通道注销的 events 键(OIDC Back-Channel Logout 1.0 §2.4)。
@@ -170,7 +170,7 @@
170170 // 3. 撤销会话与刷新令牌。
171171 if let Some(id) = session_id
172172 && let Err(error) =
173 crate::auth::oauth::refresh::revoke_session(&svc, id, Some(request_id.as_str())).await
173 crate::server::oauth::refresh::revoke_session(&svc, id, Some(request_id.as_str())).await
174174 {
175175 tracing::warn!(%error, %id, "failed to revoke oauth session tokens during logout");
176176 }
@@ -213,7 +213,7 @@
213213 svc: &AuthSvc,
214214 session_id: &str,
215215 user_id: i64,
216 client: Option<&crate::auth::client::ClientRecord>,
216 client: Option<&crate::server::client::ClientRecord>,
217217 request_id: Option<&str>,
218218) {
219219 let targets: Vec<(String, Vec<String>)> = svc
Renamed lib/identity/src/auth/oauth/mod.rs → lib/auth/src/server/oauth/mod.rs View lib/auth/src/server/oauth/mod.rs
@@ -1,6 +1,6 @@
11//! OIDC 扩展:id_token、userinfo、consent、refresh token、单点登出。
22//!
3//! OAuth 2.0 的授权码流程仍在 `crate::auth::protocol`,这里只补 OIDC 需要的额外产物。
3//! OAuth 2.0 的授权码流程仍在 `crate::server::protocol`,这里只补 OIDC 需要的额外产物。
44
55pub mod consent;
66pub mod id_token;
Renamed lib/identity/src/auth/oauth/refresh.rs → lib/auth/src/server/oauth/refresh.rs View lib/auth/src/server/oauth/refresh.rs
@@ -6,10 +6,10 @@
66};
77use uuid::Uuid;
88
9use crate::auth::AuthSvc;
10use crate::auth::errors::{AuthError, AuthResult};
11use crate::auth::share::crypto::{random_b64url, sha256_hex};
129use crate::models::users::{oauth_refresh_tokens as tokens, user_sessions};
10use crate::server::AuthSvc;
11use crate::server::errors::{AuthError, AuthResult};
12use crate::server::share::crypto::{random_b64url, sha256_hex};
1313
1414/// 明文令牌长度:48 字节随机 → 64 字符 base64url。
1515const TOKEN_BYTES: usize = 48;
Renamed lib/identity/src/auth/oauth/userinfo.rs → lib/auth/src/server/oauth/userinfo.rs View lib/auth/src/server/oauth/userinfo.rs
@@ -5,7 +5,7 @@
55use actix_web::{HttpRequest, HttpResponse, web};
66use serde_json::json;
77
8use crate::auth::AuthSvc;
8use crate::server::AuthSvc;
99
1010/// 只接受 `Authorization: Bearer` 头承载令牌(RFC 6750 §2.3:查询串会被日志/代理记录,禁止)。
1111fn bearer(req: &HttpRequest) -> Option<String> {
Renamed lib/identity/src/auth/organization/error.rs → lib/auth/src/server/organization/error.rs View lib/auth/src/server/organization/error.rs
@@ -1,4 +1,4 @@
1use crate::auth::errors::AuthError;
1use crate::server::errors::AuthError;
22
33pub(crate) fn reason_error(reason: &'static str, permission: &str) -> AuthError {
44 match reason {
Renamed lib/identity/src/auth/organization/handler.rs → lib/auth/src/server/organization/handler.rs View lib/auth/src/server/organization/handler.rs
@@ -1,15 +1,15 @@
11use actix_web::web;
22use uuid::Uuid;
33
4use crate::auth::AuthSvc;
5use crate::auth::errors::AuthError;
6use crate::auth::organization::types::{
4use crate::envelope::{Envelope, NoData};
5use crate::server::AuthSvc;
6use crate::server::errors::AuthError;
7use crate::server::organization::types::{
78 AddMemberBody, BanMemberBody, CheckPermissionBody, CreateOrganizationBody, CreateRoleBody,
89 InviteSummary, MemberSummary, OrganizationSummary, PermissionCheck, PermissionGrant,
910 RoleSummary, SetMemberRoleBody, SetRolePermissionsBody, UpdateBanBody, UpdateMemberBody,
1011 UpdateOrganizationBody,
1112};
12use crate::envelope::{Envelope, NoData};
1313use crate::session::{RequestId, Session};
1414
1515#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
Renamed lib/identity/src/auth/organization/invite.rs → lib/auth/src/server/organization/invite.rs View lib/auth/src/server/organization/invite.rs
@@ -7,19 +7,19 @@
77};
88use uuid::Uuid;
99
10use crate::auth::AuthSvc;
11use crate::auth::errors::{AuthError, AuthResult};
12use crate::auth::organization::member;
13use crate::auth::organization::service::{bump_version, normalize_reason};
14use crate::auth::organization::types::{
15 DEFAULT_INVITE_TTL_SECS, InviteSummary, SYSTEM_ROLE_MEMBER, SYSTEM_ROLE_OWNER,
16};
17use crate::auth::share::crypto;
1810use crate::events::{OrganizationEvent, RestOperate};
1911use crate::models::space::{
2012 OrgJoinMethod, OrgMemberRole, OrganizationStatus, organization_invite_redemptions,
2113 organization_invites, organization_roles,
2214};
15use crate::server::AuthSvc;
16use crate::server::errors::{AuthError, AuthResult};
17use crate::server::organization::member;
18use crate::server::organization::service::{bump_version, normalize_reason};
19use crate::server::organization::types::{
20 DEFAULT_INVITE_TTL_SECS, InviteSummary, SYSTEM_ROLE_MEMBER, SYSTEM_ROLE_OWNER,
21};
22use crate::server::share::crypto;
2323
2424impl AuthSvc {
2525 #[allow(clippy::too_many_arguments)]
@@ -98,7 +98,7 @@
9898 }
9999 }
100100 let email = email
101 .map(|value| crate::auth::share::validate::validate_email(&value))
101 .map(|value| crate::server::share::validate::validate_email(&value))
102102 .transpose()?;
103103 let method = match target_user_id {
104104 Some(user_id) => {
@@ -354,7 +354,7 @@
354354 if let Some(role) = role
355355 && role.key != SYSTEM_ROLE_OWNER
356356 {
357 crate::auth::organization::role::bind_role(&txn, row.id, role.id, invite.created_by)
357 crate::server::organization::role::bind_role(&txn, row.id, role.id, invite.created_by)
358358 .await?;
359359 }
360360 if let Some(extra) = invite.extra_role_ids.as_deref() {
@@ -372,7 +372,7 @@
372372 if role.key == SYSTEM_ROLE_OWNER || role.key == SYSTEM_ROLE_MEMBER {
373373 continue;
374374 }
375 crate::auth::organization::role::bind_role(
375 crate::server::organization::role::bind_role(
376376 &txn,
377377 row.id,
378378 role.id,
Renamed lib/identity/src/auth/organization/join.rs → lib/auth/src/server/organization/join.rs View lib/auth/src/server/organization/join.rs
@@ -6,16 +6,16 @@
66};
77use uuid::Uuid;
88
9use crate::auth::organization::types::{
10 AddMemberBody, JoinRequestSummary, JoinRuleSummary, SYSTEM_ROLE_MEMBER, SYSTEM_ROLE_OWNER,
11};
12use crate::auth::organization::{member, service};
13use crate::auth::{AuthError, AuthResult, AuthSvc};
149use crate::models::space::{
1510 OrgJoinMethod, OrgMemberRole, OrganizationJoinRequestStatus, organization_join_requests,
1611 organization_join_rules, organization_members, organization_roles, organizations,
1712};
1813use crate::models::users::users;
14use crate::server::organization::types::{
15 AddMemberBody, JoinRequestSummary, JoinRuleSummary, SYSTEM_ROLE_MEMBER, SYSTEM_ROLE_OWNER,
16};
17use crate::server::organization::{member, service};
18use crate::server::{AuthError, AuthResult, AuthSvc};
1919
2020fn rule_summary(row: &organization_join_rules::Model) -> JoinRuleSummary {
2121 JoinRuleSummary {
@@ -400,7 +400,7 @@
400400 role_keys: Vec<String>,
401401 role_ids: Vec<String>,
402402 request_id: Option<&str>,
403 ) -> AuthResult<(crate::auth::organization::types::MemberSummary, bool)> {
403 ) -> AuthResult<(crate::server::organization::types::MemberSummary, bool)> {
404404 let txn = self.db().write().begin().await?;
405405 // 机器人成员的角色上限:OWNER 只能由人类走成员面转移,不能通过内部接口直接塞入。
406406 let user = crate::models::users::users::Entity::find_by_id(user_id)
Renamed lib/identity/src/auth/organization/member.rs → lib/auth/src/server/organization/member.rs View lib/auth/src/server/organization/member.rs
@@ -7,19 +7,19 @@
77};
88use uuid::Uuid;
99
10use crate::auth::AuthSvc;
11use crate::auth::errors::{AuthError, AuthResult};
12use crate::auth::organization::role;
13use crate::auth::organization::service::{bump_version, normalize_reason};
14use crate::auth::organization::types::{
15 AddMemberBody, MAX_ALIAS_AVATAR_URL_LEN, MAX_ALIAS_NAME_LEN, MAX_REASON_LEN, MemberSummary,
16 SetMemberRoleBody, UpdateBanBody, UpdateMemberBody, normalize_alias,
17};
1810use crate::events::{OrganizationEvent, RestOperate};
1911use crate::models::space::{
2012 OrgJoinMethod, OrgMemberRole, organization_member_permissions, organization_members,
2113};
2214use crate::models::users::users;
15use crate::server::AuthSvc;
16use crate::server::errors::{AuthError, AuthResult};
17use crate::server::organization::role;
18use crate::server::organization::service::{bump_version, normalize_reason};
19use crate::server::organization::types::{
20 AddMemberBody, MAX_ALIAS_AVATAR_URL_LEN, MAX_ALIAS_NAME_LEN, MAX_REASON_LEN, MemberSummary,
21 SetMemberRoleBody, UpdateBanBody, UpdateMemberBody, normalize_alias,
22};
2323
2424pub(crate) async fn find_any<C: ConnectionTrait>(
2525 db: &C,
Renamed lib/identity/src/auth/organization/mod.rs → lib/auth/src/server/organization/mod.rs View lib/auth/src/server/organization/mod.rs

No content changes.

Renamed lib/identity/src/auth/organization/permission.rs → lib/auth/src/server/organization/permission.rs View lib/auth/src/server/organization/permission.rs
@@ -4,17 +4,17 @@
44use serde::{Deserialize, Serialize};
55use uuid::Uuid;
66
7use crate::auth::AuthSvc;
8use crate::auth::errors::{AuthError, AuthResult};
9use crate::auth::organization::types::{
10 PERMISSION_CACHE_TTL_SECS, PERMISSIONS, PermissionCheck, Resolution, SYSTEM_ROLE_ADMIN,
11 SYSTEM_ROLE_OWNER, is_admin_permission, is_known_permission,
12};
13use crate::auth::organization::{member, role, service};
147use crate::models::space::{
158 OrgMemberRole, PermissionEffect, organization_member_permissions, organization_member_roles,
169 organization_members, organization_role_permissions,
1710};
11use crate::server::AuthSvc;
12use crate::server::errors::{AuthError, AuthResult};
13use crate::server::organization::types::{
14 PERMISSION_CACHE_TTL_SECS, PERMISSIONS, PermissionCheck, Resolution, SYSTEM_ROLE_ADMIN,
15 SYSTEM_ROLE_OWNER, is_admin_permission, is_known_permission,
16};
17use crate::server::organization::{member, role, service};
1818
1919/// 缓存进 Redis 的判定核心。版本号相同的组织共享同一份核心,
2020/// 任何写操作推进 `organizations.version` 都会让整份核心失效。
Renamed lib/identity/src/auth/organization/role.rs → lib/auth/src/server/organization/role.rs View lib/auth/src/server/organization/role.rs
@@ -6,19 +6,19 @@
66};
77use uuid::Uuid;
88
9use crate::auth::AuthSvc;
10use crate::auth::errors::{AuthError, AuthResult};
11use crate::auth::organization::service::{bump_version, normalize_role_key, normalize_role_name};
12use crate::auth::organization::types::{
9use crate::events::{OrganizationEvent, RestOperate};
10use crate::models::space::{
11 PermissionEffect, organization_member_roles, organization_role_permissions, organization_roles,
12};
13use crate::server::AuthSvc;
14use crate::server::errors::{AuthError, AuthResult};
15use crate::server::organization::service::{bump_version, normalize_role_key, normalize_role_name};
16use crate::server::organization::types::{
1317 CreateRoleBody, MemberSummary, PermissionGrant, PermissionGrant as Grant, RoleSummary,
1418 SYSTEM_ROLE_ADMIN, SYSTEM_ROLE_MEMBER, SYSTEM_ROLE_OWNER, SetRolePermissionsBody,
1519 is_known_permission,
16};
17use crate::auth::organization::{error, member};
18use crate::events::{OrganizationEvent, RestOperate};
19use crate::models::space::{
20 PermissionEffect, organization_member_roles, organization_role_permissions, organization_roles,
2120};
21use crate::server::organization::{error, member};
2222
2323/// 内置角色的固有授权。OWNER 不需要显式授权(解析链直接短路),
2424/// ADMIN 的固有集写在 permissions.rs 的白名单里,这里只落 MEMBER 的默认值。
@@ -536,7 +536,7 @@
536536 role_key: &str,
537537 request_id: Option<&str>,
538538 ) -> AuthResult<Vec<String>> {
539 let member = crate::auth::organization::member::load_by_id(
539 let member = crate::server::organization::member::load_by_id(
540540 self.db().read(),
541541 organization_id,
542542 member_id,
@@ -605,7 +605,7 @@
605605 if role.key == SYSTEM_ROLE_OWNER {
606606 return Err(AuthError::OrganizationRoleSystem);
607607 }
608 let member = crate::auth::organization::member::load_by_id(
608 let member = crate::server::organization::member::load_by_id(
609609 self.db().read(),
610610 organization_id,
611611 member_id,
@@ -667,7 +667,7 @@
667667 request_id,
668668 )
669669 .await?;
670 let member = crate::auth::organization::member::load_by_id(
670 let member = crate::server::organization::member::load_by_id(
671671 self.db().read(),
672672 organization_id,
673673 member_id,
Renamed lib/identity/src/auth/organization/service.rs → lib/auth/src/server/organization/service.rs View lib/auth/src/server/organization/service.rs
@@ -7,15 +7,6 @@
77};
88use uuid::Uuid;
99
10use crate::auth::AuthSvc;
11use crate::auth::errors::{AuthError, AuthResult};
12use crate::auth::organization::types::{
13 CreateOrganizationBody, MAX_ORG_DESCRIPTION_LEN, MAX_ORG_NAME_LEN, MAX_PERMISSION_LEN,
14 MAX_ROLE_KEY_LEN, MAX_ROLE_NAME_LEN, MAX_SLUG_LEN, MemberSummary, OrganizationSummary,
15 PermissionGrant, RoleSummary, SYSTEM_ROLE_ADMIN, SYSTEM_ROLE_OWNER, UpdateOrganizationBody,
16 is_known_permission,
17};
18use crate::auth::organization::{error, member, permission, role};
1910use crate::events::{Labels, OrganizationEvent, RestOperate, RuntimeEvent};
2011use crate::models::space::{
2112 OrgMemberRole, OrganizationStatus, PermissionEffect, organization_invite_redemptions,
@@ -23,6 +14,15 @@
2314 organization_members, organization_role_permissions, organization_roles, organizations,
2415};
2516use crate::models::users::users;
17use crate::server::AuthSvc;
18use crate::server::errors::{AuthError, AuthResult};
19use crate::server::organization::types::{
20 CreateOrganizationBody, MAX_ORG_DESCRIPTION_LEN, MAX_ORG_NAME_LEN, MAX_PERMISSION_LEN,
21 MAX_ROLE_KEY_LEN, MAX_ROLE_NAME_LEN, MAX_SLUG_LEN, MemberSummary, OrganizationSummary,
22 PermissionGrant, RoleSummary, SYSTEM_ROLE_ADMIN, SYSTEM_ROLE_OWNER, UpdateOrganizationBody,
23 is_known_permission,
24};
25use crate::server::organization::{error, member, permission, role};
2626
2727pub(crate) fn perm_cache_prefix(organization_id: Uuid, user_id: i64) -> String {
2828 format!("auth:org:perm:{organization_id}:{user_id}")
Renamed lib/identity/src/auth/organization/types.rs → lib/auth/src/server/organization/types.rs View lib/auth/src/server/organization/types.rs

No content changes.

Renamed lib/identity/src/auth/password_reset/handler.rs → lib/auth/src/server/password_reset/handler.rs View lib/auth/src/server/password_reset/handler.rs
@@ -1,11 +1,11 @@
11use crate::session::{RequestId, Session};
22use actix_web::web;
33
4use crate::auth::AuthSvc;
5use crate::auth::errors::AuthError;
64use crate::envelope::{Envelope, NoData};
5use crate::server::AuthSvc;
6use crate::server::errors::AuthError;
77
8use crate::auth::password_reset::types::{
8use crate::server::password_reset::types::{
99 PasswordResetConfirmRequest, PasswordResetConfirmResponse, PasswordResetRequest,
1010 PasswordResetResponse,
1111};
Renamed lib/identity/src/auth/password_reset/mod.rs → lib/auth/src/server/password_reset/mod.rs View lib/auth/src/server/password_reset/mod.rs

No content changes.

Renamed lib/identity/src/auth/password_reset/service.rs → lib/auth/src/server/password_reset/service.rs View lib/auth/src/server/password_reset/service.rs
@@ -5,19 +5,19 @@
55use sea_orm::sea_query::{Expr, ExprTrait, Func};
66use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter};
77
8use crate::auth::AuthSvc;
9use crate::auth::errors::{AuthError, AuthResult};
10use crate::auth::password_reset::types::{
8use crate::models::users::user_events::UserEventType;
9use crate::models::users::user_verification_tokens::{self, VerificationPurpose};
10use crate::models::users::users;
11use crate::server::AuthSvc;
12use crate::server::errors::{AuthError, AuthResult};
13use crate::server::password_reset::types::{
1114 PasswordResetConfirmRequest, PasswordResetConfirmResponse, PasswordResetRequest,
1215 PasswordResetResponse,
1316};
14use crate::auth::share::codes::{consume_email_code, store_email_code};
15use crate::auth::share::crypto::{random_b64url, sha256_hex};
16use crate::auth::share::password::{hash as hash_password, validate_new_password};
17use crate::auth::share::{rate, validate};
18use crate::models::users::user_events::UserEventType;
19use crate::models::users::user_verification_tokens::{self, VerificationPurpose};
20use crate::models::users::users;
17use crate::server::share::codes::{consume_email_code, store_email_code};
18use crate::server::share::crypto::{random_b64url, sha256_hex};
19use crate::server::share::password::{hash as hash_password, validate_new_password};
20use crate::server::share::{rate, validate};
2121
2222const RESET_CODE_KEY_PREFIX: &str = "auth:code:reset:";
2323const RESET_RATE_KEY_PREFIX: &str = "auth:rate:reset:";
@@ -107,7 +107,7 @@
107107 self.publish_mail(&email, subject, &text, &html, Some(request_id.as_str()))
108108 .await?;
109109
110 crate::auth::share::audit::entry(
110 crate::server::share::audit::entry(
111111 self.db(),
112112 user.id,
113113 Some(user.id),
@@ -231,7 +231,7 @@
231231
232232 self.revoke_pending_resets(user.id, now).await?;
233233
234 crate::auth::share::audit::entry(
234 crate::server::share::audit::entry(
235235 self.db(),
236236 user.id,
237237 Some(user.id),
Renamed lib/identity/src/auth/password_reset/types.rs → lib/auth/src/server/password_reset/types.rs View lib/auth/src/server/password_reset/types.rs
@@ -1,7 +1,7 @@
11use serde::{Deserialize, Serialize};
22use utoipa::ToSchema;
33
4use crate::auth::challenge::types::PowProofRequest;
4use crate::server::challenge::types::PowProofRequest;
55
66#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
77pub struct PasswordResetRequest {
Renamed lib/identity/src/auth/pow/hash.rs → lib/auth/src/server/pow/hash.rs View lib/auth/src/server/pow/hash.rs
@@ -1,8 +1,8 @@
11use sha2::{Digest, Sha256};
22
3use crate::auth::challenge::types::{ChallengeResponse, PowProofRequest};
4use crate::auth::errors::{AuthError, AuthResult};
5use crate::auth::share::crypto;
3use crate::server::challenge::types::{ChallengeResponse, PowProofRequest};
4use crate::server::errors::{AuthError, AuthResult};
5use crate::server::share::crypto;
66
77pub fn pow_hash(challenge: &ChallengeResponse, nonce: u64, payload: &[u8]) -> [u8; 32] {
88 let mut hasher = Sha256::new();
Renamed lib/identity/src/auth/pow/mod.rs → lib/auth/src/server/pow/mod.rs View lib/auth/src/server/pow/mod.rs

No content changes.

Renamed lib/identity/src/auth/pow/store.rs → lib/auth/src/server/pow/store.rs View lib/auth/src/server/pow/store.rs
@@ -4,9 +4,9 @@
44use crate::config::pow::PowConfig;
55use crate::session::Session;
66
7use crate::auth::challenge::types::{ChallengeResponse, PowProofRequest, SESSION_CHALLENGE};
8use crate::auth::errors::{AuthError, AuthResult};
9use crate::auth::share::crypto::{now_secs, random_alnum};
7use crate::server::challenge::types::{ChallengeResponse, PowProofRequest, SESSION_CHALLENGE};
8use crate::server::errors::{AuthError, AuthResult};
9use crate::server::share::crypto::{now_secs, random_alnum};
1010
1111pub const USED_KEY_PREFIX: &str = "auth:pow:used:";
1212
@@ -34,7 +34,7 @@
3434 .get::<ChallengeResponse>(SESSION_CHALLENGE)?
3535 .ok_or(AuthError::Expired)?;
3636
37 crate::auth::pow::hash::verify_pow(&challenge, proof, expected_payload)?;
37 crate::server::pow::hash::verify_pow(&challenge, proof, expected_payload)?;
3838
3939 let remaining = challenge.expires_at.saturating_sub(now_secs()).max(1);
4040 let used_key = used_key(&challenge.context);
Renamed lib/identity/src/auth/register/age.rs → lib/auth/src/server/register/age.rs View lib/auth/src/server/register/age.rs
@@ -1,6 +1,6 @@
11use chrono::{Datelike, NaiveDate};
22
3use crate::auth::errors::{AuthError, AuthResult};
3use crate::server::errors::{AuthError, AuthResult};
44
55pub const EARLIEST_BIRTH_YEAR: i32 = 1900;
66
@@ -13,5 +13,5 @@
1313 if parsed.year() < EARLIEST_BIRTH_YEAR {
1414 return Err(AuthError::InvalidBirthDate);
1515 }
16 crate::auth::share::validate::validate_age(Some(parsed), min_age)
16 crate::server::share::validate::validate_age(Some(parsed), min_age)
1717}
Renamed lib/identity/src/auth/register/handler.rs → lib/auth/src/server/register/handler.rs View lib/auth/src/server/register/handler.rs
@@ -1,11 +1,11 @@
11use crate::session::{RequestId, Session};
22use actix_web::web;
33
4use crate::auth::AuthSvc;
5use crate::auth::errors::AuthError;
64use crate::envelope::{Envelope, NoData};
5use crate::server::AuthSvc;
6use crate::server::errors::AuthError;
77
8use crate::auth::register::types::{
8use crate::server::register::types::{
99 RegisterCodeRequest, RegisterCodeResponse, UserRegisterRequest, UserRegisterResponse,
1010};
1111
Renamed lib/identity/src/auth/register/mod.rs → lib/auth/src/server/register/mod.rs View lib/auth/src/server/register/mod.rs

No content changes.

Renamed lib/identity/src/auth/register/service.rs → lib/auth/src/server/register/service.rs View lib/auth/src/server/register/service.rs
@@ -6,18 +6,18 @@
66use sea_orm::sea_query::{Expr, ExprTrait, Func};
77use sea_orm::{ActiveModelTrait, ColumnTrait, Condition, EntityTrait, QueryFilter, SqlErr};
88
9use crate::auth::AuthSvc;
10use crate::auth::errors::{AuthError, AuthResult};
11use crate::auth::register::age;
12use crate::auth::register::types::{
9use crate::models::users::user_events::UserEventType;
10use crate::models::users::users;
11use crate::server::AuthSvc;
12use crate::server::errors::{AuthError, AuthResult};
13use crate::server::register::age;
14use crate::server::register::types::{
1315 RegisterCodeRequest, RegisterCodeResponse, UserRegisterRequest, UserRegisterResponse,
1416};
15use crate::auth::share::codes::{consume_email_code, store_email_code};
16use crate::auth::share::password::{hash as hash_password, validate_new_password};
17use crate::auth::share::validate::{validate_display_name, validate_email, validate_username};
18use crate::auth::share::{crypto, rate};
19use crate::models::users::user_events::UserEventType;
20use crate::models::users::users;
17use crate::server::share::codes::{consume_email_code, store_email_code};
18use crate::server::share::password::{hash as hash_password, validate_new_password};
19use crate::server::share::validate::{validate_display_name, validate_email, validate_username};
20use crate::server::share::{crypto, rate};
2121
2222const REGISTER_CODE_KEY_PREFIX: &str = "auth:code:register:";
2323const REGISTER_RATE_KEY_PREFIX: &str = "auth:rate:register:";
@@ -181,7 +181,7 @@
181181 self.bind_auth_session(&session, &user, false, Some(request_id.as_str()))
182182 .await?;
183183
184 crate::auth::share::audit::entry(
184 crate::server::share::audit::entry(
185185 self.db(),
186186 user.id,
187187 Some(user.id),
Renamed lib/identity/src/auth/register/types.rs → lib/auth/src/server/register/types.rs View lib/auth/src/server/register/types.rs
@@ -1,7 +1,7 @@
11use serde::{Deserialize, Serialize};
22use utoipa::ToSchema;
33
4use crate::auth::challenge::types::PowProofRequest;
4use crate::server::challenge::types::PowProofRequest;
55
66#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
77pub struct RegisterCodeRequest {
Renamed lib/identity/src/auth/share/audit.rs → lib/auth/src/server/share/audit.rs View lib/auth/src/server/share/audit.rs
@@ -6,7 +6,7 @@
66use crate::db::DbConn;
77use crate::models::users::user_events::{self, UserEventType};
88
9use crate::auth::errors::AuthResult;
9use crate::server::errors::AuthResult;
1010
1111/// 写一条用户事件;事件总线之外的持久审计兜底。
1212#[allow(clippy::too_many_arguments)]
Renamed lib/identity/src/auth/share/codes.rs → lib/auth/src/server/share/codes.rs View lib/auth/src/server/share/codes.rs
@@ -2,8 +2,8 @@
22
33use crate::cache::Cache;
44
5use crate::auth::errors::{AuthError, AuthResult};
6use crate::auth::share::crypto;
5use crate::server::errors::{AuthError, AuthResult};
6use crate::server::share::crypto;
77
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
99pub enum CodeAttempt {
Renamed lib/identity/src/auth/share/crypto.rs → lib/auth/src/server/share/crypto.rs View lib/auth/src/server/share/crypto.rs
@@ -9,7 +9,7 @@
99use rand_core::{OsRng, RngCore};
1010use sha2::{Digest, Sha256};
1111
12use crate::auth::errors::{AuthError, AuthResult};
12use crate::server::errors::{AuthError, AuthResult};
1313
1414const NONCE_LEN: usize = 12;
1515
Renamed lib/identity/src/auth/share/issue.rs → lib/auth/src/server/share/issue.rs View lib/auth/src/server/share/issue.rs
@@ -4,10 +4,10 @@
44use chrono::{DateTime, Utc};
55use uuid::Uuid;
66
7use crate::auth::AuthSvc;
8use crate::auth::errors::{AuthError, AuthResult};
9use crate::auth::share::{crypto, user as store};
107use crate::jwt::AppClaims;
8use crate::server::AuthSvc;
9use crate::server::errors::{AuthError, AuthResult};
10use crate::server::share::{crypto, user as store};
1111use crate::session::Session;
1212
1313pub struct IssuedToken {
Renamed lib/identity/src/auth/share/mfa.rs → lib/auth/src/server/share/mfa.rs View lib/auth/src/server/share/mfa.rs
@@ -2,7 +2,7 @@
22use sea_orm::sea_query::{Expr, ExprTrait};
33use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter};
44
5use crate::auth::{AuthError, AuthResult};
5use crate::server::{AuthError, AuthResult};
66
77#[tracing::instrument(skip_all, fields(request_id = %_request_id.unwrap_or_default()))]
88pub async fn consume_totp(
Renamed lib/identity/src/auth/share/mod.rs → lib/auth/src/server/share/mod.rs View lib/auth/src/server/share/mod.rs

No content changes.

Renamed lib/identity/src/auth/share/net.rs → lib/auth/src/server/share/net.rs View lib/auth/src/server/share/net.rs

No content changes.

Renamed lib/identity/src/auth/share/password.rs → lib/auth/src/server/share/password.rs View lib/auth/src/server/share/password.rs
@@ -3,7 +3,7 @@
33
44use crate::config::auth::PasswordPolicy;
55
6use crate::auth::errors::{AuthError, AuthResult};
6use crate::server::errors::{AuthError, AuthResult};
77
88const PHC_PREFIX: &str = "$argon2";
99const CLIENT_DIGEST_LEN: usize = 64;
Renamed lib/identity/src/auth/share/rate.rs → lib/auth/src/server/share/rate.rs View lib/auth/src/server/share/rate.rs
@@ -2,7 +2,7 @@
22
33use crate::cache::Cache;
44
5use crate::auth::errors::{AuthError, AuthResult};
5use crate::server::errors::{AuthError, AuthResult};
66
77#[tracing::instrument(skip_all, fields(request_id = %_request_id.unwrap_or_default()))]
88pub async fn rate_limit_once(
Renamed lib/identity/src/auth/share/totp.rs → lib/auth/src/server/share/totp.rs View lib/auth/src/server/share/totp.rs
@@ -2,7 +2,7 @@
22use sha1::Sha1;
33
44use super::crypto::{constant_time_eq, now_secs, random_bytes};
5use crate::auth::errors::{AuthError, AuthResult};
5use crate::server::errors::{AuthError, AuthResult};
66
77pub const TOTP_ISSUER: &str = "KenOAuth";
88pub const TOTP_PERIOD_SECS: u64 = 30;
Renamed lib/identity/src/auth/share/types.rs → lib/auth/src/server/share/types.rs View lib/auth/src/server/share/types.rs

No content changes.

Renamed lib/identity/src/auth/share/user.rs → lib/auth/src/server/share/user.rs View lib/auth/src/server/share/user.rs
@@ -1,10 +1,10 @@
11//! 用户加载与状态判定 helper:service 层与 gRPC 层共用的唯一实现点。
22//! gRPC 侧(`grpc::store`)re-export 这些函数,避免 service 反向依赖传输层。
33
4use crate::auth::errors::{AuthError, AuthResult};
54use crate::db::DbConn;
65use crate::models::users::user_mfa::MfaStatus as ModelMfaStatus;
76use crate::models::users::{user_mfa, users};
7use crate::server::errors::{AuthError, AuthResult};
88use chrono::Utc;
99use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
1010
Renamed lib/identity/src/auth/share/validate.rs → lib/auth/src/server/share/validate.rs View lib/auth/src/server/share/validate.rs
@@ -1,6 +1,6 @@
11use chrono::{Datelike, NaiveDate, Utc};
22
3use crate::auth::errors::{AuthError, AuthResult};
3use crate::server::errors::{AuthError, AuthResult};
44
55pub const MAX_USERNAME_LEN: usize = 64;
66pub const MAX_DISPLAY_NAME_LEN: usize = 64;
Renamed lib/identity/src/auth/ssh_key/handler.rs → lib/auth/src/server/ssh_key/handler.rs View lib/auth/src/server/ssh_key/handler.rs
@@ -2,11 +2,11 @@
22use actix_web::web;
33use uuid::Uuid;
44
5use crate::auth::AuthSvc;
6use crate::auth::errors::AuthError;
7use crate::auth::share::types::ListQuery;
8use crate::auth::ssh_key::types::{SshKeyAddRequest, SshKeySummary};
95use crate::envelope::{Envelope, NoData};
6use crate::server::AuthSvc;
7use crate::server::errors::AuthError;
8use crate::server::share::types::ListQuery;
9use crate::server::ssh_key::types::{SshKeyAddRequest, SshKeySummary};
1010
1111#[utoipa::path(
1212 get,
Renamed lib/identity/src/auth/ssh_key/mod.rs → lib/auth/src/server/ssh_key/mod.rs View lib/auth/src/server/ssh_key/mod.rs

No content changes.

Renamed lib/identity/src/auth/ssh_key/service.rs → lib/auth/src/server/ssh_key/service.rs View lib/auth/src/server/ssh_key/service.rs
@@ -14,11 +14,11 @@
1414};
1515use uuid::Uuid;
1616
17use crate::auth::AuthSvc;
18use crate::auth::errors::{AuthError, AuthResult};
19use crate::auth::share::crypto;
20use crate::auth::share::types::ListQuery;
21use crate::auth::ssh_key::types::{
17use crate::server::AuthSvc;
18use crate::server::errors::{AuthError, AuthResult};
19use crate::server::share::crypto;
20use crate::server::share::types::ListQuery;
21use crate::server::ssh_key::types::{
2222 MAX_SSH_KEY_DESCRIPTION_LEN, MAX_SSH_KEY_NAME_LEN, MAX_SSH_PUBLIC_KEY_LEN,
2323 MIN_SSH_PUBLIC_KEY_LEN, SshKeyAddRequest, SshKeyAlgorithm, SshKeySummary,
2424};
Renamed lib/identity/src/auth/ssh_key/types.rs → lib/auth/src/server/ssh_key/types.rs View lib/auth/src/server/ssh_key/types.rs

No content changes.

Renamed lib/identity/src/auth/token/handler.rs → lib/auth/src/server/token/handler.rs View lib/auth/src/server/token/handler.rs
@@ -2,9 +2,9 @@
22use crate::session::{RequestId, Session};
33use actix_web::web;
44
5use crate::auth::AuthSvc;
6use crate::auth::errors::AuthError;
7use crate::auth::token::types::{TokenRequest, TokenResponse};
5use crate::server::AuthSvc;
6use crate::server::errors::AuthError;
7use crate::server::token::types::{TokenRequest, TokenResponse};
88
99#[utoipa::path(
1010 post,
Renamed lib/identity/src/auth/token/mod.rs → lib/auth/src/server/token/mod.rs View lib/auth/src/server/token/mod.rs

No content changes.

Renamed lib/identity/src/auth/token/service.rs → lib/auth/src/server/token/service.rs View lib/auth/src/server/token/service.rs
@@ -1,9 +1,9 @@
11use crate::events::{AuthEvent, Labels, RestOperate, RuntimeEvent};
22
3use crate::auth::AuthSvc;
4use crate::auth::errors::AuthResult;
5use crate::auth::share::issue;
6use crate::auth::token::types::{
3use crate::server::AuthSvc;
4use crate::server::errors::AuthResult;
5use crate::server::share::issue;
6use crate::server::token::types::{
77 DEFAULT_TTL_SECS, MAX_TTL_SECS, TOKEN_TYPE, TokenRequest, TokenResponse,
88};
99
@@ -25,7 +25,7 @@
2525 if let Some(app_id) = app_id.as_deref() {
2626 self.apps()
2727 .find(app_id)
28 .ok_or(crate::auth::errors::AuthError::AppNotFound)?;
28 .ok_or(crate::server::errors::AuthError::AppNotFound)?;
2929 }
3030 let issued = issue::issue_user_claims(
3131 self,
Renamed lib/identity/src/auth/token/types.rs → lib/auth/src/server/token/types.rs View lib/auth/src/server/token/types.rs

No content changes.

Renamed lib/identity/src/auth/account_lifecycle.rs → lib/auth/src/server/account_lifecycle.rs View lib/auth/src/server/account_lifecycle.rs
@@ -4,12 +4,12 @@
44 ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set, TransactionTrait,
55};
66
7use crate::auth::AuthSvc;
8use crate::auth::errors::{AuthError, AuthResult};
97use crate::models::space::{OrganizationStatus, organization_members, organizations};
108use crate::models::users::{
119 user_access_tokens, user_mfa, user_mfa_backup_codes, user_sessions, user_ssh_keys, users,
1210};
11use crate::server::AuthSvc;
12use crate::server::errors::{AuthError, AuthResult};
1313
1414impl AuthSvc {
1515 /// Soft-delete the account and revoke every credential. The row (and its
Renamed lib/identity/src/auth/auth_svc.rs → lib/auth/src/server/auth_svc.rs View lib/auth/src/server/auth_svc.rs
@@ -23,9 +23,9 @@
2323 auth: Arc<AuthConfig>,
2424 pow: Arc<PowConfig>,
2525 apps: Arc<AppRegistry>,
26 signing: Arc<crate::auth::keys::SigningState>,
26 signing: Arc<crate::server::keys::SigningState>,
2727 jwt: crate::jwt::JwtState,
28 clients: Arc<crate::auth::client::ClientRegistry>,
28 clients: Arc<crate::server::client::ClientRegistry>,
2929 session_max_age_secs: u64,
3030}
3131
@@ -42,13 +42,13 @@
4242 jwt_config: JwtConfig,
4343 session_max_age_secs: u64,
4444 ) -> AuthResult<Self> {
45 crate::auth::protocol::validate_config(&auth.oauth, &jwt_config.issuer)?;
46 let signing = crate::auth::keys::SigningState::from_config(&jwt_config)?;
45 crate::server::protocol::validate_config(&auth.oauth, &jwt_config.issuer)?;
46 let signing = crate::server::keys::SigningState::from_config(&jwt_config)?;
4747 let jwt_state = crate::jwt::JwtState::load(&jwt_config)
4848 .await
4949 .map_err(|error| AuthError::Unavailable(error.to_string()))?;
5050 // 客户端注册表:配置种子落库后加载,之后由管理接口维护。
51 let clients = crate::auth::client::ClientRegistry::load(&db, &auth.oauth).await?;
51 let clients = crate::server::client::ClientRegistry::load(&db, &auth.oauth).await?;
5252 let svc = Self {
5353 db,
5454 cache,
@@ -91,7 +91,7 @@
9191 &self.apps
9292 }
9393
94 pub fn signing(&self) -> &crate::auth::keys::SigningState {
94 pub fn signing(&self) -> &crate::server::keys::SigningState {
9595 &self.signing
9696 }
9797
@@ -103,7 +103,7 @@
103103 self.events.as_ref()
104104 }
105105
106 pub fn clients(&self) -> &crate::auth::client::ClientRegistry {
106 pub fn clients(&self) -> &crate::server::client::ClientRegistry {
107107 &self.clients
108108 }
109109
Renamed lib/identity/src/auth/authority.rs → lib/auth/src/server/authority.rs View lib/auth/src/server/authority.rs
@@ -7,8 +7,8 @@
77use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, Set};
88use uuid::Uuid;
99
10use crate::auth::share::{crypto, user as store};
11use crate::auth::{AuthError, AuthResult, AuthSvc};
10use crate::server::share::{crypto, user as store};
11use crate::server::{AuthError, AuthResult, AuthSvc};
1212
1313const MAX_BATCH_PROFILES: usize = store::MAX_BATCH_USER_IDS;
1414
@@ -113,7 +113,7 @@
113113 .ok_or(JwtError::Revoked)?;
114114 // `token_hash` 是会话凭据的摘要:只有拿着明文会话 ID 的一方能算出来。
115115 // 不校验它,单有数据库读权限的人就能直接拿行里的 ID 复会话。
116 if !crate::auth::share::crypto::constant_time_eq(
116 if !crate::server::share::crypto::constant_time_eq(
117117 row.token_hash.as_bytes(),
118118 session_token_hash(id).as_bytes(),
119119 ) {
@@ -240,14 +240,15 @@
240240 }
241241 let mut active = user.clone().into_active_model();
242242 if let Some(name) = patch.get("username").and_then(|v| v.as_str()) {
243 let name = crate::auth::share::validate::validate_username(name).map_err(invalid)?;
243 let name = crate::server::share::validate::validate_username(name).map_err(invalid)?;
244244 active.lowername = Set(name.to_lowercase());
245245 active.username = Set(name);
246246 }
247247 if let Some(value) = patch.get("displayname") {
248248 active.displayname = Set(match value.as_str() {
249249 Some(value) => Some(
250 crate::auth::share::validate::validate_display_name(value).map_err(invalid)?,
250 crate::server::share::validate::validate_display_name(value)
251 .map_err(invalid)?,
251252 ),
252253 None if value.is_null() => None,
253254 _ => return Err(JwtError::Malformed),
@@ -267,7 +268,7 @@
267268 .map_err(invalid)?
268269 .pop()
269270 .ok_or(JwtError::Malformed)?;
270 crate::auth::me::service::invalidate_me_cache(self.cache(), user_id).await;
271 crate::server::me::service::invalidate_me_cache(self.cache(), user_id).await;
271272 Ok(record(updated))
272273 }
273274}
Renamed lib/identity/src/auth/errors.rs → lib/auth/src/server/errors.rs View lib/auth/src/server/errors.rs

No content changes.

Renamed lib/identity/src/auth/health.rs → lib/auth/src/server/health.rs View lib/auth/src/server/health.rs
@@ -5,8 +5,8 @@
55use serde::Serialize;
66use utoipa::ToSchema;
77
8use crate::auth::AuthSvc;
98use crate::envelope::Envelope;
9use crate::server::AuthSvc;
1010
1111/// 单个依赖项的探测上限:依赖挂住时探针必须尽快返回,否则编排器只会看到超时。
1212const PROBE_TIMEOUT: Duration = Duration::from_secs(2);
Renamed lib/identity/src/auth/keys.rs → lib/auth/src/server/keys.rs View lib/auth/src/server/keys.rs
@@ -3,7 +3,7 @@
33use actix_web::web;
44use serde::Serialize;
55
6use crate::auth::errors::{AuthError, AuthResult};
6use crate::server::errors::{AuthError, AuthResult};
77
88pub struct SigningState {
99 key: SigningKey,
@@ -66,7 +66,7 @@
6666 }
6767}
6868
69pub async fn jwks(svc: web::Data<crate::auth::AuthSvc>) -> web::Json<Jwks> {
69pub async fn jwks(svc: web::Data<crate::server::AuthSvc>) -> web::Json<Jwks> {
7070 web::Json(svc.signing().jwks().clone())
7171}
7272
Renamed lib/identity/src/auth/migrate.rs → lib/auth/src/server/migrate.rs View lib/auth/src/server/migrate.rs
@@ -1,4 +1,4 @@
1use crate::auth::errors::AuthResult;
1use crate::server::errors::AuthResult;
22
33const USER_PREFIX: &str = "models::users::";
44const SPACE_PREFIX: &str = "models::space::";
Renamed lib/identity/src/auth/mod.rs → lib/auth/src/server/mod.rs View lib/auth/src/server/mod.rs

No content changes.

Added lib/auth/src/server/openapi.rs View lib/auth/src/server/openapi.rs
@@ -0,0 +1,120 @@
1use utoipa::OpenApi;
2
3#[derive(OpenApi)]
4#[openapi(
5 info(
6 title = "auth",
7 description = "认证与账号服务:工作量证明、口令与验证码登录、二次验证、注册、口令重置、访问令牌与 SSH 公钥。",
8 version = env!("CARGO_PKG_VERSION")
9 ),
10 paths(
11 crate::server::challenge::handler::challenge,
12 crate::server::login::handler::login,
13 crate::server::login::handler::login_code,
14 crate::server::login::handler::login_code_verify,
15 crate::server::login::handler::login_verify,
16 crate::server::logout::handler::logout,
17 crate::server::me::handler::me,
18 crate::server::register::handler::register_code,
19 crate::server::register::handler::register,
20 crate::server::password_reset::handler::password_reset_request,
21 crate::server::password_reset::handler::password_reset,
22 crate::server::access_token::handler::access_token_list,
23 crate::server::access_token::handler::access_token_create,
24 crate::server::access_token::handler::access_token_revoke,
25 crate::server::app_token::handler::app_token_issue,
26 crate::server::token::handler::token_issue,
27 crate::server::ssh_key::handler::ssh_key_list,
28 crate::server::ssh_key::handler::ssh_key_add,
29 crate::server::ssh_key::handler::ssh_key_delete,
30 crate::server::protocol::authorize,
31 crate::server::protocol::token,
32 crate::server::protocol::revoke,
33 crate::server::protocol::metadata,
34 crate::server::protocol::openid_configuration,
35 crate::server::health::health,
36 crate::server::health::ready,
37 crate::server::oauth::userinfo::userinfo,
38 crate::server::oauth::logout::logout,
39 crate::server::oauth::consent::preview,
40 crate::server::oauth::consent::decide,
41 crate::server::organization::handler::create_organization,
42 crate::server::organization::handler::list_organizations,
43 crate::server::organization::handler::get_organization,
44 crate::server::organization::handler::update_organization,
45 crate::server::organization::handler::archive_organization,
46 crate::server::organization::handler::restore_organization,
47 crate::server::organization::handler::delete_organization,
48 crate::server::organization::handler::transfer_ownership,
49 crate::server::organization::handler::leave_organization,
50 crate::server::organization::handler::list_members,
51 crate::server::organization::handler::get_member,
52 crate::server::organization::handler::update_member,
53 crate::server::organization::handler::update_self_member,
54 crate::server::organization::handler::add_member,
55 crate::server::organization::handler::remove_member,
56 crate::server::organization::handler::set_member_role,
57 crate::server::organization::handler::ban_member,
58 crate::server::organization::handler::unban_member,
59 crate::server::organization::handler::set_member_permissions,
60 crate::server::organization::handler::list_bans,
61 crate::server::organization::handler::get_ban,
62 crate::server::organization::handler::update_ban,
63 crate::server::organization::handler::unban_by_user,
64 crate::server::organization::handler::list_roles,
65 crate::server::organization::handler::get_role,
66 crate::server::organization::handler::create_role,
67 crate::server::organization::handler::update_role,
68 crate::server::organization::handler::delete_role,
69 crate::server::organization::handler::set_role_permissions,
70 crate::server::organization::handler::assign_role,
71 crate::server::organization::handler::unassign_role,
72 crate::server::organization::handler::join_role,
73 crate::server::organization::handler::leave_role,
74 crate::server::organization::handler::check_permission,
75 crate::server::organization::handler::create_invite,
76 crate::server::organization::handler::list_invites,
77 crate::server::organization::handler::revoke_invite,
78 crate::server::organization::handler::redeem_invite,
79 ),
80 components(schemas(
81 crate::server::protocol::TokenRequest,
82 crate::server::protocol::RevokeRequest,
83 crate::server::health::HealthResponse,
84 crate::server::health::ReadinessResponse,
85 crate::server::health::ComponentCheck,
86 crate::server::oauth::consent::ConsentPreview,
87 crate::server::oauth::consent::ConsentDecision,
88 crate::server::oauth::consent::ConsentForm,
89 crate::server::organization::types::OrganizationSummary,
90 crate::server::organization::types::MemberSummary,
91 crate::server::organization::types::RoleSummary,
92 crate::server::organization::types::InviteSummary,
93 crate::server::organization::types::PermissionGrant,
94 crate::server::organization::types::PermissionCheck,
95 crate::server::organization::types::CreateOrganizationBody,
96 crate::server::organization::types::UpdateOrganizationBody,
97 crate::server::organization::types::AddMemberBody,
98 crate::server::organization::types::SetMemberRoleBody,
99 crate::server::organization::types::BanMemberBody,
100 crate::server::organization::types::CheckPermissionBody,
101 crate::server::organization::types::CreateRoleBody,
102 crate::server::organization::types::SetRolePermissionsBody,
103 crate::server::organization::handler::OrgPath,
104 crate::server::organization::handler::OrgMemberPath,
105 crate::server::organization::handler::OrgRolePath,
106 crate::server::organization::handler::OrgInvitePath,
107 crate::server::organization::handler::OrgListQuery,
108 crate::server::organization::handler::MemberListQuery,
109 crate::server::organization::handler::UpdateRoleBody,
110 crate::server::organization::handler::TransferBody,
111 crate::server::organization::handler::ReasonBody,
112 crate::server::organization::handler::DeleteOrgQuery,
113 crate::server::organization::handler::CreateInviteBody,
114 crate::server::organization::handler::RedeemInviteBody,
115 crate::server::organization::handler::CreateInviteResponse,
116 crate::server::organization::handler::RedeemInviteResponse,
117 crate::server::organization::handler::AssignRoleBody,
118 ))
119)]
120pub struct ApiDoc;
Renamed lib/identity/src/auth/protocol.rs → lib/auth/src/server/protocol.rs View lib/auth/src/server/protocol.rs
@@ -20,9 +20,9 @@
2020use serde::{Deserialize, Serialize};
2121use sha2::{Digest, Sha256};
2222
23use crate::auth::client::ClientRecord;
24use crate::auth::share::crypto::{constant_time_eq, random_b64url, sha256_hex};
25use crate::auth::{AuthError, AuthResult, AuthSvc};
23use crate::server::client::ClientRecord;
24use crate::server::share::crypto::{constant_time_eq, random_b64url, sha256_hex};
25use crate::server::{AuthError, AuthResult, AuthSvc};
2626
2727pub const MIN_RPC_KEY_LEN: usize = 32;
2828
@@ -62,7 +62,7 @@
6262 .iter()
6363 .any(|other| other.client_id == client.client_id);
6464 if duplicate
65 || crate::auth::client::registry::validate_client_id(&client.client_id).is_err()
65 || crate::server::client::registry::validate_client_id(&client.client_id).is_err()
6666 // 仅跑 client_credentials 的机密客户端可以没有重定向地址。
6767 || (client.kind == crate::models::users::oauth_clients::ClientKind::Public
6868 && client.redirect_uris.is_empty())
@@ -74,7 +74,7 @@
7474 .redirect_uris
7575 .iter()
7676 .any(|uri| {
77 crate::auth::client::registry::validate_uri(uri, config.allow_wildcard_redirect)
77 crate::server::client::registry::validate_uri(uri, config.allow_wildcard_redirect)
7878 .is_err()
7979 })
8080 || (client.kind == crate::models::users::oauth_clients::ClientKind::Confidential
@@ -83,7 +83,7 @@
8383 .as_deref()
8484 .is_none_or(
8585 |secret| {
86 secret.len() < crate::auth::client::registry::MIN_SECRET_LEN
86 secret.len() < crate::server::client::registry::MIN_SECRET_LEN
8787 || is_placeholder(secret)
8888 },
8989 ))
@@ -104,7 +104,7 @@
104104}
105105
106106fn endpoint(raw: &str) -> Option<Url> {
107 crate::auth::client::registry::endpoint(raw)
107 crate::server::client::registry::endpoint(raw)
108108}
109109
110110/// 一次授权请求里 `prompt` 解析结果。
@@ -388,7 +388,7 @@
388388
389389 let needs_consent = prompt.consent
390390 || (svc.auth().oauth.require_consent
391 && !crate::auth::oauth::consent::granted(
391 && !crate::server::oauth::consent::granted(
392392 &svc,
393393 user_id,
394394 &record.client_id,
@@ -822,9 +822,9 @@
822822 .iter()
823823 .any(|scope| scope == crate::jwt::scope::OPENID)
824824 {
825 let id_token = crate::auth::oauth::id_token::build(
825 let id_token = crate::server::oauth::id_token::build(
826826 svc,
827 &crate::auth::oauth::id_token::IdTokenInput {
827 &crate::server::oauth::id_token::IdTokenInput {
828828 client_id: &record.client_id,
829829 user_id: grant.user_id,
830830 username: &user.username,
@@ -841,9 +841,9 @@
841841 body["id_token"] = serde_json::Value::String(id_token);
842842 }
843843
844 let issued = crate::auth::oauth::refresh::issue(
844 let issued = crate::server::oauth::refresh::issue(
845845 svc,
846 crate::auth::oauth::refresh::Grant {
846 crate::server::oauth::refresh::Grant {
847847 user_id: grant.user_id,
848848 session_id: &grant.session_id,
849849 client_id: &record.client_id,
@@ -877,7 +877,7 @@
877877 return failure("invalid_request", false);
878878 };
879879 let result: AuthResult<serde_json::Value> = async {
880 let rotated = crate::auth::oauth::refresh::rotate(
880 let rotated = crate::server::oauth::refresh::rotate(
881881 svc,
882882 refresh_token,
883883 &record.client_id,
@@ -935,9 +935,9 @@
935935 .iter()
936936 .any(|scope| scope == crate::jwt::scope::OPENID)
937937 {
938 let id_token = crate::auth::oauth::id_token::build(
938 let id_token = crate::server::oauth::id_token::build(
939939 svc,
940 &crate::auth::oauth::id_token::IdTokenInput {
940 &crate::server::oauth::id_token::IdTokenInput {
941941 client_id: &record.client_id,
942942 user_id: rotated.user_id,
943943 username: &user.username,
@@ -1111,7 +1111,7 @@
11111111 if let Err(error) = check_client_secret(&record, form.client_secret.as_deref()) {
11121112 return cors(&svc, &web_cfg, &req, client_failure(error));
11131113 }
1114 if let Err(error) = crate::auth::oauth::refresh::revoke(
1114 if let Err(error) = crate::server::oauth::refresh::revoke(
11151115 &svc,
11161116 &form.token,
11171117 &record.client_id,
@@ -1311,8 +1311,8 @@
13111311#[cfg(test)]
13121312mod tests {
13131313 use super::*;
1314 use crate::auth::client::{ClientSpec, MIN_SECRET_LEN};
13151314 use crate::models::users::oauth_clients::{ClientKind, ClientSource};
1315 use crate::server::client::{ClientSpec, MIN_SECRET_LEN};
13161316
13171317 fn make_record(kind: ClientKind, secret: Option<&str>, scopes: &[&str]) -> ClientRecord {
13181318 ClientRecord::from_spec(
Added lib/auth/src/server/router.rs View lib/auth/src/server/router.rs
@@ -0,0 +1,304 @@
1use actix_web::web;
2
3pub fn configure(cfg: &mut web::ServiceConfig) {
4 cfg.route(
5 "/.well-known/openid-configuration",
6 web::get().to(crate::server::protocol::openid_configuration),
7 );
8 cfg.route(
9 "/.well-known/oauth-authorization-server",
10 web::get().to(crate::server::protocol::metadata),
11 );
12 cfg.route(
13 "/.well-known/jwks.json",
14 web::get().to(crate::server::keys::jwks),
15 );
16 cfg.route("/health", web::get().to(crate::server::health::health));
17 cfg.route("/ready", web::get().to(crate::server::health::ready));
18 cfg.service(web::scope("/api/v1").configure(api));
19}
20
21fn api(cfg: &mut web::ServiceConfig) {
22 cfg.route(
23 "/oauth/authorize",
24 web::get().to(crate::server::protocol::authorize),
25 );
26 cfg.route(
27 "/oauth/token",
28 web::post().to(crate::server::protocol::token),
29 );
30 cfg.route(
31 "/oauth/revoke",
32 web::post().to(crate::server::protocol::revoke),
33 );
34 cfg.route(
35 "/oauth/userinfo",
36 web::get().to(crate::server::oauth::userinfo::userinfo),
37 );
38 cfg.route(
39 "/oauth/userinfo",
40 web::post().to(crate::server::oauth::userinfo::userinfo),
41 );
42 cfg.route(
43 "/oauth/logout",
44 web::get().to(crate::server::oauth::logout::logout),
45 );
46 cfg.route(
47 "/oauth/logout",
48 web::post().to(crate::server::oauth::logout::logout),
49 );
50 cfg.route(
51 "/oauth/consent",
52 web::get().to(crate::server::oauth::consent::preview),
53 );
54 cfg.route(
55 "/oauth/consent",
56 web::post().to(crate::server::oauth::consent::decide),
57 );
58 cfg.route(
59 "/oauth/socket-tickets",
60 web::post().to(crate::server::socket_ticket::issue),
61 );
62 cfg.route(
63 "/oauth/socket-tickets",
64 web::method(actix_web::http::Method::OPTIONS).to(crate::server::protocol::preflight),
65 );
66 cfg.route(
67 "/oauth/token",
68 web::method(actix_web::http::Method::OPTIONS).to(crate::server::protocol::preflight),
69 );
70 cfg.route(
71 "/oauth/revoke",
72 web::method(actix_web::http::Method::OPTIONS).to(crate::server::protocol::preflight),
73 );
74 cfg.route(
75 "/oauth/challenge",
76 web::post().to(crate::server::challenge::handler::challenge),
77 );
78 cfg.route(
79 "/oauth/login",
80 web::post().to(crate::server::login::handler::login),
81 );
82 cfg.route(
83 "/oauth/login/code",
84 web::post().to(crate::server::login::handler::login_code),
85 );
86 cfg.route(
87 "/oauth/login/code/verify",
88 web::post().to(crate::server::login::handler::login_code_verify),
89 );
90 cfg.route(
91 "/oauth/login/verify",
92 web::post().to(crate::server::login::handler::login_verify),
93 );
94 cfg.route(
95 "/oauth/session/logout",
96 web::post().to(crate::server::logout::handler::logout),
97 );
98 cfg.route("/oauth/me", web::get().to(crate::server::me::handler::me));
99 cfg.route(
100 "/oauth/register/code",
101 web::post().to(crate::server::register::handler::register_code),
102 );
103 cfg.route(
104 "/oauth/register",
105 web::post().to(crate::server::register::handler::register),
106 );
107 cfg.route(
108 "/oauth/password/reset",
109 web::post().to(crate::server::password_reset::handler::password_reset_request),
110 );
111 cfg.route(
112 "/oauth/password/reset/confirm",
113 web::post().to(crate::server::password_reset::handler::password_reset),
114 );
115 cfg.route(
116 "/oauth/access-tokens",
117 web::get().to(crate::server::access_token::handler::access_token_list),
118 );
119 cfg.route(
120 "/oauth/access-tokens",
121 web::post().to(crate::server::access_token::handler::access_token_create),
122 );
123 cfg.route(
124 "/oauth/access-tokens/{token_id}",
125 web::delete().to(crate::server::access_token::handler::access_token_revoke),
126 );
127 cfg.route(
128 "/oauth/access-tokens/{token_id}/rotate",
129 web::post().to(crate::server::access_token::handler::access_token_rotate),
130 );
131 cfg.route(
132 "/oauth/app-tokens",
133 web::post().to(crate::server::app_token::handler::app_token_issue),
134 );
135 cfg.route(
136 "/oauth/session/token",
137 web::post().to(crate::server::token::handler::token_issue),
138 );
139 cfg.route("/oauth/jwks.json", web::get().to(crate::server::keys::jwks));
140 cfg.route(
141 "/oauth/ssh-keys",
142 web::get().to(crate::server::ssh_key::handler::ssh_key_list),
143 );
144 cfg.route(
145 "/oauth/ssh-keys",
146 web::post().to(crate::server::ssh_key::handler::ssh_key_add),
147 );
148 cfg.route(
149 "/oauth/ssh-keys/{key_id}",
150 web::delete().to(crate::server::ssh_key::handler::ssh_key_delete),
151 );
152 cfg.route(
153 "/organizations",
154 web::post().to(crate::server::organization::handler::create_organization),
155 );
156 cfg.route(
157 "/organizations",
158 web::get().to(crate::server::organization::handler::list_organizations),
159 );
160 cfg.route(
161 "/organizations/invites/redeem",
162 web::post().to(crate::server::organization::handler::redeem_invite),
163 );
164 cfg.route(
165 "/organizations/{organization_id}",
166 web::get().to(crate::server::organization::handler::get_organization),
167 );
168 cfg.route(
169 "/organizations/{organization_id}",
170 web::patch().to(crate::server::organization::handler::update_organization),
171 );
172 cfg.route(
173 "/organizations/{organization_id}",
174 web::delete().to(crate::server::organization::handler::delete_organization),
175 );
176 cfg.route(
177 "/organizations/{organization_id}/archive",
178 web::post().to(crate::server::organization::handler::archive_organization),
179 );
180 cfg.route(
181 "/organizations/{organization_id}/restore",
182 web::post().to(crate::server::organization::handler::restore_organization),
183 );
184 cfg.route(
185 "/organizations/{organization_id}/transfer",
186 web::post().to(crate::server::organization::handler::transfer_ownership),
187 );
188 cfg.route(
189 "/organizations/{organization_id}/leave",
190 web::post().to(crate::server::organization::handler::leave_organization),
191 );
192 cfg.route(
193 "/organizations/{organization_id}/members",
194 web::get().to(crate::server::organization::handler::list_members),
195 );
196 cfg.route(
197 "/organizations/{organization_id}/members",
198 web::post().to(crate::server::organization::handler::add_member),
199 );
200 cfg.route(
201 "/organizations/{organization_id}/members/@me",
202 web::patch().to(crate::server::organization::handler::update_self_member),
203 );
204 cfg.route(
205 "/organizations/{organization_id}/members/{member_id}",
206 web::get().to(crate::server::organization::handler::get_member),
207 );
208 cfg.route(
209 "/organizations/{organization_id}/members/{member_id}",
210 web::patch().to(crate::server::organization::handler::update_member),
211 );
212 cfg.route(
213 "/organizations/{organization_id}/members/{member_id}",
214 web::delete().to(crate::server::organization::handler::remove_member),
215 );
216 cfg.route(
217 "/organizations/{organization_id}/members/{member_id}/role",
218 web::patch().to(crate::server::organization::handler::set_member_role),
219 );
220 cfg.route(
221 "/organizations/{organization_id}/members/{member_id}/ban",
222 web::post().to(crate::server::organization::handler::ban_member),
223 );
224 cfg.route(
225 "/organizations/{organization_id}/members/{member_id}/unban",
226 web::post().to(crate::server::organization::handler::unban_member),
227 );
228 cfg.route(
229 "/organizations/{organization_id}/members/{member_id}/permissions",
230 web::put().to(crate::server::organization::handler::set_member_permissions),
231 );
232 cfg.route(
233 "/organizations/{organization_id}/bans",
234 web::get().to(crate::server::organization::handler::list_bans),
235 );
236 cfg.route(
237 "/organizations/{organization_id}/bans/{user_id}",
238 web::get().to(crate::server::organization::handler::get_ban),
239 );
240 cfg.route(
241 "/organizations/{organization_id}/bans/{user_id}",
242 web::patch().to(crate::server::organization::handler::update_ban),
243 );
244 cfg.route(
245 "/organizations/{organization_id}/bans/{user_id}",
246 web::delete().to(crate::server::organization::handler::unban_by_user),
247 );
248 cfg.route(
249 "/organizations/{organization_id}/roles",
250 web::get().to(crate::server::organization::handler::list_roles),
251 );
252 cfg.route(
253 "/organizations/{organization_id}/roles",
254 web::post().to(crate::server::organization::handler::create_role),
255 );
256 cfg.route(
257 "/organizations/{organization_id}/roles/assign",
258 web::post().to(crate::server::organization::handler::assign_role),
259 );
260 cfg.route(
261 "/organizations/{organization_id}/roles/unassign",
262 web::post().to(crate::server::organization::handler::unassign_role),
263 );
264 cfg.route(
265 "/organizations/{organization_id}/roles/{role_id}",
266 web::get().to(crate::server::organization::handler::get_role),
267 );
268 cfg.route(
269 "/organizations/{organization_id}/roles/{role_id}",
270 web::patch().to(crate::server::organization::handler::update_role),
271 );
272 cfg.route(
273 "/organizations/{organization_id}/roles/{role_id}/join",
274 web::post().to(crate::server::organization::handler::join_role),
275 );
276 cfg.route(
277 "/organizations/{organization_id}/roles/{role_id}/join",
278 web::delete().to(crate::server::organization::handler::leave_role),
279 );
280 cfg.route(
281 "/organizations/{organization_id}/roles/{role_id}",
282 web::delete().to(crate::server::organization::handler::delete_role),
283 );
284 cfg.route(
285 "/organizations/{organization_id}/roles/{role_id}/permissions",
286 web::put().to(crate::server::organization::handler::set_role_permissions),
287 );
288 cfg.route(
289 "/organizations/{organization_id}/permissions/check",
290 web::post().to(crate::server::organization::handler::check_permission),
291 );
292 cfg.route(
293 "/organizations/{organization_id}/invites",
294 web::post().to(crate::server::organization::handler::create_invite),
295 );
296 cfg.route(
297 "/organizations/{organization_id}/invites",
298 web::get().to(crate::server::organization::handler::list_invites),
299 );
300 cfg.route(
301 "/organizations/{organization_id}/invites/{invite_id}",
302 web::delete().to(crate::server::organization::handler::revoke_invite),
303 );
304}
Renamed lib/identity/src/auth/socket_ticket.rs → lib/auth/src/server/socket_ticket.rs View lib/auth/src/server/socket_ticket.rs
@@ -4,8 +4,8 @@
44use actix_web::{HttpRequest, HttpResponse, web};
55use serde::{Deserialize, Serialize};
66
7use crate::auth::share::crypto::{random_b64url, sha256_hex};
8use crate::auth::{AuthError, AuthResult, AuthSvc};
7use crate::server::share::crypto::{random_b64url, sha256_hex};
8use crate::server::{AuthError, AuthResult, AuthSvc};
99
1010#[derive(Deserialize)]
1111pub struct TicketRequest {
@@ -36,7 +36,7 @@
3636 let response = issue_inner(&svc, session, &req, &body, Some(request_id.as_str()))
3737 .await
3838 .unwrap_or_else(|error| error.error_response());
39 crate::auth::protocol::cors(&svc, &web_cfg, &req, response)
39 crate::server::protocol::cors(&svc, &web_cfg, &req, response)
4040}
4141
4242#[tracing::instrument(skip_all, fields(request_id = %request_id.unwrap_or_default()))]
Modified lib/auth/src/lib.rs View lib/auth/src/lib.rs
@@ -1,8 +1,25 @@
1pub mod errors;
2pub mod handlers;
1//! 认证中心:账号、会话、令牌、组织与 SSH 公钥的唯一入口。
2//!
3//! 服务端逻辑在 `server` / `oauth`,进程内 gRPC 客户端在 `client`;
4//! 其余基础设施(config、db、email、envelope、events、cache、models、
5//! oltp、protos、queue、session、shutdown、crypt)按原模块名重新导出。
6
7#![recursion_limit = "512"]
8
9pub mod client;
310pub mod oauth;
4pub mod openapi;
5pub mod routes;
6pub mod services;
7pub mod share;
8pub mod templates;
11pub mod server;
12
13pub use cache;
14pub use config::identity as config;
15pub use crypt;
16pub use db;
17pub use email;
18pub use envelope;
19pub use events;
20pub use models;
21pub use oltp::{self, shutdown};
22pub use proto as protos;
23pub use queue;
24pub use session;
25pub use token as jwt;
Renamed lib/identity/build.rs → lib/auth/build.rs View lib/auth/build.rs

No content changes.

Modified lib/auth/Cargo.toml View lib/auth/Cargo.toml
@@ -2,35 +2,101 @@
22name = "auth"
33version.workspace = true
44edition.workspace = true
5publish = false
6description = "认证中心:账号、会话、令牌、组织与 SSH 公钥的唯一入口"
7license = "MIT"
58
69[dependencies]
7identity = { workspace = true }
8async-trait = { workspace = true }
10models = { workspace = true }
911config = { workspace = true }
10deletion = { workspace = true }
11jwt = { workspace = true }
12export = { workspace = true }
13models = { workspace = true }
14space = { workspace = true }
15actix-web = { workspace = true }
16sea-orm = { workspace = true }
17tokio = { workspace = true }
18redis = { workspace = true }
19serde = { workspace = true, features = ["derive"] }
20utoipa = { workspace = true }
21serde_json = { workspace = true }
22base64 = { workspace = true }
23hmac = { workspace = true }
24sha2 = { workspace = true }
25uuid = { workspace = true }
26hkdf = { workspace = true }
27time = { workspace = true }
28argon2 = { workspace = true }
29rand = { workspace = true }
30tracing = { workspace = true }
31kenauth = { workspace = true }
32reqwest = { workspace = true }
33url = { workspace = true }
34i18n = { workspace = true }
35maud = { workspace = true }
36pulldown-cmark = { workspace = true }
12crypt = { workspace = true }
13db = { workspace = true }
14email = { workspace = true }
15envelope = { workspace = true }
16events = { workspace = true }
17cache = { workspace = true }
18oltp = { workspace = true }
19proto = { workspace = true }
20queue = { workspace = true }
21session = { workspace = true }
22token = { workspace = true }
23tokio-stream = { version = "0.1", features = ["net"] }
24actix-web = "4.16.0"
25aes-gcm = "0.11.1"
26anyhow = "1.0.104"
27argon2 = "0.6.0"
28async-trait = "0.1.92"
29base64 = "0.23.1"
30bytes = "1.12.1"
31chrono = { version = "0.4.45", features = ["serde"] }
32ed25519-dalek = "2.2.0"
33figment = { version = "0.10", default-features = false, features = [
34 "toml",
35 "json",
36 "yaml",
37 "env",
38] }
39futures-util = "0.3.34"
40hmac = "0.12.1"
41http = "1.5.0"
42http-body = "1.1.0"
43lettre = { version = "0.11.23", default-features = false, features = [
44 "smtp-transport",
45 "tokio1-rustls",
46 "rustls-tls",
47 "builder",
48 "pool",
49] }
50maud = "0.27.0"
51opentelemetry = "0.32.0"
52opentelemetry-appender-tracing = { version = "0.32.0", features = [
53 "experimental_span_attributes",
54] }
55opentelemetry-otlp = { version = "0.32.0", default-features = false, features = [
56 "http-proto",
57 "reqwest-blocking-client",
58 "internal-logs",
59 "logs",
60 "metrics",
61 "trace",
62] }
63opentelemetry_sdk = "0.32.1"
64percent-encoding = "2.3.2"
65prost = "0.14.4"
66prost-types = "0.14.4"
67rand = "0.10.3"
68rand_core = { version = "0.6.4", features = ["getrandom"] }
69reqwest = { version = "0.13.5", features = ["json", "stream", "form"] }
70rsa = { version = "0.9.10", features = ["sha2", "getrandom"] }
71rocketmq-client-rust = "0.9.0"
72rocketmq-common = "0.9.0"
73sea-orm = { version = "2.0.4", default-features = false, features = [
74 "macros",
75 "with-chrono",
76 "with-json",
77 "with-uuid",
78 "with-time",
79 "postgres-array",
80 "schema-sync",
81 "entity-registry",
82 "sqlx-postgres",
83 "runtime-tokio-rustls",
84] }
85serde = { version = "1.0.229", features = ["derive"] }
86serde_json = "1.0.154"
87sha1 = "0.10.7"
88sha2 = "0.10.9"
89sqlparser = { version = "0.63.0", default-features = false, features = ["std"] }
90thiserror = "2.0.21"
91tokio = { version = "1.53.3", features = ["full"] }
92tokio-util = "0.7.20"
93tonic = { version = "0.14.6", features = ["tls-ring"] }
94tonic-health = "0.14.6"
95tonic-prost = "0.14.6"
96tonic-reflection = "0.14.6"
97tower = "0.5.3"
98tracing = "0.1.44"
99tracing-opentelemetry = "0.33.0"
100tracing-subscriber = { version = "0.3.23", features = ["env-filter", "fmt"] }
101utoipa = { version = "6.0.0", features = ["actix_extras", "chrono", "uuid"] }
102uuid = { version = "1.28.0", features = ["serde", "v4", "v7"] }
No newline at end of file
Renamed lib/identity/OpenApi.Auth.json → lib/auth/OpenApi.Auth.json View lib/auth/OpenApi.Auth.json

No content changes.

Deleted lib/identity/src/auth/openapi.rs
@@ -1,120 +0,0 @@
1use utoipa::OpenApi;
2
3#[derive(OpenApi)]
4#[openapi(
5 info(
6 title = "auth",
7 description = "认证与账号服务:工作量证明、口令与验证码登录、二次验证、注册、口令重置、访问令牌与 SSH 公钥。",
8 version = env!("CARGO_PKG_VERSION")
9 ),
10 paths(
11 crate::auth::challenge::handler::challenge,
12 crate::auth::login::handler::login,
13 crate::auth::login::handler::login_code,
14 crate::auth::login::handler::login_code_verify,
15 crate::auth::login::handler::login_verify,
16 crate::auth::logout::handler::logout,
17 crate::auth::me::handler::me,
18 crate::auth::register::handler::register_code,
19 crate::auth::register::handler::register,
20 crate::auth::password_reset::handler::password_reset_request,
21 crate::auth::password_reset::handler::password_reset,
22 crate::auth::access_token::handler::access_token_list,
23 crate::auth::access_token::handler::access_token_create,
24 crate::auth::access_token::handler::access_token_revoke,
25 crate::auth::app_token::handler::app_token_issue,
26 crate::auth::token::handler::token_issue,
27 crate::auth::ssh_key::handler::ssh_key_list,
28 crate::auth::ssh_key::handler::ssh_key_add,
29 crate::auth::ssh_key::handler::ssh_key_delete,
30 crate::auth::protocol::authorize,
31 crate::auth::protocol::token,
32 crate::auth::protocol::revoke,
33 crate::auth::protocol::metadata,
34 crate::auth::protocol::openid_configuration,
35 crate::auth::health::health,
36 crate::auth::health::ready,
37 crate::auth::oauth::userinfo::userinfo,
38 crate::auth::oauth::logout::logout,
39 crate::auth::oauth::consent::preview,
40 crate::auth::oauth::consent::decide,
41 crate::auth::organization::handler::create_organization,
42 crate::auth::organization::handler::list_organizations,
43 crate::auth::organization::handler::get_organization,
44 crate::auth::organization::handler::update_organization,
45 crate::auth::organization::handler::archive_organization,
46 crate::auth::organization::handler::restore_organization,
47 crate::auth::organization::handler::delete_organization,
48 crate::auth::organization::handler::transfer_ownership,
49 crate::auth::organization::handler::leave_organization,
50 crate::auth::organization::handler::list_members,
51 crate::auth::organization::handler::get_member,
52 crate::auth::organization::handler::update_member,
53 crate::auth::organization::handler::update_self_member,
54 crate::auth::organization::handler::add_member,
55 crate::auth::organization::handler::remove_member,
56 crate::auth::organization::handler::set_member_role,
57 crate::auth::organization::handler::ban_member,
58 crate::auth::organization::handler::unban_member,
59 crate::auth::organization::handler::set_member_permissions,
60 crate::auth::organization::handler::list_bans,
61 crate::auth::organization::handler::get_ban,
62 crate::auth::organization::handler::update_ban,
63 crate::auth::organization::handler::unban_by_user,
64 crate::auth::organization::handler::list_roles,
65 crate::auth::organization::handler::get_role,
66 crate::auth::organization::handler::create_role,
67 crate::auth::organization::handler::update_role,
68 crate::auth::organization::handler::delete_role,
69 crate::auth::organization::handler::set_role_permissions,
70 crate::auth::organization::handler::assign_role,
71 crate::auth::organization::handler::unassign_role,
72 crate::auth::organization::handler::join_role,
73 crate::auth::organization::handler::leave_role,
74 crate::auth::organization::handler::check_permission,
75 crate::auth::organization::handler::create_invite,
76 crate::auth::organization::handler::list_invites,
77 crate::auth::organization::handler::revoke_invite,
78 crate::auth::organization::handler::redeem_invite,
79 ),
80 components(schemas(
81 crate::auth::protocol::TokenRequest,
82 crate::auth::protocol::RevokeRequest,
83 crate::auth::health::HealthResponse,
84 crate::auth::health::ReadinessResponse,
85 crate::auth::health::ComponentCheck,
86 crate::auth::oauth::consent::ConsentPreview,
87 crate::auth::oauth::consent::ConsentDecision,
88 crate::auth::oauth::consent::ConsentForm,
89 crate::auth::organization::types::OrganizationSummary,
90 crate::auth::organization::types::MemberSummary,
91 crate::auth::organization::types::RoleSummary,
92 crate::auth::organization::types::InviteSummary,
93 crate::auth::organization::types::PermissionGrant,
94 crate::auth::organization::types::PermissionCheck,
95 crate::auth::organization::types::CreateOrganizationBody,
96 crate::auth::organization::types::UpdateOrganizationBody,
97 crate::auth::organization::types::AddMemberBody,
98 crate::auth::organization::types::SetMemberRoleBody,
99 crate::auth::organization::types::BanMemberBody,
100 crate::auth::organization::types::CheckPermissionBody,
101 crate::auth::organization::types::CreateRoleBody,
102 crate::auth::organization::types::SetRolePermissionsBody,
103 crate::auth::organization::handler::OrgPath,
104 crate::auth::organization::handler::OrgMemberPath,
105 crate::auth::organization::handler::OrgRolePath,
106 crate::auth::organization::handler::OrgInvitePath,
107 crate::auth::organization::handler::OrgListQuery,
108 crate::auth::organization::handler::MemberListQuery,
109 crate::auth::organization::handler::UpdateRoleBody,
110 crate::auth::organization::handler::TransferBody,
111 crate::auth::organization::handler::ReasonBody,
112 crate::auth::organization::handler::DeleteOrgQuery,
113 crate::auth::organization::handler::CreateInviteBody,
114 crate::auth::organization::handler::RedeemInviteBody,
115 crate::auth::organization::handler::CreateInviteResponse,
116 crate::auth::organization::handler::RedeemInviteResponse,
117 crate::auth::organization::handler::AssignRoleBody,
118 ))
119)]
120pub struct ApiDoc;
Deleted lib/identity/src/auth/router.rs
@@ -1,301 +0,0 @@
1use actix_web::web;
2
3pub fn configure(cfg: &mut web::ServiceConfig) {
4 cfg.route(
5 "/.well-known/openid-configuration",
6 web::get().to(crate::auth::protocol::openid_configuration),
7 );
8 cfg.route(
9 "/.well-known/oauth-authorization-server",
10 web::get().to(crate::auth::protocol::metadata),
11 );
12 cfg.route(
13 "/.well-known/jwks.json",
14 web::get().to(crate::auth::keys::jwks),
15 );
16 cfg.route("/health", web::get().to(crate::auth::health::health));
17 cfg.route("/ready", web::get().to(crate::auth::health::ready));
18 cfg.service(web::scope("/api/v1").configure(api));
19}
20
21fn api(cfg: &mut web::ServiceConfig) {
22 cfg.route(
23 "/oauth/authorize",
24 web::get().to(crate::auth::protocol::authorize),
25 );
26 cfg.route("/oauth/token", web::post().to(crate::auth::protocol::token));
27 cfg.route(
28 "/oauth/revoke",
29 web::post().to(crate::auth::protocol::revoke),
30 );
31 cfg.route(
32 "/oauth/userinfo",
33 web::get().to(crate::auth::oauth::userinfo::userinfo),
34 );
35 cfg.route(
36 "/oauth/userinfo",
37 web::post().to(crate::auth::oauth::userinfo::userinfo),
38 );
39 cfg.route(
40 "/oauth/logout",
41 web::get().to(crate::auth::oauth::logout::logout),
42 );
43 cfg.route(
44 "/oauth/logout",
45 web::post().to(crate::auth::oauth::logout::logout),
46 );
47 cfg.route(
48 "/oauth/consent",
49 web::get().to(crate::auth::oauth::consent::preview),
50 );
51 cfg.route(
52 "/oauth/consent",
53 web::post().to(crate::auth::oauth::consent::decide),
54 );
55 cfg.route(
56 "/oauth/socket-tickets",
57 web::post().to(crate::auth::socket_ticket::issue),
58 );
59 cfg.route(
60 "/oauth/socket-tickets",
61 web::method(actix_web::http::Method::OPTIONS).to(crate::auth::protocol::preflight),
62 );
63 cfg.route(
64 "/oauth/token",
65 web::method(actix_web::http::Method::OPTIONS).to(crate::auth::protocol::preflight),
66 );
67 cfg.route(
68 "/oauth/revoke",
69 web::method(actix_web::http::Method::OPTIONS).to(crate::auth::protocol::preflight),
70 );
71 cfg.route(
72 "/oauth/challenge",
73 web::post().to(crate::auth::challenge::handler::challenge),
74 );
75 cfg.route(
76 "/oauth/login",
77 web::post().to(crate::auth::login::handler::login),
78 );
79 cfg.route(
80 "/oauth/login/code",
81 web::post().to(crate::auth::login::handler::login_code),
82 );
83 cfg.route(
84 "/oauth/login/code/verify",
85 web::post().to(crate::auth::login::handler::login_code_verify),
86 );
87 cfg.route(
88 "/oauth/login/verify",
89 web::post().to(crate::auth::login::handler::login_verify),
90 );
91 cfg.route(
92 "/oauth/session/logout",
93 web::post().to(crate::auth::logout::handler::logout),
94 );
95 cfg.route("/oauth/me", web::get().to(crate::auth::me::handler::me));
96 cfg.route(
97 "/oauth/register/code",
98 web::post().to(crate::auth::register::handler::register_code),
99 );
100 cfg.route(
101 "/oauth/register",
102 web::post().to(crate::auth::register::handler::register),
103 );
104 cfg.route(
105 "/oauth/password/reset",
106 web::post().to(crate::auth::password_reset::handler::password_reset_request),
107 );
108 cfg.route(
109 "/oauth/password/reset/confirm",
110 web::post().to(crate::auth::password_reset::handler::password_reset),
111 );
112 cfg.route(
113 "/oauth/access-tokens",
114 web::get().to(crate::auth::access_token::handler::access_token_list),
115 );
116 cfg.route(
117 "/oauth/access-tokens",
118 web::post().to(crate::auth::access_token::handler::access_token_create),
119 );
120 cfg.route(
121 "/oauth/access-tokens/{token_id}",
122 web::delete().to(crate::auth::access_token::handler::access_token_revoke),
123 );
124 cfg.route(
125 "/oauth/access-tokens/{token_id}/rotate",
126 web::post().to(crate::auth::access_token::handler::access_token_rotate),
127 );
128 cfg.route(
129 "/oauth/app-tokens",
130 web::post().to(crate::auth::app_token::handler::app_token_issue),
131 );
132 cfg.route(
133 "/oauth/session/token",
134 web::post().to(crate::auth::token::handler::token_issue),
135 );
136 cfg.route("/oauth/jwks.json", web::get().to(crate::auth::keys::jwks));
137 cfg.route(
138 "/oauth/ssh-keys",
139 web::get().to(crate::auth::ssh_key::handler::ssh_key_list),
140 );
141 cfg.route(
142 "/oauth/ssh-keys",
143 web::post().to(crate::auth::ssh_key::handler::ssh_key_add),
144 );
145 cfg.route(
146 "/oauth/ssh-keys/{key_id}",
147 web::delete().to(crate::auth::ssh_key::handler::ssh_key_delete),
148 );
149 cfg.route(
150 "/organizations",
151 web::post().to(crate::auth::organization::handler::create_organization),
152 );
153 cfg.route(
154 "/organizations",
155 web::get().to(crate::auth::organization::handler::list_organizations),
156 );
157 cfg.route(
158 "/organizations/invites/redeem",
159 web::post().to(crate::auth::organization::handler::redeem_invite),
160 );
161 cfg.route(
162 "/organizations/{organization_id}",
163 web::get().to(crate::auth::organization::handler::get_organization),
164 );
165 cfg.route(
166 "/organizations/{organization_id}",
167 web::patch().to(crate::auth::organization::handler::update_organization),
168 );
169 cfg.route(
170 "/organizations/{organization_id}",
171 web::delete().to(crate::auth::organization::handler::delete_organization),
172 );
173 cfg.route(
174 "/organizations/{organization_id}/archive",
175 web::post().to(crate::auth::organization::handler::archive_organization),
176 );
177 cfg.route(
178 "/organizations/{organization_id}/restore",
179 web::post().to(crate::auth::organization::handler::restore_organization),
180 );
181 cfg.route(
182 "/organizations/{organization_id}/transfer",
183 web::post().to(crate::auth::organization::handler::transfer_ownership),
184 );
185 cfg.route(
186 "/organizations/{organization_id}/leave",
187 web::post().to(crate::auth::organization::handler::leave_organization),
188 );
189 cfg.route(
190 "/organizations/{organization_id}/members",
191 web::get().to(crate::auth::organization::handler::list_members),
192 );
193 cfg.route(
194 "/organizations/{organization_id}/members",
195 web::post().to(crate::auth::organization::handler::add_member),
196 );
197 cfg.route(
198 "/organizations/{organization_id}/members/@me",
199 web::patch().to(crate::auth::organization::handler::update_self_member),
200 );
201 cfg.route(
202 "/organizations/{organization_id}/members/{member_id}",
203 web::get().to(crate::auth::organization::handler::get_member),
204 );
205 cfg.route(
206 "/organizations/{organization_id}/members/{member_id}",
207 web::patch().to(crate::auth::organization::handler::update_member),
208 );
209 cfg.route(
210 "/organizations/{organization_id}/members/{member_id}",
211 web::delete().to(crate::auth::organization::handler::remove_member),
212 );
213 cfg.route(
214 "/organizations/{organization_id}/members/{member_id}/role",
215 web::patch().to(crate::auth::organization::handler::set_member_role),
216 );
217 cfg.route(
218 "/organizations/{organization_id}/members/{member_id}/ban",
219 web::post().to(crate::auth::organization::handler::ban_member),
220 );
221 cfg.route(
222 "/organizations/{organization_id}/members/{member_id}/unban",
223 web::post().to(crate::auth::organization::handler::unban_member),
224 );
225 cfg.route(
226 "/organizations/{organization_id}/members/{member_id}/permissions",
227 web::put().to(crate::auth::organization::handler::set_member_permissions),
228 );
229 cfg.route(
230 "/organizations/{organization_id}/bans",
231 web::get().to(crate::auth::organization::handler::list_bans),
232 );
233 cfg.route(
234 "/organizations/{organization_id}/bans/{user_id}",
235 web::get().to(crate::auth::organization::handler::get_ban),
236 );
237 cfg.route(
238 "/organizations/{organization_id}/bans/{user_id}",
239 web::patch().to(crate::auth::organization::handler::update_ban),
240 );
241 cfg.route(
242 "/organizations/{organization_id}/bans/{user_id}",
243 web::delete().to(crate::auth::organization::handler::unban_by_user),
244 );
245 cfg.route(
246 "/organizations/{organization_id}/roles",
247 web::get().to(crate::auth::organization::handler::list_roles),
248 );
249 cfg.route(
250 "/organizations/{organization_id}/roles",
251 web::post().to(crate::auth::organization::handler::create_role),
252 );
253 cfg.route(
254 "/organizations/{organization_id}/roles/assign",
255 web::post().to(crate::auth::organization::handler::assign_role),
256 );
257 cfg.route(
258 "/organizations/{organization_id}/roles/unassign",
259 web::post().to(crate::auth::organization::handler::unassign_role),
260 );
261 cfg.route(
262 "/organizations/{organization_id}/roles/{role_id}",
263 web::get().to(crate::auth::organization::handler::get_role),
264 );
265 cfg.route(
266 "/organizations/{organization_id}/roles/{role_id}",
267 web::patch().to(crate::auth::organization::handler::update_role),
268 );
269 cfg.route(
270 "/organizations/{organization_id}/roles/{role_id}/join",
271 web::post().to(crate::auth::organization::handler::join_role),
272 );
273 cfg.route(
274 "/organizations/{organization_id}/roles/{role_id}/join",
275 web::delete().to(crate::auth::organization::handler::leave_role),
276 );
277 cfg.route(
278 "/organizations/{organization_id}/roles/{role_id}",
279 web::delete().to(crate::auth::organization::handler::delete_role),
280 );
281 cfg.route(
282 "/organizations/{organization_id}/roles/{role_id}/permissions",
283 web::put().to(crate::auth::organization::handler::set_role_permissions),
284 );
285 cfg.route(
286 "/organizations/{organization_id}/permissions/check",
287 web::post().to(crate::auth::organization::handler::check_permission),
288 );
289 cfg.route(
290 "/organizations/{organization_id}/invites",
291 web::post().to(crate::auth::organization::handler::create_invite),
292 );
293 cfg.route(
294 "/organizations/{organization_id}/invites",
295 web::get().to(crate::auth::organization::handler::list_invites),
296 );
297 cfg.route(
298 "/organizations/{organization_id}/invites/{invite_id}",
299 web::delete().to(crate::auth::organization::handler::revoke_invite),
300 );
301}
Deleted lib/identity/src/oauth/mod.rs
@@ -1,262 +0,0 @@
1mod assets;
2
3use crate::auth::AuthSvc;
4use crate::cache::Cache;
5use crate::config::Config;
6use crate::config::app::AppRegistry;
7use crate::config::auth::AuthConfig;
8use crate::config::jwt::JwtConfig;
9use crate::config::pow::PowConfig;
10use crate::config::redis::RedisConfig;
11use crate::config::rocketmq::RocketMqConfig;
12use crate::config::server::ServerConfig;
13use crate::config::session::SessionConfig;
14use crate::config::web::WebConfig;
15use crate::db::DbConn;
16use crate::email::EmailServiceBuilder;
17use crate::events::EventHandler;
18use crate::queue::RocketMqConn;
19use crate::session::{RedisStore, SessionMiddleware};
20use actix_web::{App, HttpServer, web};
21use anyhow::{Context, Result};
22use std::net::{IpAddr, SocketAddr};
23
24const APP: &str = "oauth";
25/// 邮件订阅者排空时的宽限时间。
26const EMAIL_SHUTDOWN_GRACE: std::time::Duration = std::time::Duration::from_secs(10);
27const GRPC_SHUTDOWN_GRACE_SECS: u64 = 10;
28
29#[derive(Clone)]
30struct AppState {
31 service: AuthSvc,
32 session: SessionConfig,
33 store: RedisStore,
34}
35
36/// host 网络部署下绑非回环地址即把单密钥门禁的 gRPC 面暴露公网;
37/// 显式设 KENOAUTH_ALLOW_PUBLIC_BIND=1 才放行。
38fn ensure_public_bind_allowed(addr: SocketAddr, label: &str) -> Result<SocketAddr> {
39 let loopback = match addr.ip() {
40 IpAddr::V4(ip) => ip.is_loopback(),
41 IpAddr::V6(ip) => ip.is_loopback(),
42 };
43 if loopback || std::env::var("KENOAUTH_ALLOW_PUBLIC_BIND").as_deref() == Ok("1") {
44 return Ok(addr);
45 }
46 Err(anyhow::anyhow!(
47 "{label} binds a non-loopback address ({addr}); the grpc plane is guarded by a single \
48 shared rpc_key. Set KENOAUTH_ALLOW_PUBLIC_BIND=1 to confirm public exposure."
49 ))
50}
51
52pub async fn start(config: &Config, db: DbConn) -> Result<Runtime> {
53 let server: ServerConfig = config.section()?;
54 crate::jwt::service::install(config.section()?).context("loading service identity")?;
55 let auth_config: AuthConfig = config.section()?;
56 let jwt_config: JwtConfig = config.section()?;
57 let pow_config: PowConfig = config.section()?;
58 let apps: AppRegistry = config.section_or_default()?;
59 let redis: RedisConfig = config.section()?;
60 let session_config: SessionConfig = config.section()?;
61 let rocketmq: RocketMqConfig = config.section()?;
62 let web: WebConfig = config.section_or_default()?;
63 let email_pool: crate::config::email::EmailPoolConfig = config.section_or_default()?;
64
65 auth_config
66 .validate()
67 .map_err(anyhow::Error::msg)
68 .context("invalid auth configuration")?;
69 pow_config
70 .validate()
71 .map_err(anyhow::Error::msg)
72 .context("invalid pow configuration")?;
73 apps.validate()
74 .map_err(anyhow::Error::msg)
75 .context("invalid apps configuration")?;
76 redis
77 .validate()
78 .map_err(anyhow::Error::msg)
79 .context("invalid redis configuration")?;
80 rocketmq
81 .validate()
82 .map_err(anyhow::Error::msg)
83 .context("invalid rocketmq configuration")?;
84 email_pool
85 .is_valid()
86 .map_err(anyhow::Error::msg)
87 .context("invalid email configuration")?;
88 web.is_valid()
89 .map_err(anyhow::Error::msg)
90 .context("invalid web configuration")?;
91 crate::config::session::ensure_secure_cookie(
92 session_config.secure,
93 server.http_addr,
94 std::env::var("KENOAUTH_ALLOW_INSECURE_COOKIE").as_deref() == Ok("1"),
95 )
96 .map_err(anyhow::Error::msg)
97 .context("invalid session configuration")?;
98 let cors = crate::envelope::Cors::new(&web);
99
100 let cache = Cache::connect(&redis)
101 .await
102 .context("connecting to redis")?;
103 let mq = RocketMqConn::init(&rocketmq)
104 .await
105 .context("connecting to rocketmq")?;
106 let events = EventHandler::new(mq);
107
108 let mut email_builder = EmailServiceBuilder::new(email_pool)
109 .with_events(events.clone())
110 .with_database(db.clone());
111 if config.has("smtp") {
112 let smtp: crate::config::smtp::SmtpConfig = config.section()?;
113 email_builder = email_builder.with_transport(smtp);
114 }
115 let email_service = email_builder
116 .register_default_templates()
117 .await
118 .build()
119 .await
120 .context("building the email service")?;
121 let email_enabled = email_service.enabled();
122 let email_queue_depth = email_service.depth();
123 let email = Some(email_service);
124
125 let session_max_age_secs = session_config.max_age.max(1) as u64;
126 let service = AuthSvc::new(
127 db,
128 cache.clone(),
129 email,
130 Some(events),
131 auth_config,
132 pow_config,
133 apps,
134 jwt_config,
135 session_max_age_secs,
136 )
137 .await?;
138 let state = AppState {
139 service: service.clone(),
140 session: session_config,
141 store: RedisStore::new(cache),
142 };
143
144 let grpc_addr = ensure_public_bind_allowed(server.grpc_addr, "grpc")?;
145 let grpc_listener = tokio::net::TcpListener::bind(grpc_addr)
146 .await
147 .with_context(|| format!("binding grpc on {grpc_addr}"))?;
148 let grpc = crate::auth::grpc::router(service.clone())
149 .await
150 .context("building the grpc router")?;
151
152 let http = HttpServer::new(move || {
153 App::new()
154 .wrap(SessionMiddleware::new(
155 state.session.clone(),
156 state.store.clone(),
157 ))
158 .wrap(crate::oltp::HttpTelemetry::new("oauth"))
159 .wrap(crate::envelope::EnvelopeContext)
160 .wrap(cors.clone())
161 .app_data(web::Data::new(state.service.clone()))
162 .app_data(web::Data::new(web.clone()))
163 .configure(crate::auth::router::configure)
164 .default_service(web::to(assets::serve))
165 })
166 .disable_signals()
167 .bind(ensure_public_bind_allowed(server.http_addr, "http")?)
168 .with_context(|| format!("binding http on {}", server.http_addr))?
169 .run();
170
171 let event_forwarding = service.verify_event_forwarding().await;
172 tracing::info!(
173 app = APP,
174 config = %config.path().display(),
175 http = %server.http_addr,
176 grpc = %server.grpc_addr,
177 assets = assets::count(),
178 email = email_enabled,
179 email_queue_depth,
180 event_forwarding,
181 "oauth serving"
182 );
183
184 Ok(Runtime {
185 service,
186 http,
187 grpc,
188 grpc_listener,
189 })
190}
191
192pub struct Runtime {
193 service: AuthSvc,
194 http: actix_web::dev::Server,
195 grpc: crate::auth::grpc::GrpcRouter,
196 grpc_listener: tokio::net::TcpListener,
197}
198
199impl Runtime {
200 pub fn service(&self) -> &AuthSvc {
201 &self.service
202 }
203
204 pub async fn serve_until(self, shutdown: tokio_util::sync::CancellationToken) -> Result<()> {
205 let Self {
206 service,
207 http,
208 grpc,
209 grpc_listener,
210 } = self;
211 let handle = http.handle();
212 let grpc_cancel = shutdown.clone();
213 let incoming = tokio_stream::wrappers::TcpListenerStream::new(grpc_listener);
214 let grpc = grpc.serve_with_incoming_shutdown(incoming, async move {
215 grpc_cancel.cancelled().await;
216 });
217 tokio::pin!(http, grpc);
218 let mut grpc_done = false;
219 let mut http_done = false;
220 let result = tokio::select! {
221 result = &mut http => { http_done = true; result.context("identity HTTP server stopped") },
222 result = &mut grpc => { grpc_done = true; result.context("identity gRPC server stopped") },
223 _ = shutdown.cancelled() => Ok(()),
224 };
225 shutdown.cancel();
226 let http_shutdown = async {
227 if !http_done {
228 let stop = handle.stop(true);
229 let (_, result) = tokio::join!(stop, &mut http);
230 if let Err(error) = result {
231 tracing::warn!(%error, "identity HTTP shutdown failed");
232 }
233 }
234 };
235 let grpc_shutdown = async {
236 if !grpc_done {
237 match tokio::time::timeout(
238 std::time::Duration::from_secs(GRPC_SHUTDOWN_GRACE_SECS),
239 &mut grpc,
240 )
241 .await
242 {
243 Ok(Ok(())) => {}
244 Ok(Err(error)) => tracing::warn!(%error, "identity gRPC shutdown failed"),
245 Err(_) => tracing::warn!("identity gRPC shutdown timed out"),
246 }
247 }
248 };
249 tokio::join!(http_shutdown, grpc_shutdown);
250 if let Some(email) = service.email()
251 && let Err(error) = email.shutdown(EMAIL_SHUTDOWN_GRACE).await
252 {
253 tracing::warn!(%error, "draining the email queue failed");
254 }
255 if let Some(events) = service.events()
256 && let Err(error) = events.shutdown().await
257 {
258 tracing::warn!(%error, "shutting down identity producer failed");
259 }
260 result
261 }
262}
Deleted lib/identity/src/lib.rs
@@ -1,26 +0,0 @@
1//! KenOAuth 认证中心。
2//!
3//! 业务逻辑保留在 `auth` / `oauth`;账号、会话、令牌之外的基础设施
4//! (config、db、email、envelope、events、jwt、cache、models、oltp、
5//! protos、queue、session、shutdown、crypt)已拆成工作区公共 crate,
6//! 这里按原模块名重新导出,保持既有调用路径不变。
7
8#![recursion_limit = "512"]
9
10pub mod auth;
11pub mod client;
12pub mod oauth;
13
14pub use cache;
15pub use config::identity as config;
16pub use crypt;
17pub use db;
18pub use email;
19pub use envelope;
20pub use events;
21pub use models;
22pub use oltp::{self, shutdown};
23pub use proto as protos;
24pub use queue;
25pub use session;
26pub use token as jwt;
Deleted lib/identity/Cargo.toml
@@ -1,109 +0,0 @@
1[package]
2name = "identity"
3version = "1.0.0"
4edition = "2024"
5publish = false
6autobins = false
7autoexamples = false
8description = "KenOAuth 认证中心:账号、会话、令牌与 SSH 公钥的唯一入口"
9license = "MIT"
10
11[lib]
12name = "identity"
13path = "src/lib.rs"
14
15[dependencies]
16models = { workspace = true }
17config = { workspace = true }
18crypt = { workspace = true }
19db = { workspace = true }
20email = { workspace = true }
21envelope = { workspace = true }
22events = { workspace = true }
23cache = { workspace = true }
24oltp = { workspace = true }
25proto = { workspace = true }
26queue = { workspace = true }
27session = { workspace = true }
28token = { workspace = true }
29tokio-stream = { version = "0.1", features = ["net"] }
30actix-web = "4.16.0"
31aes-gcm = "0.11.1"
32anyhow = "1.0.104"
33argon2 = "0.6.0"
34async-trait = "0.1.92"
35base64 = "0.23.1"
36bytes = "1.12.1"
37chrono = { version = "0.4.45", features = ["serde"] }
38ed25519-dalek = "2.2.0"
39figment = { version = "0.10", default-features = false, features = [
40 "toml",
41 "json",
42 "yaml",
43 "env",
44] }
45futures-util = "0.3.34"
46hmac = "0.12.1"
47http = "1.5.0"
48http-body = "1.1.0"
49lettre = { version = "0.11.23", default-features = false, features = [
50 "smtp-transport",
51 "tokio1-rustls",
52 "rustls-tls",
53 "builder",
54 "pool",
55] }
56maud = "0.27.0"
57opentelemetry = "0.32.0"
58opentelemetry-appender-tracing = { version = "0.32.0", features = [
59 "experimental_span_attributes",
60] }
61opentelemetry-otlp = { version = "0.32.0", default-features = false, features = [
62 "http-proto",
63 "reqwest-blocking-client",
64 "internal-logs",
65 "logs",
66 "metrics",
67 "trace",
68] }
69opentelemetry_sdk = "0.32.1"
70percent-encoding = "2.3.2"
71prost = "0.14.4"
72prost-types = "0.14.4"
73rand = "0.10.3"
74rand_core = { version = "0.6.4", features = ["getrandom"] }
75reqwest = { version = "0.13.5", features = ["json", "stream", "form"] }
76rsa = { version = "0.9.10", features = ["sha2", "getrandom"] }
77rocketmq-client-rust = "0.9.0"
78rocketmq-common = "0.9.0"
79sea-orm = { version = "2.0.4", default-features = false, features = [
80 "macros",
81 "with-chrono",
82 "with-json",
83 "with-uuid",
84 "with-time",
85 "postgres-array",
86 "schema-sync",
87 "entity-registry",
88 "sqlx-postgres",
89 "runtime-tokio-rustls",
90] }
91serde = { version = "1.0.229", features = ["derive"] }
92serde_json = "1.0.154"
93sha1 = "0.10.7"
94sha2 = "0.10.9"
95sqlparser = { version = "0.63.0", default-features = false, features = ["std"] }
96thiserror = "2.0.21"
97tokio = { version = "1.53.3", features = ["full"] }
98tokio-util = "0.7.20"
99tonic = { version = "0.14.6", features = ["tls-ring"] }
100tonic-health = "0.14.6"
101tonic-prost = "0.14.6"
102tonic-reflection = "0.14.6"
103tower = "0.5.3"
104tracing = "0.1.44"
105tracing-opentelemetry = "0.33.0"
106tracing-subscriber = { version = "0.3.23", features = ["env-filter", "fmt"] }
107utoipa = { version = "6.0.0", features = ["actix_extras", "chrono", "uuid"] }
108uuid = { version = "1.28.0", features = ["serde", "v4", "v7"] }
109
Deleted lib/identity/LICENSE
@@ -1,21 +0,0 @@
1MIT License
2
3Copyright (c) 2026 KenOAuth contributors
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
Modified lib/jwt/src/verifier.rs View lib/jwt/src/verifier.rs
@@ -18,7 +18,7 @@
1818}
1919
2020pub struct JwtVerifier {
21 identity: Option<identity::auth::AuthSvc>,
21 identity: Option<auth::server::AuthSvc>,
2222 issuer: String,
2323 audience: String,
2424 chat_audience: String,
@@ -40,7 +40,7 @@
4040
4141 pub fn with_identity(
4242 config: &OAuthConfig,
43 identity: Option<identity::auth::AuthSvc>,
43 identity: Option<auth::server::AuthSvc>,
4444 ) -> Result<Arc<Self>, SessionError> {
4545 if config.issuer.is_empty() {
4646 return Err(SessionError::Verifier("oauth.issuer is empty".into()));
Modified lib/jwt/Cargo.toml View lib/jwt/Cargo.toml
@@ -4,7 +4,7 @@
44edition.workspace = true
55
66[dependencies]
7identity = { workspace = true }
7auth = { workspace = true }
88config = { workspace = true }
99actix-web = { workspace = true }
1010serde = { workspace = true, features = ["derive"] }
Modified lib/kenauth/src/lib.rs View lib/kenauth/src/lib.rs
@@ -1,3 +1,3 @@
1pub use identity::client::KenAuthClient;
2pub use identity::client::error::KenAuthError;
3pub use identity::protos::auth as proto;
1pub use auth::client::KenAuthClient;
2pub use auth::client::error::KenAuthError;
3pub use auth::protos::auth as proto;
Modified lib/kenauth/Cargo.toml View lib/kenauth/Cargo.toml
@@ -4,4 +4,4 @@
44edition.workspace = true
55
66[dependencies]
7identity = { workspace = true }
7auth = { workspace = true }
Renamed lib/auth/src/handlers/accept_agreement.rs → lib/webapi/src/auth/handlers/accept_agreement.rs View lib/webapi/src/auth/handlers/accept_agreement.rs
@@ -5,9 +5,9 @@
55use serde::{Deserialize, Serialize};
66use utoipa::ToSchema;
77
8use crate::errors::ApiError;
9use crate::services::AuthService;
10use crate::services::agreements::AcceptAgreementResp;
8use crate::auth::errors::ApiError;
9use crate::auth::services::AuthService;
10use crate::auth::services::agreements::AcceptAgreementResp;
1111use jwt::share::session;
1212
1313#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
Renamed lib/auth/src/handlers/account_deletion.rs → lib/webapi/src/auth/handlers/account_deletion.rs View lib/webapi/src/auth/handlers/account_deletion.rs
@@ -6,8 +6,8 @@
66use time::OffsetDateTime;
77use utoipa::ToSchema;
88
9use crate::errors::{ApiError, AuthError};
10use crate::services::AuthService;
9use crate::auth::errors::{ApiError, AuthError};
10use crate::auth::services::AuthService;
1111
1212#[derive(Debug, Clone, Serialize, ToSchema)]
1313pub struct AccountDeletionDto {
Renamed lib/auth/src/handlers/agreement_page.rs → lib/webapi/src/auth/handlers/agreement_page.rs View lib/webapi/src/auth/handlers/agreement_page.rs
@@ -1,9 +1,9 @@
11use export::http::{HeaderMap, Html, Path, State};
22use i18n::catalog;
33
4use crate::errors::ApiError;
5use crate::services::AuthService;
6use crate::templates;
4use crate::auth::errors::ApiError;
5use crate::auth::services::AuthService;
6use crate::auth::templates;
77
88pub async fn agreement_page(
99 State(service): State<AuthService>,
Renamed lib/auth/src/handlers/create_report.rs → lib/webapi/src/auth/handlers/create_report.rs View lib/webapi/src/auth/handlers/create_report.rs
@@ -3,9 +3,9 @@
33use export::rest::{AppResponseData, NoData};
44use jwt::Session;
55
6use crate::errors::ApiError;
7use crate::services::AuthService;
8use crate::services::reports::{CreateReportCmd, ReportDto};
6use crate::auth::errors::ApiError;
7use crate::auth::services::AuthService;
8use crate::auth::services::reports::{CreateReportCmd, ReportDto};
99use jwt::share::session;
1010
1111#[utoipa::path(
Renamed lib/auth/src/handlers/delete_notification.rs → lib/webapi/src/auth/handlers/delete_notification.rs View lib/webapi/src/auth/handlers/delete_notification.rs
@@ -3,8 +3,8 @@
33use jwt::Session;
44use uuid::Uuid;
55
6use crate::errors::ApiError;
7use crate::services::AuthService;
6use crate::auth::errors::ApiError;
7use crate::auth::services::AuthService;
88use jwt::share::session;
99
1010#[utoipa::path(
Renamed lib/auth/src/handlers/devices.rs → lib/webapi/src/auth/handlers/devices.rs View lib/webapi/src/auth/handlers/devices.rs
@@ -10,9 +10,9 @@
1010use utoipa::ToSchema;
1111use uuid::Uuid;
1212
13use crate::errors::ApiError;
14use crate::services::AuthService;
15use crate::share::rpc;
13use crate::auth::errors::ApiError;
14use crate::auth::services::AuthService;
15use crate::auth::share::rpc;
1616
1717const SESSION_PAGE_SIZE: i32 = 100;
1818
Renamed lib/auth/src/handlers/get_preferences.rs → lib/webapi/src/auth/handlers/get_preferences.rs View lib/webapi/src/auth/handlers/get_preferences.rs
@@ -2,9 +2,9 @@
22use export::rest::{AppResponseData, NoData};
33use jwt::Session;
44
5use crate::errors::ApiError;
6use crate::services::AuthService;
7use crate::services::preferences::UserPreferencesDto;
5use crate::auth::errors::ApiError;
6use crate::auth::services::AuthService;
7use crate::auth::services::preferences::UserPreferencesDto;
88use jwt::share::session;
99
1010#[utoipa::path(
Renamed lib/auth/src/handlers/get_user.rs → lib/webapi/src/auth/handlers/get_user.rs View lib/webapi/src/auth/handlers/get_user.rs
@@ -3,9 +3,9 @@
33use jwt::Session;
44use jwt::share::session;
55
6use crate::errors::ApiError;
7use crate::services::AuthService;
8use crate::share::types::UserPublic;
6use crate::auth::errors::ApiError;
7use crate::auth::services::AuthService;
8use crate::auth::share::types::UserPublic;
99
1010#[utoipa::path(
1111 get,
Renamed lib/auth/src/handlers/jwt_request.rs → lib/webapi/src/auth/handlers/jwt_request.rs View lib/webapi/src/auth/handlers/jwt_request.rs
@@ -2,8 +2,8 @@
22use serde::{Deserialize, Serialize};
33use utoipa::ToSchema;
44
5use crate::errors::ApiError;
6use crate::services::AuthService;
5use crate::auth::errors::ApiError;
6use crate::auth::services::AuthService;
77use export::rest::{AppResponseData, NoData};
88use jwt::Session;
99use jwt::share::session;
Renamed lib/auth/src/handlers/list_agreements.rs → lib/webapi/src/auth/handlers/list_agreements.rs View lib/webapi/src/auth/handlers/list_agreements.rs
@@ -1,9 +1,9 @@
11use export::http::State;
22use export::rest::{AppResponseData, NoData};
33
4use crate::errors::ApiError;
5use crate::services::AuthService;
6use crate::share::types::AgreementDoc;
4use crate::auth::errors::ApiError;
5use crate::auth::services::AuthService;
6use crate::auth::share::types::AgreementDoc;
77
88#[utoipa::path(
99 get,
Renamed lib/auth/src/handlers/list_notifications.rs → lib/webapi/src/auth/handlers/list_notifications.rs View lib/webapi/src/auth/handlers/list_notifications.rs
@@ -4,9 +4,9 @@
44use serde::Deserialize;
55use utoipa::IntoParams;
66
7use crate::errors::ApiError;
8use crate::services::AuthService;
9use crate::services::notifications::NotificationDto;
7use crate::auth::errors::ApiError;
8use crate::auth::services::AuthService;
9use crate::auth::services::notifications::NotificationDto;
1010use jwt::share::session;
1111
1212#[derive(Debug, Clone, Copy, Default, Deserialize, IntoParams)]
Renamed lib/auth/src/handlers/mark_notifications_read.rs → lib/webapi/src/auth/handlers/mark_notifications_read.rs View lib/webapi/src/auth/handlers/mark_notifications_read.rs
@@ -4,8 +4,8 @@
44use serde::Deserialize;
55use uuid::Uuid;
66
7use crate::errors::ApiError;
8use crate::services::AuthService;
7use crate::auth::errors::ApiError;
8use crate::auth::services::AuthService;
99use jwt::share::session;
1010
1111#[derive(Debug, Deserialize, utoipa::ToSchema)]
Renamed lib/auth/src/handlers/me.rs → lib/webapi/src/auth/handlers/me.rs View lib/webapi/src/auth/handlers/me.rs
@@ -3,9 +3,9 @@
33use serde::Serialize;
44use utoipa::ToSchema;
55
6use crate::errors::ApiError;
7use crate::services::AuthService;
8use crate::services::profile::{ProfileDto, UserMeDto};
6use crate::auth::errors::ApiError;
7use crate::auth::services::AuthService;
8use crate::auth::services::profile::{ProfileDto, UserMeDto};
99use jwt::Session;
1010use jwt::share::session;
1111
Renamed lib/auth/src/handlers/mod.rs → lib/webapi/src/auth/handlers/mod.rs View lib/webapi/src/auth/handlers/mod.rs

No content changes.

Renamed lib/auth/src/handlers/password.rs → lib/webapi/src/auth/handlers/password.rs View lib/webapi/src/auth/handlers/password.rs
@@ -5,9 +5,9 @@
55use serde::Deserialize;
66use utoipa::ToSchema;
77
8use crate::errors::ApiError;
9use crate::services::AuthService;
10use crate::share::rpc;
8use crate::auth::errors::ApiError;
9use crate::auth::services::AuthService;
10use crate::auth::share::rpc;
1111
1212#[derive(Debug, Deserialize, ToSchema)]
1313pub struct ChangePasswordCmd {
Renamed lib/auth/src/handlers/sessions.rs → lib/webapi/src/auth/handlers/sessions.rs View lib/webapi/src/auth/handlers/sessions.rs
@@ -10,9 +10,9 @@
1010use utoipa::ToSchema;
1111use uuid::Uuid;
1212
13use crate::errors::ApiError;
14use crate::services::AuthService;
15use crate::share::rpc;
13use crate::auth::errors::ApiError;
14use crate::auth::services::AuthService;
15use crate::auth::share::rpc;
1616
1717const SESSION_PAGE_SIZE: i32 = 100;
1818
Renamed lib/auth/src/handlers/two_factor.rs → lib/webapi/src/auth/handlers/two_factor.rs View lib/webapi/src/auth/handlers/two_factor.rs
@@ -6,9 +6,9 @@
66use serde::{Deserialize, Serialize};
77use utoipa::ToSchema;
88
9use crate::errors::ApiError;
10use crate::services::AuthService;
11use crate::share::rpc;
9use crate::auth::errors::ApiError;
10use crate::auth::services::AuthService;
11use crate::auth::share::rpc;
1212
1313#[derive(Debug, Serialize, ToSchema)]
1414pub struct TotpStatusResp {
Renamed lib/auth/src/handlers/unread_notifications_count.rs → lib/webapi/src/auth/handlers/unread_notifications_count.rs View lib/webapi/src/auth/handlers/unread_notifications_count.rs
@@ -4,8 +4,8 @@
44use serde::Serialize;
55use utoipa::ToSchema;
66
7use crate::errors::ApiError;
8use crate::services::AuthService;
7use crate::auth::errors::ApiError;
8use crate::auth::services::AuthService;
99use jwt::share::session;
1010
1111#[derive(Debug, Clone, Serialize, ToSchema)]
Renamed lib/auth/src/handlers/update_preferences.rs → lib/webapi/src/auth/handlers/update_preferences.rs View lib/webapi/src/auth/handlers/update_preferences.rs
@@ -3,9 +3,9 @@
33use export::rest::{AppResponseData, NoData};
44use jwt::Session;
55
6use crate::errors::ApiError;
7use crate::services::AuthService;
8use crate::services::preferences::{UpdatePreferencesCmd, UserPreferencesDto};
6use crate::auth::errors::ApiError;
7use crate::auth::services::AuthService;
8use crate::auth::services::preferences::{UpdatePreferencesCmd, UserPreferencesDto};
99use jwt::share::session;
1010
1111#[utoipa::path(
Renamed lib/auth/src/handlers/update_profile.rs → lib/webapi/src/auth/handlers/update_profile.rs View lib/webapi/src/auth/handlers/update_profile.rs
@@ -3,9 +3,9 @@
33use export::rest::{AppResponseData, NoData};
44use jwt::Session;
55
6use crate::errors::ApiError;
7use crate::services::AuthService;
8use crate::services::profile::UpdateProfileCmd;
6use crate::auth::errors::ApiError;
7use crate::auth::services::AuthService;
8use crate::auth::services::profile::UpdateProfileCmd;
99use jwt::share::session;
1010
1111#[utoipa::path(
Renamed lib/auth/src/handlers/users.rs → lib/webapi/src/auth/handlers/users.rs View lib/webapi/src/auth/handlers/users.rs
@@ -5,9 +5,9 @@
55use serde::Deserialize;
66use utoipa::IntoParams;
77
8use crate::errors::ApiError;
9use crate::services::AuthService;
10use crate::share::types::UserPublic;
8use crate::auth::errors::ApiError;
9use crate::auth::services::AuthService;
10use crate::auth::share::types::UserPublic;
1111
1212#[derive(Debug, Deserialize, IntoParams)]
1313pub struct UsersBatchQuery {
Renamed lib/auth/src/oauth/callback.rs → lib/webapi/src/auth/oauth/callback.rs View lib/webapi/src/auth/oauth/callback.rs
@@ -3,9 +3,9 @@
33use export::http::{Extension, Query, Response, State};
44use serde::Deserialize;
55
6use crate::errors::ApiError;
7use crate::oauth::{exchange_code, project, redirect_with_cookies, state};
8use crate::services::AuthService;
6use crate::auth::errors::ApiError;
7use crate::auth::oauth::{exchange_code, project, redirect_with_cookies, state};
8use crate::auth::services::AuthService;
99
1010#[derive(Debug, Deserialize)]
1111pub struct CallbackQuery {
@@ -59,7 +59,7 @@
5959 let id_claims = verifier
6060 .verify_id(id_token)
6161 .await
62 .map_err(|_| ApiError::from(crate::errors::AuthError::Unauthorized))?;
62 .map_err(|_| ApiError::from(crate::auth::errors::AuthError::Unauthorized))?;
6363 if id_claims.nonce.as_deref() != Some(login_state.nonce.as_str()) {
6464 return Err(ApiError::bad_request("id_token nonce does not match"));
6565 }
@@ -71,7 +71,7 @@
7171 let claims = verifier
7272 .verify_access(&tokens.access_token)
7373 .await
74 .map_err(|_| ApiError::from(crate::errors::AuthError::Unauthorized))?;
74 .map_err(|_| ApiError::from(crate::auth::errors::AuthError::Unauthorized))?;
7575 if id_claims.sub != claims.sub.to_string() {
7676 return Err(ApiError::bad_request("id_token subject does not match"));
7777 }
@@ -80,10 +80,9 @@
8080 .kenauth
8181 .as_ref()
8282 .ok_or_else(|| ApiError::internal("kenoauth client is not configured"))?;
83 let public = kenauth
84 .get_user_public(claims.sub)
85 .await
86 .map_err(|error| ApiError::from(crate::errors::AuthError::Internal(error.to_string())))?;
83 let public = kenauth.get_user_public(claims.sub).await.map_err(|error| {
84 ApiError::from(crate::auth::errors::AuthError::Internal(error.to_string()))
85 })?;
8786 project::upsert(&service, &public)
8887 .await
8988 .map_err(ApiError::from)?;
Renamed lib/auth/src/oauth/flow.rs → lib/webapi/src/auth/oauth/flow.rs View lib/webapi/src/auth/oauth/flow.rs
@@ -4,8 +4,8 @@
44
55use config::oauth::OAuthConfig;
66
7use crate::errors::AuthError;
8use crate::services::AuthService;
7use crate::auth::errors::AuthError;
8use crate::auth::services::AuthService;
99
1010pub const STATE_TTL_SECS: u64 = 600;
1111pub const REFRESH_LOCK_TTL_SECS: u64 = 10;
@@ -79,7 +79,7 @@
7979 let config = &service.config().oauth;
8080 local_grant(
8181 service,
82 identity::auth::protocol::TokenRequest {
82 auth::server::protocol::TokenRequest {
8383 grant_type: "authorization_code".to_owned(),
8484 code: Some(code.to_owned()),
8585 redirect_uri: Some(redirect_uri.to_owned()),
@@ -100,7 +100,7 @@
100100 let config = &service.config().oauth;
101101 local_grant(
102102 service,
103 identity::auth::protocol::TokenRequest {
103 auth::server::protocol::TokenRequest {
104104 grant_type: "refresh_token".to_owned(),
105105 code: None,
106106 redirect_uri: None,
@@ -116,14 +116,14 @@
116116
117117async fn local_grant(
118118 service: &AuthService,
119 form: identity::auth::protocol::TokenRequest,
119 form: auth::server::protocol::TokenRequest,
120120) -> Result<TokenResponse, AuthError> {
121121 let client = service
122122 .state
123123 .kenauth
124124 .as_ref()
125125 .ok_or_else(|| AuthError::Internal("identity service is unavailable".to_owned()))?;
126 let value = identity::auth::protocol::exchange_local(client.service(), &form)
126 let value = auth::server::protocol::exchange_local(client.service(), &form)
127127 .await
128128 .map_err(|error| {
129129 if error.status >= 500 {
Renamed lib/auth/src/oauth/login.rs → lib/webapi/src/auth/oauth/login.rs View lib/webapi/src/auth/oauth/login.rs
@@ -4,9 +4,9 @@
44
55use config::oauth::OAuthConfig;
66
7use crate::errors::ApiError;
8use crate::oauth::{LoginState, pkce_challenge, random_token, resolve_redirect_uri, state};
9use crate::services::AuthService;
7use crate::auth::errors::ApiError;
8use crate::auth::oauth::{LoginState, pkce_challenge, random_token, resolve_redirect_uri, state};
9use crate::auth::services::AuthService;
1010
1111#[derive(Debug, Deserialize)]
1212pub struct LoginQuery {
Renamed lib/auth/src/oauth/logout.rs → lib/webapi/src/auth/oauth/logout.rs View lib/webapi/src/auth/oauth/logout.rs
@@ -2,9 +2,9 @@
22
33use export::http::{Extension, HeaderMap, Redirect, Response, State};
44
5use crate::errors::ApiError;
6use crate::oauth::{append_cookie, read_cookie_header};
7use crate::services::AuthService;
5use crate::auth::errors::ApiError;
6use crate::auth::oauth::{append_cookie, read_cookie_header};
7use crate::auth::services::AuthService;
88
99pub async fn logout(
1010 State(service): State<AuthService>,
Added lib/webapi/src/auth/oauth/mod.rs View lib/webapi/src/auth/oauth/mod.rs
@@ -0,0 +1,11 @@
1pub mod callback;
2pub mod login;
3pub mod logout;
4pub mod project;
5pub mod refresh;
6pub mod revalidate;
7pub mod state;
8
9mod flow;
10
11pub use flow::*;
Renamed lib/auth/src/oauth/project.rs → lib/webapi/src/auth/oauth/project.rs View lib/webapi/src/auth/oauth/project.rs
@@ -2,8 +2,8 @@
22use sea_orm::{ActiveModelTrait, EntityTrait, Set};
33use time::OffsetDateTime;
44
5use crate::errors::AuthError;
6use crate::services::AuthService;
5use crate::auth::errors::AuthError;
6use crate::auth::services::AuthService;
77
88/// Ensure the local settings row for an authenticated account exists.
99///
Renamed lib/auth/src/oauth/refresh.rs → lib/webapi/src/auth/oauth/refresh.rs View lib/webapi/src/auth/oauth/refresh.rs
@@ -3,9 +3,9 @@
33use actix_web::http::StatusCode;
44use export::http::{Extension, HeaderMap, Response, State};
55
6use crate::errors::ApiError;
7use crate::oauth::{REFRESH_LOCK_TTL_SECS, append_cookie, read_cookie_header, refresh_grant};
8use crate::services::AuthService;
6use crate::auth::errors::ApiError;
7use crate::auth::oauth::{REFRESH_LOCK_TTL_SECS, append_cookie, read_cookie_header, refresh_grant};
8use crate::auth::services::AuthService;
99
1010pub async fn refresh(
1111 State(service): State<AuthService>,
@@ -49,7 +49,7 @@
4949 };
5050
5151 if verifier.verify_access(&tokens.access_token).await.is_err() {
52 return Err(ApiError::from(crate::errors::AuthError::Unauthorized));
52 return Err(ApiError::from(crate::auth::errors::AuthError::Unauthorized));
5353 }
5454
5555 let mut response = Response::build(StatusCode::NO_CONTENT).finish();
Renamed lib/auth/src/oauth/revalidate.rs → lib/webapi/src/auth/oauth/revalidate.rs View lib/webapi/src/auth/oauth/revalidate.rs
@@ -8,7 +8,7 @@
88
99use export::AppState;
1010
11use crate::oauth::{append_cookie, read_cookie_header};
11use crate::auth::oauth::{append_cookie, read_cookie_header};
1212
1313const SKIP_PREFIXES: [&str; 8] = [
1414 "/healthz",
Renamed lib/auth/src/oauth/state.rs → lib/webapi/src/auth/oauth/state.rs View lib/webapi/src/auth/oauth/state.rs
@@ -1,8 +1,8 @@
11use export::redis;
22
3use crate::errors::AuthError;
4use crate::oauth::{LoginState, STATE_TTL_SECS};
5use crate::services::AuthService;
3use crate::auth::errors::AuthError;
4use crate::auth::oauth::{LoginState, STATE_TTL_SECS};
5use crate::auth::services::AuthService;
66
77fn key(state: &str) -> String {
88 format!("oauth:state:{state}")
Renamed lib/auth/src/services/agreements.rs → lib/webapi/src/auth/services/agreements.rs View lib/webapi/src/auth/services/agreements.rs
@@ -5,8 +5,8 @@
55use uuid::Uuid;
66
77use super::AuthService;
8use crate::errors::AuthError;
9use crate::share::types::AgreementDoc;
8use crate::auth::errors::AuthError;
9use crate::auth::share::types::AgreementDoc;
1010
1111#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
1212pub struct AcceptAgreementResp {
Renamed lib/auth/src/services/auth_service.rs → lib/webapi/src/auth/services/auth_service.rs View lib/webapi/src/auth/services/auth_service.rs
@@ -4,7 +4,7 @@
44use export::{AppDatabase, AppRedis, AppState};
55use models::users::access_scope::AccessKeyScope;
66
7use crate::errors::AuthError;
7use crate::auth::errors::AuthError;
88
99pub struct VerifiedAccessKey {
1010 pub user_id: i64,
Renamed lib/auth/src/services/mod.rs → lib/webapi/src/auth/services/mod.rs View lib/webapi/src/auth/services/mod.rs

No content changes.

Renamed lib/auth/src/services/notifications.rs → lib/webapi/src/auth/services/notifications.rs View lib/webapi/src/auth/services/notifications.rs
@@ -10,7 +10,7 @@
1010use uuid::Uuid;
1111
1212use super::AuthService;
13use crate::errors::AuthError;
13use crate::auth::errors::AuthError;
1414
1515#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
1616pub struct NotificationDto {
Renamed lib/auth/src/services/preferences.rs → lib/webapi/src/auth/services/preferences.rs View lib/webapi/src/auth/services/preferences.rs
@@ -5,7 +5,7 @@
55use time::OffsetDateTime;
66
77use super::AuthService;
8use crate::errors::AuthError;
8use crate::auth::errors::AuthError;
99
1010#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
1111pub struct UserPreferencesDto {
Renamed lib/auth/src/services/profile.rs → lib/webapi/src/auth/services/profile.rs View lib/webapi/src/auth/services/profile.rs
@@ -5,9 +5,9 @@
55use time::{Date, OffsetDateTime};
66
77use super::AuthService;
8use crate::errors::AuthError;
9use crate::share::types::UserPublic;
10use crate::share::validate;
8use crate::auth::errors::AuthError;
9use crate::auth::share::types::UserPublic;
10use crate::auth::share::validate;
1111
1212#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
1313pub struct UserMeDto {
@@ -276,7 +276,7 @@
276276 uid: i64,
277277 new_username: &str,
278278 ) -> Result<UserPublic, AuthError> {
279 let username = crate::share::validate::validate_username(new_username.trim())?;
279 let username = crate::auth::share::validate::validate_username(new_username.trim())?;
280280 let db = self.db();
281281 let local = user::Entity::find_by_id(uid).one(db.read()).await?;
282282
Renamed lib/auth/src/services/reports.rs → lib/webapi/src/auth/services/reports.rs View lib/webapi/src/auth/services/reports.rs
@@ -6,7 +6,7 @@
66use uuid::Uuid;
77
88use super::AuthService;
9use crate::errors::AuthError;
9use crate::auth::errors::AuthError;
1010
1111#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
1212pub struct CreateReportCmd {
Renamed lib/auth/src/services/suspensions.rs → lib/webapi/src/auth/services/suspensions.rs View lib/webapi/src/auth/services/suspensions.rs
@@ -5,7 +5,7 @@
55use uuid::Uuid;
66
77use super::AuthService;
8use crate::errors::AuthError;
8use crate::auth::errors::AuthError;
99
1010#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
1111pub struct SuspensionDto {
Renamed lib/auth/src/services/users.rs → lib/webapi/src/auth/services/users.rs View lib/webapi/src/auth/services/users.rs
@@ -5,8 +5,8 @@
55use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
66
77use super::AuthService;
8use crate::errors::AuthError;
9use crate::share::types::UserPublic;
8use crate::auth::errors::AuthError;
9use crate::auth::share::types::UserPublic;
1010
1111const MAX_BATCH_USERS: usize = 100;
1212
Renamed lib/auth/src/share/guard.rs → lib/webapi/src/auth/share/guard.rs View lib/webapi/src/auth/share/guard.rs

No content changes.

Renamed lib/auth/src/share/mod.rs → lib/webapi/src/auth/share/mod.rs View lib/webapi/src/auth/share/mod.rs

No content changes.

Renamed lib/auth/src/share/rpc.rs → lib/webapi/src/auth/share/rpc.rs View lib/webapi/src/auth/share/rpc.rs
@@ -6,7 +6,7 @@
66use sha2::{Digest, Sha256};
77use time::OffsetDateTime;
88
9use crate::errors::ApiError;
9use crate::auth::errors::ApiError;
1010
1111pub fn client(state: &AppState) -> Result<&Arc<KenAuthClient>, ApiError> {
1212 state
Renamed lib/auth/src/share/types.rs → lib/webapi/src/auth/share/types.rs View lib/webapi/src/auth/share/types.rs

No content changes.

Renamed lib/auth/src/share/validate.rs → lib/webapi/src/auth/share/validate.rs View lib/webapi/src/auth/share/validate.rs
@@ -1,6 +1,6 @@
11use time::{Date, OffsetDateTime};
22
3use crate::errors::AuthError;
3use crate::auth::errors::AuthError;
44
55pub fn validate_email(raw: &str) -> Result<String, AuthError> {
66 let email = raw.trim().to_lowercase();
Renamed lib/auth/src/templates/common.rs → lib/webapi/src/auth/templates/common.rs View lib/webapi/src/auth/templates/common.rs

No content changes.

Renamed lib/auth/src/templates/mod.rs → lib/webapi/src/auth/templates/mod.rs View lib/webapi/src/auth/templates/mod.rs

No content changes.

Renamed lib/auth/src/templates/page.rs → lib/webapi/src/auth/templates/page.rs View lib/webapi/src/auth/templates/page.rs
@@ -2,7 +2,7 @@
22use i18n::{UiLocale, catalog};
33use maud::html;
44
5use crate::share::types::AgreementDoc;
5use crate::auth::share::types::AgreementDoc;
66
77use super::common;
88
Renamed lib/auth/src/errors.rs → lib/webapi/src/auth/errors.rs View lib/webapi/src/auth/errors.rs

No content changes.

Added lib/webapi/src/auth/mod.rs View lib/webapi/src/auth/mod.rs
@@ -0,0 +1,8 @@
1pub mod errors;
2pub mod handlers;
3pub mod oauth;
4pub mod openapi;
5pub mod routes;
6pub mod services;
7pub mod share;
8pub mod templates;
Renamed lib/auth/src/openapi.rs → lib/webapi/src/auth/openapi.rs View lib/webapi/src/auth/openapi.rs
@@ -2,16 +2,16 @@
22use models::users::user_notifications::NotificationType;
33use utoipa::OpenApi;
44
5use crate::handlers;
6use crate::handlers::accept_agreement::AcceptAgreementCmd;
7use crate::handlers::me::MeResp;
8use crate::handlers::unread_notifications_count::UnreadCountResp;
9use crate::services::agreements::AcceptAgreementResp;
10use crate::services::notifications::NotificationDto;
11use crate::services::preferences::{UpdatePreferencesCmd, UserPreferencesDto};
12use crate::services::profile::{ProfileDto, UpdateProfileCmd, UserMeDto};
13use crate::services::reports::{CreateReportCmd, ReportDto};
14use crate::share::types::{AgreementDoc, UserPublic};
5use crate::auth::handlers;
6use crate::auth::handlers::accept_agreement::AcceptAgreementCmd;
7use crate::auth::handlers::me::MeResp;
8use crate::auth::handlers::unread_notifications_count::UnreadCountResp;
9use crate::auth::services::agreements::AcceptAgreementResp;
10use crate::auth::services::notifications::NotificationDto;
11use crate::auth::services::preferences::{UpdatePreferencesCmd, UserPreferencesDto};
12use crate::auth::services::profile::{ProfileDto, UpdateProfileCmd, UserMeDto};
13use crate::auth::services::reports::{CreateReportCmd, ReportDto};
14use crate::auth::share::types::{AgreementDoc, UserPublic};
1515
1616#[derive(OpenApi)]
1717#[openapi(
Renamed lib/auth/src/routes.rs → lib/webapi/src/auth/routes.rs View lib/webapi/src/auth/routes.rs
@@ -1,24 +1,24 @@
11use export::http::Router;
22use export::http::routing::{delete, get, post, put};
33
4use crate::handlers::accept_agreement::accept_agreement;
5use crate::handlers::account_deletion::{
4use crate::auth::handlers::accept_agreement::accept_agreement;
5use crate::auth::handlers::account_deletion::{
66 account_deletion_status, cancel_account_deletion, request_account_deletion,
77};
8use crate::handlers::agreement_page::agreement_page;
9use crate::handlers::create_report::create_report;
10use crate::handlers::delete_notification::delete_notification;
11use crate::handlers::get_preferences::get_preferences;
12use crate::handlers::get_user::get_user;
13use crate::handlers::list_agreements::list_agreements;
14use crate::handlers::list_notifications::list_notifications;
15use crate::handlers::me::me;
16use crate::handlers::unread_notifications_count::unread_notifications_count;
17use crate::handlers::update_preferences::update_preferences;
18use crate::handlers::update_profile::update_profile;
19use crate::handlers::users;
20use crate::oauth;
21use crate::services::AuthService;
8use crate::auth::handlers::agreement_page::agreement_page;
9use crate::auth::handlers::create_report::create_report;
10use crate::auth::handlers::delete_notification::delete_notification;
11use crate::auth::handlers::get_preferences::get_preferences;
12use crate::auth::handlers::get_user::get_user;
13use crate::auth::handlers::list_agreements::list_agreements;
14use crate::auth::handlers::list_notifications::list_notifications;
15use crate::auth::handlers::me::me;
16use crate::auth::handlers::unread_notifications_count::unread_notifications_count;
17use crate::auth::handlers::update_preferences::update_preferences;
18use crate::auth::handlers::update_profile::update_profile;
19use crate::auth::handlers::users;
20use crate::auth::oauth;
21use crate::auth::services::AuthService;
2222
2323pub fn router(_service: AuthService) -> Router<AuthService> {
2424 let public = Router::<AuthService>::new()
@@ -45,7 +45,7 @@
4545 )
4646 .route(
4747 "/auth/jwt-request",
48 get(crate::handlers::jwt_request::jwt_request),
48 get(crate::auth::handlers::jwt_request::jwt_request),
4949 )
5050 .route("/me/username", put(users::update_username))
5151 .route(
@@ -64,44 +64,47 @@
6464 )
6565 .route(
6666 "/me/notifications/read",
67 put(crate::handlers::mark_notifications_read::mark_notifications_read),
67 put(crate::auth::handlers::mark_notifications_read::mark_notifications_read),
6868 )
6969 .route("/me/reports", post(create_report))
7070 .route(
7171 "/auth/password/change",
72 post(crate::handlers::password::change_password),
72 post(crate::auth::handlers::password::change_password),
7373 )
7474 .route(
7575 "/auth/2fa/status",
76 get(crate::handlers::two_factor::totp_status),
76 get(crate::auth::handlers::two_factor::totp_status),
7777 )
7878 .route(
7979 "/auth/2fa/setup",
80 post(crate::handlers::two_factor::totp_setup),
80 post(crate::auth::handlers::two_factor::totp_setup),
8181 )
8282 .route(
8383 "/auth/2fa/enable",
84 post(crate::handlers::two_factor::totp_enable),
84 post(crate::auth::handlers::two_factor::totp_enable),
8585 )
8686 .route(
8787 "/auth/2fa/disable",
88 post(crate::handlers::two_factor::totp_disable),
88 post(crate::auth::handlers::two_factor::totp_disable),
8989 )
9090 .route(
9191 "/auth/2fa/recovery-codes",
92 get(crate::handlers::two_factor::recovery_codes)
93 .put(crate::handlers::two_factor::regenerate_recovery_codes),
92 get(crate::auth::handlers::two_factor::recovery_codes)
93 .put(crate::auth::handlers::two_factor::regenerate_recovery_codes),
9494 )
9595 .route(
9696 "/me/sessions",
97 get(crate::handlers::sessions::list_sessions)
98 .delete(crate::handlers::sessions::revoke_all_sessions),
97 get(crate::auth::handlers::sessions::list_sessions)
98 .delete(crate::auth::handlers::sessions::revoke_all_sessions),
9999 )
100100 .route(
101101 "/me/sessions/{session_id}",
102 delete(crate::handlers::sessions::revoke_session),
102 delete(crate::auth::handlers::sessions::revoke_session),
103103 )
104 .route("/me/devices", get(crate::handlers::devices::list_devices))
104 .route(
105 "/me/devices",
106 get(crate::auth::handlers::devices::list_devices),
107 )
105108 .wrap(export::http::Guard::Session);
106109
107110 public.merge(authed)
Modified lib/webapi/src/lib.rs View lib/webapi/src/lib.rs
@@ -1,3 +1,4 @@
1pub mod auth;
12pub mod cleanup;
23pub mod openapi;
34
@@ -34,7 +35,7 @@
3435}
3536
3637pub fn scope(state: AppState) -> Scope {
37 let auth = auth::services::AuthService::new(state.clone());
38 let auth = crate::auth::services::AuthService::new(state.clone());
3839 let chat = chat::services::service::ChatService::new(state.clone());
3940 let issues = issues::services::service::IssueService::new(state.clone());
4041 let space = space::services::service::SpaceService::new(state.clone());
@@ -46,7 +47,7 @@
4647 let cleanup_router = cleanup::router(space.clone(), issues.clone(), git.clone());
4748
4849 let public = Router::<()>::new()
49 .merge(auth::routes::router(auth.clone()).with_state(auth.clone()))
50 .merge(crate::auth::routes::router(auth.clone()).with_state(auth.clone()))
5051 .merge(chat::routes::router(chat.clone(), space.clone()).with_state(chat.clone()))
5152 .merge(issues::routes::router(issues.clone()).with_state(issues))
5253 .merge(space::routes::router(space.clone()).with_state(space))
@@ -63,7 +64,7 @@
6364 Router::<()>::new()
6465 .nest("/api/v1/internal", internal)
6566 .nest("/api/v1", public)
66 .nest("/pages", auth::routes::pages_router(auth.clone()))
67 .nest("/pages", crate::auth::routes::pages_router(auth.clone()))
6768 .merge(export::health::router(state))
6869 .into_scope(web::scope(""))
6970}
Modified lib/webapi/src/openapi.rs View lib/webapi/src/openapi.rs
@@ -105,7 +105,7 @@
105105 }
106106 }};
107107 }
108 m!("auth", auth::openapi::AuthApiDoc::openapi());
108 m!("auth", crate::auth::openapi::AuthApiDoc::openapi());
109109 m!("chat", chat::openapi::ChatApiDoc::openapi());
110110 m!("issues", issues::openapi::IssuesApiDoc::openapi());
111111 m!("space", space::openapi::SpaceApiDoc::openapi());
Modified lib/webapi/Cargo.toml View lib/webapi/Cargo.toml
@@ -7,6 +7,16 @@
77config = { path = "../config" }
88auth = { workspace = true }
99chat = { workspace = true }
10deletion = { workspace = true }
11i18n = { workspace = true }
12kenauth = { workspace = true }
13redis = { workspace = true }
14maud = { workspace = true }
15pulldown-cmark = { workspace = true }
16base64 = { workspace = true }
17sha2 = { workspace = true }
18rand = { workspace = true }
19url = { workspace = true }
1020issues = { workspace = true }
1121pulls = { workspace = true }
1222space = { workspace = true }
Modified Cargo.lock View Cargo.lock
@@ -762,34 +762,66 @@
762762version = "1.0.0"
763763dependencies = [
764764 "actix-web",
765 "aes-gcm 0.11.1",
766 "anyhow",
765767 "argon2",
766768 "async-trait",
767769 "base64 0.23.1",
770 "bytes",
771 "cache",
772 "chrono",
768773 "config 1.0.0",
769 "deletion",
770 "export",
771 "hkdf 0.13.0",
772 "hmac 0.13.0",
773 "i18n",
774 "identity",
775 "jwt",
776 "kenauth",
774 "crypt",
775 "db",
776 "ed25519-dalek",
777 "email",
778 "envelope",
779 "events",
780 "figment",
781 "futures-util",
782 "hmac 0.12.1",
783 "http 1.5.0",
784 "http-body 1.1.0",
785 "lettre",
777786 "maud",
778787 "models",
779 "pulldown-cmark",
780 "rand 0.8.8",
781 "redis",
782 "reqwest 0.12.28",
788 "oltp",
789 "opentelemetry",
790 "opentelemetry-appender-tracing",
791 "opentelemetry-otlp",
792 "opentelemetry_sdk",
793 "percent-encoding 2.3.2",
794 "prost 0.14.4",
795 "prost-types 0.14.4",
796 "proto",
797 "queue",
798 "rand 0.10.3",
799 "rand_core 0.6.4",
800 "reqwest 0.13.5",
801 "rocketmq-client-rust",
802 "rocketmq-common",
803 "rsa",
783804 "sea-orm",
784805 "serde",
785806 "serde_json",
786 "sha2 0.11.1",
787 "space",
788 "time 0.3.55",
807 "session",
808 "sha1 0.10.7",
809 "sha2 0.10.9",
810 "sqlparser",
811 "thiserror 2.0.21",
812 "token",
789813 "tokio",
814 "tokio-stream",
815 "tokio-util",
816 "tonic",
817 "tonic-health",
818 "tonic-prost",
819 "tonic-reflection",
820 "tower",
790821 "tracing",
791 "url 2.5.8",
792 "utoipa 5.5.0",
822 "tracing-opentelemetry",
823 "tracing-subscriber",
824 "utoipa 6.0.0",
793825 "uuid",
794826]
795827
@@ -3456,74 +3488,6 @@
34563488checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
34573489
34583490[[package]]
3459name = "identity"
3460version = "1.0.0"
3461dependencies = [
3462 "actix-web",
3463 "aes-gcm 0.11.1",
3464 "anyhow",
3465 "argon2",
3466 "async-trait",
3467 "base64 0.23.1",
3468 "bytes",
3469 "cache",
3470 "chrono",
3471 "config 1.0.0",
3472 "crypt",
3473 "db",
3474 "ed25519-dalek",
3475 "email",
3476 "envelope",
3477 "events",
3478 "figment",
3479 "futures-util",
3480 "hmac 0.12.1",
3481 "http 1.5.0",
3482 "http-body 1.1.0",
3483 "lettre",
3484 "maud",
3485 "models",
3486 "oltp",
3487 "opentelemetry",
3488 "opentelemetry-appender-tracing",
3489 "opentelemetry-otlp",
3490 "opentelemetry_sdk",
3491 "percent-encoding 2.3.2",
3492 "prost 0.14.4",
3493 "prost-types 0.14.4",
3494 "proto",
3495 "queue",
3496 "rand 0.10.3",
3497 "rand_core 0.6.4",
3498 "reqwest 0.13.5",
3499 "rocketmq-client-rust",
3500 "rocketmq-common",
3501 "rsa",
3502 "sea-orm",
3503 "serde",
3504 "serde_json",
3505 "session",
3506 "sha1 0.10.7",
3507 "sha2 0.10.9",
3508 "sqlparser",
3509 "thiserror 2.0.21",
3510 "token",
3511 "tokio",
3512 "tokio-stream",
3513 "tokio-util",
3514 "tonic",
3515 "tonic-health",
3516 "tonic-prost",
3517 "tonic-reflection",
3518 "tower",
3519 "tracing",
3520 "tracing-opentelemetry",
3521 "tracing-subscriber",
3522 "utoipa 6.0.0",
3523 "uuid",
3524]
3525
3526[[package]]
35273491name = "idna"
35283492version = "0.1.5"
35293493source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3861,9 +3825,9 @@
38613825version = "1.0.0"
38623826dependencies = [
38633827 "actix-web",
3828 "auth",
38643829 "base64 0.23.1",
38653830 "config 1.0.0",
3866 "identity",
38673831 "jsonwebtoken 9.3.1",
38683832 "reqwest 0.12.28",
38693833 "serde",
@@ -3937,7 +3901,6 @@
39373901 "deletion",
39383902 "events",
39393903 "export",
3940 "identity",
39413904 "jwt",
39423905 "kenauth",
39433906 "models",
@@ -3959,7 +3922,7 @@
39593922name = "kenauth"
39603923version = "1.0.0"
39613924dependencies = [
3962 "identity",
3925 "auth",
39633926]
39643927
39653928[[package]]
@@ -8897,21 +8860,31 @@
88978860 "actix-cors",
88988861 "actix-web",
88998862 "auth",
8863 "base64 0.23.1",
89008864 "chat",
89018865 "config 1.0.0",
8866 "deletion",
89028867 "export",
89038868 "git",
8869 "i18n",
89048870 "issues",
89058871 "jwt",
8872 "kenauth",
8873 "maud",
89068874 "models",
8875 "pulldown-cmark",
89078876 "pulls",
8877 "rand 0.8.8",
8878 "redis",
89088879 "sea-orm",
89098880 "serde",
89108881 "serde_json",
8882 "sha2 0.11.1",
89118883 "space",
89128884 "time 0.3.55",
89138885 "tokio",
89148886 "tracing",
8887 "url 2.5.8",
89158888 "user",
89168889 "utoipa 5.5.0",
89178890 "uuid",
Modified Cargo.toml View Cargo.toml
@@ -29,7 +29,6 @@
2929i18n = { path = "lib/i18n" }
3030imaging = { path = "lib/imaging" }
3131kenauth = { path = "lib/kenauth" }
32identity = { path = "lib/identity" }
3332crypt = { path = "lib/crypt" }
3433db = { path = "lib/db" }
3534email = { path = "lib/email" }
@@ -74,9 +73,7 @@
7473rand = "0.8"
7574sha2 = "0.11.0"
7675hmac = "0.13"
77hkdf = "0.13"
7876uuid = { version = "1", features = ["v7", "serde"] }
79argon2 = "0.6.0"
8077time = { version = "0.3", features = ["serde", "serde-human-readable"] }
8178bytes = "1"
8279futures = "0.3"