Newer
Older
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
use crate::{
middleware::AuthenticatedAdminMiddleware,
model::AdminAuthCredentials,
// view_resource::{ViewResource, ViewResourceDescriptor},
AppState,
};
use actix_web::{web::Form, HttpMessage, HttpRequest, HttpResponse};
use std::{env::var as env_var, fs::read_to_string as file_to_string, path::PathBuf};
#[derive(Debug, Clone)]
/// Loads a static resource data allowing it to be served by the get_view service.
/// It holds a name, allowing the resource to be retrived by name,
/// a content which can be any text content stored in a string (like an html document),
/// a path to the directory of the actual static resource, and a boolean which indicates wether
/// or not an authentication verification should be applied.
pub struct ViewResource {
pub name: String,
pub string_contents: String,
pub dir_path: PathBuf,
pub apply_auth_middleware: bool,
}
#[derive(Debug, Clone)]
/// Defines the values that will be used to construct a ViewResource.
/// It must be passed to the AppViewResourceManager for resource registration
pub struct ViewResourceDescriptor<'a> {
pub path_str: &'a str,
pub index_file_name: &'a str,
pub resource_name: &'a str,
pub apply_auth_middleware: bool,
}
#[derive(Debug, Clone)]
/// A structure reponsible of registering and retrieving static resources.
pub struct ViewResourceManager {
resources: Vec<ViewResource>,
}
impl ViewResourceManager {
pub fn new() -> Self {
ViewResourceManager { resources: vec![] }
}
/// Calls the constructor and registers the resources described as argument before returning the instance
pub fn with_views(resource_descriptors: Vec<ViewResourceDescriptor>) -> Self {
let mut instance = Self::new();
instance.register_batch(resource_descriptors);
instance
}
/// Registers a new static resource in the instance.
/// The path provided in the argument must point to an existing file
pub fn register(&mut self, desc: ViewResourceDescriptor) {
let static_dir = std::path::PathBuf::from(
env_var("RESOURCES_DIR").expect("RESOURCES_DIR is not defined"),
)
.join("public/views");
let dir_path = static_dir.join(desc.path_str);
let path: PathBuf = format!("{}/{}", dir_path.to_str().unwrap(), desc.index_file_name)
.parse()
.expect(&format!(
"Failed to pare resource index file path {:?}",
desc.index_file_name
));
let string_contents = file_to_string(path).unwrap();
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
name: desc.resource_name.to_string(),
dir_path,
string_contents,
apply_auth_middleware: desc.apply_auth_middleware,
});
}
/// Registers a collection of multiple resources.
pub fn register_batch(&mut self, resource_descriptors: Vec<ViewResourceDescriptor>) {
for desc in resource_descriptors.iter() {
self.register(desc.clone());
}
}
/// Retrieves a resource by name and returns a reference to it or None.
pub fn get_resource(&self, name: &str) -> Option<&ViewResource> {
self.resources.iter().find(|res| res.name == name)
}
/// Retrieves a resource by name and returns it as an http response.
/// This can be returned as it by a service.
pub async fn get_resource_as_http_response<'a>(
&self,
app_state: &AppState,
auth_middleware: &AuthenticatedAdminMiddleware<'a>,
req: &HttpRequest,
auth_data: Option<Form<AdminAuthCredentials>>,
resource_name: &str,
) -> HttpResponse {
match self.get_resource(resource_name) {
Some(res) => {
if res.apply_auth_middleware {
let auth_cookie = auth_middleware.exec(app_state, req, auth_data).await;
if auth_cookie.is_err() {
let unauthorized_view = match self.get_resource("unauthorized") {
Some(res_404) => res_404.string_contents.to_string(),
None => {
println!("WARNING: missing Unauthorized view resource");
"
<h1>Unauthorized</h1>
<p>You must login as an administrator to access this page</p>
<a href='/v/admin-login'>Login page</a>
"
.to_string()
}
};
let mut response_builder = HttpResponse::Unauthorized();
return match req.cookie(auth_middleware.cookie_name) {
Some(cookie) => {
// Invalidate auth_cookie if auth failed in any way
response_builder
.del_cookie(&cookie)
.content_type("text/html")
.body(unauthorized_view)
}
None => response_builder
.content_type("text/html")
.body(unauthorized_view),
};
} else {
return HttpResponse::Ok()
.content_type("text/html")
.cookie(auth_cookie.unwrap())
.body(&res.string_contents);
}
}
HttpResponse::Ok()
.content_type("text/html")
.body(&res.string_contents)
}
None => match self.get_resource("404") {
Some(res_404) => HttpResponse::NotFound()
.content_type("text/html")
.body(&res_404.string_contents),
None => {
println!("WARNING: missing 404 view resource");
HttpResponse::NotFound().finish()
}
},
}
}
}