package server import ( "html/template" "net/http" ) // The server has no browsable UI. These three pages exist only because a // browser is the right place to approve a device, redeem an invite and run an // OIDC round trip. var pages = template.Must(template.New("layout").Parse(` {{define "layout"}} {{.Title}} · KeepOrg
{{template "body" .}}
{{end}} `)) var deviceTmpl = template.Must(template.Must(pages.Clone()).Parse(` {{define "body"}}

Approve this device

Sign in to let the client on your device sync your databases.

{{if .Error}}

{{.Error}}

{{end}}
{{if .OIDC}}Sign in with single sign-on →{{end}} {{end}}`)) var inviteTmpl = template.Must(template.Must(pages.Clone()).Parse(` {{define "body"}}

Create your account

You were invited to a KeepOrg server.

{{if .Error}}

{{.Error}}

{{end}}
{{end}}`)) var signInTmpl = template.Must(template.Must(pages.Clone()).Parse(` {{define "body"}}

KeepOrg

Sign in to create and manage your vaults.

{{if .Error}}

{{.Error}}

{{end}}
{{if .OIDC}}Sign in with single sign-on →{{end}} {{end}}`)) var vaultsTmpl = template.Must(template.Must(pages.Clone()).Parse(` {{define "body"}}

Your vaults

{{.User}}

{{if .Error}}

{{.Error}}

{{end}} {{if .Notice}}

{{.Notice}}

{{end}} {{if .Vaults}} {{range .Vaults}}{{end}}
VaultAccessOn conflictVersionLast saved
{{.Name}}.kdbx {{.Perm}} {{.Strategy}} {{.Version}} {{.Updated}}{{if .By}}
by {{.By}}{{end}}
{{else}}

No vaults yet. Create one below, then open it from the KeepOrg client on your computer or phone.

{{end}} {{if .Groups}}
Create a vault

This password encrypts the vault itself and is what everyone with access types into KeePass. It is not your account password, and it cannot be recovered: write it down before you continue.

Merging requires the server to keep this password, so a merge vault can be read by whoever controls the server. Any other setting keeps the key off the server.

{{else}}

You do not administer a group yet, so there is nowhere to put a vault. Ask an administrator to add you to one.

{{end}} {{end}}`)) var doneTmpl = template.Must(template.Must(pages.Clone()).Parse(` {{define "body"}}

{{.Title}}

{{.Message}}

{{end}}`)) func (s *Server) renderDevice(w http.ResponseWriter, code, errMsg string) { render(w, deviceTmpl, map[string]any{ "Title": "Approve device", "Code": code, "Error": errMsg, "OIDC": s.oidc != nil, }) } func (s *Server) renderInvite(w http.ResponseWriter, token, errMsg string) { render(w, inviteTmpl, map[string]any{"Title": "Create account", "Token": token, "Error": errMsg}) } func (s *Server) renderSignIn(w http.ResponseWriter, errMsg string) { render(w, signInTmpl, map[string]any{ "Title": "Sign in", "Error": errMsg, "OIDC": s.oidc != nil, }) } func (s *Server) renderVaults(w http.ResponseWriter, sess *webSession, errMsg, notice string) { vaults, groups := s.vaultRows(sess.user) render(w, vaultsTmpl, map[string]any{ "Title": "Vaults", "Wide": true, "User": sess.user.Username, "CSRF": sess.csrf, "Vaults": vaults, "Groups": groups, "Error": errMsg, "Notice": notice, }) } func (s *Server) renderDone(w http.ResponseWriter, title, msg string) { render(w, doneTmpl, map[string]any{"Title": title, "Message": msg}) } func render(w http.ResponseWriter, t *template.Template, data map[string]any) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Referrer-Policy", "no-referrer") _ = t.ExecuteTemplate(w, "layout", data) }