-
-
Notifications
You must be signed in to change notification settings - Fork 40
docs: migrate docs from cot-site #489
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
Open
m4tx
wants to merge
21
commits into
master
Choose a base branch
from
docs2
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
470814c
feat: finish the rest of the guide chapters, add FAQ and Licenses pages
m4tx b1b7414
feat: add FAQ
m4tx 2832577
chore: fix invalid struct name in introduction
m4tx ead9edf
Secure admin user creation (#8)
mandarvaze de9a689
feat: add a Framework comparison page stub
m4tx 7acc764
docs: update guide introduction dynamic routes example (missing closi…
kecci e5f420f
chore: fix the code in admin-panel.md
m4tx e2feabd
feat: setup guide versioning (#17)
c1f4252
feat: add v0.2
m4tx 13bb90c
docs: update migrations command to match new cli version
seqre f44482c
docs: Fix Urls import path in Templates guide (#21)
julienr 6b4a12c
docs: optimize imports
m4tx 5d00681
docs: fix command typo in `db-models.md` (#28)
ClanEver 68b6672
feat: add v0.3 docs (#29)
m4tx 6fc1b74
feat: cot v0.4 docs, "master" version (#44)
m4tx e421209
feat: v0.5 docs (#60)
m4tx 170683b
chore: use cot::Template instead of askama::Template in guide (#62)
m4tx 937e45e
fix: admin user retrieval code in `admin-panel.md` (#64)
mjul 148de32
chore: remove disclaimer from introduction.md (#71)
m4tx e79c39c
chore: update on functionality of `cot::reverse` in docs (#73)
xelab04 36ed504
Add 'docs/' from commit 'e79c39c42cac3342e38638aced289b3a5b74ae44'
m4tx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| --- | ||
| title: Admin panel | ||
| --- | ||
|
|
||
| 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. | ||
|
|
||
| ## Enabling the Admin Interface | ||
|
|
||
| First, add the admin app and the dependencies required to your project in `src/main.rs`: | ||
|
|
||
| ```rust | ||
| use cot::admin::AdminApp; | ||
| use cot::auth::db::{DatabaseUser, DatabaseUserApp}; | ||
| use cot::middleware::SessionMiddleware; | ||
| use cot::project::{MiddlewareContext, RegisterAppsContext, RootHandler, RootHandlerBuilder}; | ||
| use cot::static_files::StaticFilesMiddleware; | ||
|
|
||
| struct MyProject; | ||
|
|
||
| impl Project for MyProject { | ||
| fn register_apps(&self, apps: &mut AppBuilder, _context: &RegisterAppsContext) { | ||
| apps.register(DatabaseUserApp::new()); // Needed for admin authentication | ||
| apps.register_with_views(AdminApp::new(), "/admin"); // Register the admin app | ||
| apps.register_with_views(MyApp, ""); | ||
| } | ||
|
|
||
| fn middlewares( | ||
| &self, | ||
| handler: RootHandlerBuilder, | ||
| app_context: &MiddlewareContext, | ||
| ) -> RootHandler { | ||
| handler | ||
| .middleware(StaticFilesMiddleware::from_context(app_context)) | ||
| .middleware(SessionMiddleware::new()) // Required for admin login | ||
| .build() | ||
| } | ||
|
|
||
| // ... | ||
| } | ||
| ``` | ||
|
|
||
| ## Admin User Creation | ||
|
|
||
| By default, the admin interface uses Cot's authentication system. Therefore, you need to create an admin user if it doesn't exist: | ||
|
|
||
| ```rust | ||
| use async_trait::async_trait; // cargo add async-trait | ||
| use cot::ProjectContext; | ||
| use cot::auth::db::DatabaseUser; | ||
| use cot::common_types::Password; | ||
| use std::env; | ||
|
|
||
| // In your main.rs: | ||
| #[async_trait] | ||
| impl App for MyApp { | ||
| async fn init(&self, context: &mut ProjectContext) -> cot::Result<()> { | ||
| // Check if admin user exists | ||
| let admin_username = env::var("ADMIN_USER") | ||
| .unwrap_or_else(|_| "admin".to_string()); | ||
| let user = DatabaseUser::get_by_username(context.database(), &admin_username).await?; | ||
| if user.is_none() { | ||
| let password = env::var("ADMIN_PASSWORD") | ||
| .unwrap_or_else(|_| "change_me".to_string()); | ||
| // Create admin user | ||
| DatabaseUser::create_user( | ||
| context.database(), | ||
| &admin_username, | ||
| &Password::new(&password) | ||
| ).await?; | ||
| } | ||
| Ok(()) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Registering Models in the Admin | ||
|
|
||
| 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: | ||
|
|
||
| ```rust | ||
| use cot::admin::AdminModel; | ||
| use cot::db::{model, Auto}; | ||
| use cot::form::Form; | ||
|
|
||
| #[derive(Debug, Form, AdminModel)] | ||
| #[model] | ||
| struct BlogPost { | ||
| #[model(primary_key)] | ||
| id: Auto<i32>, | ||
| title: String, | ||
| content: String, | ||
| published: bool, | ||
| } | ||
| ``` | ||
|
|
||
| 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: | ||
|
|
||
| ```rust | ||
| impl Display for BlogPost { | ||
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
| write!(f, "{}", self.title) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| 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: | ||
|
|
||
| ```rust | ||
| impl App for MyApp { | ||
| fn admin_model_managers(&self) -> Vec<Box<dyn AdminModelManager>> { | ||
| vec![Box::new(DefaultAdminModelManager::<BlogPost>::new())] | ||
| } | ||
|
|
||
| // ... | ||
| } | ||
| ``` | ||
|
|
||
| Now your model can be managed through the admin interface at `http://localhost:8000/admin/`! | ||
|
|
||
| ## Summary | ||
|
|
||
| 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. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| --- | ||
| title: Caching | ||
| --- | ||
|
|
||
| Cot provides a flexible caching system that allows you to store and retrieve data quickly, reducing the load on your database and improving response times. The caching system is designed to be pluggable, meaning you can switch between different cache backends without changing your application code. | ||
|
|
||
| ## Configuration | ||
|
|
||
| To use the caching system, you first need to configure it in your `ProjectConfig` (or via configuration files). | ||
|
|
||
| ### Configuration via TOML | ||
|
|
||
| You can configure the cache in your `config/*.toml` files: | ||
|
|
||
| ```toml | ||
| [cache] | ||
| prefix = "myapp" # Optional: prefix for all cache keys | ||
| max_retries = 3 # Optional: max retries for cache operations (default: 3) | ||
| timeout = "5s" # Optional: timeout for cache operations (default: 5s) | ||
|
|
||
| [cache.store] | ||
| type = "memory" # Options: "memory", "redis", "file" (if enabled) | ||
| ``` | ||
|
Comment on lines
+16
to
+23
|
||
|
|
||
| For Redis: | ||
|
|
||
| ```toml | ||
| [cache.store] | ||
| type = "redis" | ||
| url = "redis://127.0.0.1:6379" | ||
| pool_size = 20 # Optional: connection pool size | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| You can access the cache by using the `Cache` extractor. The cache interface provides standard methods like `get`, `insert`, `remove`, etc. | ||
|
|
||
| ```rust | ||
| use cot::cache::Cache; | ||
| use cot::html::Html; | ||
|
|
||
| async fn cache_example(cache: Cache) -> cot::Result<Html> { | ||
| // Insert a value (uses default expiration if set in config, or infinite) | ||
| cache.insert("user_1_name", "Alice").await?; | ||
|
|
||
| // Get a value | ||
| let name: Option<String> = cache.get("user_1_name").await?; | ||
|
|
||
| if let Some(n) = name { | ||
| println!("Found user: {}", n); | ||
| } | ||
|
|
||
| Ok(Html::new("OK")) | ||
| } | ||
| ``` | ||
|
|
||
| ### Expiration | ||
|
|
||
| You can set an expiration time for specific keys: | ||
|
|
||
| ```rust | ||
| use std::time::Duration; | ||
| use cot::config::Timeout; | ||
|
|
||
| // Cache for 60 seconds | ||
| cache.insert_expiring( | ||
| "temp_key", | ||
| "temp_value", | ||
| Timeout::After(Duration::from_secs(60)) | ||
| ).await?; | ||
| ``` | ||
|
|
||
| ## Advanced Topics | ||
|
|
||
| #### Lazy Computation | ||
|
|
||
| You can use `get_or_insert_with` to lazily compute and cache values: | ||
|
|
||
| ```rust | ||
| let value: String = cache.get_or_insert_with("expensive_key", || async { | ||
| // Perform expensive computation | ||
| Ok("expensive_result".to_string()) | ||
| }).await?; | ||
| ``` | ||
|
|
||
| #### Prefix | ||
|
|
||
| Sharing a cache instance between different environments (e.g., production and dev), or between different versions of the same | ||
| application can cause data collisions and bugs. To prevent this, you can specify a prefix for the cache keys. When a prefix | ||
| is set, all keys will be formatted as `{prefix}:{key}`, ensuring each server instance has its own isolated namespace. | ||
|
|
||
| The prefix can be set in the configuration file: | ||
|
|
||
| ```toml | ||
| [cache] | ||
| prefix = "v1" | ||
| ``` | ||
|
|
||
| ## Cache Backends | ||
|
|
||
| Cot supports the following cache backends: | ||
|
|
||
| - **Memory**: Stores data in memory. Fast, but data is lost when the server restarts. Good for development or short-lived cache. | ||
| - **Redis**: Stores data in a Redis instance. Persistent and shared across multiple server instances. Requires the `redis` feature. | ||
| - **File**: Stores data in files. Persistent but slower than memory/Redis. Requires configuring a path. | ||
|
|
||
| To use Redis, make sure to enable the `redis` feature in your `Cargo.toml`: | ||
|
|
||
| ```toml | ||
| [dependencies] | ||
| cot = { version = "0.5", features = ["redis"] } | ||
| ``` | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
SessionMiddleware::new()requires a session store argument; calling it with no args won’t compile. Also, the admin panel setup needsAuthMiddleware(seeexamples/admin/src/main.rs) to enforce authentication. Consider usingSessionMiddleware::from_context(...)and addingAuthMiddleware::new()in the middleware chain.