Skip to content

Commit da68fe2

Browse files
committed
404 hosts polish
1 parent 18537b9 commit da68fe2

File tree

10 files changed

+95
-25
lines changed

10 files changed

+95
-25
lines changed

README.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,6 @@ Sometimes this can take a little bit because of the entropy of keys.
8888

8989
[http://127.0.0.1:81](http://127.0.0.1:81)
9090

91-
Default Admin User:
92-
```
93-
Email: admin@example.com
94-
Password: changeme
95-
```
96-
97-
Immediately after logging in with this default user you will be asked to modify your details and change your password.
98-
9991

10092
## Contributing
10193

backend/internal/dead-host.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const internalDeadHost = {
6363
action: "created",
6464
object_type: "dead-host",
6565
object_id: row.id,
66-
meta: _.assign({}, data.meta || {}, row.meta),
66+
meta: thisData,
6767
});
6868

6969
if (createCertificate) {
@@ -240,13 +240,15 @@ const internalDeadHost = {
240240
// Delete Nginx Config
241241
await internalNginx.deleteConfig("dead_host", row);
242242
await internalNginx.reload();
243+
243244
// Add to audit log
244245
await internalAuditLog.add(access, {
245246
action: "deleted",
246247
object_type: "dead-host",
247248
object_id: row.id,
248249
meta: _.omit(row, omissions()),
249250
});
251+
return true;
250252
},
251253

252254
/**

backend/internal/nginx.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,11 @@ const internalNginx = {
301301
* @param {String} filename
302302
*/
303303
deleteFile: (filename) => {
304-
logger.debug(`Deleting file: ${filename}`);
304+
if (!fs.existsSync(filename)) {
305+
return;
306+
}
305307
try {
308+
logger.debug(`Deleting file: ${filename}`);
306309
fs.unlinkSync(filename);
307310
} catch (err) {
308311
logger.debug("Could not delete file:", JSON.stringify(err, null, 2));

backend/routes/nginx/dead_hosts.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ router
121121
/**
122122
* PUT /api/nginx/dead-hosts/123
123123
*
124-
* Update and existing dead-host
124+
* Update an existing dead-host
125125
*/
126126
.put(async (req, res, next) => {
127127
try {
@@ -138,7 +138,7 @@ router
138138
/**
139139
* DELETE /api/nginx/dead-hosts/123
140140
*
141-
* Update and existing dead-host
141+
* Delete a dead-host
142142
*/
143143
.delete(async (req, res, next) => {
144144
try {

frontend/src/components/Table/Formatter/DomainsFormatter.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,32 @@ interface Props {
44
domains: string[];
55
createdOn?: string;
66
}
7+
8+
const DomainLink = ({ domain }: { domain: string }) => {
9+
// when domain contains a wildcard, make the link go nowhere.
10+
let onClick: ((e: React.MouseEvent) => void) | undefined;
11+
if (domain.includes("*")) {
12+
onClick = (e: React.MouseEvent) => e.preventDefault();
13+
}
14+
return (
15+
<a
16+
key={domain}
17+
href={`http://${domain}`}
18+
target="_blank"
19+
onClick={onClick}
20+
className="badge bg-yellow-lt domain-name me-2"
21+
>
22+
{domain}
23+
</a>
24+
);
25+
};
26+
727
export function DomainsFormatter({ domains, createdOn }: Props) {
828
return (
929
<div className="flex-fill">
1030
<div className="font-weight-medium">
1131
{domains.map((domain: string) => (
12-
<a key={domain} href={`http://${domain}`} className="badge bg-yellow-lt domain-name">
13-
{domain}
14-
</a>
32+
<DomainLink key={domain} domain={domain} />
1533
))}
1634
</div>
1735
{createdOn ? (

frontend/src/components/Table/Formatter/EventFormatter.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const getEventValue = (event: AuditLog) => {
1010
switch (event.objectType) {
1111
case "user":
1212
return event.meta?.name;
13+
case "dead-host":
14+
return event.meta?.domainNames?.join(", ") || "N/A";
1315
default:
1416
return `UNKNOWN EVENT TYPE: ${event.objectType}`;
1517
}

frontend/src/locale/lang/en.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
"column.status": "Status",
4242
"created-on": "Created: {date}",
4343
"dashboard.title": "Dashboard",
44+
"dead-host.delete.content": "Are you sure you want to delete this 404 host?",
45+
"dead-host.delete.title": "Delete 404 Host",
4446
"dead-host.edit": "Edit 404 Host",
4547
"dead-host.new": "New 404 Host",
4648
"dead-hosts.actions-title": "404 Host #{id}",
@@ -67,8 +69,11 @@
6769
"error.max-domains": "Too many domains, max is {max}",
6870
"error.passwords-must-match": "Passwords must match",
6971
"error.required": "This is required",
72+
"event.created-dead-host": "Created 404 Host",
7073
"event.created-user": "Created User",
7174
"event.deleted-user": "Deleted User",
75+
"event.disabled-dead-host": "Disabled 404 Host",
76+
"event.enabled-dead-host": "Enabled 404 Host",
7277
"event.updated-user": "Updated User",
7378
"footer.github-fork": "Fork me on Github",
7479
"hosts.title": "Hosts",
@@ -84,6 +89,9 @@
8489
"notfound.title": "Oops… You just found an error page",
8590
"notification.dead-host-saved": "404 Host has been saved",
8691
"notification.error": "Error",
92+
"notification.host-deleted": "Host has been deleted",
93+
"notification.host-disabled": "Host has been disabled",
94+
"notification.host-enabled": "Host has been enabled",
8795
"notification.success": "Success",
8896
"notification.user-deleted": "User has been deleted",
8997
"notification.user-saved": "User has been saved",

frontend/src/locale/src/en.json

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,18 @@
134134
"dead-hosts.count": {
135135
"defaultMessage": "{count} 404 Hosts"
136136
},
137-
"dead-host.edit": {
138-
"defaultMessage": "Edit 404 Host"
139-
},
140137
"dead-hosts.empty": {
141138
"defaultMessage": "There are no 404 Hosts"
142139
},
140+
"dead-host.delete.content": {
141+
"defaultMessage": "Are you sure you want to delete this 404 host?"
142+
},
143+
"dead-host.delete.title": {
144+
"defaultMessage": "Delete 404 Host"
145+
},
146+
"dead-host.edit": {
147+
"defaultMessage": "Edit 404 Host"
148+
},
143149
"dead-host.new": {
144150
"defaultMessage": "New 404 Host"
145151
},
@@ -200,12 +206,21 @@
200206
"error.required": {
201207
"defaultMessage": "This is required"
202208
},
209+
"event.created-dead-host": {
210+
"defaultMessage": "Created 404 Host"
211+
},
203212
"event.created-user": {
204213
"defaultMessage": "Created User"
205214
},
206215
"event.deleted-user": {
207216
"defaultMessage": "Deleted User"
208217
},
218+
"event.disabled-dead-host": {
219+
"defaultMessage": "Disabled 404 Host"
220+
},
221+
"event.enabled-dead-host": {
222+
"defaultMessage": "Enabled 404 Host"
223+
},
209224
"event.updated-user": {
210225
"defaultMessage": "Updated User"
211226
},
@@ -254,9 +269,18 @@
254269
"notification.error": {
255270
"defaultMessage": "Error"
256271
},
272+
"notification.host-deleted": {
273+
"defaultMessage": "Host has been deleted"
274+
},
257275
"notification.user-deleted": {
258276
"defaultMessage": "User has been deleted"
259277
},
278+
"notification.host-disabled": {
279+
"defaultMessage": "Host has been disabled"
280+
},
281+
"notification.host-enabled": {
282+
"defaultMessage": "Host has been enabled"
283+
},
260284
"notification.user-saved": {
261285
"defaultMessage": "User has been saved"
262286
},

frontend/src/pages/Nginx/DeadHosts/Table.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ interface Props {
1212
isFetching?: boolean;
1313
onEdit?: (id: number) => void;
1414
onDelete?: (id: number) => void;
15+
onDisableToggle?: (id: number, enabled: boolean) => void;
1516
onNew?: () => void;
1617
}
17-
export default function Table({ data, isFetching, onEdit, onDelete, onNew }: Props) {
18+
export default function Table({ data, isFetching, onEdit, onDelete, onDisableToggle, onNew }: Props) {
1819
const columnHelper = createColumnHelper<DeadHost>();
1920
const columns = useMemo(
2021
() => [
@@ -83,9 +84,18 @@ export default function Table({ data, isFetching, onEdit, onDelete, onNew }: Pro
8384
<IconEdit size={16} />
8485
{intl.formatMessage({ id: "action.edit" })}
8586
</a>
86-
<a className="dropdown-item" href="#">
87+
<a
88+
className="dropdown-item"
89+
href="#"
90+
onClick={(e) => {
91+
e.preventDefault();
92+
onDisableToggle?.(info.row.original.id, !info.row.original.enabled);
93+
}}
94+
>
8795
<IconPower size={16} />
88-
{intl.formatMessage({ id: "action.disable" })}
96+
{intl.formatMessage({
97+
id: info.row.original.enabled ? "action.disable" : "action.enable",
98+
})}
8999
</a>
90100
<div className="dropdown-divider" />
91101
<a
@@ -108,7 +118,7 @@ export default function Table({ data, isFetching, onEdit, onDelete, onNew }: Pro
108118
},
109119
}),
110120
],
111-
[columnHelper, onDelete, onEdit],
121+
[columnHelper, onDelete, onEdit, onDisableToggle],
112122
);
113123

114124
const tableInstance = useReactTable<DeadHost>({

frontend/src/pages/Nginx/DeadHosts/TableWrapper.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { IconSearch } from "@tabler/icons-react";
2+
import { useQueryClient } from "@tanstack/react-query";
23
import { useState } from "react";
34
import Alert from "react-bootstrap/Alert";
5+
import { deleteDeadHost, toggleDeadHost } from "src/api/backend";
46
import { Button, LoadingPage } from "src/components";
57
import { useDeadHosts } from "src/hooks";
68
import { intl } from "src/locale";
@@ -9,6 +11,7 @@ import { showSuccess } from "src/notifications";
911
import Table from "./Table";
1012

1113
export default function TableWrapper() {
14+
const queryClient = useQueryClient();
1215
const [deleteId, setDeleteId] = useState(0);
1316
const [editId, setEditId] = useState(0 as number | "new");
1417
const { isFetching, isLoading, isError, error, data } = useDeadHosts(["owner", "certificate"]);
@@ -22,10 +25,17 @@ export default function TableWrapper() {
2225
}
2326

2427
const handleDelete = async () => {
25-
// await deleteUser(deleteId);
28+
await deleteDeadHost(deleteId);
2629
showSuccess(intl.formatMessage({ id: "notification.host-deleted" }));
2730
};
2831

32+
const handleDisableToggle = async (id: number, enabled: boolean) => {
33+
await toggleDeadHost(id, enabled);
34+
queryClient.invalidateQueries({ queryKey: ["dead-hosts"] });
35+
queryClient.invalidateQueries({ queryKey: ["dead-host", id] });
36+
showSuccess(intl.formatMessage({ id: enabled ? "notification.host-enabled" : "notification.host-disabled" }));
37+
};
38+
2939
return (
3040
<div className="card mt-4">
3141
<div className="card-status-top bg-red" />
@@ -60,17 +70,18 @@ export default function TableWrapper() {
6070
isFetching={isFetching}
6171
onEdit={(id: number) => setEditId(id)}
6272
onDelete={(id: number) => setDeleteId(id)}
73+
onDisableToggle={handleDisableToggle}
6374
onNew={() => setEditId("new")}
6475
/>
6576
{editId ? <DeadHostModal id={editId} onClose={() => setEditId(0)} /> : null}
6677
{deleteId ? (
6778
<DeleteConfirmModal
68-
title={intl.formatMessage({ id: "user.delete.title" })}
79+
title={intl.formatMessage({ id: "dead-host.delete.title" })}
6980
onConfirm={handleDelete}
7081
onClose={() => setDeleteId(0)}
7182
invalidations={[["dead-hosts"], ["dead-host", deleteId]]}
7283
>
73-
{intl.formatMessage({ id: "user.delete.content" })}
84+
{intl.formatMessage({ id: "dead-host.delete.content" })}
7485
</DeleteConfirmModal>
7586
) : null}
7687
</div>

0 commit comments

Comments
 (0)