cleanup examples
This commit is contained in:
parent
48e57a2e10
commit
ce964220b7
18
Cargo.toml
18
Cargo.toml
@ -15,17 +15,17 @@ exclude = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4.0.1"
|
actix-web = "^4.0.1"
|
||||||
actix-session = { version = "0.7.1", features = [] }
|
actix-session = { version = "^0.7.1", features = [] }
|
||||||
actix-multipart = "0.4.0"
|
actix-multipart = "^0.4.0"
|
||||||
futures-util = "0.3.21"
|
futures-util = "0.3.21"
|
||||||
chrono = "0.4.20"
|
chrono = "0.4.20"
|
||||||
tera = "1.16.0"
|
tera = "^1.16.0"
|
||||||
async-trait = "0.1.53"
|
async-trait = "^0.1.53"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "^1.4.0"
|
||||||
itertools = "0.10.3"
|
itertools = "^0.10.3"
|
||||||
serde = "1.0.136"
|
serde = "^1.0.136"
|
||||||
serde_derive = "1.0.136"
|
serde_derive = "^1.0.136"
|
||||||
sea-orm = { version = "^0.9.1", features = [], default-features = false }
|
sea-orm = { version = "^0.9.1", features = [], default-features = false }
|
||||||
actix-admin-macros = { version = "0.2.0", path = "actix_admin_macros" }
|
actix-admin-macros = { version = "0.2.0", path = "actix_admin_macros" }
|
||||||
derive_more = "0.99.17"
|
derive_more = "0.99.17"
|
||||||
|
@ -38,7 +38,6 @@ pub fn derive_actix_admin(_input: proc_macro::TokenStream) -> proc_macro::TokenS
|
|||||||
EntityTrait
|
EntityTrait
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use actix_session::{Session};
|
|
||||||
};
|
};
|
||||||
proc_macro::TokenStream::from(expanded)
|
proc_macro::TokenStream::from(expanded)
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ layout: default
|
|||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
* See the [example](https://github.com/mgugger/actix-admin/tree/main/example) and run with ```cargo run```.
|
* See the [basic example](https://github.com/mgugger/actix-admin/tree/main/examples/basic) and run with ```cargo run```.
|
||||||
* See the step by [step tutorial](https://github.com/mgugger/actix-admin/tree/main/example/StepbyStep.md)
|
|
||||||
|
|
||||||
## Quick overview
|
## Quick overview
|
||||||
|
|
||||||
@ -15,21 +14,14 @@ sea-orm = { version = "^0.9.1", features = [ "sqlx-sqlite", "runtime-actix-nativ
|
|||||||
actix_admin = { version = "^0.2.0" }
|
actix_admin = { version = "^0.2.0" }
|
||||||
```
|
```
|
||||||
|
|
||||||
### See inlined steps
|
### Steps
|
||||||
|
1. Import ActixAdmin in the main.rs and your database models:
|
||||||
```rust
|
```rust
|
||||||
use sea_orm::entity::prelude::*;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use actix_admin::prelude::*;
|
|
||||||
use actix_web::web;
|
|
||||||
use actix_web::App;
|
|
||||||
use actix_web::HttpServer;
|
|
||||||
use sea_orm::entity::prelude::*;
|
|
||||||
use sea_orm::entity::prelude::*;
|
|
||||||
use actix_admin::prelude::*;
|
|
||||||
// 1. Import ActixAdmin
|
|
||||||
use actix_admin::prelude::*;
|
use actix_admin::prelude::*;
|
||||||
|
```
|
||||||
|
|
||||||
// 2. Use DeriveActixAmin* Macros to implement the traits for the model
|
2. Use the DeriveActixAdminMacros on the Database models to implement required traits:
|
||||||
|
```rust
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize,
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize,
|
||||||
DeriveActixAdmin, DeriveActixAdminModel, DeriveActixAdminViewModel
|
DeriveActixAdmin, DeriveActixAdminModel, DeriveActixAdminViewModel
|
||||||
)]
|
)]
|
||||||
@ -41,20 +33,19 @@ pub struct Model {
|
|||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub comment: String
|
pub comment: String
|
||||||
}
|
}
|
||||||
impl ActixAdminModelValidationTrait<ActiveModel> for Entity {}
|
```
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
3. Add ActixAdmin to the actix admin app state
|
||||||
pub enum Relation { }
|
```rust
|
||||||
|
|
||||||
// 3. Add actix-admin to the AppState
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub db: DatabaseConnection,
|
pub db: DatabaseConnection,
|
||||||
pub actix_admin: ActixAdmin,
|
pub actix_admin: ActixAdmin,
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
// 4. Implement the ActixAdminAppDataTrait for the AppState
|
4. Implement the ActixAdminAppDataTrait for the AppState
|
||||||
|
```rust
|
||||||
impl ActixAdminAppDataTrait for AppState {
|
impl ActixAdminAppDataTrait for AppState {
|
||||||
fn get_db(&self) -> &DatabaseConnection {
|
fn get_db(&self) -> &DatabaseConnection {
|
||||||
&self.db
|
&self.db
|
||||||
@ -64,8 +55,10 @@ impl ActixAdminAppDataTrait for AppState {
|
|||||||
&self.actix_admin
|
&self.actix_admin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
// 5. Setup the actix admin configuration
|
5. Setup the actix admin configuration and add database models to it in main.rs
|
||||||
|
```rust
|
||||||
pub fn create_actix_admin_builder() -> ActixAdminBuilder {
|
pub fn create_actix_admin_builder() -> ActixAdminBuilder {
|
||||||
let comment_view_model = ActixAdminViewModel::from(Entity);
|
let comment_view_model = ActixAdminViewModel::from(Entity);
|
||||||
|
|
||||||
@ -81,21 +74,25 @@ pub fn create_actix_admin_builder() -> ActixAdminBuilder {
|
|||||||
|
|
||||||
admin_builder
|
admin_builder
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
// 6. Add to the actix app
|
6. Add to the actix app in main.rs
|
||||||
let actix_admin = create_actix_admin_builder().get_actix_admin();
|
```rust
|
||||||
let opt = ConnectOptions::new("sqlite::memory:".to_owned());
|
let opt = ConnectOptions::new("sqlite::memory:".to_owned());
|
||||||
let conn = sea_orm::Database::connect(opt).unwrap();
|
let conn = sea_orm::Database::connect(opt).unwrap();
|
||||||
let app_state = AppState {
|
|
||||||
db: conn,
|
|
||||||
actix_admin: actix_admin,
|
|
||||||
};
|
|
||||||
|
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
|
let actix_admin_builder = create_actix_admin_builder();
|
||||||
|
|
||||||
|
let app_state = AppState {
|
||||||
|
db: conn.clone(),
|
||||||
|
actix_admin: actix_admin_builder.get_actix_admin(),
|
||||||
|
};
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
//.app_data(web::Data::new(app_state.clone()))
|
.app_data(web::Data::new(app_state.clone()))
|
||||||
.service(
|
.service(
|
||||||
create_actix_admin_builder().get_scope::<AppState>()
|
actix_admin_builder.get_scope::<AppState>()
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -6,16 +6,16 @@ list_title: ' '
|
|||||||
The actix-admin crate aims at creating a web admin interface similar to other admin interfaces (such as [flask-admin](https://github.com/flask-admin/flask-admin) in python).
|
The actix-admin crate aims at creating a web admin interface similar to other admin interfaces (such as [flask-admin](https://github.com/flask-admin/flask-admin) in python).
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
1. Async: Builds on [sea-orm](https://crates.io/crates/sea-orm) for the database backend
|
1. Async: Builds on [sea-orm](https://crates.io/crates/sea-orm) as the database backend
|
||||||
2. Macros: Generate the required implementations for models automatically
|
2. Macros generate the required implementations for models
|
||||||
3. Authentication: optionally pass authentication handler to implement authentication for views
|
3. Authentication: optionally pass authentication handler to implement authentication for views
|
||||||
4. Supports custom validation rules
|
4. Supports custom validation rules
|
||||||
5. Searchable attributes can be specified
|
5. Searchable attributes can be specified
|
||||||
6. Supports custom views which are added to the Navbar
|
6. Supports custom views, handlers and groups in the Navbar
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
Check the [example](https://github.com/mgugger/actix-admin/tree/main/example) and run with ```cargo run```. The admin interface is accessible under ```localhost:5000/admin/```.
|
Check the [examples](https://github.com/mgugger/actix-admin/tree/main/examples) and run with ```cargo run```. The admin interface is accessible under ```localhost:5000/admin/```.
|
||||||
|
|
||||||
## Screenshot
|
## Screenshot
|
||||||
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
DATABASE_URL=sqlite://database.db
|
|
||||||
OAUTH2_CLIENT_SECRET= "TODO"
|
|
||||||
OAUTH2_CLIENT_ID= "TODO"
|
|
||||||
OAUTH2_SERVER= URL + TenantId like "login.microsoftonline.com/a5f5xxxx-xxxx-414a-8463-xxxxxxxxxxxxx"
|
|
@ -1 +0,0 @@
|
|||||||
# TODO
|
|
12
examples/basic/Cargo.toml
Normal file
12
examples/basic/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "actix-admin-example"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = "4.0.1"
|
||||||
|
actix-rt = "2.7.0"
|
||||||
|
serde = "1.0.136"
|
||||||
|
serde_derive = "1.0.136"
|
||||||
|
sea-orm = { version = "^0.9.1", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = true }
|
||||||
|
actix-admin = { path = "../../" }
|
86
examples/basic/src/main.rs
Normal file
86
examples/basic/src/main.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
use actix_admin::prelude::*;
|
||||||
|
use actix_web::{web, App, HttpServer, middleware};
|
||||||
|
use sea_orm::{ConnectOptions, DatabaseConnection};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
mod entity;
|
||||||
|
use entity::{Post, Comment};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AppState {
|
||||||
|
pub db: DatabaseConnection,
|
||||||
|
pub actix_admin: ActixAdmin,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActixAdminAppDataTrait for AppState {
|
||||||
|
fn get_db(&self) -> &DatabaseConnection {
|
||||||
|
&self.db
|
||||||
|
}
|
||||||
|
fn get_actix_admin(&self) -> &ActixAdmin {
|
||||||
|
&self.actix_admin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_actix_admin_builder() -> ActixAdminBuilder {
|
||||||
|
let post_view_model = ActixAdminViewModel::from(Post);
|
||||||
|
let comment_view_model = ActixAdminViewModel::from(Comment);
|
||||||
|
|
||||||
|
let configuration = ActixAdminConfiguration {
|
||||||
|
enable_auth: false,
|
||||||
|
user_is_logged_in: None,
|
||||||
|
login_link: None,
|
||||||
|
logout_link: None
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut admin_builder = ActixAdminBuilder::new(configuration);
|
||||||
|
|
||||||
|
let some_category = "Groupings";
|
||||||
|
admin_builder.add_entity::<AppState, Post>(&post_view_model);
|
||||||
|
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category);
|
||||||
|
|
||||||
|
admin_builder
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_db_options() -> ConnectOptions {
|
||||||
|
let db_url = "sqlite::memory:".to_string();
|
||||||
|
let mut opt = ConnectOptions::new(db_url);
|
||||||
|
opt.max_connections(100)
|
||||||
|
.min_connections(5)
|
||||||
|
.connect_timeout(Duration::from_secs(8))
|
||||||
|
.idle_timeout(Duration::from_secs(8))
|
||||||
|
.sqlx_logging(true);
|
||||||
|
opt
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::main]
|
||||||
|
async fn main() {
|
||||||
|
let opt = get_db_options();
|
||||||
|
let conn = sea_orm::Database::connect(opt).await.unwrap();
|
||||||
|
let _ = entity::create_post_table(&conn).await;
|
||||||
|
|
||||||
|
println!("The admin interface will be available at http://localhost:5000/admin/");
|
||||||
|
|
||||||
|
HttpServer::new(move || {
|
||||||
|
|
||||||
|
let actix_admin_builder = create_actix_admin_builder();
|
||||||
|
|
||||||
|
let app_state = AppState {
|
||||||
|
db: conn.clone(),
|
||||||
|
actix_admin: actix_admin_builder.get_actix_admin(),
|
||||||
|
};
|
||||||
|
|
||||||
|
App::new()
|
||||||
|
.app_data(web::Data::new(app_state))
|
||||||
|
.service(
|
||||||
|
actix_admin_builder.get_scope::<AppState>()
|
||||||
|
)
|
||||||
|
.wrap(middleware::Logger::default())
|
||||||
|
})
|
||||||
|
.bind("127.0.0.1:5000")
|
||||||
|
.expect("Can not bind to port 5000")
|
||||||
|
.run()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
15
examples/basic/templates/index.html
Normal file
15
examples/basic/templates/index.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Actix Admin Example</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/admin/">Go to Actix-Admin</a></li>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
3
examples/with_azure_auth/.env.example
Normal file
3
examples/with_azure_auth/.env.example
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
OAUTH2_CLIENT_SECRET= "TODO"
|
||||||
|
OAUTH2_CLIENT_ID= "TODO"
|
||||||
|
OAUTH2_SERVER= "login.microsoftonline.com/a5f5xxxx-xxxx-414a-8463-xxxxxxxxxxxxx(tenantId)"
|
@ -13,5 +13,5 @@ dotenv = "0.15"
|
|||||||
serde = "1.0.136"
|
serde = "1.0.136"
|
||||||
serde_derive = "1.0.136"
|
serde_derive = "1.0.136"
|
||||||
sea-orm = { version = "^0.9.1", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = true }
|
sea-orm = { version = "^0.9.1", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = true }
|
||||||
actix-admin = { path = "../" }
|
actix-admin = { path = "../../" }
|
||||||
azure_auth = { path = "./azure_auth" }
|
azure_auth = { path = "./azure_auth" }
|
1
examples/with_azure_auth/README.md
Normal file
1
examples/with_azure_auth/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Rename .env.example to .env and update the oauth client credentials
|
51
examples/with_azure_auth/src/entity/comment.rs
Normal file
51
examples/with_azure_auth/src/entity/comment.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use actix_admin::prelude::*;
|
||||||
|
use super::Post;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize, DeriveActixAdmin, DeriveActixAdminModel, DeriveActixAdminViewModel)]
|
||||||
|
#[sea_orm(table_name = "comment")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
#[actix_admin(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub comment: String,
|
||||||
|
#[sea_orm(column_type = "Text")]
|
||||||
|
#[actix_admin(html_input_type = "email")]
|
||||||
|
pub user: String,
|
||||||
|
#[sea_orm(column_type = "DateTime")]
|
||||||
|
pub insert_date: DateTime,
|
||||||
|
pub is_visible: bool,
|
||||||
|
#[actix_admin(select_list="Post")]
|
||||||
|
pub post_id: Option<i32>,
|
||||||
|
pub my_decimal: Decimal
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::post::Entity",
|
||||||
|
from = "Column::PostId",
|
||||||
|
to = "super::post::Column::Id"
|
||||||
|
)]
|
||||||
|
Post,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::post::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Post.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
impl ActixAdminModelValidationTrait<ActiveModel> for Entity {
|
||||||
|
fn validate(model: &ActiveModel) -> HashMap<String, String> {
|
||||||
|
let mut errors = HashMap::new();
|
||||||
|
if model.my_decimal.clone().unwrap() < Decimal::from(100 as i16) {
|
||||||
|
errors.insert("my_decimal".to_string(), "Must be larger than 100".to_string());
|
||||||
|
}
|
||||||
|
errors
|
||||||
|
}
|
||||||
|
}
|
62
examples/with_azure_auth/src/entity/mod.rs
Normal file
62
examples/with_azure_auth/src/entity/mod.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// setup
|
||||||
|
use sea_orm::sea_query::{ForeignKeyCreateStatement, ColumnDef, TableCreateStatement};
|
||||||
|
use sea_orm::{error::*, sea_query, ConnectionTrait, DbConn, ExecResult};
|
||||||
|
pub mod comment;
|
||||||
|
pub mod post;
|
||||||
|
pub use comment::Entity as Comment;
|
||||||
|
pub use post::Entity as Post;
|
||||||
|
|
||||||
|
// setup
|
||||||
|
async fn create_table(db: &DbConn, stmt: &TableCreateStatement) -> Result<ExecResult, DbErr> {
|
||||||
|
let builder = db.get_database_backend();
|
||||||
|
db.execute(builder.build(stmt)).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_post_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||||
|
let stmt = sea_query::Table::create()
|
||||||
|
.table(post::Entity)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(post::Column::Id)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.auto_increment()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(post::Column::Title).string().not_null())
|
||||||
|
.col(ColumnDef::new(post::Column::Text).string().not_null())
|
||||||
|
.col(ColumnDef::new(post::Column::TeaMandatory).string().not_null())
|
||||||
|
.col(ColumnDef::new(post::Column::TeaOptional).string())
|
||||||
|
.col(ColumnDef::new(post::Column::InsertDate).date())
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
let _result = create_table(db, &stmt).await;
|
||||||
|
|
||||||
|
let stmt = sea_query::Table::create()
|
||||||
|
.table(comment::Entity)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(post::Column::Id)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.auto_increment()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(comment::Column::Comment).string().not_null())
|
||||||
|
.col(ColumnDef::new(comment::Column::User).string().not_null())
|
||||||
|
.col(ColumnDef::new(comment::Column::InsertDate).date_time().not_null())
|
||||||
|
.col(ColumnDef::new(comment::Column::IsVisible).boolean().not_null())
|
||||||
|
.col(ColumnDef::new(comment::Column::MyDecimal).decimal().not_null())
|
||||||
|
.col(ColumnDef::new(comment::Column::PostId).integer())
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKeyCreateStatement::new()
|
||||||
|
.name("fk-comment-post")
|
||||||
|
.from_tbl(Comment)
|
||||||
|
.from_col(comment::Column::PostId)
|
||||||
|
.to_tbl(Post)
|
||||||
|
.to_col(post::Column::Id),
|
||||||
|
)
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
create_table(db, &stmt).await
|
||||||
|
}
|
79
examples/with_azure_auth/src/entity/post.rs
Normal file
79
examples/with_azure_auth/src/entity/post.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use actix_admin::prelude::*;
|
||||||
|
use std::fmt;
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize, DeriveActixAdmin, DeriveActixAdminViewModel, DeriveActixAdminModel, DeriveActixAdminModelSelectList)]
|
||||||
|
#[sea_orm(table_name = "post")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
#[actix_admin(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
#[actix_admin(searchable)]
|
||||||
|
pub title: String,
|
||||||
|
#[sea_orm(column_type = "Text")]
|
||||||
|
#[actix_admin(searchable, textarea)]
|
||||||
|
pub text: String,
|
||||||
|
#[actix_admin(select_list="Tea")]
|
||||||
|
pub tea_mandatory: Tea,
|
||||||
|
#[actix_admin(select_list="Tea")]
|
||||||
|
pub tea_optional: Option<Tea>,
|
||||||
|
pub insert_date: Date,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Model {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match &*self {
|
||||||
|
_ => write!(formatter, "{} {}", &self.title, &self.insert_date),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(has_many = "super::comment::Entity")]
|
||||||
|
Comment,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::comment::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Comment.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, EnumIter, DeriveActiveEnum, Deserialize, Serialize, DeriveActixAdminEnumSelectList)]
|
||||||
|
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "tea")]
|
||||||
|
pub enum Tea {
|
||||||
|
#[sea_orm(string_value = "EverydayTea")]
|
||||||
|
EverydayTea,
|
||||||
|
#[sea_orm(string_value = "BreakfastTea")]
|
||||||
|
BreakfastTea,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Tea {
|
||||||
|
type Err = ();
|
||||||
|
|
||||||
|
fn from_str(input: &str) -> Result<Tea, Self::Err> {
|
||||||
|
match input {
|
||||||
|
"EverydayTea" => Ok(Tea::EverydayTea),
|
||||||
|
"BreakfastTea" => Ok(Tea::BreakfastTea),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Tea {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match &*self {
|
||||||
|
Tea::EverydayTea => write!(formatter, "{}", String::from("EverydayTea")),
|
||||||
|
Tea::BreakfastTea => write!(formatter, "{}", String::from("BreakfastTea")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActixAdminModelValidationTrait<ActiveModel> for Entity {}
|
@ -103,7 +103,7 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
|
|||||||
let comment_view_model = ActixAdminViewModel::from(Comment);
|
let comment_view_model = ActixAdminViewModel::from(Comment);
|
||||||
|
|
||||||
let configuration = ActixAdminConfiguration {
|
let configuration = ActixAdminConfiguration {
|
||||||
enable_auth: false,
|
enable_auth: true,
|
||||||
user_is_logged_in: Some(|session: &Session| -> bool {
|
user_is_logged_in: Some(|session: &Session| -> bool {
|
||||||
let user_info = session.get::<UserInfo>("user_info").unwrap();
|
let user_info = session.get::<UserInfo>("user_info").unwrap();
|
||||||
user_info.is_some()
|
user_info.is_some()
|
||||||
@ -137,24 +137,9 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
|
|||||||
async fn main() {
|
async fn main() {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
|
|
||||||
let actix_admin = create_actix_admin_builder().get_actix_admin();
|
let oauth2_client_id = env::var("OAUTH2_CLIENT_ID").expect("Missing the OAUTH2_CLIENT_ID environment variable.");
|
||||||
|
let oauth2_client_secret = env::var("OAUTH2_CLIENT_SECRET").expect("Missing the OAUTH2_CLIENT_SECRET environment variable.");
|
||||||
let oauth2_client_id;
|
let oauth2_server= env::var("OAUTH2_SERVER").expect("Missing the OAUTH2_SERVER environment variable.");
|
||||||
let oauth2_client_secret;
|
|
||||||
let oauth2_server;
|
|
||||||
|
|
||||||
match actix_admin.configuration.enable_auth {
|
|
||||||
true => {
|
|
||||||
oauth2_client_id = env::var("OAUTH2_CLIENT_ID").expect("Missing the OAUTH2_CLIENT_ID environment variable.");
|
|
||||||
oauth2_client_secret = env::var("OAUTH2_CLIENT_SECRET").expect("Missing the OAUTH2_CLIENT_SECRET environment variable.");
|
|
||||||
oauth2_server= env::var("OAUTH2_SERVER").expect("Missing the OAUTH2_SERVER environment variable.");
|
|
||||||
},
|
|
||||||
false => {
|
|
||||||
oauth2_client_id = String::new();
|
|
||||||
oauth2_client_secret = String::new();
|
|
||||||
oauth2_server = String::new();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let azure_auth = AzureAuth::new(&oauth2_server, &oauth2_client_id, &oauth2_client_secret);
|
let azure_auth = AzureAuth::new(&oauth2_server, &oauth2_client_id, &oauth2_client_secret);
|
||||||
|
|
||||||
@ -183,22 +168,24 @@ async fn main() {
|
|||||||
let conn = sea_orm::Database::connect(opt).await.unwrap();
|
let conn = sea_orm::Database::connect(opt).await.unwrap();
|
||||||
let _ = entity::create_post_table(&conn).await;
|
let _ = entity::create_post_table(&conn).await;
|
||||||
|
|
||||||
let app_state = AppState {
|
|
||||||
oauth: client,
|
|
||||||
tmpl: tera,
|
|
||||||
db: conn,
|
|
||||||
actix_admin: actix_admin,
|
|
||||||
};
|
|
||||||
|
|
||||||
let cookie_secret_key = Key::generate();
|
let cookie_secret_key = Key::generate();
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
|
let actix_admin_builder = create_actix_admin_builder();
|
||||||
|
|
||||||
|
let app_state = AppState {
|
||||||
|
oauth: client.clone(),
|
||||||
|
tmpl: tera.clone(),
|
||||||
|
db: conn.clone(),
|
||||||
|
actix_admin: actix_admin_builder.get_actix_admin(),
|
||||||
|
};
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
.app_data(web::Data::new(app_state.clone()))
|
.app_data(web::Data::new(app_state.clone()))
|
||||||
.wrap(SessionMiddleware::new(CookieSessionStore::default(), cookie_secret_key.clone()))
|
.wrap(SessionMiddleware::new(CookieSessionStore::default(), cookie_secret_key.clone()))
|
||||||
.route("/", web::get().to(index))
|
.route("/", web::get().to(index))
|
||||||
.service(azure_auth.clone().create_scope::<AppState>())
|
.service(azure_auth.clone().create_scope::<AppState>())
|
||||||
.service(
|
.service(
|
||||||
create_actix_admin_builder().get_scope::<AppState>()
|
actix_admin_builder.get_scope::<AppState>()
|
||||||
)
|
)
|
||||||
.wrap(middleware::Logger::default())
|
.wrap(middleware::Logger::default())
|
||||||
})
|
})
|
@ -36,6 +36,7 @@ pub mod prelude {
|
|||||||
pub use itertools::izip;
|
pub use itertools::izip;
|
||||||
pub use lazy_static::lazy_static;
|
pub use lazy_static::lazy_static;
|
||||||
pub use async_trait::async_trait;
|
pub use async_trait::async_trait;
|
||||||
|
pub use actix_session::{Session};
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user