unstable: initial tags

This commit is contained in:
ston1th 2019-08-20 23:57:43 +02:00
commit b3b62af3a4
28 changed files with 503 additions and 91 deletions

View file

@ -7,6 +7,7 @@ import (
"git.giftfish.de/ston1th/docstore/pkg/fs"
"git.giftfish.de/ston1th/docstore/pkg/log"
"git.giftfish.de/ston1th/docstore/pkg/otp"
"git.giftfish.de/ston1th/docstore/pkg/tags"
"git.giftfish.de/ston1th/jwt/v3"
"html/template"
"net/http"
@ -197,12 +198,17 @@ func indexHandler(ctx *Context) {
log.Printf("scanner: %s: %s", path, err)
return
}
id, err := ctx.Srv.DB.Index.Add(txt)
t, err := ctx.Srv.DB.GetAllTags()
if err != nil {
log.Printf("getTags: %s: %s", path, err)
}
found := tags.Find(txt, t)
id, err := ctx.Srv.DB.Index.Add(txt, found)
if err != nil {
log.Printf("index: %s: %s", path, err)
return
}
err = ctx.Srv.DB.NewFile(id, file)
err = ctx.Srv.DB.NewFile(id, file, found)
if err != nil {
log.Printf("newFile: %s: %s", path, err)
}
@ -687,6 +693,94 @@ func userTotpHandler(ctx *Context) {
}
}
func tagsHandler(ctx *Context) {
ctx.Template("tagsHandler")
ctx.Data = webData{
Title: "Tags",
BodyTitle: "Tags",
}
t, err := ctx.Srv.DB.GetAllTags()
if err != nil {
ctx.Error(err)
return
}
ctx.Data.Data = t
switch ctx.Method() {
case "GET":
ctx.Exec()
}
}
func tagsEditHandler(ctx *Context) {
ctx.Template("tagsEditHandler")
ctx.Data = webData{
Title: "Edit User",
BodyTitle: "Edit User",
}
u, err := ctx.Srv.DB.GetUserWithoutPassword()
if err != nil {
ctx.Error(err)
return
}
ctx.Data.Data = u
switch ctx.Method() {
case "GET":
ctx.Exec()
case "POST":
if !ctx.CheckXsrf() {
return
}
password := ctx.Form("password")
repeat := ctx.Form("repeat")
if password != repeat {
ctx.Error("passwords do not match")
return
}
if err := ctx.Srv.DB.UpdateUserPassword(password); err != nil {
ctx.Error(err)
return
}
log.Printf("update: %s updated\n", ctx.User())
ctx.Redirect(core.IndexURI, http.StatusFound)
}
}
func tagsDelHandler(ctx *Context) {
ctx.Template("tagsDelHandler")
ctx.Data = webData{
Title: "Edit User",
BodyTitle: "Edit User",
}
u, err := ctx.Srv.DB.GetUserWithoutPassword()
if err != nil {
ctx.Error(err)
return
}
ctx.Data.Data = u
switch ctx.Method() {
case "GET":
ctx.Exec()
case "POST":
if !ctx.CheckXsrf() {
return
}
password := ctx.Form("password")
repeat := ctx.Form("repeat")
if password != repeat {
ctx.Error("passwords do not match")
return
}
if err := ctx.Srv.DB.UpdateUserPassword(password); err != nil {
ctx.Error(err)
return
}
log.Printf("update: %s updated\n", ctx.User())
ctx.Redirect(core.IndexURI, http.StatusFound)
}
}
func logoutHandler(ctx *Context) {
user := ctx.User()
if user == "" {

View file

@ -89,7 +89,7 @@ var prefixRoutes = []route{
var routes = append(static, []route{
{
"/search",
core.SearchURI,
jwtHandler(
authHandler(
searchHandler)),
@ -122,6 +122,27 @@ var routes = append(static, []route{
userTotpHandler)),
[]string{"GET", "POST"},
},
{
"/tags",
jwtHandler(
authHandler(
tagsHandler)),
[]string{"GET"},
},
{
"/tags/{tag:[a-zA-Z0-9]+}/edit",
jwtHandler(
authHandler(
tagsEditHandler)),
[]string{"GET", "POST"},
},
{
"/tags/{tag:[a-zA-Z0-9]+}/del",
jwtHandler(
authHandler(
tagsDelHandler)),
[]string{"GET", "POST"},
},
{
core.LogoutURI,
jwtHandler(

View file

@ -127,6 +127,7 @@ const (
<a href="/index{{.Data.Name}}" class="btn btn-sm btn-success">Index</a>
{{end}}
{{end}}
<a target="_blank" href="{{.Data.Abs}}" class="btn btn-sm btn-primary">Raw</a>
<a href="/move{{.Data.Name}}" class="btn btn-sm btn-primary">Move</a>
<a href="/delete{{.Data.Name}}" class="btn btn-sm btn-danger">Delete</a>
</div>
@ -159,7 +160,7 @@ const (
<title>DocStore | {{.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-3YeveuySvBgp2GItUS8eV1R/9T1zcPMyvw22SyVf8qo="></link>
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-VMvzVve7KY7ia4G8uBrASNEZ/Qc/5jCqVV3WWU+Y9ao="></link>
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-NLGEBzpF8t2UDEPzWyOYGGP/HWLNb29ar1MdYlwJroQ="></link>
<meta name="theme-color" content="#375a7f">
<meta name="description" content="{{.Title}}">
</head>
@ -265,6 +266,9 @@ const (
menu = `{{define "menu"}}
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link" href="/">Root</a></li>
{{if .Login}}
<li class="nav-item"><a class="nav-link" href="/tags">Tags</a></li>
{{end}}
</ul>
<form class="form-inline" method="post" action="/search">
<input type="hidden" name="token" value="{{.Token}}">
@ -426,6 +430,86 @@ const (
</tbody>
</table>
</div>
{{end}}`
tagsDel = `{{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="/tags/{{.Data.Name}}/edit" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<div class="form-group">
<label class="col-form-label" for="name">Name</label>
<input class="form-control input-sm" type="text" id="name" name="name" disabled>
</div>
<div class="form-group">
<label class="col-form-label" for="regex">Regex</label>
<input class="form-control input-sm" type="text" id="regex" name="regex" value="{{.Data.Regex}}">
</div>
<button class="btn btn-sm btn-primary" type="submit">Update</button>
<a href="/tags" class="btn btn-sm btn-primary">Back</a>
</form>
</div>
</div>
</div>
</div>
{{end}}`
tagsEdit = `{{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="/tags/{{.Data.Name}}/edit" method="post">
<input type="hidden" name="token" value="{{.Token}}">
<div class="form-group">
<label class="col-form-label" for="name">Name</label>
<input class="form-control input-sm" type="text" id="name" name="name" disabled>
</div>
<div class="form-group">
<label class="col-form-label" for="regex">Regex</label>
<input class="form-control input-sm" type="text" id="regex" name="regex" value="{{.Data.Regex}}">
</div>
<button class="btn btn-sm btn-primary" type="submit">Update</button>
<a href="/tags" class="btn btn-sm btn-primary">Back</a>
</form>
</div>
</div>
</div>
</div>
{{end}}`
tagsList = `{{define "body"}}
<div class="row">
<table class="table table-stripped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Regex</th>
<th>Options</th>
</tr>
</thead>
<tbody>
{{if .Data}}
{{range $item := .Data}}
{{$len := len $item.Regex}}
<tr>
<td>{{$item.Name}}</td>
<td><code>{{printf "%.50s" $item.Regex}}{{if gt $len 50}}...{{end}}</code></td>
<td><div class="btn-group">
<a href="/tags/{{$item.Name}}/edit" class="btn btn-sm btn-primary">Edit</a>
<a href="/tags/{{$item.Name}}/del" class="btn btn-sm btn-danger">Delete</a>
</div></td>
</tr>
{{end}}
{{end}}
</tbody>
</table>
</div>
{{end}}`
upload = `{{define "body"}}
<div class="row">
@ -579,7 +663,7 @@ a.anchor {
top: -70px;
visibility: hidden;
}
a.mono {
.mono {
font-family: monospace;
}
.alert-primary {
@ -744,6 +828,10 @@ func (s *HTTPServer) loadTemplates() {
s.templ["userEditHandler"] = parse(index, menu, userEdit)
// totp
s.templ["userTotpHandler"] = parse(index, menu, userTotp)
// tags
s.templ["tagsHandler"] = parse(index, menu, tagsList)
s.templ["tagsEditHandler"] = parse(index, menu, tagsEdit)
s.templ["tagsDelHandler"] = parse(index, menu, tagsDel)
if fatal {
log.Fatal("parse: ", errors.New("parsing templates failed"))