working sections version

This commit is contained in:
ston1th 2019-03-27 23:08:59 +01:00
commit 9424084a36
28 changed files with 367 additions and 251 deletions

View file

@ -115,6 +115,16 @@ type loginData struct {
Referer string
}
type sectionData struct {
Name string
Members map[string]bool
}
type pageData struct {
Page core.Page
Sections map[string]bool
}
func (c *Context) Exec() {
defer c.log()
if c.T == nil {

View file

@ -215,7 +215,7 @@ func sectionsHandler(ctx *Context) {
BodyTitle: "All Sections",
Admin: ctx.Admin(),
}
ctx.Data.Data = ctx.Srv.DB.GetAllSections(ctx.User())
ctx.Data.Data = ctx.Srv.DB.GetAllSections(ctx.User(), ctx.Admin())
ctx.Exec()
}
@ -228,7 +228,7 @@ func sectionHandler(ctx *Context) {
Admin: ctx.Admin(),
}
var err error
ctx.Data.Data, err = ctx.Srv.DB.GetAllSectionPages(section, ctx.User())
ctx.Data.Data, err = ctx.Srv.DB.GetAllSectionPages(section, ctx.User(), ctx.Admin())
if err != nil {
ctx.NotFound()
return
@ -238,61 +238,140 @@ func sectionHandler(ctx *Context) {
func sectionNewHandler(ctx *Context) {
ctx.Template("sectionNewHandler")
section := ctx.Var("section")
ctx.Data = webData{
Title: section,
BodyTitle: section,
Admin: ctx.Admin(),
Title: "New Section",
BodyTitle: "New Section",
}
var err error
ctx.Data.Data, err = ctx.Srv.DB.GetAllSectionPages(section, ctx.User())
users, err := ctx.Srv.DB.GetUsers()
if err != nil {
ctx.NotFound()
ctx.Error(err)
return
}
ctx.Exec()
}
func sectionDelHandler(ctx *Context) {
ctx.Template("sectionDelHandler")
section := ctx.Var("section")
ctx.Data = webData{
Title: section,
BodyTitle: section,
Admin: ctx.Admin(),
sd := sectionData{Members: make(map[string]bool)}
for _, u := range users {
sd.Members[u.Username] = false
}
var err error
ctx.Data.Data, err = ctx.Srv.DB.GetAllSectionPages(section, ctx.User())
if err != nil {
ctx.NotFound()
return
switch ctx.Method() {
case "GET":
ctx.Data.Data = sd
ctx.Exec()
case "POST":
if !ctx.CheckXsrf() {
return
}
section := ctx.Form("section")
members := ctx.FormSlice("members")
for _, m := range members {
sd.Members[m] = true
}
ctx.Data.Data = sd
if section == "" {
ctx.Error("empty section")
return
}
err = ctx.Srv.DB.CreateSection(section, members, false)
if err != nil {
ctx.Error(err)
return
}
log.Printf("create: section %s created by %s\n", section, ctx.User())
ctx.Redirect(core.SectionsURI, http.StatusFound)
}
ctx.Exec()
}
func sectionEditHandler(ctx *Context) {
ctx.Template("sectionEditHandler")
section := ctx.Var("section")
ctx.Data = webData{
Title: section,
BodyTitle: section,
Admin: ctx.Admin(),
Title: "Edit Section",
BodyTitle: "Edit Section",
}
var err error
ctx.Data.Data, err = ctx.Srv.DB.GetAllSectionPages(section, ctx.User())
users, err := ctx.Srv.DB.GetUsers()
if err != nil {
ctx.NotFound()
ctx.Error(err)
return
}
ctx.Exec()
sd := sectionData{Members: make(map[string]bool)}
for _, u := range users {
sd.Members[u.Username] = false
}
s, err := ctx.Srv.DB.GetSection(ctx.Var("section"))
if err != nil {
ctx.Error(err)
return
}
sd.Name = s.Name
switch ctx.Method() {
case "GET":
for _, m := range s.Members {
sd.Members[m] = true
}
ctx.Data.Data = sd
ctx.Exec()
case "POST":
if !ctx.CheckXsrf() {
return
}
members := ctx.FormSlice("members")
for _, m := range members {
sd.Members[m] = true
}
ctx.Data.Data = sd
err = ctx.Srv.DB.UpdateSection(s.Name, members, s.User)
if err != nil {
ctx.Error(err)
return
}
log.Printf("update: section %s updated by %s\n", s.Name, ctx.User())
ctx.Redirect(core.SectionsURI, http.StatusFound)
}
}
func sectionDelHandler(ctx *Context) {
ctx.Template("sectionDelHandler")
ctx.Data = webData{
Title: "Delete Section",
BodyTitle: "Delete Section",
}
s, err := ctx.Srv.DB.GetSection(ctx.Var("section"))
if err != nil {
ctx.Error(err)
return
}
if s.User {
ctx.Error("user section can not be deleted")
return
}
switch ctx.Method() {
case "GET":
ctx.Data.Data = s.Name
ctx.Exec()
case "POST":
if !ctx.CheckXsrf() {
return
}
err := ctx.Srv.DB.DeleteSection(s.Name)
if err != nil {
ctx.Error(err)
return
}
log.Printf("delete: section %s deleted by %s\n", s.Name, ctx.User())
ctx.Redirect(core.SectionsURI, http.StatusFound)
}
}
func pageNewHandler(ctx *Context) {
ctx.Template("pageNewHandler")
ctx.Data = webData{Title: "New Page"}
user := ctx.User()
secs, err := ctx.Srv.DB.GetUserSections(user)
if err != nil {
ctx.Error(err)
return
}
switch ctx.Method() {
case "GET":
ctx.Data.Data = core.Page{Perm: core.Public}
secs[user] = true
ctx.Data.Data = pageData{core.Page{Perm: core.Public}, secs}
ctx.Exec()
case "POST":
if !ctx.CheckXsrf() {
@ -307,7 +386,8 @@ func pageNewHandler(ctx *Context) {
Markdown: markdown,
Perm: perm,
}
ctx.Data.Data = p
secs[section] = true
ctx.Data.Data = pageData{p, secs}
if title == "" {
ctx.Error("empty title")
return
@ -317,10 +397,7 @@ func pageNewHandler(ctx *Context) {
return
}
if section != core.WikiSection {
section = ctx.User()
}
page, err := ctx.Srv.DB.CreatePage(title, section, markdown, ctx.User(), perm)
page, err := ctx.Srv.DB.CreatePage(title, section, markdown, user, perm)
if err != nil {
ctx.Error(err)
return
@ -540,12 +617,12 @@ func pageDelHandler(ctx *Context) {
}
}
func userHandler(ctx *Context) {
func usersHandler(ctx *Context) {
if !ctx.LoggedOn() {
ctx.NotFound()
return
}
ctx.Template("userHandler")
ctx.Template("usersHandler")
ctx.Data = webData{
Title: "Users",
BodyTitle: "Users",
@ -593,8 +670,8 @@ func userNewHandler(ctx *Context) {
ctx.Error(err)
return
}
log.Printf("create: %s created by %s\n", user, ctx.User())
ctx.Redirect("/user", http.StatusFound)
log.Printf("create: user %s created by %s\n", user, ctx.User())
ctx.Redirect("/users", http.StatusFound)
}
}
@ -635,8 +712,8 @@ func userEditHandler(ctx *Context) {
ctx.Error(err)
return
}
log.Printf("update: %s updated by %s\n", user, ctx.User())
ctx.Redirect("/user", http.StatusFound)
log.Printf("update: user %s updated by %s\n", user, ctx.User())
ctx.Redirect("/users", http.StatusFound)
return
}
if err := ctx.Srv.DB.UpdateUserPassword(user, password); err != nil {
@ -724,7 +801,7 @@ func userUnlockHandler(ctx *Context) {
log.Println("unlock:", err)
}
log.Printf("unlock: %s unlocked by %s\n", user, ctx.User())
ctx.Redirect("/user", http.StatusFound)
ctx.Redirect("/users", http.StatusFound)
}
func userDelHandler(ctx *Context) {
@ -751,12 +828,12 @@ func userDelHandler(ctx *Context) {
if err := ctx.Srv.DB.DeleteUser(user); err != nil {
log.Println("delete:", err)
}
log.Printf("delete: %s deleted by %s\n", user, self)
log.Printf("delete: user %s deleted by %s\n", user, self)
if user == self {
ctx.Redirect("/logout", http.StatusFound)
return
}
ctx.Redirect("/user", http.StatusFound)
ctx.Redirect("/users", http.StatusFound)
}
}

View file

@ -35,23 +35,23 @@ var routes = []route{
[]string{"GET"},
},
{
"/sections/new",
"/section/new",
adminAuthHandler(
sectionNewHandler),
[]string{"GET", "POST"},
},
{
"/section/del/{section:[a-zA-Z0-9]+$}",
adminAuthHandler(
sectionDelHandler),
[]string{"GET", "POST"},
},
{
"/section/edit/{section:[a-zA-Z0-9]+$}",
adminAuthHandler(
sectionEditHandler),
[]string{"GET", "POST"},
},
{
"/section/del/{section:[a-zA-Z0-9]+$}",
adminAuthHandler(
sectionDelHandler),
[]string{"GET", "POST"},
},
{
"/search",
searchHandler,
@ -81,9 +81,9 @@ var routes = []route{
[]string{"GET", "POST"},
},
{
"/user",
"/users",
adminAuthHandler(
userHandler),
usersHandler),
[]string{"GET"},
},
{
@ -92,18 +92,18 @@ var routes = []route{
userNewHandler),
[]string{"GET", "POST"},
},
{
"/user/del/{user:[a-zA-Z0-9]+$}",
userAuthHandler(
userDelHandler),
[]string{"GET", "POST"},
},
{
"/user/edit/{user:[a-zA-Z0-9]+$}",
userAuthHandler(
userEditHandler),
[]string{"GET", "POST"},
},
{
"/user/del/{user:[a-zA-Z0-9]+$}",
userAuthHandler(
userDelHandler),
[]string{"GET", "POST"},
},
{
"/user/totp/{user:[a-zA-Z0-9]+$}",
userAuthHandler(

View file

@ -36,7 +36,7 @@ const (
<title>GoWiki | {{.Title}}</title>
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" integrity="sha256-bgotk/IPq4Yvt6s8AQGPTM5ZjPjQ6rrBRa2EyxpnFSc="></link>
<link rel="stylesheet" type="text/css" href="/bootstrap.css" media="screen" integrity="sha256-NeLmQ7cX66J4MdtgGlG3O/TgvsSyP1b9WbaQtxYZUbQ="></link>
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-o0xveJH8qNnWr/39Jnx97yDlYrvjuUnzE4q3p+94Yp4="></link>
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-5/Vbh+c9BC042HeSbJXZZVIc1dD2b9cy6uH9LFAOSfo="></link>
<meta name="theme-color" content="#375a7f">
<meta name="description" content="{{.Title}}">
</head>
@ -150,7 +150,7 @@ const (
<ul class="nav navbar-nav ml-auto">
{{if .Login}}
{{if .Admin}}
<li class="nav-item"><a class="nav-link" href="/user">Users</a></li>
<li class="nav-item"><a class="nav-link" href="/users">Users</a></li>
{{else}}
<li class="nav-item"><a class="nav-link" href="/user/edit/{{.User}}">Profile</a></li>
{{end}}
@ -243,11 +243,7 @@ const (
</div>
<div class="custom-control custom-radio">
<input type="radio" id="perm2" name="perm" value="2" class="custom-control-input" {{if eq .Data.Perm 2}}checked=""{{end}}>
<label class="custom-control-label" for="perm2">Internal</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" id="perm3" name="perm" value="3" class="custom-control-input" {{if eq .Data.Perm 3}}checked=""{{end}}>
<label class="custom-control-label" for="perm3">Private</label>
<label class="custom-control-label" for="perm2">Private</label>
</div>
</div>
<button class="btn btn-sm btn-primary" type="submit">Update</button>
@ -271,9 +267,6 @@ const (
<span class="badge badge-primary">Public</span>
{{end}}
{{if eq .Data.Perm 2}}
<span class="badge badge-warning">Internal</span>
{{end}}
{{if eq .Data.Perm 3}}
<span class="badge badge-danger">Private</span>
{{end}}
<br>
@ -321,30 +314,31 @@ const (
<div class="form-group">
<label class="col-form-label" for="section">Section</label>
<select class="form-control input-sm" id="section" name="section" required>
<option>wiki</option>
<option>{{.User}}</option>
{{range $section, $selected := .Data.Sections}}
{{if $selected}}
<option value="{{$section}}" selected>{{$section}}</option>
{{else}}
<option value="{{$section}}">{{$section}}</option>
{{end}}
{{end}}
</select>
</div>
<div class="form-group">
<label class="col-form-label" for="title">Title</label>
<input class="form-control input-sm" type="text" id="title" name="title" placeholder="Title" value="{{.Data.Title}}" spellcheck="false" autocomplete="off" autofocus required>
<input class="form-control input-sm" type="text" id="title" name="title" placeholder="Title" value="{{.Data.Page.Title}}" spellcheck="false" autocomplete="off" autofocus required>
</div>
<div class="form-group">
<label class="col-form-label" for="markdown">Markdown</label>
<textarea class="form-control input-sm md-text" id="markdown" name="markdown" rows="30" spellcheck="false">{{.Data.Markdown}}</textarea>
<textarea class="form-control input-sm md-text" id="markdown" name="markdown" rows="30" spellcheck="false">{{.Data.Page.Markdown}}</textarea>
</div>
<div class="form-group">
<div class="custom-control custom-radio">
<input type="radio" id="perm1" name="perm" value="1" class="custom-control-input" {{if eq .Data.Perm 1}}checked=""{{end}}>
<input type="radio" id="perm1" name="perm" value="1" class="custom-control-input" {{if eq .Data.Page.Perm 1}}checked=""{{end}}>
<label class="custom-control-label" for="perm1">Public</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" id="perm2" name="perm" value="2" class="custom-control-input" {{if eq .Data.Perm 2}}checked=""{{end}}>
<label class="custom-control-label" for="perm2">Internal</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" id="perm3" name="perm" value="3" class="custom-control-input" {{if eq .Data.Perm 3}}checked=""{{end}}>
<label class="custom-control-label" for="perm3">Private</label>
<input type="radio" id="perm2" name="perm" value="2" class="custom-control-input" {{if eq .Data.Page.Perm 2}}checked=""{{end}}>
<label class="custom-control-label" for="perm2">Private</label>
</div>
</div>
<button class="btn btn-sm btn-primary" type="submit">Create</button>
@ -410,9 +404,6 @@ const (
<span class="badge badge-primary">Public</span>
{{end}}
{{if eq .Data.Perm 2}}
<span class="badge badge-warning">Internal</span>
{{end}}
{{if eq .Data.Perm 3}}
<span class="badge badge-danger">Private</span>
{{end}}
<br>
@ -467,14 +458,14 @@ const (
<div class="col-xs-4 offset-4">
<div class="card border-danger mx-auto">
<div class="card-header">
<strong>Delete {{.Data.Username}}?</strong>
<strong>Delete {{.Data}}?</strong>
</div>
<div class="card-body">
<p>You are about to delete user <a href="/{{.Data.Username}}">{{.Data.Username}}</a>.<br>This will also remove all private pages of this user.</p>
<form class="form-horizontal" action="/user/del/{{.Data.Username}}" method="post">
<p>You are about to delete section <a href="/{{.Data}}">{{.Data}}</a>.<br>This will also remove all pages of this section.</p>
<form class="form-horizontal" action="/section/del/{{.Data}}" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<button class="btn btn-sm btn-danger" type="submit">Delete</button>
<a href="/user" class="btn btn-sm btn-primary">Back</a>
<a href="/{{.Data}}" class="btn btn-sm btn-primary">Back</a>
</form>
</div>
</div>
@ -484,72 +475,52 @@ const (
{{end}}
{{end}}`
sectionEdit = `{{define "body"}}
{{if .Data}}
<div class="row">
<div class="col-xs-4 offset-4">
<div class="card border-primary mx-auto">
<div class="card-header">
<strong>{{.BodyTitle}}</strong>
{{if .Data.Secret}}
<a href="/user/totp/{{.Data.Username}}" class="btn btn-sm btn-danger float-right">Disable TOTP</a>
{{else}}
<a href="/user/totp/{{.Data.Username}}" class="btn btn-sm btn-success float-right">Enable TOTP</a>
{{end}}
</div>
<div class="card-body">
<form class="form-horizontal" action="/user/edit/{{.Data.Username}}" method="post">
<form class="form-horizontal" action="/section/edit/{{.Data.Name}}" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<div class="form-group">
<label class="col-form-label" for="user">Username</label>
<input class="form-control input-sm" type="text" id="user" name="user" value="{{.Data.Username}}" disabled>
<label class="col-form-label" for="section">Section</label>
<input class="form-control input-sm" type="text" id="section" name="section" value="{{.Data.Name}}" disabled>
</div>
<div class="form-group">
<label class="col-form-label" for="password">Password</label>
<input class="form-control input-sm" type="password" id="password" name="password" autofocus>
</div>
<div class="form-group">
<label class="col-form-label" for="repeat">Repeat</label>
<input class="form-control input-sm" type="password" id="repeat" name="repeat">
</div>
{{if .Admin}}
<div class="form-group">
<label class="col-form-label" for="admin">Admin Privileges</label>
{{if .Data.Admin}}
<input type="checkbox" id="admin" name="admin" value="0" checked>
{{else}}
<input type="checkbox" id="admin" name="admin" value="0">
<label class="col-form-label" for="members">Members</label>
<select class="form-control input-sm sections" id="members" name="members" multiple required>
{{range $user, $member := .Data.Members}}
{{if $member}}
<option value="{{$user}}" selected>{{$user}}</option>
{{else}}
<option value="{{$user}}">{{$user}}</option>
{{end}}
{{end}}
</select>
</div>
{{end}}
<button class="btn btn-sm btn-primary" type="submit">Update</button>
{{if .Admin}}
<a href="/user" class="btn btn-sm btn-primary">Back</a>
{{else}}
<a href="/" class="btn btn-sm btn-primary">Back</a>
{{end}}
<a class="btn btn-sm btn-danger" href="/user/del/{{.Data.Username}}">Delete</a>
<a href="/{{.Data.Name}}" class="btn btn-sm btn-primary">Back</a>
</form>
{{if .Admin}}
{{if eq .Data.Locked 3}}
<form class="form-horizontal" action="/user/unlock/{{.Data.Username}}" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<div class="form-group">
<label class="col-form-label" for="unlock">Locked</label>
<button class="btn btn-sm btn-warning" type="submit" id="unlock">Unlock</button>
</div>
</form>
{{end}}
{{end}}
</div>
</div>
</div>
</div>
{{end}}
{{end}}`
section = `{{define "body"}}
<div class="page-header">
<div class="row">
<h2>{{.BodyTitle}}</h2>
<div class="col">
<h2>{{.BodyTitle}}</h2>
</div>
<div class="col">
{{if .Admin}}
<div class="btn-group float-right">
<a class="btn btn-sm btn-primary" href="/section/edit/{{.BodyTitle}}">Edit</a>
<a class="btn btn-sm btn-danger" href="/section/del/{{.BodyTitle}}">Delete</a>
</div>
{{end}}
</div>
</div>
{{if .Data}}
@ -570,26 +541,26 @@ const (
<strong>{{.BodyTitle}}</strong>
</div>
<div class="card-body">
<form class="form-horizontal" action="/user/new" method="post">
<form class="form-horizontal" action="/section/new" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<div class="form-group">
<label class="col-form-label" for="user">Username</label>
<input class="form-control input-sm" type="text" id="user" name="user" autocomplete="off" autofocus required>
<label class="col-form-label" for="section">Section</label>
<input class="form-control input-sm" type="text" id="section" name="section" autocomplete="off" value="{{.Data.Name}}" autofocus required>
</div>
<div class="form-group">
<label class="col-form-label" for="password">Password</label>
<input class="form-control input-sm" type="password" id="password" name="password" required>
</div>
<div class="form-group">
<label class="col-form-label" for="repeat">Repeat</label>
<input class="form-control input-sm" type="password" id="repeat" name="repeat" required>
</div>
<div class="form-group">
<label class="col-form-label" for="admin">Admin Privileges</label>
<input type="checkbox" id="admin" name="admin" value="0">
<label class="col-form-label" for="members">Members</label>
<select class="form-control input-sm sections" id="members" name="members" multiple required>
{{range $user, $member := .Data.Members}}
{{if $member}}
<option value="{{$user}}" selected>{{$user}}</option>
{{else}}
<option value="{{$user}}">{{$user}}</option>
{{end}}
{{end}}
</select>
</div>
<button class="btn btn-sm btn-primary" type="submit">Create</button>
<a href="/user" class="btn btn-sm btn-primary">Back</a>
<a href="/sections" class="btn btn-sm btn-primary">Back</a>
</form>
</div>
</div>
@ -602,6 +573,13 @@ const (
<h2>{{.BodyTitle}}</h2>
</div>
</div>
{{if .Admin}}
<div class="row mb-3">
<div class="col-xs-5">
<a class="btn btn-sm btn-primary" href="/section/new"><b>New Section</b></a>
</div>
</div>
{{end}}
{{if .Data}}
<div class="row">
{{range $index, $item := .Data}}
@ -632,11 +610,11 @@ const (
<strong>Delete {{.Data.Username}}?</strong>
</div>
<div class="card-body">
<p>You are about to delete user <a href="/{{.Data.Username}}">{{.Data.Username}}</a>.<br>This will also remove all private pages of this user.</p>
<p>You are about to delete user <a href="/{{.Data.Username}}">{{.Data.Username}}</a>.<br>This will also remove all pages of this user.</p>
<form class="form-horizontal" action="/user/del/{{.Data.Username}}" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<button class="btn btn-sm btn-danger" type="submit">Delete</button>
<a href="/user" class="btn btn-sm btn-primary">Back</a>
<a href="/users" class="btn btn-sm btn-primary">Back</a>
</form>
</div>
</div>
@ -685,7 +663,7 @@ const (
{{end}}
<button class="btn btn-sm btn-primary" type="submit">Update</button>
{{if .Admin}}
<a href="/user" class="btn btn-sm btn-primary">Back</a>
<a href="/users" class="btn btn-sm btn-primary">Back</a>
{{else}}
<a href="/" class="btn btn-sm btn-primary">Back</a>
{{end}}
@ -708,7 +686,41 @@ const (
</div>
{{end}}
{{end}}`
user = `{{define "body"}}
userNew = `{{define "body"}}
<div class="row">
<div class="col-xs-4 offset-4">
<div class="card border-primary mx-auto">
<div class="card-header">
<strong>{{.BodyTitle}}</strong>
</div>
<div class="card-body">
<form class="form-horizontal" action="/user/new" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<div class="form-group">
<label class="col-form-label" for="user">Username</label>
<input class="form-control input-sm" type="text" id="user" name="user" autocomplete="off" autofocus required>
</div>
<div class="form-group">
<label class="col-form-label" for="password">Password</label>
<input class="form-control input-sm" type="password" id="password" name="password" required>
</div>
<div class="form-group">
<label class="col-form-label" for="repeat">Repeat</label>
<input class="form-control input-sm" type="password" id="repeat" name="repeat" required>
</div>
<div class="form-group">
<label class="col-form-label" for="admin">Admin Privileges</label>
<input type="checkbox" id="admin" name="admin" value="0">
</div>
<button class="btn btn-sm btn-primary" type="submit">Create</button>
<a href="/users" class="btn btn-sm btn-primary">Back</a>
</form>
</div>
</div>
</div>
</div>
{{end}}`
users = `{{define "body"}}
<div class="page-header">
<div class="row">
<h2>{{.BodyTitle}}</h2>
@ -762,40 +774,6 @@ const (
{{end}}
</div>
</div>
{{end}}`
userNew = `{{define "body"}}
<div class="row">
<div class="col-xs-4 offset-4">
<div class="card border-primary mx-auto">
<div class="card-header">
<strong>{{.BodyTitle}}</strong>
</div>
<div class="card-body">
<form class="form-horizontal" action="/user/new" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<div class="form-group">
<label class="col-form-label" for="user">Username</label>
<input class="form-control input-sm" type="text" id="user" name="user" autocomplete="off" autofocus required>
</div>
<div class="form-group">
<label class="col-form-label" for="password">Password</label>
<input class="form-control input-sm" type="password" id="password" name="password" required>
</div>
<div class="form-group">
<label class="col-form-label" for="repeat">Repeat</label>
<input class="form-control input-sm" type="password" id="repeat" name="repeat" required>
</div>
<div class="form-group">
<label class="col-form-label" for="admin">Admin Privileges</label>
<input type="checkbox" id="admin" name="admin" value="0">
</div>
<button class="btn btn-sm btn-primary" type="submit">Create</button>
<a href="/user" class="btn btn-sm btn-primary">Back</a>
</form>
</div>
</div>
</div>
</div>
{{end}}`
userTotp = `{{define "body"}}
{{if .Data}}
@ -955,6 +933,9 @@ textarea,input,select {
color: #e2e2e2 !important;
background-color: #444444 !important;
}
select.sections {
height: 120px !important;
}
input.menu {
color: #e2e2e2 !important;
background-color: #222222 !important;
@ -1045,7 +1026,7 @@ func (s *HTTPServer) loadTemplates() {
s.templ["sectionEditHandler"] = parse(index, menu, sectionEdit)
s.templ["sectionDelHandler"] = parse(index, menu, sectionDel)
// users
s.templ["userHandler"] = parse(index, menu, user)
s.templ["usersHandler"] = parse(index, menu, users)
s.templ["userNewHandler"] = parse(index, menu, userNew)
s.templ["userEditHandler"] = parse(index, menu, userEdit)
s.templ["userDelHandler"] = parse(index, menu, userDel)