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

Implement ability to update user principals #5220

Merged
merged 23 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions backend/canister_installer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ async fn install_service_canisters_impl(
local_user_index_canister_wasm: CanisterWasm::default(),
group_index_canister_id: canister_ids.group_index,
notifications_index_canister_id: canister_ids.notifications_index,
identity_canister_id: canister_ids.identity,
proposals_bot_canister_id: canister_ids.proposals_bot,
storage_index_canister_id: canister_ids.storage_index,
cycles_dispenser_canister_id: canister_ids.cycles_dispenser,
Expand Down Expand Up @@ -100,6 +101,7 @@ async fn install_service_canisters_impl(

let identity_canister_wasm = get_canister_wasm(CanisterName::Identity, version);
let identity_init_args = identity_canister::init::Args {
governance_principals: vec![principal],
user_index_canister_id: canister_ids.user_index,
cycles_dispenser_canister_id: canister_ids.cycles_dispenser,
wasm_version: version,
Expand Down
1 change: 1 addition & 0 deletions backend/canisters/community/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Expose details of timer jobs for public Communities ([#5154](https://github.com/open-chat-labs/open-chat/pull/5154))
- Notify community when p2p swap status changes ([#5201](https://github.com/open-chat-labs/open-chat/pull/5201))
- Implement `cancel_p2p_swap` for communities ([#5204](https://github.com/open-chat-labs/open-chat/pull/5204))
- Implement ability to update user principals ([#5220](https://github.com/open-chat-labs/open-chat/pull/5220))

### Changed

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use types::{UpdateUserPrincipalArgs, UpdateUserPrincipalResponse};

pub type Args = UpdateUserPrincipalArgs;
pub type Response = UpdateUserPrincipalResponse;
1 change: 1 addition & 0 deletions backend/canisters/community/api/src/updates/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod c2c_set_user_suspended;
pub mod c2c_tip_message;
pub mod c2c_unfreeze_community;
pub mod c2c_update_proposals;
pub mod c2c_update_user_principal;
pub mod cancel_invites;
pub mod cancel_p2p_swap;
pub mod change_channel_role;
Expand Down
6 changes: 6 additions & 0 deletions backend/canisters/community/impl/src/model/members.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,12 @@ impl CommunityMembers {
self.display_names_last_updated
}

pub fn update_user_principal(&mut self, old_principal: Principal, new_principal: Principal) {
if let Some(user_id) = self.principal_to_user_id_map.remove(&old_principal) {
self.principal_to_user_id_map.insert(new_principal, user_id);
}
}

pub fn mark_member_joined_channel(&mut self, user_id: &UserId, channel_id: ChannelId) {
if let Some(member) = self.members.get_mut(user_id) {
member.channels.insert(channel_id);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::guards::caller_is_user_index;
use crate::{mutate_state, run_regular_jobs, RuntimeState};
use canister_api_macros::update_msgpack;
use canister_tracing_macros::trace;
use community_canister::c2c_update_user_principal::*;

#[update_msgpack(guard = "caller_is_user_index")]
#[trace]
async fn c2c_update_user_principal(args: Args) -> Response {
run_regular_jobs();

mutate_state(|state| c2c_update_user_principal_impl(args, state))
}

fn c2c_update_user_principal_impl(args: Args, state: &mut RuntimeState) -> Response {
state
.data
.members
.update_user_principal(args.old_principal, args.new_principal);

Response::Success
}
1 change: 1 addition & 0 deletions backend/canisters/community/impl/src/updates/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod c2c_set_user_suspended;
pub mod c2c_tip_message;
pub mod c2c_unfreeze_community;
pub mod c2c_update_proposals;
pub mod c2c_update_user_principal;
pub mod cancel_invites;
pub mod cancel_p2p_swap;
pub mod change_channel_role;
Expand Down
1 change: 1 addition & 0 deletions backend/canisters/group/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Expose details of timer jobs for public Groups ([#5154](https://github.com/open-chat-labs/open-chat/pull/5154))
- Notify group when p2p swap status changes ([#5201](https://github.com/open-chat-labs/open-chat/pull/5201))
- Implement `cancel_p2p_swap` for groups ([#5204](https://github.com/open-chat-labs/open-chat/pull/5204))
- Implement ability to update user principals ([#5220](https://github.com/open-chat-labs/open-chat/pull/5220))

### Changed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
use candid::{CandidType, Principal};
use serde::{Deserialize, Serialize};
use types::{UpdateUserPrincipalArgs, UpdateUserPrincipalResponse};

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub old_principal: Principal,
pub new_principal: Principal,
}

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub enum Response {
Success,
UserNotFound,
}
pub type Args = UpdateUserPrincipalArgs;
pub type Response = UpdateUserPrincipalResponse;
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::guards::caller_is_user_index;
use crate::{mutate_state, run_regular_jobs, RuntimeState};
use canister_api_macros::update_msgpack;
use canister_tracing_macros::trace;
use group_canister::c2c_update_user_principal::{Response::*, *};
use group_canister::c2c_update_user_principal::*;

#[update_msgpack(guard = "caller_is_user_index")]
#[trace]
Expand All @@ -15,9 +15,6 @@ async fn c2c_update_user_principal(args: Args) -> Response {
fn c2c_update_user_principal_impl(args: Args, state: &mut RuntimeState) -> Response {
if let Some(user_id) = state.data.principal_to_user_id_map.remove(&args.old_principal) {
state.data.principal_to_user_id_map.insert(args.new_principal, user_id);

Success
} else {
UserNotFound
}
Response::Success
}
2 changes: 2 additions & 0 deletions backend/canisters/identity/api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod lifecycle;
mod updates;

pub use lifecycle::*;
pub use updates::*;
3 changes: 2 additions & 1 deletion backend/canisters/identity/api/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use candid::CandidType;
use candid::{CandidType, Principal};
use serde::{Deserialize, Serialize};
use types::{BuildVersion, CanisterId};

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub governance_principals: Vec<Principal>,
pub user_index_canister_id: CanisterId,
pub cycles_dispenser_canister_id: CanisterId,
pub wasm_version: BuildVersion,
Expand Down
1 change: 1 addition & 0 deletions backend/canisters/identity/api/src/updates/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod update_user_principal;
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ use serde::{Deserialize, Serialize};

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub struct Args {
pub old_principal: Principal,
pub new_principal: Principal,
}

#[derive(CandidType, Serialize, Deserialize, Debug)]
pub enum Response {
Success,
InternalError(String),
}
2 changes: 2 additions & 0 deletions backend/canisters/identity/impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ serializer = { path = "../../../libraries/serializer" }
stable_memory = { path = "../../../libraries/stable_memory" }
tracing = { workspace = true }
types = { path = "../../../libraries/types" }
user_index_canister = { path = "../../user_index/api" }
user_index_canister_c2c_client = { path = "../../user_index/c2c_client" }
utils = { path = "../../../libraries/utils" }
9 changes: 9 additions & 0 deletions backend/canisters/identity/impl/src/guards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use crate::read_state;

pub fn caller_is_governance_principal() -> Result<(), String> {
if read_state(|state| state.is_caller_governance_principal()) {
Ok(())
} else {
Err("Caller is not the governance principal".to_owned())
}
}
18 changes: 17 additions & 1 deletion backend/canisters/identity/impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use candid::Principal;
use canister_state_macros::canister_state;
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::collections::HashSet;
use types::{BuildVersion, CanisterId, Cycles, TimestampMillis, Timestamped};
use utils::env::Environment;

mod guards;
mod lifecycle;
mod memory;
mod queries;
mod updates;

thread_local! {
static WASM_VERSION: RefCell<Timestamped<BuildVersion>> = RefCell::default();
Expand All @@ -24,6 +28,11 @@ impl RuntimeState {
RuntimeState { env, data }
}

pub fn is_caller_governance_principal(&self) -> bool {
let caller = self.env.caller();
self.data.governance_principals.contains(&caller)
}

pub fn metrics(&self) -> Metrics {
Metrics {
memory_used: utils::memory::used(),
Expand All @@ -41,15 +50,22 @@ impl RuntimeState {

#[derive(Serialize, Deserialize)]
struct Data {
pub governance_principals: HashSet<Principal>,
pub user_index_canister_id: CanisterId,
pub cycles_dispenser_canister_id: CanisterId,
pub rng_seed: [u8; 32],
pub test_mode: bool,
}

impl Data {
pub fn new(user_index_canister_id: CanisterId, cycles_dispenser_canister_id: CanisterId, test_mode: bool) -> Data {
pub fn new(
governance_principals: HashSet<Principal>,
user_index_canister_id: CanisterId,
cycles_dispenser_canister_id: CanisterId,
test_mode: bool,
) -> Data {
Data {
governance_principals,
user_index_canister_id,
cycles_dispenser_canister_id,
rng_seed: [0; 32],
Expand Down
7 changes: 6 additions & 1 deletion backend/canisters/identity/impl/src/lifecycle/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ fn init(args: Args) {
init_cycles_dispenser_client(args.cycles_dispenser_canister_id, args.test_mode);

let env = init_env([0; 32]);
let data = Data::new(args.user_index_canister_id, args.cycles_dispenser_canister_id, args.test_mode);
let data = Data::new(
args.governance_principals.into_iter().collect(),
args.user_index_canister_id,
args.cycles_dispenser_canister_id,
args.test_mode,
);

init_state(env, data, args.wasm_version);

Expand Down
1 change: 1 addition & 0 deletions backend/canisters/identity/impl/src/updates/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod update_user_principal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::guards::caller_is_governance_principal;
use crate::read_state;
use canister_tracing_macros::trace;
use ic_cdk_macros::update;
use identity_canister::update_user_principal::{Response::*, *};

#[update(guard = "caller_is_governance_principal")]
#[trace]
async fn update_user_principal(args: Args) -> Response {
let user_index_canister_id = read_state(|state| state.data.user_index_canister_id);

match user_index_canister_c2c_client::c2c_update_user_principal(
user_index_canister_id,
&user_index_canister::c2c_update_user_principal::Args {
old_principal: args.old_principal,
new_principal: args.new_principal,
},
)
.await
{
Ok(user_index_canister::c2c_update_user_principal::Response::Success) => Success,
Ok(user_index_canister::c2c_update_user_principal::Response::InternalError(error)) => InternalError(error),
Err(error) => InternalError(format!("{error:?}")),
}
}
3 changes: 2 additions & 1 deletion backend/canisters/local_user_index/api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use types::nns::CryptoAmount;
use types::{
CanisterId, ChannelLatestMessageIndex, ChatId, CommunityId, Cryptocurrency, DiamondMembershipPlanDuration, MessageContent,
MessageIndex, PhoneNumber, ReferralType, SuspensionDuration, TimestampMillis, UserId,
MessageIndex, PhoneNumber, ReferralType, SuspensionDuration, TimestampMillis, UpdateUserPrincipalArgs, UserId,
};

mod lifecycle;
Expand All @@ -30,6 +30,7 @@ pub enum Event {
DiamondMembershipPaymentReceived(DiamondMembershipPaymentReceived),
OpenChatBotMessage(Box<OpenChatBotMessage>),
ReferralCodeAdded(ReferralCodeAdded),
UserPrincipalUpdated(UpdateUserPrincipalArgs),
}

#[derive(Serialize, Deserialize, Clone, Debug)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct Args {

pub user_index_canister_id: CanisterId,
pub group_index_canister_id: CanisterId,
pub identity_canister_id: CanisterId,
pub notifications_canister_id: CanisterId,
pub proposals_bot_canister_id: CanisterId,
pub cycles_dispenser_canister_id: CanisterId,
Expand Down
10 changes: 10 additions & 0 deletions backend/canisters/local_user_index/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ impl RuntimeState {
canister_ids: CanisterIds {
user_index: self.data.user_index_canister_id,
group_index: self.data.group_index_canister_id,
identity: self.data.identity_canister_id,
notifications: self.data.notifications_canister_id,
proposals_bot: self.data.proposals_bot_canister_id,
cycles_dispenser: self.data.cycles_dispenser_canister_id,
Expand All @@ -195,6 +196,8 @@ struct Data {
pub user_canister_wasm_for_upgrades: CanisterWasm,
pub user_index_canister_id: CanisterId,
pub group_index_canister_id: CanisterId,
#[serde(default = "identity_canister_id")]
pub identity_canister_id: CanisterId,
pub notifications_canister_id: CanisterId,
pub proposals_bot_canister_id: CanisterId,
pub cycles_dispenser_canister_id: CanisterId,
Expand All @@ -215,6 +218,10 @@ struct Data {
pub rng_seed: [u8; 32],
}

fn identity_canister_id() -> CanisterId {
CanisterId::from_text("6klfq-niaaa-aaaar-qadbq-cai").unwrap()
megrogan marked this conversation as resolved.
Show resolved Hide resolved
}

#[derive(Serialize, Deserialize)]
pub struct FailedMessageUsers {
pub sender: UserId,
Expand All @@ -227,6 +234,7 @@ impl Data {
user_canister_wasm: CanisterWasm,
user_index_canister_id: CanisterId,
group_index_canister_id: CanisterId,
identity_canister_id: CanisterId,
notifications_canister_id: CanisterId,
proposals_bot_canister_id: CanisterId,
cycles_dispenser_canister_id: CanisterId,
Expand All @@ -242,6 +250,7 @@ impl Data {
user_canister_wasm_for_upgrades: user_canister_wasm,
user_index_canister_id,
group_index_canister_id,
identity_canister_id,
notifications_canister_id,
proposals_bot_canister_id,
cycles_dispenser_canister_id,
Expand Down Expand Up @@ -291,6 +300,7 @@ pub struct Metrics {
pub struct CanisterIds {
pub user_index: CanisterId,
pub group_index: CanisterId,
pub identity: CanisterId,
pub notifications: CanisterId,
pub proposals_bot: CanisterId,
pub cycles_dispenser: CanisterId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ fn init(args: Args) {
args.user_canister_wasm,
args.user_index_canister_id,
args.group_index_canister_id,
args.identity_canister_id,
args.notifications_canister_id,
args.proposals_bot_canister_id,
args.cycles_dispenser_canister_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ impl GlobalUserMap {
self.diamond_membership_expiry_dates.insert(user_id, expires_at);
}

pub fn update_user_principal(&mut self, old_principal: Principal, new_principal: Principal) {
if let Some(user_id) = self.principal_to_user_id.remove(&old_principal) {
self.principal_to_user_id.insert(new_principal, user_id);
self.user_id_to_principal.insert(user_id, new_principal);
}
}

pub fn is_bot(&self, user_id: &UserId) -> bool {
self.bots.contains(user_id)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,11 @@ fn handle_event(event: Event, state: &mut RuntimeState) {
.referral_codes
.add(ev.referral_type, ev.code, ev.expiry, state.env.now());
}
Event::UserPrincipalUpdated(update) => {
state
.data
.global_users
.update_user_principal(update.old_principal, update.new_principal);
}
}
}
Loading
Loading