File size: 4,756 Bytes
c6d0d85
 
 
d94c6df
c6d0d85
f102c60
 
3245107
d94c6df
3245107
d94c6df
 
 
 
f102c60
f4d1c72
 
 
3245107
 
 
6ad8d57
f102c60
 
 
f4d1c72
6ad8d57
 
d94c6df
 
3245107
d94c6df
 
3245107
d94c6df
 
 
 
 
 
 
 
6ad8d57
f4d1c72
f102c60
 
 
 
 
 
 
 
 
 
3245107
 
 
 
 
 
f4d1c72
f102c60
 
 
 
 
3245107
f4d1c72
 
 
 
 
3245107
f4d1c72
 
 
f102c60
 
 
 
 
 
 
3245107
 
 
 
 
 
 
 
d94c6df
 
 
 
 
3245107
d94c6df
f102c60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d94c6df
 
 
 
 
 
 
249b27c
1eb186a
 
d94c6df
 
 
 
 
1eb186a
 
d94c6df
 
 
 
1eb186a
d94c6df
 
1eb186a
 
3245107
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
mod api;
mod entity;
mod service;
mod errors;

use std::env;
use actix_files::Files;
use actix_identity::{ CookieIdentityPolicy, IdentityService, RequestIdentity };
use actix_session::CookieSession;
use actix_web::{ web, App, HttpServer, middleware, Error };
use actix_web::cookie::time::Duration;
use actix_web::dev::ServiceRequest;
use actix_web::error::ErrorUnauthorized;
use actix_web_httpauth::extractors::bearer::BearerAuth;
use listenfd::ListenFd;
use minio::s3::client::Client;
use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl;
use sea_orm::{ Database, DatabaseConnection };
use migration::{ Migrator, MigratorTrait };
use crate::errors::{ AppError, UserError };

#[derive(Debug, Clone)]
struct AppState {
    conn: DatabaseConnection,
    s3_client: Client,
}

pub(crate) async fn validator(
    req: ServiceRequest,
    credentials: BearerAuth
) -> Result<ServiceRequest, Error> {
    if let Some(token) = req.get_identity() {
        println!("{}, {}", credentials.token(), token);
        (credentials.token() == token)
            .then(|| req)
            .ok_or(ErrorUnauthorized(UserError::InvalidToken))
    } else {
        Err(ErrorUnauthorized(UserError::NotLoggedIn))
    }
}

#[actix_web::main]
async fn main() -> Result<(), AppError> {
    std::env::set_var("RUST_LOG", "debug");
    tracing_subscriber::fmt::init();

    // get env vars
    dotenvy::dotenv().ok();
    let db_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set in .env file");
    let host = env::var("HOST").expect("HOST is not set in .env file");
    let port = env::var("PORT").expect("PORT is not set in .env file");
    let server_url = format!("{host}:{port}");

    let mut s3_base_url = env::var("MINIO_HOST").expect("MINIO_HOST is not set in .env file");
    let s3_access_key = env::var("MINIO_USR").expect("MINIO_USR is not set in .env file");
    let s3_secret_key = env::var("MINIO_PWD").expect("MINIO_PWD is not set in .env file");
    if s3_base_url.find("http") != Some(0) {
        s3_base_url = format!("http://{}", s3_base_url);
    }

    // establish connection to database and apply migrations
    // -> create post table if not exists
    let conn = Database::connect(&db_url).await.unwrap();
    Migrator::up(&conn, None).await.unwrap();

    let static_provider = StaticProvider::new(s3_access_key.as_str(), s3_secret_key.as_str(), None);

    let s3_client = Client::new(
        s3_base_url.parse::<BaseUrl>()?,
        Some(Box::new(static_provider)),
        None,
        Some(true)
    )?;

    let state = AppState { conn, s3_client };

    // create server and try to serve over socket if possible
    let mut listenfd = ListenFd::from_env();
    let mut server = HttpServer::new(move || {
        App::new()
            .service(Files::new("/static", "./static"))
            .app_data(web::Data::new(state.clone()))
            .wrap(
                IdentityService::new(
                    CookieIdentityPolicy::new(&[0; 32])
                        .name("auth-cookie")
                        .login_deadline(Duration::seconds(120))
                        .secure(false)
                )
            )
            .wrap(
                CookieSession::signed(&[0; 32])
                    .name("session-cookie")
                    .secure(false)
                    // WARNING(alex): This uses the `time` crate, not `std::time`!
                    .expires_in_time(Duration::seconds(60))
            )
            .wrap(middleware::Logger::default())
            .configure(init)
    });

    server = match listenfd.take_tcp_listener(0)? {
        Some(listener) => server.listen(listener)?,
        None => server.bind(&server_url)?,
    };

    println!("Starting server at {server_url}");
    server.run().await?;

    Ok(())
}

fn init(cfg: &mut web::ServiceConfig) {
    cfg.service(api::tag_info::create);
    cfg.service(api::tag_info::delete);
    cfg.service(api::tag_info::list);

    cfg.service(api::kb_info::create);
    cfg.service(api::kb_info::delete);
    cfg.service(api::kb_info::list);
    cfg.service(api::kb_info::add_docs_to_kb);
    cfg.service(api::kb_info::anti_kb_docs);
    cfg.service(api::kb_info::all_relevents);

    cfg.service(api::doc_info::list);
    cfg.service(api::doc_info::delete);
    cfg.service(api::doc_info::mv);
    cfg.service(api::doc_info::upload);
    cfg.service(api::doc_info::new_folder);
    cfg.service(api::doc_info::rename);

    cfg.service(api::dialog_info::list);
    cfg.service(api::dialog_info::delete);
    cfg.service(api::dialog_info::create);
    cfg.service(api::dialog_info::update_history);

    cfg.service(api::user_info::login);
    cfg.service(api::user_info::register);
    cfg.service(api::user_info::setting);
}