change javascript into typescript for webaccount and webadmin interface

all ui frontend code is now in typescript. we no longer need jshint, and we
build the frontend code during "make build".

this also changes tlsrpt types for a Report, not encoding field names with
dashes, but to keep them valid identifiers in javascript. this makes it more
conveniently to work with in the frontend, and works around a sherpats
limitation.
This commit is contained in:
Mechiel Lukkien
2023-12-31 11:55:22 +01:00
parent da3ed38a5c
commit a9940f9855
37 changed files with 11539 additions and 5019 deletions

View File

@ -18,11 +18,11 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"reflect"
"runtime/debug"
"sort"
@ -67,12 +67,22 @@ import (
var pkglog = mlog.New("webadmin", nil)
//go:embed adminapi.json
//go:embed api.json
var adminapiJSON []byte
//go:embed admin.html
var adminHTML []byte
//go:embed admin.js
var adminJS []byte
var webadminFile = &mox.WebappFile{
HTML: adminHTML,
JS: adminJS,
HTMLPath: filepath.FromSlash("webadmin/admin.html"),
JSPath: filepath.FromSlash("webadmin/admin.js"),
}
var adminDoc = mustParseAPI("admin", adminapiJSON)
var adminSherpaHandler http.Handler
@ -206,18 +216,15 @@ func Handle(w http.ResponseWriter, r *http.Request) {
lw.AddAttr(slog.Bool("authadmin", true))
}
if r.Method == "GET" && r.URL.Path == "/" {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Cache-Control", "no-cache; max-age=0")
// We typically return the embedded admin.html, but during development it's handy
// to load from disk.
f, err := os.Open("webadmin/admin.html")
if err == nil {
defer f.Close()
_, _ = io.Copy(w, f)
} else {
_, _ = w.Write(adminHTML)
if r.URL.Path == "/" {
switch r.Method {
default:
http.Error(w, "405 - method not allowed - use get", http.StatusMethodNotAllowed)
return
case "GET", "HEAD":
}
webadminFile.Serve(ctx, pkglog.WithContext(ctx), w, r)
return
}
adminSherpaHandler.ServeHTTP(w, r.WithContext(ctx))
@ -338,7 +345,7 @@ type MTASTSCheckResult struct {
}
type SRVConfCheckResult struct {
SRVs map[string][]*net.SRV // Service (e.g. "_imaps") to records.
SRVs map[string][]net.SRV // Service (e.g. "_imaps") to records.
Result
}
@ -416,6 +423,17 @@ func (Admin) CheckDomain(ctx context.Context, domainName string) (r CheckResult)
return checkDomain(nctx, resolver, dialer, domainName)
}
func unptr[T any](l []*T) []T {
if l == nil {
return nil
}
r := make([]T, len(l))
for i, e := range l {
r[i] = *e
}
return r
}
func checkDomain(ctx context.Context, resolver dns.Resolver, dialer *net.Dialer, domainName string) (r CheckResult) {
log := pkglog.WithContext(ctx)
@ -1362,11 +1380,11 @@ When enabling MTA-STS, or updating a policy, always update the policy first (thr
srvwg.Wait()
instr := "Ensure DNS records like the following exist:\n\n"
r.SRVConf.SRVs = map[string][]*net.SRV{}
r.SRVConf.SRVs = map[string][]net.SRV{}
for _, req := range reqs {
name := req.name + "_.tcp." + domain.ASCII
instr += fmt.Sprintf("\t%s._tcp.%-*s SRV 0 1 %d %s\n", req.name, len("_submissions")-len(req.name)+len(domain.ASCII+"."), domain.ASCII+".", req.port, req.host)
r.SRVConf.SRVs[req.name] = req.srvs
r.SRVConf.SRVs[req.name] = unptr(req.srvs)
if err != nil {
addf(&r.SRVConf.Errors, "Looking up SRV record %q: %s", name, err)
} else if len(req.srvs) == 0 {

File diff suppressed because it is too large Load Diff

2978
webadmin/admin.js Normal file

File diff suppressed because it is too large Load Diff

2982
webadmin/admin.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2157,7 +2157,6 @@
"Typewords": [
"{}",
"[]",
"nullable",
"SRV"
]
},
@ -2496,38 +2495,38 @@
},
{
"Name": "Report",
"Docs": "Report is a TLSRPT report, transmitted in JSON format.",
"Docs": "Report is a TLSRPT report.",
"Fields": [
{
"Name": "organization-name",
"Name": "OrganizationName",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "date-range",
"Name": "DateRange",
"Docs": "",
"Typewords": [
"TLSRPTDateRange"
]
},
{
"Name": "contact-info",
"Docs": "Email address.",
"Typewords": [
"string"
]
},
{
"Name": "report-id",
"Name": "ContactInfo",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "policies",
"Name": "ReportID",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "Policies",
"Docs": "",
"Typewords": [
"[]",
@ -2541,14 +2540,14 @@
"Docs": "note: with TLSRPT prefix to prevent clash in sherpadoc types.",
"Fields": [
{
"Name": "start-datetime",
"Name": "Start",
"Docs": "",
"Typewords": [
"timestamp"
]
},
{
"Name": "end-datetime",
"Name": "End",
"Docs": "",
"Typewords": [
"timestamp"
@ -2561,21 +2560,21 @@
"Docs": "",
"Fields": [
{
"Name": "policy",
"Name": "Policy",
"Docs": "",
"Typewords": [
"ResultPolicy"
]
},
{
"Name": "summary",
"Name": "Summary",
"Docs": "",
"Typewords": [
"Summary"
]
},
{
"Name": "failure-details",
"Name": "FailureDetails",
"Docs": "",
"Typewords": [
"[]",
@ -2589,14 +2588,14 @@
"Docs": "",
"Fields": [
{
"Name": "policy-type",
"Name": "Type",
"Docs": "",
"Typewords": [
"PolicyType"
]
},
{
"Name": "policy-string",
"Name": "String",
"Docs": "",
"Typewords": [
"[]",
@ -2604,15 +2603,15 @@
]
},
{
"Name": "policy-domain",
"Name": "Domain",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "mx-host",
"Docs": "Example in RFC has errata, it originally was a single string. ../rfc/8460-eid6241 ../rfc/8460:1779",
"Name": "MXHost",
"Docs": "",
"Typewords": [
"[]",
"string"
@ -2625,14 +2624,14 @@
"Docs": "",
"Fields": [
{
"Name": "total-successful-session-count",
"Name": "TotalSuccessfulSessionCount",
"Docs": "",
"Typewords": [
"int64"
]
},
{
"Name": "total-failure-session-count",
"Name": "TotalFailureSessionCount",
"Docs": "",
"Typewords": [
"int64"
@ -2645,57 +2644,56 @@
"Docs": "",
"Fields": [
{
"Name": "result-type",
"Name": "ResultType",
"Docs": "",
"Typewords": [
"ResultType"
]
},
{
"Name": "sending-mta-ip",
"Name": "SendingMTAIP",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "receiving-mx-hostname",
"Name": "ReceivingMXHostname",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "receiving-mx-helo",
"Docs": "",
"Typewords": [
"nullable",
"string"
]
},
{
"Name": "receiving-ip",
"Name": "ReceivingMXHelo",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "failed-session-count",
"Name": "ReceivingIP",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "FailedSessionCount",
"Docs": "",
"Typewords": [
"int64"
]
},
{
"Name": "additional-information",
"Name": "AdditionalInformation",
"Docs": "",
"Typewords": [
"string"
]
},
{
"Name": "failure-reason-code",
"Name": "FailureReasonCode",
"Docs": "",
"Typewords": [
"string"

1879
webadmin/api.ts Normal file

File diff suppressed because it is too large Load Diff