Implement account removal API #1
23
README.md
23
README.md
@ -1,8 +1,6 @@
|
|||||||
# mail-connect
|
# mail-connect
|
||||||
|
|
||||||
API bridge for docker-mailserver
|
API bridge for docker-mailserver. **Still in beta.**
|
||||||
|
|
||||||
*mail-connect is still in early beta*
|
|
||||||
|
|
||||||
## What is it
|
## What is it
|
||||||
|
|
||||||
@ -12,7 +10,7 @@ We provide an extendable API which interacts with the `setup` utility via a Dock
|
|||||||
|
|
||||||
## What this API is NOT
|
## What this API is NOT
|
||||||
|
|
||||||
This API is insecure by nature, however not completely. `mail-connect` is intended to be an API which is used internally _only_. The systems connected to this API should have proper protections against abuse. Think about it... would you like me to direct your mailserver security? I sure hope not...
|
This API is insecure by nature, however not completely. `mail-connect` is intended to be an API which is used internally **only**. The systems connected to this API should have proper protections against abuse. Think about it... would you like me to direct your mailserver security? I sure hope not...
|
||||||
|
|
||||||
As such, users who have access to this API are able to create unlimited accounts, and modify anyone's email address. Thus, your code should be the only user of this API. Once again, **do not make this API public**.
|
As such, users who have access to this API are able to create unlimited accounts, and modify anyone's email address. Thus, your code should be the only user of this API. Once again, **do not make this API public**.
|
||||||
|
|
||||||
@ -59,13 +57,13 @@ All features marked with an **E** are extended features, and are not a part of t
|
|||||||
|
|
||||||
### Email
|
### Email
|
||||||
|
|
||||||
- [X] Create email
|
- [X] Create account/email
|
||||||
- [X] List emails
|
- [X] List accounts
|
||||||
- [X] **E** View individual user details
|
- [X] **E** View individual account details
|
||||||
- [X] **E** Create email from file
|
- [X] **E** Create an account from file
|
||||||
- [X] Change password
|
- [X] Change password
|
||||||
- [ ] Delete email
|
- [X] Delete account/email
|
||||||
- [ ] Restrict email
|
- [ ] Restrict account
|
||||||
|
|
||||||
### Alias
|
### Alias
|
||||||
|
|
||||||
@ -113,8 +111,3 @@ All features marked with an **E** are extended features, and are not a part of t
|
|||||||
I plan to implement a *much* more powerful API, when everything else has settled. I will be taking a look at the setup utility itself, and seeing how a more efficient approach can be taken.
|
I plan to implement a *much* more powerful API, when everything else has settled. I will be taking a look at the setup utility itself, and seeing how a more efficient approach can be taken.
|
||||||
|
|
||||||
Since `docker-mailserver` is built on Dovecot and Postfix, I am confident we can improve this API to be speedy and efficient as ever.
|
Since `docker-mailserver` is built on Dovecot and Postfix, I am confident we can improve this API to be speedy and efficient as ever.
|
||||||
|
|
||||||
## To-Do
|
|
||||||
|
|
||||||
- [ ] Implement aforementioned features
|
|
||||||
- [ ] Swagger support
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mail-connect",
|
"name": "mail-connect",
|
||||||
"module": "src/server.ts",
|
"module": "src/server.ts",
|
||||||
|
"version": "0.1.2",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "bun src/server.js",
|
"start": "bun src/server.js",
|
||||||
|
80
src/actions/accounts/deleteAccount.ts
Normal file
80
src/actions/accounts/deleteAccount.ts
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { Request, Response } from "express";
|
||||||
|
import { accounts } from "../../db/schema";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { validateEmail } from "../../utils/validators";
|
||||||
|
import { drizzle } from "drizzle-orm/bun-sqlite";
|
||||||
|
import { containerExec } from "../../utils/docker";
|
||||||
|
import { updateAccountsCache } from "../../utils/updateAccountsCache";
|
||||||
|
|
||||||
|
const db = drizzle(process.env.DB_FILE_NAME!);
|
||||||
|
|
||||||
|
export const deleteAccount = async (req: Request, res: Response): Promise<void> => {
|
||||||
|
const { email } = req.body;
|
||||||
|
|
||||||
|
if (!email) {
|
||||||
|
console.log("[!] Error\nTASK| deleteAccount\nERR | Missing email\nACC |", email);
|
||||||
|
res.status(400).json({ success: false, error: "Missing email" });
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateEmail(email)) {
|
||||||
|
console.log("[!] Error\nTASK| deleteAccount\nERR | Invalid email format\nACC |", email);
|
||||||
|
res.status(400).json({ success: false, error: "Invalid email format" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const accInDb = await db
|
||||||
|
.select()
|
||||||
|
.from(accounts)
|
||||||
|
.where(eq(accounts.email, email))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (!accInDb || accInDb.length === 0) {
|
||||||
|
console.log("[!] Error\nTASK| deleteAccount\nERR | Account not found\nACC |", email);
|
||||||
|
res.status(404).json({ success: false, error: "Account not found" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[*] Task started\nTASK| deleteAccount\nACC |", email);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.delete(accounts).where(eq(accounts.email, email));
|
||||||
|
console.log("[+] Internal account deleted\nTASK| deleteAccount\nACC |", email);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const output = await containerExec(["setup", "email", "del", email]);
|
||||||
|
if (/ERROR/i.test(output)) {
|
||||||
|
console.log("[!] Error\nTASK| deleteAccount\nERR | Mail account removal failed\nACC |", email);
|
||||||
|
res.status(500).json({ success: false, error: "Mail account removal failed" });
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
console.log("[+] Mail account removed\nTASK| deleteAccount\nACC |", email);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("[!] Error\nTASK| deleteAccount\nERR | Mail account removal failed\nACC |", email);
|
||||||
|
res.status(500).json({ success: false, error: "Mail account removal failed" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("[-] Updating accounts cache");
|
||||||
|
await updateAccountsCache();
|
||||||
|
|
||||||
|
console.log("[-] Performing final checks");
|
||||||
|
const accInDb = await db
|
||||||
|
.select()
|
||||||
|
.from(accounts)
|
||||||
|
.where(eq(accounts.email, email))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (!accInDb || accInDb.length === 0) {
|
||||||
|
console.log("[*] Task completed\nTASK| deleteAccount\nACC |", email);
|
||||||
|
res.json({ success: true });
|
||||||
|
} else {
|
||||||
|
console.log("[!] Error\nTASK| deleteAccount\nERR | Account not found\nACC |", email);
|
||||||
|
res.status(404).json({ success: false, error: "Account not found" });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log("[!] Error\nTASK| deleteAccount\nERR | Unspecified error\nACC |", email);
|
||||||
|
res.status(500).json({ success: false, error: (err as Error).message });
|
||||||
|
}
|
||||||
|
};
|
@ -6,6 +6,8 @@ import { getUserAccount } from "./actions/accounts/getUserAccount";
|
|||||||
import { updatePassword } from "./actions/accounts/updatePassword";
|
import { updatePassword } from "./actions/accounts/updatePassword";
|
||||||
import { addAccount } from "./actions/accounts/addAccount";
|
import { addAccount } from "./actions/accounts/addAccount";
|
||||||
import initialChecks from "./actions/initialChecks";
|
import initialChecks from "./actions/initialChecks";
|
||||||
|
import { deleteAccount } from "./actions/accounts/deleteAccount";
|
||||||
|
import { updateAccountsCache } from "./utils/updateAccountsCache";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
@ -19,6 +21,11 @@ if (!rCResult) {
|
|||||||
console.log("\n==== SELF CHECK PASS ====\n");
|
console.log("\n==== SELF CHECK PASS ====\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get version
|
||||||
|
const pkg = Bun.file("package.json");
|
||||||
|
const pkgData = await pkg.json();
|
||||||
|
const version = pkgData.version;
|
||||||
|
|
||||||
interface RateLimitOptions {
|
interface RateLimitOptions {
|
||||||
windowMs: number;
|
windowMs: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
@ -37,19 +44,22 @@ app.get("/accounts/list", listAccounts);
|
|||||||
app.post("/accounts/user", getUserAccount);
|
app.post("/accounts/user", getUserAccount);
|
||||||
app.post("/accounts/update/password", updatePassword);
|
app.post("/accounts/update/password", updatePassword);
|
||||||
app.post("/accounts/add", addAccount);
|
app.post("/accounts/add", addAccount);
|
||||||
|
app.post("/accounts/delete", deleteAccount);
|
||||||
|
|
||||||
const PORT = 3000;
|
const PORT = 3000;
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
figlet('mail-connect', (err, data) => {
|
figlet('mail-connect', (err, data) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log('mail-connect');
|
console.log('mail-connect');
|
||||||
console.log('Version: 0.1.1');
|
console.log(`Version: ${version}`);
|
||||||
console.log(`API listening on port ${PORT}\n`);
|
console.log(`API listening on port ${PORT}\n`);
|
||||||
console.log("[!] " + err);
|
console.log("[!] " + err);
|
||||||
|
updateAccountsCache();
|
||||||
} else {
|
} else {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
console.log('Version: 0.1.1');
|
console.log(`Version: ${version}`);
|
||||||
console.log(`API listening on port ${PORT}\n`);
|
console.log(`API listening on port ${PORT}\n`);
|
||||||
|
updateAccountsCache();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -14,4 +14,5 @@ export const updateAccountsCache = async () => {
|
|||||||
.insert(cacheInfo)
|
.insert(cacheInfo)
|
||||||
.values({ lastUpdated: Date.now() })
|
.values({ lastUpdated: Date.now() })
|
||||||
.onConflictDoUpdate({ target: cacheInfo.id, set: { lastUpdated: Date.now() } });
|
.onConflictDoUpdate({ target: cacheInfo.id, set: { lastUpdated: Date.now() } });
|
||||||
|
console.log("[+] Accounts cache updated");
|
||||||
};
|
};
|
Loading…
x
Reference in New Issue
Block a user