Prepare release generation
This commit is contained in:
		
							
								
								
									
										18
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					DOCKER_TEMP_DIR=temp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					all: frontend backend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					frontend:
 | 
				
			||||||
 | 
						cd moneymgr_web && npm run build && cd ..
 | 
				
			||||||
 | 
						rm -rf moneymgr_backend/static
 | 
				
			||||||
 | 
						mv moneymgr_web/dist moneymgr_backend/static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					backend: frontend
 | 
				
			||||||
 | 
						cd moneymgr_backend && cargo clippy -- -D warnings && cargo build --release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					backend_docker: backend
 | 
				
			||||||
 | 
						rm -rf $(DOCKER_TEMP_DIR)
 | 
				
			||||||
 | 
						mkdir $(DOCKER_TEMP_DIR)
 | 
				
			||||||
 | 
						cp moneymgr_backend/target/release/moneymgr_backend $(DOCKER_TEMP_DIR)
 | 
				
			||||||
 | 
						docker build -t pierre42100/moneymgr_backend -f moneymgr_backend/docker/moneymgr_backend/Dockerfile "$(DOCKER_TEMP_DIR)"
 | 
				
			||||||
 | 
						rm -rf $(DOCKER_TEMP_DIR)
 | 
				
			||||||
							
								
								
									
										1
									
								
								moneymgr_backend/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								moneymgr_backend/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
target
 | 
					target
 | 
				
			||||||
.idea
 | 
					.idea
 | 
				
			||||||
storage
 | 
					storage
 | 
				
			||||||
 | 
					static
 | 
				
			||||||
							
								
								
									
										80
									
								
								moneymgr_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										80
									
								
								moneymgr_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -2043,6 +2043,16 @@ version = "0.3.17"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 | 
					checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "mime_guess"
 | 
				
			||||||
 | 
					version = "2.0.5"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "mime",
 | 
				
			||||||
 | 
					 "unicase",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "minidom"
 | 
					name = "minidom"
 | 
				
			||||||
version = "0.16.0"
 | 
					version = "0.16.0"
 | 
				
			||||||
@@ -2094,7 +2104,9 @@ dependencies = [
 | 
				
			|||||||
 "lazy_static",
 | 
					 "lazy_static",
 | 
				
			||||||
 "light-openid",
 | 
					 "light-openid",
 | 
				
			||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
 | 
					 "mime_guess",
 | 
				
			||||||
 "rand 0.9.0",
 | 
					 "rand 0.9.0",
 | 
				
			||||||
 | 
					 "rust-embed",
 | 
				
			||||||
 "rust-s3",
 | 
					 "rust-s3",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
@@ -2712,6 +2724,40 @@ dependencies = [
 | 
				
			|||||||
 "zeroize",
 | 
					 "zeroize",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rust-embed"
 | 
				
			||||||
 | 
					version = "8.6.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "0b3aba5104622db5c9fc61098de54708feb732e7763d7faa2fa625899f00bf6f"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "rust-embed-impl",
 | 
				
			||||||
 | 
					 "rust-embed-utils",
 | 
				
			||||||
 | 
					 "walkdir",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rust-embed-impl"
 | 
				
			||||||
 | 
					version = "8.6.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "1f198c73be048d2c5aa8e12f7960ad08443e56fd39cc26336719fdb4ea0ebaae"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "rust-embed-utils",
 | 
				
			||||||
 | 
					 "syn",
 | 
				
			||||||
 | 
					 "walkdir",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rust-embed-utils"
 | 
				
			||||||
 | 
					version = "8.6.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "5a2fcdc9f40c8dc2922842ca9add611ad19f332227fc651d015881ad1552bd9a"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "sha2",
 | 
				
			||||||
 | 
					 "walkdir",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rust-ini"
 | 
					name = "rust-ini"
 | 
				
			||||||
version = "0.21.1"
 | 
					version = "0.21.1"
 | 
				
			||||||
@@ -2855,6 +2901,15 @@ version = "1.0.20"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 | 
					checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "same-file"
 | 
				
			||||||
 | 
					version = "1.0.6"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "winapi-util",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "schannel"
 | 
					name = "schannel"
 | 
				
			||||||
version = "0.1.27"
 | 
					version = "0.1.27"
 | 
				
			||||||
@@ -3447,6 +3502,12 @@ version = "1.18.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
 | 
					checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "unicase"
 | 
				
			||||||
 | 
					version = "2.8.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "unicode-ident"
 | 
					name = "unicode-ident"
 | 
				
			||||||
version = "1.0.18"
 | 
					version = "1.0.18"
 | 
				
			||||||
@@ -3522,6 +3583,16 @@ version = "0.9.5"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
 | 
					checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "walkdir"
 | 
				
			||||||
 | 
					version = "2.5.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "same-file",
 | 
				
			||||||
 | 
					 "winapi-util",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "want"
 | 
					name = "want"
 | 
				
			||||||
version = "0.3.1"
 | 
					version = "0.3.1"
 | 
				
			||||||
@@ -3649,6 +3720,15 @@ dependencies = [
 | 
				
			|||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "winapi-util"
 | 
				
			||||||
 | 
					version = "0.1.9"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "windows-sys 0.59.0",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "windows-link"
 | 
					name = "windows-link"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,4 +26,6 @@ light-openid = "1.0.4"
 | 
				
			|||||||
rand = "0.9.0"
 | 
					rand = "0.9.0"
 | 
				
			||||||
ipnet = { version = "2.11.0", features = ["serde"] }
 | 
					ipnet = { version = "2.11.0", features = ["serde"] }
 | 
				
			||||||
lazy-regex = "3.4.1"
 | 
					lazy-regex = "3.4.1"
 | 
				
			||||||
jwt-simple = { version = "0.12.11", default-features = false, features = ["pure-rust"] }
 | 
					jwt-simple = { version = "0.12.11", default-features = false, features = ["pure-rust"] }
 | 
				
			||||||
 | 
					mime_guess = "2.0.5"
 | 
				
			||||||
 | 
					rust-embed = { version = "8.6.0" }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								moneymgr_backend/docker/moneymgr_backend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								moneymgr_backend/docker/moneymgr_backend/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					FROM debian:bookworm-slim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN apt-get update \
 | 
				
			||||||
 | 
					  && apt-get install -y libcurl4 libpq5 \
 | 
				
			||||||
 | 
					  && rm -rf /var/lib/apt/lists/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY moneymgr_backend /usr/local/bin/moneymgr_backend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENTRYPOINT ["/usr/local/bin/moneymgr_backend"]
 | 
				
			||||||
@@ -4,6 +4,7 @@ use std::error::Error;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub mod auth_controller;
 | 
					pub mod auth_controller;
 | 
				
			||||||
pub mod server_controller;
 | 
					pub mod server_controller;
 | 
				
			||||||
 | 
					pub mod static_controller;
 | 
				
			||||||
pub mod tokens_controller;
 | 
					pub mod tokens_controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(thiserror::Error, Debug)]
 | 
					#[derive(thiserror::Error, Debug)]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										45
									
								
								moneymgr_backend/src/controllers/static_controller.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								moneymgr_backend/src/controllers/static_controller.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					#[cfg(debug_assertions)]
 | 
				
			||||||
 | 
					pub use serve_static_debug::{root_index, serve_static_content};
 | 
				
			||||||
 | 
					#[cfg(not(debug_assertions))]
 | 
				
			||||||
 | 
					pub use serve_static_release::{root_index, serve_static_content};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(debug_assertions)]
 | 
				
			||||||
 | 
					mod serve_static_debug {
 | 
				
			||||||
 | 
					    use actix_web::{HttpResponse, Responder};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn root_index() -> impl Responder {
 | 
				
			||||||
 | 
					        HttpResponse::Ok().body("Hello world! Debug=on for Money manager!")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn serve_static_content() -> impl Responder {
 | 
				
			||||||
 | 
					        HttpResponse::NotFound().body("Hello world! Static assets are not served in debug mode")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(not(debug_assertions))]
 | 
				
			||||||
 | 
					mod serve_static_release {
 | 
				
			||||||
 | 
					    use actix_web::{HttpResponse, Responder, web};
 | 
				
			||||||
 | 
					    use rust_embed::RustEmbed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[derive(RustEmbed)]
 | 
				
			||||||
 | 
					    #[folder = "static/"]
 | 
				
			||||||
 | 
					    struct Asset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn handle_embedded_file(path: &str, can_fallback: bool) -> HttpResponse {
 | 
				
			||||||
 | 
					        match (Asset::get(path), can_fallback) {
 | 
				
			||||||
 | 
					            (Some(content), _) => HttpResponse::Ok()
 | 
				
			||||||
 | 
					                .content_type(mime_guess::from_path(path).first_or_octet_stream().as_ref())
 | 
				
			||||||
 | 
					                .body(content.data.into_owned()),
 | 
				
			||||||
 | 
					            (None, false) => HttpResponse::NotFound().body("404 Not Found"),
 | 
				
			||||||
 | 
					            (None, true) => handle_embedded_file("index.html", false),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn root_index() -> impl Responder {
 | 
				
			||||||
 | 
					        handle_embedded_file("index.html", false)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn serve_static_content(path: web::Path<String>) -> impl Responder {
 | 
				
			||||||
 | 
					        handle_embedded_file(path.as_ref(), !path.as_ref().starts_with("static/"))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -100,6 +100,12 @@ async fn main() -> std::io::Result<()> {
 | 
				
			|||||||
                "/api/tokens/{id}",
 | 
					                "/api/tokens/{id}",
 | 
				
			||||||
                web::delete().to(tokens_controller::delete),
 | 
					                web::delete().to(tokens_controller::delete),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					            // Static assets
 | 
				
			||||||
 | 
					            .route("/", web::get().to(static_controller::root_index))
 | 
				
			||||||
 | 
					            .route(
 | 
				
			||||||
 | 
					                "/{tail:.*}",
 | 
				
			||||||
 | 
					                web::get().to(static_controller::serve_static_content),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .bind(AppConfig::get().listen_address.as_str())?
 | 
					    .bind(AppConfig::get().listen_address.as_str())?
 | 
				
			||||||
    .run()
 | 
					    .run()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,16 @@
 | 
				
			|||||||
 | 
					import AddIcon from "@mui/icons-material/Add";
 | 
				
			||||||
import DeleteIcon from "@mui/icons-material/DeleteOutlined";
 | 
					import DeleteIcon from "@mui/icons-material/DeleteOutlined";
 | 
				
			||||||
import { Alert, AlertTitle, Button, IconButton, Tooltip } from "@mui/material";
 | 
					import RefreshIcon from "@mui/icons-material/Refresh";
 | 
				
			||||||
 | 
					import { Alert, AlertTitle, IconButton, Tooltip } from "@mui/material";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  DataGrid,
 | 
					  DataGrid,
 | 
				
			||||||
  GridActionsCellItem,
 | 
					  GridActionsCellItem,
 | 
				
			||||||
  GridColDef,
 | 
					  GridColDef,
 | 
				
			||||||
  GridRowId,
 | 
					  GridRowId,
 | 
				
			||||||
} from "@mui/x-data-grid";
 | 
					} from "@mui/x-data-grid";
 | 
				
			||||||
 | 
					import { QRCodeCanvas } from "qrcode.react";
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import { APIClient } from "../api/ApiClient";
 | 
				
			||||||
import { Token, TokenWithSecret, TokensApi } from "../api/TokensApi";
 | 
					import { Token, TokenWithSecret, TokensApi } from "../api/TokensApi";
 | 
				
			||||||
import { CreateTokenDialog } from "../dialogs/CreateTokenDialog";
 | 
					import { CreateTokenDialog } from "../dialogs/CreateTokenDialog";
 | 
				
			||||||
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
 | 
					import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
 | 
				
			||||||
@@ -16,10 +20,6 @@ import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
				
			|||||||
import { CopyTextChip } from "../widgets/CopyTextChip";
 | 
					import { CopyTextChip } from "../widgets/CopyTextChip";
 | 
				
			||||||
import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
 | 
					import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer";
 | 
				
			||||||
import { TimeWidget } from "../widgets/TimeWidget";
 | 
					import { TimeWidget } from "../widgets/TimeWidget";
 | 
				
			||||||
import { QRCodeCanvas } from "qrcode.react";
 | 
					 | 
				
			||||||
import { APIClient } from "../api/ApiClient";
 | 
					 | 
				
			||||||
import AddIcon from "@mui/icons-material/Add";
 | 
					 | 
				
			||||||
import RefreshIcon from "@mui/icons-material/Refresh";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function TokensRoute(): React.ReactElement {
 | 
					export function TokensRoute(): React.ReactElement {
 | 
				
			||||||
  const count = React.useRef(0);
 | 
					  const count = React.useRef(0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,11 +7,9 @@ import {
 | 
				
			|||||||
  ListItemText,
 | 
					  ListItemText,
 | 
				
			||||||
} from "@mui/material";
 | 
					} from "@mui/material";
 | 
				
			||||||
import { useLocation } from "react-router-dom";
 | 
					import { useLocation } from "react-router-dom";
 | 
				
			||||||
import { useAuthInfo } from "./BaseAuthenticatedPage";
 | 
					 | 
				
			||||||
import { RouterLink } from "./RouterLink";
 | 
					import { RouterLink } from "./RouterLink";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function MoneyNavList(): React.ReactElement {
 | 
					export function MoneyNavList(): React.ReactElement {
 | 
				
			||||||
  const user = useAuthInfo().info;
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <List
 | 
					    <List
 | 
				
			||||||
      dense
 | 
					      dense
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user