Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add endpoint /v1/session/logout and record client session ID in meta. #16281

Merged
merged 25 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c815b35
rename TokenManager to ClientSessionManager.
youngsofun Aug 16, 2024
245aaea
meta add ClientSession.
youngsofun Aug 17, 2024
6ee57dd
SessionCtx add field client_session_id.
youngsofun Aug 17, 2024
2920b44
rename TokenMgr ClientSessionMgr.
youngsofun Aug 17, 2024
9f00e94
add endpoint /session/logout
youngsofun Aug 19, 2024
abc4c97
remove outdated comments.
youngsofun Aug 19, 2024
b8161ca
http query check session id.
youngsofun Aug 19, 2024
8899973
http query log client session id.
youngsofun Aug 19, 2024
3e1ec8a
test logout.
youngsofun Aug 19, 2024
3d506c4
impl<T> MemSized for Option<T>
youngsofun Aug 19, 2024
e528908
fix merge up/main
youngsofun Aug 19, 2024
b5c8134
fix test
youngsofun Aug 19, 2024
4b29651
small refactor
youngsofun Aug 19, 2024
abbebbf
Merge remote-tracking branch 'up/main' into session
youngsofun Aug 19, 2024
91bc78a
rm secondary_roles in LoginRequest.
youngsofun Aug 20, 2024
0497cf8
fix http error code
youngsofun Aug 20, 2024
94e1150
Merge remote-tracking branch 'up/main' into session
youngsofun Aug 20, 2024
01e46ac
change error code of AuthenticateFailure.
youngsofun Aug 21, 2024
699060b
Merge remote-tracking branch 'up/main' into session
youngsofun Aug 21, 2024
db93806
fix error code in test.
youngsofun Aug 21, 2024
1e2057d
Merge remote-tracking branch 'up/main' into session
youngsofun Aug 21, 2024
7ef6073
update tests.
youngsofun Aug 21, 2024
9d860de
update tests.
youngsofun Aug 21, 2024
847e767
Merge remote-tracking branch 'up/main' into session
youngsofun Aug 21, 2024
ddaf8c9
fix clippy
youngsofun Aug 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/common/cache/src/mem_sized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,14 @@ impl MemSized for String {
self.len()
}
}

impl<T> MemSized for Option<T>
where T: MemSized
{
fn mem_bytes(&self) -> usize {
match self {
None => 0,
Some(s) => s.mem_bytes(),
}
}
}
15 changes: 8 additions & 7 deletions src/common/exception/src/exception_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ build_exceptions! {
BadBytes(1046),
InitPrometheusFailure(1047),
Overflow(1049),
AuthenticateFailure(1051),
TLSConfigurationFailure(1052),
UnknownSession(1053),
SHA1CheckFailed(1057),
Expand All @@ -123,7 +122,6 @@ build_exceptions! {
UnknownFormat(1074),
UnknownCompressionType(1075),
InvalidCompressionData(1076),
InvalidAuthInfo(1077),
InvalidTimezone(1078),
InvalidDate(1079),
InvalidTimestamp(1080),
Expand Down Expand Up @@ -420,11 +418,14 @@ build_exceptions! {

// Service errors [5001,6000].
build_exceptions! {
// A task that already stopped and can not stopped twice.
// A task that already stopped and can not stop twice.
AlreadyStopped(5002),

SessionTokenExpired(5100),
RefreshTokenExpired(5101),
SessionTokenNotFound(5102),
RefreshTokenNotFound(5103)
// auth related
AuthenticateFailure(5100),
// the flowing 4 code is used by clients
SessionTokenExpired(5101),
RefreshTokenExpired(5102),
SessionTokenNotFound(5103),
RefreshTokenNotFound(5104)
}
21 changes: 21 additions & 0 deletions src/meta/app/src/principal/client_session.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2021 Datafuse Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use serde::Deserialize;
use serde::Serialize;

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct ClientSession {
pub user_name: String,
}
60 changes: 60 additions & 0 deletions src/meta/app/src/principal/client_session_ident.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2021 Datafuse Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::tenant_key::ident::TIdent;

/// Define the meta-service key for a user setting.
pub type ClientSessionIdent = TIdent<Resource>;

pub use kvapi_impl::Resource;

mod kvapi_impl {

use databend_common_meta_kvapi::kvapi;

use crate::principal::client_session::ClientSession;
use crate::tenant_key::resource::TenantResource;

pub struct Resource;
impl TenantResource for Resource {
const PREFIX: &'static str = "__fd_session";
const TYPE: &'static str = "ClientSession";
const HAS_TENANT: bool = true;
type ValueType = ClientSession;
}

impl kvapi::Value for ClientSession {
fn dependency_keys(&self) -> impl IntoIterator<Item = String> {
[]
}
}
}

#[cfg(test)]
mod tests {
use databend_common_meta_kvapi::kvapi::Key;

use crate::principal::client_session_ident::ClientSessionIdent;
use crate::tenant::Tenant;

#[test]
fn test_setting_ident() {
let tenant = Tenant::new_literal("tenant1");
let ident = ClientSessionIdent::new(tenant.clone(), "test");
assert_eq!("__fd_session/tenant1/test", ident.to_string_key());

let got = ClientSessionIdent::from_str_key(&ident.to_string_key()).unwrap();
assert_eq!(ident, got);
}
}
2 changes: 2 additions & 0 deletions src/meta/app/src/principal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ mod user_stage;

mod ownership_object;

pub mod client_session;
pub mod client_session_ident;
pub mod connection_ident;
pub mod network_policy_ident;
pub mod password_policy_ident;
Expand Down
4 changes: 2 additions & 2 deletions src/meta/app/src/principal/user_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl FromStr for AuthType {
DOUBLE_SHA1_PASSWORD_STR => Ok(AuthType::DoubleSha1Password),
NO_PASSWORD_STR => Ok(AuthType::NoPassword),
JWT_AUTH_STR => Ok(AuthType::JWT),
_ => Err(ErrorCode::InvalidAuthInfo(AuthType::bad_auth_types(s))),
_ => Err(ErrorCode::AuthenticateFailure(AuthType::bad_auth_types(s))),
}
}
}
Expand Down Expand Up @@ -133,7 +133,7 @@ impl AuthInfo {
need_change,
})
}
None => Err(ErrorCode::InvalidAuthInfo("need password".to_string())),
None => Err(ErrorCode::AuthenticateFailure("need password".to_string())),
},
}
}
Expand Down
52 changes: 52 additions & 0 deletions src/meta/proto-conv/src/client_session_from_to_protobuf_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2021 Datafuse Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! This mod is the key point about compatibility.
//! Everytime update anything in this file, update the `VER` and let the tests pass.

use databend_common_meta_app::principal::client_session as mt;
use databend_common_protos::pb;

use crate::reader_check_msg;
use crate::FromToProto;
use crate::Incompatible;
use crate::MIN_READER_VER;
use crate::VER;

impl FromToProto for mt::ClientSession {
type PB = pb::ClientSession;

fn get_pb_ver(p: &Self::PB) -> u64 {
p.ver
}

fn from_pb(p: Self::PB) -> Result<Self, Incompatible>
where Self: Sized {
reader_check_msg(p.ver, p.min_reader_ver)?;

let v = Self {
user_name: p.user_name,
};
Ok(v)
}

fn to_pb(&self) -> Result<Self::PB, Incompatible> {
let p = pb::ClientSession {
ver: VER,
min_reader_ver: MIN_READER_VER,
user_name: self.user_name.clone(),
};
Ok(p)
}
}
1 change: 1 addition & 0 deletions src/meta/proto-conv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
mod background_job_from_to_protobuf_impl;
mod background_task_from_to_protobuf_impl;
mod catalog_from_to_protobuf_impl;
mod client_session_from_to_protobuf_impl;
mod config_from_to_protobuf_impl;
mod connection_from_to_protobuf_impl;
mod data_mask_from_to_protobuf_impl;
Expand Down
27 changes: 27 additions & 0 deletions src/meta/protos/proto/client_session.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2021 Datafuse Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// The identifier of a database by name. Names can be changed.
// There is no guarantee that two get-database request by name will return the
// same instance.

syntax = "proto3";

package databend_proto;

message ClientSession {
uint64 ver = 100;
uint64 min_reader_ver = 101;
string user_name = 2;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use std::time::Duration;
use databend_common_exception::Result;
use databend_common_meta_api::kv_pb_api::KVPbApi;
use databend_common_meta_api::kv_pb_api::UpsertPB;
use databend_common_meta_app::principal::client_session::ClientSession;
use databend_common_meta_app::principal::client_session_ident::ClientSessionIdent;
use databend_common_meta_app::principal::user_token::QueryTokenInfo;
use databend_common_meta_app::principal::user_token_ident::TokenIdent;
use databend_common_meta_app::tenant::Tenant;
Expand All @@ -29,14 +31,14 @@ use databend_common_meta_types::MetaError;
use databend_common_meta_types::Operation;
use databend_common_meta_types::With;

pub struct TokenMgr {
pub struct ClientSessionMgr {
kv_api: Arc<dyn kvapi::KVApi<Error = MetaError>>,
tenant: Tenant,
}

impl TokenMgr {
impl ClientSessionMgr {
pub fn create(kv_api: Arc<dyn kvapi::KVApi<Error = MetaError>>, tenant: &Tenant) -> Self {
TokenMgr {
ClientSessionMgr {
kv_api,
tenant: tenant.clone(),
}
Expand All @@ -45,9 +47,12 @@ impl TokenMgr {
fn token_ident(&self, token_hash: &str) -> TokenIdent {
TokenIdent::new(self.tenant.clone(), token_hash)
}
fn session_ident(&self, client_session_id: &str) -> ClientSessionIdent {
ClientSessionIdent::new(self.tenant.clone(), client_session_id)
}
}

impl TokenMgr {
impl ClientSessionMgr {
#[async_backtrace::framed]
#[fastrace::trace]
pub async fn upsert_token(
Expand Down Expand Up @@ -94,4 +99,39 @@ impl TokenMgr {

Ok(())
}

#[async_backtrace::framed]
#[fastrace::trace]
pub async fn upsert_client_session_id(
&self,
client_session_id: &str,
value: ClientSession,
ttl: Duration,
) -> Result<bool> {
let ident = self.session_ident(client_session_id);
let seq = MatchSeq::GE(0);
let upsert = UpsertPB::update(ident, value).with(seq).with_ttl(ttl);

let res = self.kv_api.upsert_pb(&upsert).await?;

Ok(res.prev.is_none())
}

#[async_backtrace::framed]
#[fastrace::trace]
pub async fn drop_client_session_id(&self, client_session_id: &str) -> Result<()> {
let key = self.session_ident(client_session_id).to_string_key();

// simply ignore the result
self.kv_api
.upsert_kv(UpsertKVReq::new(
&key,
MatchSeq::GE(0),
Operation::Delete,
None,
))
.await?;

Ok(())
}
}
4 changes: 2 additions & 2 deletions src/query/management/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ mod stage;
pub mod udf;
mod user;

mod client_session;
pub mod errors;
mod token;

pub use client_session::ClientSessionMgr;
pub use cluster::ClusterApi;
pub use cluster::ClusterMgr;
pub use connection::ConnectionMgr;
Expand All @@ -47,6 +48,5 @@ pub use setting::SettingApi;
pub use setting::SettingMgr;
pub use stage::StageApi;
pub use stage::StageMgr;
pub use token::TokenMgr;
pub use user::UserApi;
pub use user::UserMgr;
Loading
Loading