-
Notifications
You must be signed in to change notification settings - Fork 1
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
Set default security shield API #362
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #362 +/- ##
==========================================
+ Coverage 92.59% 92.64% +0.04%
==========================================
Files 1172 1180 +8
Lines 26255 26618 +363
Branches 81 77 -4
==========================================
+ Hits 24312 24660 +348
- Misses 1932 1947 +15
Partials 11 11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
}); | ||
} | ||
|
||
Ok(p.app_preferences |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer creating a method for this inside Profile logic crate.
Better to delegate as much logic relating to profile changes as possible to Profile logic crate. And let SargonOS be a as dumb as possible "coordinator"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm you mean in the profile_update.rs
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done ?
&mut self, | ||
shield_id: &SecurityStructureID, | ||
) -> Result<bool> { | ||
Ok(self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why return Result
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ID not found. Right.
So do you map to correct Error if not found?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as I wrote in #362 (review) there should be an update method on AppPreferences , which should actually should delegate to Security
which should have this impl, but you need to change the impl to actually return an Error if not found - which you are not doing now. So Result<()>
is correct, but now you are incorrectly returning Bool
which you unconditionally wrap in a Result
.
impl Security {
/// # Throws
/// Throws `CommonError:InvalidSecurityStructureID` if the structure identified by `shield_id` does not exist.
fn update_security_structure_remove_flag_default(
&mut self,
shield_id: &SecurityStructureID,
) -> Result<()> {
self
.security_structures_of_factor_source_ids
.try_update_with(shield_id, |s| {
s.metadata.remove_flag(SecurityStructureFlag::Default)
}))
.map(|_| CommonError::InvalidSecurityStructureID { bad_value: shield_id.to_string() })
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and then ofc unit test all the way :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why you want reusable functions and not having profile logic in SargonOS, but I don't understand at all where am I supposed to place the new functions. The way the profile-logic is structured doesn't really help me.
Therefore we need the following functions:
update_security_structure_remove_flag_default
: where this is supposed to go? in (profile crate)models/app_preferences
, I see there is a query fun therehas_gateway_with_url
. But it doesn't seem the right place to me. Should it be in theprofile_update
? Should I create asecurity_structures_logic
file underprofile/logic
?update_security_structure_set_flag_default
: same as aboveget_default_scurity_structure
: a new filequery_app_preferences
underprofile/logic
? or in themodels/app_preferences
?set_default_security_structure
: it looks like it has to toprofile_update
or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean you should do this - favour composition of many small resusable functions, instead of a bigger function which is not reausable.
The idea of SargonOS is to not have Profile model logic. So it should delegate that logic to profile-logic
crate.
// In os-factors crate
async fn set_default_security_structure(
&self,
shield_id: SecurityStructureID,
) -> Result<()> {
let updated_ids = self.update_profile_with(|p| Ok(p.set_default_security_structure(shield_id)))?;
// Emit event
self.event_bus
.emit(EventNotification::profile_modified(
EventProfileModified::SecurityStructuresUpdated {
ids: updated_ids,
},
))
.await;
Ok(())
}
// In Profile Logic crate
impl AppPreferences {
fn get_default_scurity_structure(&self) -> Option<SecurityStructureOfFactorSourceIds> {
self
.security
.security_structures_of_factor_source_ids
.iter()
.find(|s| s.metadata.is_default());
}
}
impl Profile {
fn get_default_Security_structure(&self) -> Option<SecurityStructureOfFactorSourceIds> {
self
.app_preferences.get_default_security_structure()
}
/// Returns the list of IDs of updated SecurityShields - either one or two elements,
/// depending on if shield identified by `shield_id` already was "default" shield or not.
fn set_default_security_structure(
&self,
shield_id: SecurityStructureID,
) -> Result<<Vec<SecurityStructureID>> {
let current_default_shield = self.get_default_Security_structure();
let updated_ids = match current_default_shield {
Some(ref current_default_shield) => {
vec![current_default_shield.metadata.id, shield_id]
}
None => vec![shield_id],
};
if let Some(current_default_shield) = ¤t_default_shield {
self.update_security_structure_remove_flag_default(
¤t_default_shield.metadata.id,
)
}
p.update_security_structure_add_flag_default(&shield_id)
updated_ids
}
}
/// Used to mark a Security Shield as "default". We can only have one. | ||
Default, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we call it Main
as we do on FactorSourceFlag
(despite in UI it will be treated as "default")?
If so, I would update the name of every related function as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it’s not exactly the same. “Main” indicates the primary or most important option, while “default” refers to something preselected. That’s why in UI, it is (correctly) defined as “default.”
Based on that, do you really think we should treat it as “main” in the code? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they are both (Device Factor Sources & Security Shields) kind of the same. Nothing prevents using a non-main factor source/security shield, but host apps will use the main one when either creating/securifying an entity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah main
in code makes sense to call it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have democracy, so if the majority agrees, I will change it 😄
) | ||
} | ||
|
||
pub fn set_flag(&mut self, flag: SecurityStructureFlag) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
insert_flag
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅
assert!(event_bus_driver.recorded().iter().any(|e| e.event | ||
== Event::ProfileModified { | ||
change: EventProfileModified::SecurityStructuresUpdated { | ||
ids: vec![structure_ids_sample_other.metadata.id()] | ||
} | ||
})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to check ProfileSaved
was emitted as well
Also, we should check that SecurityStructuresUpdated
is emitted with two ids when there was an existent main shield, and with one id when there isn't
…tructures_update for AppPreferences logic
This PR is part of the ABW-4146.
It adds an API to change the default security shield