Browse Source

SVI Добавление запросов для анонимного доступа

SVI 2 years ago
parent
commit
62044e4d2b

+ 79 - 0
internal/serv_http/router_anonym/anonym_del/anonym_del.go

@@ -0,0 +1,79 @@
+// package anonym_del -- анонимное удаление ключа из хранилища
+package anonym_del
+
+import (
+	"fmt"
+	"log"
+
+	"github.com/gofiber/fiber/v2"
+
+	"git.p78su.freemyip.com/svi/gostore/pkg/types"
+)
+
+// AnonymDel -- анонимное удаление ключа из хранилища
+type AnonymDel struct {
+	serv  types.IService
+	store types.IStore
+}
+
+// NewAnonymDel -- возвращает анонимное удаление ключа из хранилища
+func NewAnonymDel(servHttp types.IServHttp, router fiber.Router) (*AnonymDel, error) {
+	{ // Предусловия
+		if servHttp == nil {
+			return nil, fmt.Errorf("NewAnonymDel(): IServHttp==nil")
+		}
+		if router == nil {
+			return nil, fmt.Errorf("NewAnonymDel(): router==nil")
+		}
+	}
+	sf := &AnonymDel{
+		serv:  servHttp.Service(),
+		store: servHttp.Service().Store(),
+	}
+	router.Get("/del", sf.get)
+	router.Post("/del_check_key", sf.delCheckKey)
+	router.Post("/del", sf.post)
+	return sf, nil
+}
+
+// DelRequest -- удаление значение из анонимного хранилища
+type DelRequest struct {
+	Key_ string `json:"key" form:"key"` // Ключ для хранилища
+}
+
+// Проверяет допустимость ключа для анонимного хранилища
+func (sf *AnonymDel) delCheckKey(ctx *fiber.Ctx) error {
+	strBody := string(ctx.Body())
+	log.Println("AnonymDel.delCheckKey():", strBody)
+	req := &DelRequest{}
+	err := ctx.BodyParser(req)
+	if err != nil {
+		return ctx.SendString("AnonymDel.delCheckKey(): " + err.Error())
+	}
+	if req.Key_ == "" {
+		return ctx.SendString("AnonymDel.delCheckKey(): ключ не может быть пустым")
+	}
+	return ctx.SendString("AnonymDel.delCheckKey(): годный ключ")
+}
+
+// Возвращает страницу анонимного раздела
+func (sf *AnonymDel) get(ctx *fiber.Ctx) error {
+	return ctx.Render("anonym_del", fiber.Map{})
+}
+
+// Возвращает значение из анонимного хранилища
+func (sf *AnonymDel) post(ctx *fiber.Ctx) error {
+	req := &DelRequest{}
+	if err := ctx.BodyParser(req); err != nil {
+		return ctx.Render("anonym_del", fiber.Map{
+			"res": fmt.Sprintf("AnonymDel.post(): при парсинге формы, err=%v", err),
+		})
+	}
+	if req.Key_ == "" {
+		return ctx.Render("anonym_del", fiber.Map{
+			"res": "AnonymDel.post(): ключ не может быть пустым",
+		})
+	}
+	sf.store.Del("anon/" + req.Key_)
+	return ctx.SendString(fmt.Sprintf("AnonymDel.post(): ключ %q удален из хранилища", req.Key_))
+}

+ 92 - 0
internal/serv_http/router_anonym/anonym_find/anonym_find.go

@@ -0,0 +1,92 @@
+// package anonym_find -- анонимный поиск ключей по префиксу в хранилище
+package anonym_find
+
+import (
+	"encoding/json"
+	"fmt"
+	"log"
+	"strings"
+
+	"github.com/gofiber/fiber/v2"
+
+	"git.p78su.freemyip.com/svi/gostore/pkg/types"
+)
+
+// AnonymFind -- анонимный поиск ключей по префиксу в хранилище
+type AnonymFind struct {
+	serv  types.IService
+	store types.IStore
+}
+
+// NewAnonymFind -- возвращает анонимный поиск ключей по префиксу в хранилище
+func NewAnonymFind(servHttp types.IServHttp, router fiber.Router) (*AnonymFind, error) {
+	{ // Предусловия
+		if servHttp == nil {
+			return nil, fmt.Errorf("NewAnonymFind(): IServHttp==nil")
+		}
+		if router == nil {
+			return nil, fmt.Errorf("NewAnonymFind(): router==nil")
+		}
+	}
+	sf := &AnonymFind{
+		serv:  servHttp.Service(),
+		store: servHttp.Service().Store(),
+	}
+	router.Get("/find", sf.get)
+	router.Post("/find_check_prefix", sf.findCheckPrefix)
+	router.Post("/find", sf.post)
+	return sf, nil
+}
+
+// FindRequest -- читает значение из анонимного хранилища
+type FindRequest struct {
+	Key_    string   `json:"key" form:"key"`    // Ключ для поиска в хранилище
+	Values_ []string `json:"values" form:"val"` // Ключи в хранилище по префиксу
+}
+
+// Проверяет допустимость ключа для анонимного хранилища
+func (sf *AnonymFind) findCheckPrefix(ctx *fiber.Ctx) error {
+	strBody := string(ctx.Body())
+	log.Println("AnonymFind.findCheckPrefix():", strBody)
+	req := &FindRequest{}
+	err := ctx.BodyParser(req)
+	if err != nil {
+		return ctx.SendString("AnonymFind.findCheckPrefix(): " + err.Error())
+	}
+	if req.Key_ == "" {
+		return ctx.SendString("AnonymFind.findCheckPrefix(): ключ не может быть пустым")
+	}
+	return ctx.SendString("AnonymFind.findCheckPrefix(): годный ключ")
+}
+
+// Возвращает страницу анонимного раздела
+func (sf *AnonymFind) get(ctx *fiber.Ctx) error {
+	return ctx.Render("anonym_find", fiber.Map{})
+}
+
+// Возвращает список ключей по префиксу из анонимного хранилища
+func (sf *AnonymFind) post(ctx *fiber.Ctx) error {
+	req := &FindRequest{}
+	if err := ctx.BodyParser(req); err != nil {
+		return ctx.Render("anonym_find", fiber.Map{
+			"res": fmt.Sprintf("AnonymFind.post(): при парсинге формы, err=%v", err),
+		})
+	}
+	if req.Key_ == "" {
+		return ctx.Render("anonym_find", fiber.Map{
+			"res": "AnonymFind.post(): ключ не может быть пустым",
+		})
+	}
+	var err error
+	req.Values_, err = sf.store.Find("anon/" + req.Key_)
+	if err != nil {
+		return ctx.Render("anonym_find", fiber.Map{
+			"res": fmt.Sprintf("AnonymFind.post(): при поиске ключей по префиксу %q из хранилища, err=%v", req.Key_, err),
+		})
+	}
+	for adr, val := range req.Values_ {
+		req.Values_[adr] = strings.TrimPrefix(val, "anon/")
+	}
+	binResp, _ := json.MarshalIndent(req, "", "  ")
+	return ctx.SendString(string(binResp))
+}

+ 98 - 0
internal/serv_http/router_anonym/anonym_list/anonym_list.go

@@ -0,0 +1,98 @@
+// package anonym_list -- список анонимных ключей в хранилище
+package anonym_list
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/gofiber/fiber/v2"
+
+	"git.p78su.freemyip.com/svi/gostore/pkg/types"
+)
+
+// AnonymList -- список анонимный ключей в хранилище
+type AnonymList struct {
+	serv  types.IService
+	store types.IStore
+}
+
+// NewAnonymList -- возвращает список анонимных ключей в хранилище
+func NewAnonymList(servHttp types.IServHttp, router fiber.Router) (*AnonymList, error) {
+	{ // Предусловия
+		if servHttp == nil {
+			return nil, fmt.Errorf("NewAnonymList(): IServHttp==nil")
+		}
+		if router == nil {
+			return nil, fmt.Errorf("NewAnonymList(): router==nil")
+		}
+	}
+	sf := &AnonymList{
+		serv:  servHttp.Service(),
+		store: servHttp.Service().Store(),
+	}
+	router.Get("/list", sf.get)
+	router.Post("/list", sf.post)
+	return sf, nil
+}
+
+// Возвращает страницу анонимного раздела
+func (sf *AnonymList) get(ctx *fiber.Ctx) error {
+	return ctx.Render("anonym_list", fiber.Map{})
+}
+
+// ReadRequest -- читает значение из анонимного хранилища
+type ReadRequest struct {
+	Key_   string `json:"key" form:"key"` // Ключ для хранилища
+	Value_ string `json:"val" form:"val"` // Значение для хранилища
+}
+
+const (
+	strRow = `<div class="row">
+	<div class="col-2">
+		{{key}}
+	</div>
+	<div class="col-10">
+		{{val}}
+	</div>
+	</div>
+`
+)
+
+// Возвращает список ключей по префиксу из анонимного хранилища
+func (sf *AnonymList) post(ctx *fiber.Ctx) error {
+	req := &ReadRequest{}
+	_ = ctx.BodyParser(req)
+	lstKey, err := sf.store.Find("anon/" + req.Key_)
+	if err != nil {
+		return ctx.Render("anonym_list", fiber.Map{
+			"res": fmt.Sprintf("AnonymList.post(): при поиске анонимных ключей в хранилище, err=%v", err),
+		})
+	}
+	strOut := ""
+	for adr, val := range lstKey {
+		binVal, err := sf.store.Get(val)
+		if err != nil {
+			binVal = []byte(fmt.Sprintf("AnonymList.post(): при поиске анонимного ключа %q в хранилище, err=%v", val, err))
+		}
+		req := &ReadRequest{
+			Key_:   strings.TrimPrefix(val, "anon/"),
+			Value_: string(binVal),
+		}
+		_row := strings.ReplaceAll(strRow, "{{key}}", req.Key_)
+		_row = strings.ReplaceAll(_row, "{{val}}", req.Value_)
+		strOut += _row
+		if adr >= 50 {
+			break
+		}
+	}
+	strOut = `<div class="container-fluid border border-2 rounded-2">
+<div class="row">
+	<div class="col-2 border border-1 text-center">
+			Ключ
+	</div>
+	<div class="col-10 border border-1 text-center">
+		Значение
+	</div>
+</div>` + strOut + "</div><br>"
+	return ctx.SendString(strOut)
+}

+ 1 - 1
internal/serv_http/router_anonym/anonym_put/anonym_put.go

@@ -75,7 +75,7 @@ func (sf *AnonymPut) post(ctx *fiber.Ctx) error {
 			"res": "AnonymPut.post(): ключ не может быть пустым",
 		})
 	}
-	err := sf.store.Put(req.Key_, []byte(req.Value_))
+	err := sf.store.Put("anon/"+req.Key_, []byte(req.Value_))
 	if err != nil {
 		return ctx.Render("anonym_put", fiber.Map{
 			"res": fmt.Sprintf("AnonymPut.post(): при размещении ключа %q в хранилище, err=%v", req.Key_, err),

+ 1 - 1
internal/serv_http/router_anonym/anonym_read/anonym_read.go

@@ -76,7 +76,7 @@ func (sf *AnonymRead) post(ctx *fiber.Ctx) error {
 			"res": "AnonymRead.post(): ключ не может быть пустым",
 		})
 	}
-	binVal, err := sf.store.Get(req.Key_)
+	binVal, err := sf.store.Get("anon/" + req.Key_)
 	if err != nil {
 		return ctx.Render("anonym_get", fiber.Map{
 			"res": fmt.Sprintf("AnonymRead.post(): при получении ключа %q из хранилища, err=%v", req.Key_, err),

+ 24 - 24
internal/serv_http/router_anonym/router_anonym.go

@@ -5,6 +5,9 @@ import (
 	"fmt"
 	"time"
 
+	"git.p78su.freemyip.com/svi/gostore/internal/serv_http/router_anonym/anonym_del"
+	"git.p78su.freemyip.com/svi/gostore/internal/serv_http/router_anonym/anonym_find"
+	"git.p78su.freemyip.com/svi/gostore/internal/serv_http/router_anonym/anonym_list"
 	"git.p78su.freemyip.com/svi/gostore/internal/serv_http/router_anonym/anonym_put"
 	"git.p78su.freemyip.com/svi/gostore/internal/serv_http/router_anonym/anonym_read"
 	"git.p78su.freemyip.com/svi/gostore/pkg/types"
@@ -15,6 +18,9 @@ import (
 type RouterAnonym struct {
 	*anonym_put.AnonymPut
 	*anonym_read.AnonymRead
+	*anonym_find.AnonymFind
+	*anonym_del.AnonymDel
+	*anonym_list.AnonymList
 	serv     types.IService
 	servHttp types.IServHttp
 	router   fiber.Router
@@ -41,35 +47,29 @@ func NewRouterAnonym(servHttp types.IServHttp) (*RouterAnonym, error) {
 	if err != nil {
 		return nil, fmt.Errorf("NewRouterAnonym(): in create AnonymRead, err=\n\t%w", err)
 	}
-	sf.router.Post("/del", sf.del)
-	sf.router.Post("/find", sf.find)
-	sf.router.Post("/time", sf.postTime)
-	sf.router.Get("/time", sf.getTime)
+	sf.AnonymFind, err = anonym_find.NewAnonymFind(servHttp, sf.router)
+	if err != nil {
+		return nil, fmt.Errorf("NewRouterAnonym(): in create AnonymFind, err=\n\t%w", err)
+	}
+	sf.AnonymDel, err = anonym_del.NewAnonymDel(servHttp, sf.router)
+	if err != nil {
+		return nil, fmt.Errorf("NewRouterAnonym(): in create AnonymDel, err=\n\t%w", err)
+	}
+	sf.AnonymList, err = anonym_list.NewAnonymList(servHttp, sf.router)
+	if err != nil {
+		return nil, fmt.Errorf("NewRouterAnonym(): in create AnonymList, err=\n\t%w", err)
+	}
+	sf.router.Post("/time", sf.time)
 	return sf, nil
 }
 
-// Возвращает страницу анонимнго раздела
+// Возвращает страницу анонимного раздела
 func (sf *RouterAnonym) get(c *fiber.Ctx) error {
 	return c.Render("anonym_put", fiber.Map{})
 }
 
-// Удаляет значение из анонимного хранилища
-func (sf *RouterAnonym) del(c *fiber.Ctx) error {
-	return nil
-}
-
-// Находит значение в анонимном хранилище
-func (sf *RouterAnonym) find(c *fiber.Ctx) error {
-	return nil
-}
-
-// Возвращает страницу отображения времени по запросу
-func (sf *RouterAnonym) getTime(c *fiber.Ctx) error {
-	return c.Render("time", fiber.Map{})
-}
-
-// Возвращает время по запросу
-func (sf *RouterAnonym) postTime(ctx *fiber.Ctx) error {
-	ctx.Response().Header.Add("Cache-Control", "no-cache") // Cache-Control: no-cache
-	return ctx.SendString(time.Now().Local().Format("2006-01-02 15:04:05.000 MST -07"))
+// Возвращает текущее время
+func (sf *RouterAnonym) time(c *fiber.Ctx) error {
+	strTime := time.Now().Local().Format("2006-01-02 15:04:05 MST -07")
+	return c.SendString(strTime)
 }

+ 22 - 0
static/tmpl/anonym_del.tmpl.html

@@ -0,0 +1,22 @@
+{{ define "anonym_del" }}
+{{ template "header" }}
+<h1>Список анонимных ключей</h1>
+{{ template "links" }}
+{{ template "anonym_links" }}
+<!-- Получение из хранилища анонимно -->
+<form action="/anonym/del" method="post">
+    <div class="mb-3">
+        <label for="key" class="form-label">key</label>
+        <input type="input" name="key" class="form-control" id="key" aria-describedby="Ключ хранения"
+            hx-post="/anonym/find_check_key" hx-trigger="input changed delay:500ms" hx-target="#keyHelp">
+        <div id="keyHelp" class="form-text">Ключ не может быть пустым</div>
+    </div>
+    <button type="submit" class="btn btn-primary">Отправить</button>
+    <div id="valHelp" class="form-text"></div>
+</form>
+<br>
+{{ if .res}}
+res={{.res}}
+{{end}}
+{{ template "footer" }}
+{{ end }}

+ 22 - 0
static/tmpl/anonym_find.tmpl.html

@@ -0,0 +1,22 @@
+{{ define "anonym_find" }}
+{{ template "header" }}
+<h1>Анонимный поиск ключей</h1>
+{{ template "links" }}
+{{ template "anonym_links" }}
+<!-- Получение из хранилища анонимно -->
+<form action="/anonym/find" method="post">
+    <div class="mb-3">
+        <label for="key" class="form-label">key</label>
+        <input type="input" name="key" class="form-control" id="key" aria-describedby="Ключ хранения"
+            hx-post="/anonym/find_check_key" hx-trigger="input changed delay:500ms" hx-target="#keyHelp">
+        <div id="keyHelp" class="form-text">Ключ не может быть пустым</div>
+    </div>
+    <button type="submit" class="btn btn-primary">Отправить</button>
+    <div id="valHelp" class="form-text"></div>
+</form>
+<br>
+{{ if .res}}
+res={{.res}}
+{{end}}
+{{ template "footer" }}
+{{ end }}

+ 1 - 0
static/tmpl/anonym_links.tmpl.html

@@ -4,5 +4,6 @@
     <a href="/anonym/get" class="nav-link text-bg-dark p-3">[Чтение]</a>
     <a href="/anonym/find" class="nav-link text-bg-dark p-3">[Поиск по префиксу]</a>
     <a href="/anonym/del" class="nav-link text-bg-dark p-3">[Удаление]</a>
+    <a href="/anonym/list" class="nav-link text-bg-dark p-3">[Список]</a>
 </div>
 {{end}}

+ 21 - 0
static/tmpl/anonym_list.tmpl.html

@@ -0,0 +1,21 @@
+{{ define "anonym_list" }}
+{{ template "header" }}
+<h1>Анонимный поиск ключей</h1>
+{{ template "links" }}
+{{ template "anonym_links" }}
+<!-- Получение из хранилища анонимно -->
+<form action="/anonym/list" method="post">
+    <div class="mb-3">
+        <label for="key" class="form-label">key</label>
+        <input type="hidden" hx-post="/anonym/list" hx-trigger="load" hx-target="#keyHelp">
+        <input type="input" name="key" class="form-control" id="key" aria-describedby="Ключ хранения"
+            hx-post="/anonym/list" hx-trigger="input changed delay:500ms" hx-target="#keyHelp">
+    </div>
+</form>
+<br>
+<div id="keyHelp" class="form-text">Ключ не может быть пустым</div>
+{{ if .res}}
+res={{.res}}
+{{end}}
+{{ template "footer" }}
+{{ end }}