How to hide/show some json fields of a struct depending on the User role? We don't really want to create x different types of our struct. Or x types of an database user or multiple (same) sql commands. Do you guys have some recommendations? Which crate fits there? On Golang we used a reflect package to compare if the field tag containts the role.
The Export example should be equal like this:
Filtering with role user:
{
"id": "1",
"name": "Jack"
}
Filtering with role hr:
{
"id": "1",
"name": "Jack",
"salary": 100000,
"boss": {
"id": "2",
"name": "John",
"salary": 120000,
"password": "pwd",
"rights": {
"create": true,
"update": true
}
}
}
Filtering with role admin:
{
"id": "1",
"name": "Jack",
"salary": 100000,
"password": "password321",
"rights": {
"create": false,
"update": false
},
"boss": {
"id": "2",
"name": "John",
"salary": 120000,
"password": "pwd",
"rights": {
"create": true,
"update": true
}
}
}
These question is similar to the question and answer asked with the language golang GOALNG :Control field visibility depending on User role but how does it look like in rust?
CodePudding user response:
The most commonly used JSON crate in Rust is serde. One way you can achieve what you want is to create different Values, depending on user's role (by using the json! macro or by manually creating Value instances, for example). Another is to use enums with 3 variants - one variant for each user role (see Enum representations).
As a side note, I couldn't help but notice you are returning passwords in your JSON. That really looks like a serious security problem and I can hardly think of situations where I would want to return even encoded passwords to the client. Normally, passwords only go "one way": from the client to the server.
CodePudding user response:
Complementary to at54321's solution, you don't actually have to duplicate the struct itself, instead you can use flattening and / or conditional serialisation skipping e.g.
#[derive(Serialize)]
struct User {
id: String,
name: String,
#[serde(flatten, skip_serializing_if = "Option::is_none")]
_hr: Option<HrView>,
#[serde(flatten, skip_serializing_if = "Option::is_none")]
_admin: Option<AdminView>
}
#[derive(Serialize)]
struct HrView {
salary: u32,
#[serde(skip_serializing_if = "Option::is_none")]
boss: Option<Box<User>>
}
#[derive(Serialize)]
struct AdminView {
password: String,
rights: Rights,
}
#[derive(Serialize)]
struct Rights {
create: bool,
update: bool
}
