fix(core): add email whitelisting, small fixes

main
Guus van Meerveld 1 year ago
parent bd894476f4
commit 47dfb18391
Signed by: Guusvanmeerveld
GPG Key ID: 2BA7D7912771966E

@ -1,7 +1,7 @@
import type { Request as ExpressRequest } from "express";
import { AuthService } from "./auth.service";
import { allowedDomains } from "./constants";
import { allowedAddresses, allowedDomains } from "./constants";
import type { SecurityType } from "./interfaces/config.interface";
import { JwtToken } from "./interfaces/jwt.interface";
import { StringValidationPipe } from "./pipes/string.pipe";
@ -34,12 +34,14 @@ import handleError from "@utils/handleError";
@Controller("auth")
export class AuthController {
private allowedDomains?: string[];
private allowedAddresses?: string[];
constructor(
private authService: AuthService,
private jwtService: JwtService
) {
if (allowedDomains) this.allowedDomains = allowedDomains.split(",");
if (allowedAddresses) this.allowedAddresses = allowedAddresses.split(",");
}
@Post("login")
@ -72,7 +74,10 @@ export class AuthController {
if (!incomingServer || !outgoingServer) {
const result = await mailDiscover(incomingUsername).catch(() => {
incomingServer = "mail.";
const server = incomingUsername.split("@").pop() as string;
incomingServer = "mail." + server;
outgoingServer = "mail." + server;
});
if (result) {
@ -122,6 +127,17 @@ export class AuthController {
if (!outgoingUsername) outgoingUsername = incomingUsername;
if (!outgoingPassword) outgoingPassword = outgoingPassword;
if (
this.allowedAddresses &&
(!this.allowedAddresses.includes(incomingUsername) ||
!this.allowedAddresses.includes(outgoingUsername))
) {
throw new BadRequestException({
code: UserError.Misc,
message: "Email address is not on whitelist"
});
}
if (!incomingService) {
incomingService = (await detectServiceFromConfig({
security: incomingSecurity,

@ -1 +1,2 @@
export const allowedDomains = process.env.ALLOWED_DOMAINS;
export const allowedAddresses = process.env.ALLOWED_ADDRESSES;

@ -29,7 +29,11 @@ export class ImapService {
password: config.password,
host: config.server,
port: config.port,
tls: config.security != "NONE"
tls: config.security != "NONE",
authTimeout: 30 * 1000,
tlsOptions: {
rejectUnauthorized: false
}
});
return await connect(client).then((_client) => {

@ -10,6 +10,8 @@ lerna-debug.log*
dist-ssr
*.local
/stats.*
# Editor directories and files
.vscode/*
!.vscode/extensions.json

@ -73,6 +73,7 @@
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.7.1",
"rollup-plugin-visualizer": "^5.8.1",
"size-limit": "^7.0.8",
"typescript": "^4.5.4",
"vite": "^3.0.3",

@ -3,7 +3,7 @@
"build": {
"beforeBuildCommand": "pnpm build",
"beforeDevCommand": "pnpm dev",
"devPath": "http://localhost:3000/",
"devPath": "http://localhost:5173/",
"distDir": "../dist",
"withGlobalTauri": true
},

@ -1,7 +1,12 @@
import { FC } from "react";
import { FC, useState } from "react";
import Box from "@mui/material/Box";
import FormControl from "@mui/material/FormControl";
import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import Modal from "@mui/material/Modal";
import Select from "@mui/material/Select";
import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import modalStyles from "@styles/modal";
@ -9,21 +14,73 @@ import modalStyles from "@styles/modal";
import useStore from "@utils/hooks/useStore";
import useTheme from "@utils/hooks/useTheme";
type FolderType = "unified" | "normal" | "none";
const AddBox: FC = () => {
const theme = useTheme();
const setShowAddBox = useStore((state) => state.setShowAddBox);
const showAddBox = useStore((state) => state.showAddBox);
const [folderType, setFolderType] = useState<FolderType>("none");
const [folderName, setFolderName] = useState<string>();
const handleClose = (): void => setShowAddBox(false);
return (
<Modal open={showAddBox} onClose={handleClose}>
<Box sx={modalStyles(theme)}>
<Typography gutterBottom variant="h3">
Add new folder
</Typography>
</Box>
<Stack spacing={2} direction="column" sx={modalStyles(theme)}>
<Typography variant="h3">Add new folder</Typography>
<FormControl fullWidth>
<InputLabel id="folder-type-label">Folder type</InputLabel>
<Select
labelId="folder-type-label"
id="folder-type"
value={folderType}
label="Folder type"
onChange={(e) => setFolderType(e.target.value as FolderType)}
>
<MenuItem value="none">None</MenuItem>
<MenuItem value="unified">
Unified
<Typography
sx={{
ml: 2,
display: "inline",
color: theme.palette.text.secondary
}}
>
Create a (local) inbox that unifies together multiple inboxes
</Typography>
</MenuItem>
<MenuItem value="normal">
Normal{" "}
<Typography
sx={{
ml: 2,
display: "inline",
color: theme.palette.text.secondary
}}
>
Create a new inbox on the server
</Typography>
</MenuItem>
</Select>
</FormControl>
{folderType != "none" && (
<TextField
fullWidth
value={folderName}
onChange={(e) => setFolderName(e.target.value)}
label="Folder name"
/>
)}
{folderType != "none" && <TextField fullWidth label="Parent folder" />}
</Stack>
</Modal>
);
};

@ -4,6 +4,8 @@ import { defineConfig } from "vite";
import { VitePWA } from "vite-plugin-pwa";
import tsconfigPaths from "vite-tsconfig-paths";
import { visualizer } from "rollup-plugin-visualizer";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
@ -45,7 +47,8 @@ export default defineConfig({
}
}),
react(),
tsconfigPaths()
tsconfigPaths(),
visualizer({ template: "sunburst" })
],
esbuild: {
logOverride: { "this-is-undefined-in-esm": "silent" }

@ -2,7 +2,7 @@ version: '3.3'
services:
app:
image: dust-mail
container_name: dust-mail
build: .
container_name: dust-mail-development
ports:
- 3000:80

@ -196,6 +196,7 @@ importers:
react-query: ^3.39.1
react-router: ^6.3.0
react-router-dom: ^6.3.0
rollup-plugin-visualizer: ^5.8.1
size-limit: ^7.0.8
slate: ^0.81.1
slate-react: ^0.81.0
@ -248,10 +249,11 @@ importers:
eslint-plugin-react: 7.30.1_eslint@8.20.0
eslint-plugin-react-hooks: 4.6.0_eslint@8.20.0
prettier: 2.7.1
rollup-plugin-visualizer: 5.8.1
size-limit: 7.0.8
typescript: 4.7.4
vite: 3.0.4
vite-plugin-pwa: 0.12.3_6x7hwu2tvelmeqj2f3gkeezd4u
vite-plugin-pwa: 0.12.3_vite@3.0.4
vite-tsconfig-paths: 3.5.0_vite@3.0.4
vitest: 0.20.3_c8@7.12.0
workbox-window: 6.5.4
@ -5162,6 +5164,11 @@ packages:
clone: 1.0.4
dev: true
/define-lazy-prop/2.0.0:
resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
engines: {node: '>=8'}
dev: true
/define-properties/1.1.4:
resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==}
engines: {node: '>= 0.4'}
@ -7027,6 +7034,12 @@ packages:
has-tostringtag: 1.0.0
dev: true
/is-docker/2.2.1:
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
engines: {node: '>=8'}
hasBin: true
dev: true
/is-extglob/2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
@ -7164,6 +7177,13 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/is-wsl/2.2.0:
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
engines: {node: '>=8'}
dependencies:
is-docker: 2.2.1
dev: true
/isarray/0.0.1:
resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==}
dev: false
@ -8557,6 +8577,15 @@ packages:
mimic-fn: 2.1.0
dev: true
/open/8.4.0:
resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==}
engines: {node: '>=12'}
dependencies:
define-lazy-prop: 2.0.0
is-docker: 2.2.1
is-wsl: 2.2.0
dev: true
/optionator/0.9.1:
resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==}
engines: {node: '>= 0.8.0'}
@ -9482,6 +9511,22 @@ packages:
typescript: 4.7.4
dev: true
/rollup-plugin-visualizer/5.8.1:
resolution: {integrity: sha512-NBT/xN/LWCwDM2/j5vYmjzpEAKHyclo/8Cv8AfTCwgADAG+tLJDy1vzxMw6NO0dSDjmTeRELD9UU3FwknLv0GQ==}
engines: {node: '>=14'}
hasBin: true
peerDependencies:
rollup: ^2.0.0
peerDependenciesMeta:
rollup:
optional: true
dependencies:
nanoid: 3.3.4
open: 8.4.0
source-map: 0.7.3
yargs: 17.5.1
dev: true
/rollup/2.77.2:
resolution: {integrity: sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g==}
engines: {node: '>=10.0.0'}
@ -10816,11 +10861,10 @@ packages:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
/vite-plugin-pwa/0.12.3_6x7hwu2tvelmeqj2f3gkeezd4u:
/vite-plugin-pwa/0.12.3_vite@3.0.4:
resolution: {integrity: sha512-gmYdIVXpmBuNjzbJFPZFzxWYrX4lHqwMAlOtjmXBbxApiHjx9QPXKQPJjSpeTeosLKvVbNcKSAAhfxMda0QVNQ==}
peerDependencies:
vite: ^2.0.0 || ^3.0.0-0
workbox-window: ^6.4.0
dependencies:
debug: 4.3.4
fast-glob: 3.2.11

Loading…
Cancel
Save