Limit user role to archive viewer
This commit is contained in:
parent
53a87e57dd
commit
3426cea58c
2 changed files with 100 additions and 45 deletions
|
|
@ -119,6 +119,10 @@ func splitRecipients(value string) ([]string, error) {
|
|||
}
|
||||
|
||||
func homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !CanManageAccounts(r) {
|
||||
http.Redirect(w, r, "/view", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
renderStartPage(w, r)
|
||||
}
|
||||
|
||||
|
|
@ -128,28 +132,18 @@ func renderStartPage(w http.ResponseWriter, r *http.Request) {
|
|||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Mail-Graveyard</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-15">
|
||||
<script src="/static/app.js?v=20260713-15" defer></script></head>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-16">
|
||||
<script src="/static/app.js?v=20260713-16" defer></script></head>
|
||||
<body class="ol2013">
|
||||
<header class="ribbon">
|
||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||
%s
|
||||
<nav class="ribbon-tabs">
|
||||
%s
|
||||
%s
|
||||
</nav>
|
||||
%s
|
||||
</header>
|
||||
<aside class="backstage-menu" aria-label="Mail-Graveyard-Menue">
|
||||
<a class="backstage-item active" href="/">Start</a>
|
||||
<a class="backstage-item" href="/view">Archiv-Boxen</a>
|
||||
<a class="backstage-item" href="/import-export">Import/Export</a>
|
||||
<a class="backstage-item" href="/accounts">Konten-Verwaltung</a>
|
||||
<a class="backstage-item" href="/archives">Archiv-mbox Verwaltung</a>
|
||||
<a class="backstage-item" href="/transfer/postfach-archiv">Mail-Transfer</a>
|
||||
<a class="backstage-item" href="/users">Benutzerverwaltung</a>
|
||||
<a class="backstage-item" href="/logout">Logout</a>
|
||||
</aside>
|
||||
<button class="backstage-shade" type="button" aria-label="Menue schliessen" data-backstage-close></button>
|
||||
%s
|
||||
<main class="start-page">
|
||||
<section class="welcome-panel">
|
||||
<div class="welcome-kicker">Willkommen</div>
|
||||
|
|
@ -163,7 +157,7 @@ func renderStartPage(w http.ResponseWriter, r *http.Request) {
|
|||
</section>
|
||||
</main>
|
||||
<footer class="statusbar"><span>bereit</span></footer>
|
||||
</body></html>`, renderRibbonEmailBoxMenu("home"), renderRibbonTransferMenu(""), renderRibbonActions(false, user), html.EscapeString(userDisplayLabel(user)))
|
||||
</body></html>`, renderAppMenuButton(user), renderRibbonEmailBoxMenuForUser("home", user), renderRibbonTransferMenuForUser("", user), renderRibbonActions(false, user), renderBackstageForUser("home", user), html.EscapeString(userDisplayLabel(user)))
|
||||
}
|
||||
|
||||
// renderShell ist das Grundgeruest im Outlook-2013-Look:
|
||||
|
|
@ -176,32 +170,19 @@ func renderShell(w http.ResponseWriter, r *http.Request, active, readingPane str
|
|||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Mail-Graveyard</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-15">
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-16">
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<script src="/static/app.js?v=20260713-15" defer></script></head>
|
||||
<script src="/static/app.js?v=20260713-16" defer></script></head>
|
||||
<body class="ol2013">
|
||||
<header class="ribbon">
|
||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||
%s
|
||||
<nav class="ribbon-tabs">
|
||||
%s
|
||||
%s
|
||||
</nav>
|
||||
%s
|
||||
</header>
|
||||
<aside class="backstage-menu" aria-label="Mail-Graveyard-Menue">
|
||||
<a class="backstage-item active" href="/view">Archiv-Boxen</a>
|
||||
<a class="backstage-item" href="/import-export">Import/Export</a>
|
||||
<a class="backstage-item" href="/accounts">Konten-Verwaltung</a>
|
||||
<a class="backstage-item" href="/archives">Archiv-mbox Verwaltung</a>
|
||||
<a class="backstage-item" href="/transfer/postfach-archiv">Mail-Transfer</a>
|
||||
<a class="backstage-item transfer-sub" href="/transfer/postfach-archiv">Postfach <--> Archiv-MBox</a>
|
||||
<a class="backstage-item transfer-sub" href="/transfer/archiv-postfach">Archiv-MBox <--> Postfach</a>
|
||||
<a class="backstage-item transfer-sub" href="/transfer/postfach-postfach">Postfach <--> Postfach</a>
|
||||
<a class="backstage-item transfer-sub" href="/transfer/archiv-archiv">Archiv-MBox <--> Archiv-MBox</a>
|
||||
<a class="backstage-item" href="/users">Benutzerverwaltung</a>
|
||||
<a class="backstage-item" href="/logout">Logout</a>
|
||||
</aside>
|
||||
<button class="backstage-shade" type="button" aria-label="Menue schliessen" data-backstage-close></button>
|
||||
%s
|
||||
<div class="three-pane">
|
||||
<aside class="pane pane-tree" id="tree"
|
||||
hx-get="/view" hx-trigger="load" hx-target="#tree" hx-swap="innerHTML">
|
||||
|
|
@ -218,7 +199,7 @@ func renderShell(w http.ResponseWriter, r *http.Request, active, readingPane str
|
|||
</div>
|
||||
<footer class="statusbar"><span id="mig-status"
|
||||
hx-get="/migrate/status" hx-trigger="every 3s" hx-swap="innerHTML">bereit</span></footer>
|
||||
</body></html>`, renderRibbonEmailBoxMenu("archive"), renderRibbonTransferMenu(""), renderRibbonActions(false, user), renderInitialReadPane(readingPane))
|
||||
</body></html>`, renderAppMenuButton(user), renderRibbonEmailBoxMenuForUser("archive", user), renderRibbonTransferMenuForUser("", user), renderRibbonActions(false, user), renderBackstageForUser("archive", user), renderInitialReadPane(readingPane))
|
||||
}
|
||||
|
||||
func accountsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
@ -359,6 +340,9 @@ func transferHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func emailBoxHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireManager(w, r) {
|
||||
return
|
||||
}
|
||||
accounts, err := ListAccounts()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
|
@ -392,6 +376,9 @@ func emailBoxHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func sourceMailboxMessagesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireManager(w, r) {
|
||||
return
|
||||
}
|
||||
accountName := strings.TrimSpace(r.URL.Query().Get("source"))
|
||||
folder := strings.TrimSpace(r.URL.Query().Get("folder"))
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
|
@ -414,6 +401,9 @@ func sourceMailboxMessagesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func sourceMailboxMessageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireManager(w, r) {
|
||||
return
|
||||
}
|
||||
accountName := strings.TrimSpace(r.URL.Query().Get("source"))
|
||||
folder := strings.TrimSpace(r.URL.Query().Get("folder"))
|
||||
index, err := strconv.Atoi(r.URL.Query().Get("index"))
|
||||
|
|
@ -436,6 +426,9 @@ func sourceMailboxMessageHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func targetMailboxMessagesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireManager(w, r) {
|
||||
return
|
||||
}
|
||||
accountName := strings.TrimSpace(r.URL.Query().Get("target"))
|
||||
folder := strings.TrimSpace(r.URL.Query().Get("folder"))
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
|
@ -458,6 +451,9 @@ func targetMailboxMessagesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func targetMailboxMessageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireManager(w, r) {
|
||||
return
|
||||
}
|
||||
accountName := strings.TrimSpace(r.URL.Query().Get("target"))
|
||||
folder := strings.TrimSpace(r.URL.Query().Get("folder"))
|
||||
index, err := strconv.Atoi(r.URL.Query().Get("index"))
|
||||
|
|
@ -570,6 +566,10 @@ func migrateRunHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func migrateStatusHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !CanManageAccounts(r) {
|
||||
fmt.Fprint(w, "bereit")
|
||||
return
|
||||
}
|
||||
type job struct {
|
||||
Account string
|
||||
Started string
|
||||
|
|
@ -752,9 +752,9 @@ func renderAccountsPage(w http.ResponseWriter, r *http.Request, accounts []Accou
|
|||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Konten-Verwaltung - Mail-Graveyard</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-15">
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-16">
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<script src="/static/app.js?v=20260713-15" defer></script></head>
|
||||
<script src="/static/app.js?v=20260713-16" defer></script></head>
|
||||
<body class="ol2013">
|
||||
<header class="ribbon">
|
||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||
|
|
@ -798,9 +798,9 @@ func renderArchivesPage(w http.ResponseWriter, r *http.Request, archives []strin
|
|||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Archiv-mbox Verwaltung - Mail-Graveyard</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-15">
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-16">
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<script src="/static/app.js?v=20260713-15" defer></script></head>
|
||||
<script src="/static/app.js?v=20260713-16" defer></script></head>
|
||||
<body class="ol2013">
|
||||
<header class="ribbon">
|
||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||
|
|
@ -846,9 +846,9 @@ func renderUsersPage(w http.ResponseWriter, r *http.Request, users []AppUser, ed
|
|||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Benutzerverwaltung - Mail-Graveyard</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-15">
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-16">
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<script src="/static/app.js?v=20260713-15" defer></script></head>
|
||||
<script src="/static/app.js?v=20260713-16" defer></script></head>
|
||||
<body class="ol2013">
|
||||
<header class="ribbon">
|
||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||
|
|
@ -920,9 +920,9 @@ func renderTransferPage(w http.ResponseWriter, r *http.Request, mode transferMod
|
|||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>%s - Mail-Graveyard</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-15">
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-16">
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<script src="/static/app.js?v=20260713-15" defer></script></head>
|
||||
<script src="/static/app.js?v=20260713-16" defer></script></head>
|
||||
<body class="ol2013">
|
||||
<header class="ribbon">
|
||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||
|
|
@ -964,6 +964,9 @@ func renderTransferPage(w http.ResponseWriter, r *http.Request, mode transferMod
|
|||
}
|
||||
|
||||
func transferSideHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireManager(w, r) {
|
||||
return
|
||||
}
|
||||
side := transferSide(r.URL.Query().Get("side"))
|
||||
kind := strings.TrimSpace(r.URL.Query().Get("kind"))
|
||||
value := strings.TrimSpace(r.URL.Query().Get("value"))
|
||||
|
|
@ -984,6 +987,9 @@ func transferSideHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func transferMessagesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireManager(w, r) {
|
||||
return
|
||||
}
|
||||
side := transferSide(r.URL.Query().Get("side"))
|
||||
kind := strings.TrimSpace(r.URL.Query().Get("kind"))
|
||||
value := strings.TrimSpace(r.URL.Query().Get("value"))
|
||||
|
|
@ -994,6 +1000,9 @@ func transferMessagesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func transferMessageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !requireManager(w, r) {
|
||||
return
|
||||
}
|
||||
kind := strings.TrimSpace(r.URL.Query().Get("kind"))
|
||||
value := strings.TrimSpace(r.URL.Query().Get("value"))
|
||||
folder := strings.TrimSpace(r.URL.Query().Get("folder"))
|
||||
|
|
@ -1372,9 +1381,9 @@ func renderSourceEmailBoxPage(w http.ResponseWriter, r *http.Request, accounts [
|
|||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Quell-Postfach - Mail-Graveyard</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-15">
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-16">
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<script src="/static/app.js?v=20260713-15" defer></script></head>
|
||||
<script src="/static/app.js?v=20260713-16" defer></script></head>
|
||||
<body class="ol2013">
|
||||
<header class="ribbon">
|
||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||
|
|
@ -1416,9 +1425,9 @@ func renderTargetEmailBoxPage(w http.ResponseWriter, r *http.Request, accounts [
|
|||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Ziel-Postfach - Mail-Graveyard</title>
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-15">
|
||||
<link rel="stylesheet" href="/static/style.css?v=20260713-16">
|
||||
<script src="/static/htmx.min.js"></script>
|
||||
<script src="/static/app.js?v=20260713-15" defer></script></head>
|
||||
<script src="/static/app.js?v=20260713-16" defer></script></head>
|
||||
<body class="ol2013">
|
||||
<header class="ribbon">
|
||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||
|
|
@ -1973,11 +1982,47 @@ func renderRibbonEmailBoxMenu(active string) string {
|
|||
return b.String()
|
||||
}
|
||||
|
||||
func renderAppMenuButton(user AppUser) string {
|
||||
if !hasRole(user, roleManager) {
|
||||
return ""
|
||||
}
|
||||
return `<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>`
|
||||
}
|
||||
|
||||
func renderRibbonEmailBoxMenuForUser(active string, user AppUser) string {
|
||||
if hasRole(user, roleManager) {
|
||||
return renderRibbonEmailBoxMenu(active)
|
||||
}
|
||||
var b strings.Builder
|
||||
homeClass := "tab app-tab"
|
||||
if active == "home" {
|
||||
homeClass += " active"
|
||||
}
|
||||
archiveClass := "tab"
|
||||
if active == "archive" {
|
||||
archiveClass += " active"
|
||||
}
|
||||
fmt.Fprintf(&b, `<a class="%s" href="/">Mail-Graveyard</a>`, homeClass)
|
||||
fmt.Fprintf(&b, `<a class="%s" href="/view">Archiv-Boxen</a>`, archiveClass)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func renderRibbonTransferMenuForUser(active string, user AppUser) string {
|
||||
if !hasRole(user, roleManager) {
|
||||
return ""
|
||||
}
|
||||
return renderRibbonTransferMenu(active)
|
||||
}
|
||||
|
||||
func renderRibbonActions(settingsActive bool, user AppUser) string {
|
||||
settingsClass := "ribbon-icon"
|
||||
if settingsActive {
|
||||
settingsClass += " active"
|
||||
}
|
||||
if !hasRole(user, roleManager) {
|
||||
return fmt.Sprintf(`<div class="ribbon-spacer"></div><span class="ribbon-user" title="%s">%s</span><a class="ribbon-icon" href="/logout" title="Logout" aria-label="Logout">⏻</a>`,
|
||||
html.EscapeString(user.Username), html.EscapeString(userDisplayName(user)))
|
||||
}
|
||||
return fmt.Sprintf(`<div class="ribbon-spacer"></div><span class="ribbon-user" title="%s">%s</span><a class="%s" href="/users" title="Einstellungen" aria-label="Einstellungen">⚙</a><a class="ribbon-icon" href="/logout" title="Logout" aria-label="Logout">⏻</a>`,
|
||||
html.EscapeString(user.Username), html.EscapeString(userDisplayName(user)), settingsClass)
|
||||
}
|
||||
|
|
@ -2037,6 +2082,13 @@ func renderBackstage(active string) string {
|
|||
return b.String()
|
||||
}
|
||||
|
||||
func renderBackstageForUser(active string, user AppUser) string {
|
||||
if !hasRole(user, roleManager) {
|
||||
return ""
|
||||
}
|
||||
return renderBackstage(active)
|
||||
}
|
||||
|
||||
func renderTransferPicker(kind string, accounts []Account, archives []string) string {
|
||||
var b strings.Builder
|
||||
b.WriteString(`<div class="transfer-picker">`)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue