|
| 1 | +--- |
| 2 | +title: Admin panel |
| 3 | +--- |
| 4 | + |
| 5 | +The Cot admin panel provides an automatic interface for managing your models. It allows you to add, edit, delete and view records without writing any custom views or templates. This is perfect for prototyping your application and for managing your data in cases where you don't need a custom interface, as the Cot admin panel is automatically generated based on your models. |
| 6 | + |
| 7 | +## Enabling the Admin Interface |
| 8 | + |
| 9 | +First, add the admin app and the dependencies required to your project in `src/main.rs`: |
| 10 | + |
| 11 | +```rust |
| 12 | +use cot::admin::AdminApp; |
| 13 | +use cot::auth::db::{DatabaseUser, DatabaseUserApp}; |
| 14 | +use cot::middleware::SessionMiddleware; |
| 15 | +use cot::project::{MiddlewareContext, RegisterAppsContext, RootHandler, RootHandlerBuilder}; |
| 16 | +use cot::static_files::StaticFilesMiddleware; |
| 17 | + |
| 18 | +struct MyProject; |
| 19 | + |
| 20 | +impl Project for MyProject { |
| 21 | + fn register_apps(&self, apps: &mut AppBuilder, _context: &RegisterAppsContext) { |
| 22 | + apps.register(DatabaseUserApp::new()); // Needed for admin authentication |
| 23 | + apps.register_with_views(AdminApp::new(), "/admin"); // Register the admin app |
| 24 | + apps.register_with_views(MyApp, ""); |
| 25 | + } |
| 26 | + |
| 27 | + fn middlewares( |
| 28 | + &self, |
| 29 | + handler: RootHandlerBuilder, |
| 30 | + app_context: &MiddlewareContext, |
| 31 | + ) -> RootHandler { |
| 32 | + handler |
| 33 | + .middleware(StaticFilesMiddleware::from_context(app_context)) |
| 34 | + .middleware(SessionMiddleware::new()) // Required for admin login |
| 35 | + .build() |
| 36 | + } |
| 37 | + |
| 38 | + // ... |
| 39 | +} |
| 40 | +``` |
| 41 | + |
| 42 | +## Admin User Creation |
| 43 | + |
| 44 | +By default, the admin interface uses Cot's authentication system. Therefore, you need to create an admin user if it doesn't exist: |
| 45 | + |
| 46 | +```rust |
| 47 | +use async_trait::async_trait; // cargo add async-trait |
| 48 | +use cot::ProjectContext; |
| 49 | +use cot::auth::db::DatabaseUser; |
| 50 | +use cot::common_types::Password; |
| 51 | +use std::env; |
| 52 | + |
| 53 | +// In your main.rs: |
| 54 | +#[async_trait] |
| 55 | +impl App for MyApp { |
| 56 | + async fn init(&self, context: &mut ProjectContext) -> cot::Result<()> { |
| 57 | + // Check if admin user exists |
| 58 | + let admin_username = env::var("ADMIN_USER") |
| 59 | + .unwrap_or_else(|_| "admin".to_string()); |
| 60 | + let user = DatabaseUser::get_by_username(context.database(), &admin_username).await?; |
| 61 | + if user.is_none() { |
| 62 | + let password = env::var("ADMIN_PASSWORD") |
| 63 | + .unwrap_or_else(|_| "change_me".to_string()); |
| 64 | + // Create admin user |
| 65 | + DatabaseUser::create_user( |
| 66 | + context.database(), |
| 67 | + &admin_username, |
| 68 | + &Password::new(&password) |
| 69 | + ).await?; |
| 70 | + } |
| 71 | + Ok(()) |
| 72 | + } |
| 73 | +} |
| 74 | +``` |
| 75 | + |
| 76 | +## Registering Models in the Admin |
| 77 | + |
| 78 | +To make your models appear in the admin interface, you need to implement the `AdminModel` trait. The easiest way is to use the `#[derive(AdminModel)]` macro: |
| 79 | + |
| 80 | +```rust |
| 81 | +use cot::admin::AdminModel; |
| 82 | +use cot::db::{model, Auto}; |
| 83 | +use cot::form::Form; |
| 84 | + |
| 85 | +#[derive(Debug, Form, AdminModel)] |
| 86 | +#[model] |
| 87 | +struct BlogPost { |
| 88 | + #[model(primary_key)] |
| 89 | + id: Auto<i32>, |
| 90 | + title: String, |
| 91 | + content: String, |
| 92 | + published: bool, |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +Note however that in order to derive the `AdminModel` trait, you need to also derive the `Form` and `Model` traits (the latter is provided by the `#[model]` attribute). In addition to that, your model needs to implement the `Display` trait—for instance, in the case above, we could add it like so: |
| 97 | + |
| 98 | +```rust |
| 99 | +impl Display for BlogPost { |
| 100 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 101 | + write!(f, "{}", self.title) |
| 102 | + } |
| 103 | +} |
| 104 | +``` |
| 105 | + |
| 106 | +After adding the `AdminModel` trait, you can add your model to the admin panel using `DefaultAdminModelManager`. This is as easy as adding the following code to your `App` implementation: |
| 107 | + |
| 108 | +```rust |
| 109 | +impl App for MyApp { |
| 110 | + fn admin_model_managers(&self) -> Vec<Box<dyn AdminModelManager>> { |
| 111 | + vec![Box::new(DefaultAdminModelManager::<BlogPost>::new())] |
| 112 | + } |
| 113 | + |
| 114 | + // ... |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +Now your model can be managed through the admin interface at `http://localhost:8000/admin/`! |
| 119 | + |
| 120 | +## Summary |
| 121 | + |
| 122 | +In this chapter, you learned how to enable the Cot admin panel, create an admin user, and register your models in the admin interface. In the next chapter, we'll learn how to handle static assets in Cot. |
0 commit comments