use crate::db::internal::unsafe_get_doc;
use crate::db::store::internal_set_doc_store;
use crate::db::types::store::AssertSetDocOptions;
use crate::errors::user::JUNO_DATASTORE_ERROR_USER_REGISTER_PROVIDER_INVALID_DATA;
use crate::rules::store::get_rule_db;
use crate::user::core::types::state::{OpenIdData, ProviderData, UserData};
use crate::Doc;
use candid::Principal;
use junobuild_auth::delegation::types::UserKey;
use junobuild_auth::openid::credentials::delegation::types::interface::OpenIdDelegationCredential;
use junobuild_auth::openid::types::provider::OpenIdDelegationProvider;
use junobuild_collections::constants::db::COLLECTION_USER_KEY;
use junobuild_collections::msg::msg_db_collection_not_found;
use junobuild_shared::ic::api::id;
use junobuild_utils::decode_doc_data;
pub fn register_user(
public_key: &UserKey,
provider: &OpenIdDelegationProvider,
credential: &OpenIdDelegationCredential,
) -> Result<Doc, String> {
let user_collection = COLLECTION_USER_KEY.to_string();
let rule = get_rule_db(&user_collection)
.ok_or_else(|| msg_db_collection_not_found(&user_collection))?;
let user_id = Principal::self_authenticating(public_key);
let user_key = user_id.to_text();
let current_user = unsafe_get_doc(&user_collection.to_string(), &user_key, &rule)?;
let current_user_data = if let Some(current_user) = ¤t_user {
Some(decode_doc_data::<UserData>(¤t_user.data)?)
} else {
None
};
let banned = current_user_data
.as_ref()
.and_then(|user_data| user_data.banned.clone());
let existing_provider_data: Option<&OpenIdData> = match current_user_data.as_ref() {
None => None, Some(user_data) => match user_data.provider_data.as_ref() {
Some(ProviderData::OpenId(provider_data)) => Some(provider_data),
_ => return Err(JUNO_DATASTORE_ERROR_USER_REGISTER_PROVIDER_INVALID_DATA.to_string()),
},
};
if let (Some(existing_provider_data), Some(current_user)) =
(existing_provider_data, current_user.as_ref())
{
let new_provider_data = OpenIdData::from(credential);
if *existing_provider_data == new_provider_data {
return Ok(current_user.clone());
}
}
let provider_data = if let Some(existing_provider_data) = existing_provider_data {
OpenIdData::merge(existing_provider_data, credential)
} else {
OpenIdData::from(credential)
};
let caller = if existing_provider_data.is_some() {
id()
} else {
user_id
};
let user_data: UserData = UserData {
banned,
provider: Some(provider.into()),
provider_data: Some(ProviderData::OpenId(provider_data)),
};
let user_data = UserData::prepare_set_doc(&user_data, ¤t_user)?;
let assert_options = AssertSetDocOptions {
with_assert_rate: false,
};
let result = internal_set_doc_store(
caller,
user_collection,
user_key,
user_data,
&assert_options,
)?;
Ok(result.data.after)
}