Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Hiding Sensitive Data

πŸ“‹ See test

Let’s add users to our task manager. Users have passwords, but we never want to expose password hashes.

A User Entity

#[derive(Clone, Debug, DeriveEntityModel, EntityToModels)]
#[crudcrate(generate_router)]
#[sea_orm(table_name = "users")]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    #[crudcrate(primary_key, exclude(create, update), on_create = Uuid::new_v4())]
    pub id: Uuid,

    #[crudcrate(filterable)]
    pub email: String,

    pub name: String,

    #[crudcrate(exclude(one, list))]  // Never return this
    pub password_hash: String,

    #[crudcrate(exclude(create, update), on_create = chrono::Utc::now())]
    pub created_at: DateTime<Utc>,
}

What exclude(one, list) Does

Exclude TargetEffect
oneHidden from GET /users/:id responses
listHidden from GET /users responses
one, listHidden from all GET responses

Test It

# Create a user (password_hash is accepted in POST)
curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "name": "Alice", "password_hash": "hashed123"}'

Response - no password_hash:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "email": "[email protected]",
  "name": "Alice",
  "created_at": "2024-01-15T10:30:00Z"
}
# List users - no password_hash
curl http://localhost:3000/users

# Get one user - no password_hash
curl http://localhost:3000/users/550e8400-e29b-41d4-a716-446655440000

All Exclude Options

AttributeEffectTest
exclude(create)Not in POST bodyπŸ“‹ See test
exclude(update)Not in PUT bodyπŸ“‹ See test
exclude(one)Not in GET /:id responseπŸ“‹ See test
exclude(list)Not in GET / responseπŸ“‹ See test

You can combine them:

// Auto-generated, never returned
#[crudcrate(exclude(create, update, one, list), on_create = Uuid::new_v4())]
pub internal_id: Uuid,

// Can create, can't update, hidden from lists
#[crudcrate(exclude(update, list))]
pub secret_code: String,

Excluding from Lists Only

Sometimes you want full data in detail views but not in lists:

#[crudcrate(exclude(list))]  // Show in GET /:id, hide in GET /
pub full_description: String,

This is useful for large fields that you don’t need in list views.


Summary

Our entities now have proper data protection:

Task - filtering, sorting, search, timestamps User - hidden password_hash

But tasks should belong to users. How do we connect them?

Next: Relationships - connect tasks to users.