Use custom ent codegen plugin for admin.

This commit is contained in:
mikestefanello 2025-04-08 14:02:45 -04:00
parent 9139942794
commit ce9b58bf4a
33 changed files with 750 additions and 13452 deletions

70
ent/admin/extension.go Normal file
View file

@ -0,0 +1,70 @@
package admin
import (
"embed"
"strings"
"text/template"
"unicode"
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
)
var (
//go:embed templates
templateDir embed.FS
)
type Extension struct {
entc.DefaultExtension
}
func (*Extension) Templates() []*gen.Template {
return []*gen.Template{
gen.MustParse(
gen.NewTemplate("admin").
Funcs(template.FuncMap{
"fieldName": fieldName,
"fieldLabel": fieldLabel,
}).
ParseFS(templateDir, "templates/*tmpl"),
),
}
}
func fieldName(name string) string {
if len(name) == 0 {
return name
}
parts := strings.Split(name, "_")
for i := 0; i < len(parts); i++ {
parts[i] = upperFirst(parts[i])
}
return strings.Join(parts, "")
}
func fieldLabel(name string) string {
if len(name) == 0 {
return name
}
out := strings.ReplaceAll(name, "_", " ")
return upperFirst(out)
}
func upperFirst(s string) string {
if len(s) == 0 {
return s
}
out := []rune(s)
out[0] = unicode.ToUpper(out[0])
return string(out)
}
/*
TODO:
1) How to handle fields like password that need to be transformed or omitted, etc?
2) Should we use the HTML datetime format and string fields rather than time.Time?
*/

262
ent/admin/handler.go Normal file
View file

@ -0,0 +1,262 @@
// Code generated by ent, DO NOT EDIT.
package admin
import (
"fmt"
"strconv"
"entgo.io/ent/dialect/sql"
"github.com/labstack/echo/v4"
"github.com/mikestefanello/pagoda/ent"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
)
type Handler struct {
client *ent.Client
itemsPerPage int
}
func NewHandler(client *ent.Client, itemsPerPage int) *Handler {
return &Handler{
client: client,
itemsPerPage: itemsPerPage,
}
}
func (h *Handler) Create(ctx echo.Context, entityType string) error {
switch entityType {
case "PasswordToken":
return h.PasswordTokenCreate(ctx)
case "User":
return h.UserCreate(ctx)
default:
return fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) Get(ctx echo.Context, entityType string, id int) error {
// TODO
switch entityType {
case "PasswordToken":
return h.PasswordTokenGet(ctx, id)
case "User":
return h.UserGet(ctx, id)
default:
return fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) Delete(ctx echo.Context, entityType string, id int) error {
switch entityType {
case "PasswordToken":
return h.PasswordTokenDelete(ctx, id)
case "User":
return h.UserDelete(ctx, id)
default:
return fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) Update(ctx echo.Context, entityType string, id int) error {
switch entityType {
case "PasswordToken":
return h.PasswordTokenUpdate(ctx, id)
case "User":
return h.UserUpdate(ctx, id)
default:
return fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) List(ctx echo.Context, entityType string) (*EntityList, error) {
switch entityType {
case "PasswordToken":
return h.PasswordTokenList(ctx)
case "User":
return h.UserList(ctx)
default:
return nil, fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) PasswordTokenCreate(ctx echo.Context) error {
var payload PasswordToken
if err := ctx.Bind(&payload); err != nil {
return err
}
op := h.client.PasswordToken.Create()
op.SetHash(payload.Hash)
op.SetCreatedAt(payload.CreatedAt)
op.SetUserID(payload.User)
_, err := op.Save(ctx.Request().Context())
return err
}
func (h *Handler) PasswordTokenUpdate(ctx echo.Context, id int) error {
entity, err := h.client.PasswordToken.Get(ctx.Request().Context(), id)
if err != nil {
return err
}
var payload PasswordToken
if err = ctx.Bind(&payload); err != nil {
return err
}
op := entity.Update()
op.SetHash(payload.Hash)
op.SetCreatedAt(payload.CreatedAt)
op.SetUserID(payload.User)
_, err = op.Save(ctx.Request().Context())
return err
}
func (h *Handler) PasswordTokenDelete(ctx echo.Context, id int) error {
return h.client.PasswordToken.DeleteOneID(id).
Exec(ctx.Request().Context())
}
func (h *Handler) PasswordTokenList(ctx echo.Context) (*EntityList, error) {
res, err := h.client.PasswordToken.
Query().
Limit(h.itemsPerPage + 1).
Offset(h.getOffset(ctx)).
Order(passwordtoken.ByID(sql.OrderDesc())).
All(ctx.Request().Context())
if err != nil {
return nil, err
}
list := &EntityList{
Columns: []string{
"Created at",
// "User", ?
},
Entities: make([]EntityValues, 0, len(res)),
HasNextPage: len(res) > h.itemsPerPage,
}
for i := 0; i < len(res)-1; i++ {
list.Entities = append(list.Entities, EntityValues{
ID: res[i].ID,
Values: []string{
fmt.Sprint(res[i].CreatedAt),
// TODO User ?
},
})
}
return list, err
}
func (h *Handler) PasswordTokenGet(ctx echo.Context, id int) error {
_, err := h.client.PasswordToken.Get(ctx.Request().Context(), id)
if err != nil {
return err
}
// TODO
return nil
}
func (h *Handler) UserCreate(ctx echo.Context) error {
var payload User
if err := ctx.Bind(&payload); err != nil {
return err
}
op := h.client.User.Create()
op.SetName(payload.Name)
op.SetEmail(payload.Email)
op.SetPassword(payload.Password)
op.SetVerified(payload.Verified)
op.SetCreatedAt(payload.CreatedAt)
_, err := op.Save(ctx.Request().Context())
return err
}
func (h *Handler) UserUpdate(ctx echo.Context, id int) error {
entity, err := h.client.User.Get(ctx.Request().Context(), id)
if err != nil {
return err
}
var payload User
if err = ctx.Bind(&payload); err != nil {
return err
}
op := entity.Update()
op.SetName(payload.Name)
op.SetEmail(payload.Email)
op.SetPassword(payload.Password)
op.SetVerified(payload.Verified)
_, err = op.Save(ctx.Request().Context())
return err
}
func (h *Handler) UserDelete(ctx echo.Context, id int) error {
return h.client.User.DeleteOneID(id).
Exec(ctx.Request().Context())
}
func (h *Handler) UserList(ctx echo.Context) (*EntityList, error) {
res, err := h.client.User.
Query().
Limit(h.itemsPerPage + 1).
Offset(h.getOffset(ctx)).
Order(user.ByID(sql.OrderDesc())).
All(ctx.Request().Context())
if err != nil {
return nil, err
}
list := &EntityList{
Columns: []string{
"Name",
"Email",
"Verified",
"Created at",
},
Entities: make([]EntityValues, 0, len(res)),
HasNextPage: len(res) > h.itemsPerPage,
}
for i := 0; i <= len(res)-1; i++ {
list.Entities = append(list.Entities, EntityValues{
ID: res[i].ID,
Values: []string{
res[i].Name,
res[i].Email,
fmt.Sprint(res[i].Verified),
fmt.Sprint(res[i].CreatedAt),
},
})
}
return list, err
}
func (h *Handler) UserGet(ctx echo.Context, id int) error {
_, err := h.client.User.Get(ctx.Request().Context(), id)
if err != nil {
return err
}
// TODO
return nil
}
func (h *Handler) getOffset(ctx echo.Context) int {
if page, err := strconv.Atoi(ctx.QueryParam("page")); err == nil {
if page > 1 {
return (page - 1) * h.itemsPerPage
}
}
return 0
}

View file

@ -0,0 +1,215 @@
{{/* Tell Intellij/GoLand to enable the autocompletion based on the *gen.Graph type. */}}
{{/* gotype: entgo.io/ent/entc/gen.Graph */}}
{{ define "admin/handler" }}
// Code generated by ent, DO NOT EDIT.
{{- $pkg := base $.Config.Package }}
package admin
import (
"fmt"
"strconv"
"entgo.io/ent/dialect/sql"
"github.com/labstack/echo/v4"
"{{ $.Config.Package }}"
{{- range $n := $.Nodes }}
"{{ $.Config.Package }}/{{ $n.Package }}"
{{- end }}
)
type Handler struct {
client *{{ $pkg }}.Client
itemsPerPage int
}
func NewHandler(client *{{ $pkg }}.Client, itemsPerPage int) *Handler {
return &Handler{
client: client,
itemsPerPage: itemsPerPage,
}
}
func (h *Handler) Create(ctx echo.Context, entityType string) error {
switch entityType {
{{- range $n := $.Nodes }}
case "{{ $n.Name }}":
return h.{{ $n.Name }}Create(ctx)
{{- end }}
default:
return fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) Get(ctx echo.Context, entityType string, id int) error {
// TODO
switch entityType {
{{- range $n := $.Nodes }}
case "{{ $n.Name }}":
return h.{{ $n.Name }}Get(ctx, id)
{{- end }}
default:
return fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) Delete(ctx echo.Context, entityType string, id int) error {
switch entityType {
{{- range $n := $.Nodes }}
case "{{ $n.Name }}":
return h.{{ $n.Name }}Delete(ctx, id)
{{- end }}
default:
return fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) Update(ctx echo.Context, entityType string, id int) error {
switch entityType {
{{- range $n := $.Nodes }}
case "{{ $n.Name }}":
return h.{{ $n.Name }}Update(ctx, id)
{{- end }}
default:
return fmt.Errorf("unsupported entity type: %s", entityType)
}
}
func (h *Handler) List(ctx echo.Context, entityType string) (*EntityList, error) {
switch entityType {
{{- range $n := $.Nodes }}
case "{{ $n.Name }}":
return h.{{ $n.Name }}List(ctx)
{{- end }}
default:
return nil, fmt.Errorf("unsupported entity type: %s", entityType)
}
}
{{ range $n := $.Nodes }}
func (h *Handler) {{ $n.Name }}Create(ctx echo.Context) error {
var payload {{ $n.Name }}
if err := ctx.Bind(&payload); err != nil {
return err
}
op := h.client.{{ $n.Name }}.Create()
{{- range $f := $n.Fields }}
op.Set{{ fieldName $f.Name }}(payload.{{ fieldName $f.Name }})
{{- end }}
{{- range $e := $n.Edges }}
{{- if not $e.Inverse}}
op.Set{{ fieldName $e.Name }}ID(payload.{{ fieldName $e.Name }})
{{- end }}
{{- end }}
_, err := op.Save(ctx.Request().Context())
return err
}
func (h *Handler) {{ $n.Name }}Update(ctx echo.Context, id int) error {
entity, err := h.client.{{ $n.Name }}.Get(ctx.Request().Context(), id)
if err != nil {
return err
}
var payload {{ $n.Name }}
if err = ctx.Bind(&payload); err != nil {
return err
}
op := entity.Update()
{{- range $f := $n.Fields }}
{{- if not $f.Immutable }}
op.Set{{ fieldName $f.Name }}(payload.{{ fieldName $f.Name }})
{{- end }}
{{- end }}
{{- range $e := $n.Edges }}
{{- if not $e.Inverse}}
op.Set{{ fieldName $e.Name }}ID(payload.{{ fieldName $e.Name }})
{{- end }}
{{- end }}
_, err = op.Save(ctx.Request().Context())
return err
}
func (h *Handler) {{ $n.Name }}Delete(ctx echo.Context, id int) error {
return h.client.{{ $n.Name }}.DeleteOneID(id).
Exec(ctx.Request().Context())
}
func (h *Handler) {{ $n.Name }}List(ctx echo.Context) (*EntityList, error) {
res, err := h.client.{{ $n.Name }}.
Query().
Limit(h.itemsPerPage+1).
Offset(h.getOffset(ctx)).
Order({{ $n.Package }}.ByID(sql.OrderDesc())).
All(ctx.Request().Context())
if err != nil {
return nil, err
}
list := &EntityList{
Columns: []string{
{{- range $f := $n.Fields }}
{{- if not $f.Sensitive }}
"{{ fieldLabel $f.Name }}",
{{- end }}
{{- end }}
{{- range $e := $n.Edges }}
{{- if not $e.Inverse}}
// "{{ fieldLabel $e.Name }}", ?
{{- end }}
{{- end }}
},
Entities: make([]EntityValues, 0, len(res)),
HasNextPage: len(res) > h.itemsPerPage,
}
for i := 0; i <= len(res)-1; i++ {
list.Entities = append(list.Entities, EntityValues{
ID: res[i].ID,
Values: []string{
{{- range $f := $n.Fields }}
{{- if not $f.Sensitive }}
{{- if eq $f.Type.String "string" }}
res[i].{{ fieldName $f.Name }},
{{- else }}
fmt.Sprint(res[i].{{ fieldName $f.Name }}),
{{- end }}
{{- end }}
{{- end }}
{{- range $e := $n.Edges }}
{{- if not $e.Inverse}}
// TODO {{ fieldName $e.Name }} ?
{{- end }}
{{- end }}
},
})
}
return list, err
}
func (h *Handler) {{ $n.Name }}Get(ctx echo.Context, id int) error {
_, err := h.client.{{ $n.Name }}.Get(ctx.Request().Context(), id)
if err != nil {
return err
}
// TODO
return nil
}
{{ end }}
func (h *Handler) getOffset(ctx echo.Context) int {
if page, err := strconv.Atoi(ctx.QueryParam("page")); err == nil {
if page > 1 {
return (page-1) * h.itemsPerPage
}
}
return 0
}
{{ end }}

View file

@ -0,0 +1,34 @@
{{/* Tell Intellij/GoLand to enable the autocompletion based on the *gen.Graph type. */}}
{{/* gotype: entgo.io/ent/entc/gen.Graph */}}
{{ define "admin/types" }}
// Code generated by ent, DO NOT EDIT.
package admin
{{ range $n := $.Nodes }}
type {{ $n.Name }} struct {
// Fields.
{{- range $f := $n.Fields }}
{{ fieldName $f.Name }} {{ $f.Type }} `form:"{{ $f.Name }}"`
{{- end }}
// Edges.
{{- range $e := $n.Edges }}
{{- if not $e.Inverse}}
{{ fieldName $e.Name }} int `form:"{{ $e.Name }}"`
{{- end }}
{{- end }}
}
{{ end }}
type EntityList struct {
Columns []string
Entities []EntityValues
HasNextPage bool
}
type EntityValues struct {
ID int
Values []string
}
{{ end }}

33
ent/admin/types.go Normal file
View file

@ -0,0 +1,33 @@
// Code generated by ent, DO NOT EDIT.
package admin
import "time"
type PasswordToken struct {
// Fields.
Hash string `form:"hash"`
CreatedAt time.Time `form:"created_at"`
// Edges.
User int `form:"user"`
}
type User struct {
// Fields.
Name string `form:"name"`
Email string `form:"email"`
Password string `form:"password"`
Verified bool `form:"verified"`
CreatedAt time.Time `form:"created_at"`
// Edges.
}
type EntityList struct {
Columns []string
Entities []EntityValues
HasNextPage bool
}
type EntityValues struct {
ID int
Values []string
}

View file

@ -1,44 +1,22 @@
//go:build ignore
// +build ignore
package main
import (
"log"
"ariga.io/ogent"
"entgo.io/contrib/entoas"
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
"github.com/ogen-go/ogen"
"github.com/mikestefanello/pagoda/ent/admin"
)
var returnAllErrors = gen.MustParse(gen.NewTemplate("").Parse(`
{{ define "ogent/ogent/helper/error" }}{{/* gotype: entgo.io/ent/entc/gen.typeScope */}}
{{- $pkg := base $.Type.Config.Package }}
if err != nil {
{{- with $.Scope.Tx }}
if rErr := {{ . }}.Rollback(); rErr != nil {
return nil, fmt.Errorf("%w: %v", err, rErr)
}
{{- end }}
// Let the server handle the error.
return nil, err
}
{{ end }}
`))
func main() {
spec := new(ogen.Spec)
oas, err := entoas.NewExtension(entoas.Spec(spec))
err := entc.Generate("./schema",
&gen.Config{},
entc.Extensions(&admin.Extension{}),
)
if err != nil {
log.Fatalf("creating entoas extension: %v", err)
}
ogent, err := ogent.NewExtension(spec, ogent.Templates(returnAllErrors))
if err != nil {
log.Fatalf("creating ogent extension: %v", err)
}
err = entc.Generate("./schema", &gen.Config{}, entc.Extensions(ogent, oas))
if err != nil {
log.Fatalf("running ent codegen: %v", err)
log.Fatal("running ent codegen:", err)
}
}

View file

@ -1,4 +1,3 @@
package ent
//go:generate go run -mod=mod entc.go
//go:generate sed -i -e "s/json:\"/form:\"/g" ogent/oas_schemas_gen.go

View file

@ -1,277 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"net/http"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/instrument"
"go.opentelemetry.io/otel/trace"
ht "github.com/ogen-go/ogen/http"
"github.com/ogen-go/ogen/middleware"
"github.com/ogen-go/ogen/ogenerrors"
"github.com/ogen-go/ogen/otelogen"
)
var (
// Allocate option closure once.
clientSpanKind = trace.WithSpanKind(trace.SpanKindClient)
// Allocate option closure once.
serverSpanKind = trace.WithSpanKind(trace.SpanKindServer)
)
type (
optionFunc[C any] func(*C)
otelOptionFunc func(*otelConfig)
)
type otelConfig struct {
TracerProvider trace.TracerProvider
Tracer trace.Tracer
MeterProvider metric.MeterProvider
Meter metric.Meter
}
func (cfg *otelConfig) initOTEL() {
if cfg.TracerProvider == nil {
cfg.TracerProvider = otel.GetTracerProvider()
}
if cfg.MeterProvider == nil {
cfg.MeterProvider = metric.NewNoopMeterProvider()
}
cfg.Tracer = cfg.TracerProvider.Tracer(otelogen.Name,
trace.WithInstrumentationVersion(otelogen.SemVersion()),
)
cfg.Meter = cfg.MeterProvider.Meter(otelogen.Name)
}
// ErrorHandler is error handler.
type ErrorHandler = ogenerrors.ErrorHandler
type serverConfig struct {
otelConfig
NotFound http.HandlerFunc
MethodNotAllowed func(w http.ResponseWriter, r *http.Request, allowed string)
ErrorHandler ErrorHandler
Prefix string
Middleware Middleware
MaxMultipartMemory int64
}
// ServerOption is server config option.
type ServerOption interface {
applyServer(*serverConfig)
}
var _ = []ServerOption{
(optionFunc[serverConfig])(nil),
(otelOptionFunc)(nil),
}
func (o optionFunc[C]) applyServer(c *C) {
o(c)
}
func (o otelOptionFunc) applyServer(c *serverConfig) {
o(&c.otelConfig)
}
func newServerConfig(opts ...ServerOption) serverConfig {
cfg := serverConfig{
NotFound: http.NotFound,
MethodNotAllowed: func(w http.ResponseWriter, r *http.Request, allowed string) {
w.Header().Set("Allow", allowed)
w.WriteHeader(http.StatusMethodNotAllowed)
},
ErrorHandler: ogenerrors.DefaultErrorHandler,
Middleware: nil,
MaxMultipartMemory: 32 << 20, // 32 MB
}
for _, opt := range opts {
opt.applyServer(&cfg)
}
cfg.initOTEL()
return cfg
}
type baseServer struct {
cfg serverConfig
requests instrument.Int64Counter
errors instrument.Int64Counter
duration instrument.Int64Histogram
}
func (s baseServer) notFound(w http.ResponseWriter, r *http.Request) {
s.cfg.NotFound(w, r)
}
func (s baseServer) notAllowed(w http.ResponseWriter, r *http.Request, allowed string) {
s.cfg.MethodNotAllowed(w, r, allowed)
}
func (cfg serverConfig) baseServer() (s baseServer, err error) {
s = baseServer{cfg: cfg}
if s.requests, err = s.cfg.Meter.Int64Counter(otelogen.ServerRequestCount); err != nil {
return s, err
}
if s.errors, err = s.cfg.Meter.Int64Counter(otelogen.ServerErrorsCount); err != nil {
return s, err
}
if s.duration, err = s.cfg.Meter.Int64Histogram(otelogen.ServerDuration); err != nil {
return s, err
}
return s, nil
}
type clientConfig struct {
otelConfig
Client ht.Client
}
// ClientOption is client config option.
type ClientOption interface {
applyClient(*clientConfig)
}
var _ = []ClientOption{
(optionFunc[clientConfig])(nil),
(otelOptionFunc)(nil),
}
func (o optionFunc[C]) applyClient(c *C) {
o(c)
}
func (o otelOptionFunc) applyClient(c *clientConfig) {
o(&c.otelConfig)
}
func newClientConfig(opts ...ClientOption) clientConfig {
cfg := clientConfig{
Client: http.DefaultClient,
}
for _, opt := range opts {
opt.applyClient(&cfg)
}
cfg.initOTEL()
return cfg
}
type baseClient struct {
cfg clientConfig
requests instrument.Int64Counter
errors instrument.Int64Counter
duration instrument.Int64Histogram
}
func (cfg clientConfig) baseClient() (c baseClient, err error) {
c = baseClient{cfg: cfg}
if c.requests, err = c.cfg.Meter.Int64Counter(otelogen.ClientRequestCount); err != nil {
return c, err
}
if c.errors, err = c.cfg.Meter.Int64Counter(otelogen.ClientErrorsCount); err != nil {
return c, err
}
if c.duration, err = c.cfg.Meter.Int64Histogram(otelogen.ClientDuration); err != nil {
return c, err
}
return c, nil
}
// Option is config option.
type Option interface {
ServerOption
ClientOption
}
// WithTracerProvider specifies a tracer provider to use for creating a tracer.
//
// If none is specified, the global provider is used.
func WithTracerProvider(provider trace.TracerProvider) Option {
return otelOptionFunc(func(cfg *otelConfig) {
if provider != nil {
cfg.TracerProvider = provider
}
})
}
// WithMeterProvider specifies a meter provider to use for creating a meter.
//
// If none is specified, the metric.NewNoopMeterProvider is used.
func WithMeterProvider(provider metric.MeterProvider) Option {
return otelOptionFunc(func(cfg *otelConfig) {
if provider != nil {
cfg.MeterProvider = provider
}
})
}
// WithClient specifies http client to use.
func WithClient(client ht.Client) ClientOption {
return optionFunc[clientConfig](func(cfg *clientConfig) {
if client != nil {
cfg.Client = client
}
})
}
// WithNotFound specifies Not Found handler to use.
func WithNotFound(notFound http.HandlerFunc) ServerOption {
return optionFunc[serverConfig](func(cfg *serverConfig) {
if notFound != nil {
cfg.NotFound = notFound
}
})
}
// WithMethodNotAllowed specifies Method Not Allowed handler to use.
func WithMethodNotAllowed(methodNotAllowed func(w http.ResponseWriter, r *http.Request, allowed string)) ServerOption {
return optionFunc[serverConfig](func(cfg *serverConfig) {
if methodNotAllowed != nil {
cfg.MethodNotAllowed = methodNotAllowed
}
})
}
// WithErrorHandler specifies error handler to use.
func WithErrorHandler(h ErrorHandler) ServerOption {
return optionFunc[serverConfig](func(cfg *serverConfig) {
if h != nil {
cfg.ErrorHandler = h
}
})
}
// WithPathPrefix specifies server path prefix.
func WithPathPrefix(prefix string) ServerOption {
return optionFunc[serverConfig](func(cfg *serverConfig) {
cfg.Prefix = prefix
})
}
// WithMiddleware specifies middlewares to use.
func WithMiddleware(m ...Middleware) ServerOption {
return optionFunc[serverConfig](func(cfg *serverConfig) {
switch len(m) {
case 0:
cfg.Middleware = nil
case 1:
cfg.Middleware = m[0]
default:
cfg.Middleware = middleware.ChainMiddlewares(m...)
}
})
}
// WithMaxMultipartMemory specifies limit of memory for storing file parts.
// File parts which can't be stored in memory will be stored on disk in temporary files.
func WithMaxMultipartMemory(max int64) ServerOption {
return optionFunc[serverConfig](func(cfg *serverConfig) {
if max > 0 {
cfg.MaxMultipartMemory = max
}
})
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,50 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
type CreatePasswordTokenRes interface {
createPasswordTokenRes()
}
type CreateUserRes interface {
createUserRes()
}
type DeletePasswordTokenRes interface {
deletePasswordTokenRes()
}
type DeleteUserRes interface {
deleteUserRes()
}
type ListPasswordTokenRes interface {
listPasswordTokenRes()
}
type ListUserOwnerRes interface {
listUserOwnerRes()
}
type ListUserRes interface {
listUserRes()
}
type ReadPasswordTokenRes interface {
readPasswordTokenRes()
}
type ReadPasswordTokenUserRes interface {
readPasswordTokenUserRes()
}
type ReadUserRes interface {
readUserRes()
}
type UpdatePasswordTokenRes interface {
updatePasswordTokenRes()
}
type UpdateUserRes interface {
updateUserRes()
}

File diff suppressed because it is too large Load diff

View file

@ -1,10 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"github.com/ogen-go/ogen/middleware"
)
// Middleware is middleware type.
type Middleware = middleware.Middleware

View file

@ -1,947 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"net/http"
"net/url"
"github.com/go-faster/errors"
"github.com/ogen-go/ogen/conv"
"github.com/ogen-go/ogen/middleware"
"github.com/ogen-go/ogen/ogenerrors"
"github.com/ogen-go/ogen/uri"
"github.com/ogen-go/ogen/validate"
)
// DeletePasswordTokenParams is parameters of deletePasswordToken operation.
type DeletePasswordTokenParams struct {
// ID of the PasswordToken.
ID int
}
func unpackDeletePasswordTokenParams(packed middleware.Parameters) (params DeletePasswordTokenParams) {
{
key := middleware.ParameterKey{
Name: "id",
In: "path",
}
params.ID = packed[key].(int)
}
return params
}
func decodeDeletePasswordTokenParams(args [1]string, r *http.Request) (params DeletePasswordTokenParams, _ error) {
// Decode path: id.
if err := func() error {
param, err := url.PathUnescape(args[0])
if err != nil {
return errors.Wrap(err, "unescape path")
}
if len(param) > 0 {
d := uri.NewPathDecoder(uri.PathDecoderConfig{
Param: "id",
Value: param,
Style: uri.PathStyleSimple,
Explode: false,
})
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
params.ID = c
return nil
}(); err != nil {
return err
}
} else {
return validate.ErrFieldRequired
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "id",
In: "path",
Err: err,
}
}
return params, nil
}
// DeleteUserParams is parameters of deleteUser operation.
type DeleteUserParams struct {
// ID of the User.
ID int
}
func unpackDeleteUserParams(packed middleware.Parameters) (params DeleteUserParams) {
{
key := middleware.ParameterKey{
Name: "id",
In: "path",
}
params.ID = packed[key].(int)
}
return params
}
func decodeDeleteUserParams(args [1]string, r *http.Request) (params DeleteUserParams, _ error) {
// Decode path: id.
if err := func() error {
param, err := url.PathUnescape(args[0])
if err != nil {
return errors.Wrap(err, "unescape path")
}
if len(param) > 0 {
d := uri.NewPathDecoder(uri.PathDecoderConfig{
Param: "id",
Value: param,
Style: uri.PathStyleSimple,
Explode: false,
})
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
params.ID = c
return nil
}(); err != nil {
return err
}
} else {
return validate.ErrFieldRequired
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "id",
In: "path",
Err: err,
}
}
return params, nil
}
// ListPasswordTokenParams is parameters of listPasswordToken operation.
type ListPasswordTokenParams struct {
// What page to render.
Page OptInt
// Item count to render per page.
ItemsPerPage OptInt
}
func unpackListPasswordTokenParams(packed middleware.Parameters) (params ListPasswordTokenParams) {
{
key := middleware.ParameterKey{
Name: "page",
In: "query",
}
if v, ok := packed[key]; ok {
params.Page = v.(OptInt)
}
}
{
key := middleware.ParameterKey{
Name: "itemsPerPage",
In: "query",
}
if v, ok := packed[key]; ok {
params.ItemsPerPage = v.(OptInt)
}
}
return params
}
func decodeListPasswordTokenParams(args [0]string, r *http.Request) (params ListPasswordTokenParams, _ error) {
q := uri.NewQueryDecoder(r.URL.Query())
// Decode query: page.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "page",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
var paramsDotPageVal int
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
paramsDotPageVal = c
return nil
}(); err != nil {
return err
}
params.Page.SetTo(paramsDotPageVal)
return nil
}); err != nil {
return err
}
if err := func() error {
if params.Page.Set {
if err := func() error {
if err := (validate.Int{
MinSet: true,
Min: 1,
MaxSet: false,
Max: 0,
MinExclusive: false,
MaxExclusive: false,
MultipleOfSet: false,
MultipleOf: 0,
}).Validate(int64(params.Page.Value)); err != nil {
return errors.Wrap(err, "int")
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "page",
In: "query",
Err: err,
}
}
// Decode query: itemsPerPage.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "itemsPerPage",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
var paramsDotItemsPerPageVal int
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
paramsDotItemsPerPageVal = c
return nil
}(); err != nil {
return err
}
params.ItemsPerPage.SetTo(paramsDotItemsPerPageVal)
return nil
}); err != nil {
return err
}
if err := func() error {
if params.ItemsPerPage.Set {
if err := func() error {
if err := (validate.Int{
MinSet: true,
Min: 1,
MaxSet: true,
Max: 255,
MinExclusive: false,
MaxExclusive: false,
MultipleOfSet: false,
MultipleOf: 0,
}).Validate(int64(params.ItemsPerPage.Value)); err != nil {
return errors.Wrap(err, "int")
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "itemsPerPage",
In: "query",
Err: err,
}
}
return params, nil
}
// ListUserParams is parameters of listUser operation.
type ListUserParams struct {
// What page to render.
Page OptInt
// Item count to render per page.
ItemsPerPage OptInt
}
func unpackListUserParams(packed middleware.Parameters) (params ListUserParams) {
{
key := middleware.ParameterKey{
Name: "page",
In: "query",
}
if v, ok := packed[key]; ok {
params.Page = v.(OptInt)
}
}
{
key := middleware.ParameterKey{
Name: "itemsPerPage",
In: "query",
}
if v, ok := packed[key]; ok {
params.ItemsPerPage = v.(OptInt)
}
}
return params
}
func decodeListUserParams(args [0]string, r *http.Request) (params ListUserParams, _ error) {
q := uri.NewQueryDecoder(r.URL.Query())
// Decode query: page.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "page",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
var paramsDotPageVal int
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
paramsDotPageVal = c
return nil
}(); err != nil {
return err
}
params.Page.SetTo(paramsDotPageVal)
return nil
}); err != nil {
return err
}
if err := func() error {
if params.Page.Set {
if err := func() error {
if err := (validate.Int{
MinSet: true,
Min: 1,
MaxSet: false,
Max: 0,
MinExclusive: false,
MaxExclusive: false,
MultipleOfSet: false,
MultipleOf: 0,
}).Validate(int64(params.Page.Value)); err != nil {
return errors.Wrap(err, "int")
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "page",
In: "query",
Err: err,
}
}
// Decode query: itemsPerPage.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "itemsPerPage",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
var paramsDotItemsPerPageVal int
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
paramsDotItemsPerPageVal = c
return nil
}(); err != nil {
return err
}
params.ItemsPerPage.SetTo(paramsDotItemsPerPageVal)
return nil
}); err != nil {
return err
}
if err := func() error {
if params.ItemsPerPage.Set {
if err := func() error {
if err := (validate.Int{
MinSet: true,
Min: 1,
MaxSet: true,
Max: 255,
MinExclusive: false,
MaxExclusive: false,
MultipleOfSet: false,
MultipleOf: 0,
}).Validate(int64(params.ItemsPerPage.Value)); err != nil {
return errors.Wrap(err, "int")
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "itemsPerPage",
In: "query",
Err: err,
}
}
return params, nil
}
// ListUserOwnerParams is parameters of listUserOwner operation.
type ListUserOwnerParams struct {
// ID of the User.
ID int
// What page to render.
Page OptInt
// Item count to render per page.
ItemsPerPage OptInt
}
func unpackListUserOwnerParams(packed middleware.Parameters) (params ListUserOwnerParams) {
{
key := middleware.ParameterKey{
Name: "id",
In: "path",
}
params.ID = packed[key].(int)
}
{
key := middleware.ParameterKey{
Name: "page",
In: "query",
}
if v, ok := packed[key]; ok {
params.Page = v.(OptInt)
}
}
{
key := middleware.ParameterKey{
Name: "itemsPerPage",
In: "query",
}
if v, ok := packed[key]; ok {
params.ItemsPerPage = v.(OptInt)
}
}
return params
}
func decodeListUserOwnerParams(args [1]string, r *http.Request) (params ListUserOwnerParams, _ error) {
q := uri.NewQueryDecoder(r.URL.Query())
// Decode path: id.
if err := func() error {
param, err := url.PathUnescape(args[0])
if err != nil {
return errors.Wrap(err, "unescape path")
}
if len(param) > 0 {
d := uri.NewPathDecoder(uri.PathDecoderConfig{
Param: "id",
Value: param,
Style: uri.PathStyleSimple,
Explode: false,
})
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
params.ID = c
return nil
}(); err != nil {
return err
}
} else {
return validate.ErrFieldRequired
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "id",
In: "path",
Err: err,
}
}
// Decode query: page.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "page",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
var paramsDotPageVal int
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
paramsDotPageVal = c
return nil
}(); err != nil {
return err
}
params.Page.SetTo(paramsDotPageVal)
return nil
}); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "page",
In: "query",
Err: err,
}
}
// Decode query: itemsPerPage.
if err := func() error {
cfg := uri.QueryParameterDecodingConfig{
Name: "itemsPerPage",
Style: uri.QueryStyleForm,
Explode: true,
}
if err := q.HasParam(cfg); err == nil {
if err := q.DecodeParam(cfg, func(d uri.Decoder) error {
var paramsDotItemsPerPageVal int
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
paramsDotItemsPerPageVal = c
return nil
}(); err != nil {
return err
}
params.ItemsPerPage.SetTo(paramsDotItemsPerPageVal)
return nil
}); err != nil {
return err
}
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "itemsPerPage",
In: "query",
Err: err,
}
}
return params, nil
}
// ReadPasswordTokenParams is parameters of readPasswordToken operation.
type ReadPasswordTokenParams struct {
// ID of the PasswordToken.
ID int
}
func unpackReadPasswordTokenParams(packed middleware.Parameters) (params ReadPasswordTokenParams) {
{
key := middleware.ParameterKey{
Name: "id",
In: "path",
}
params.ID = packed[key].(int)
}
return params
}
func decodeReadPasswordTokenParams(args [1]string, r *http.Request) (params ReadPasswordTokenParams, _ error) {
// Decode path: id.
if err := func() error {
param, err := url.PathUnescape(args[0])
if err != nil {
return errors.Wrap(err, "unescape path")
}
if len(param) > 0 {
d := uri.NewPathDecoder(uri.PathDecoderConfig{
Param: "id",
Value: param,
Style: uri.PathStyleSimple,
Explode: false,
})
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
params.ID = c
return nil
}(); err != nil {
return err
}
} else {
return validate.ErrFieldRequired
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "id",
In: "path",
Err: err,
}
}
return params, nil
}
// ReadPasswordTokenUserParams is parameters of readPasswordTokenUser operation.
type ReadPasswordTokenUserParams struct {
// ID of the PasswordToken.
ID int
}
func unpackReadPasswordTokenUserParams(packed middleware.Parameters) (params ReadPasswordTokenUserParams) {
{
key := middleware.ParameterKey{
Name: "id",
In: "path",
}
params.ID = packed[key].(int)
}
return params
}
func decodeReadPasswordTokenUserParams(args [1]string, r *http.Request) (params ReadPasswordTokenUserParams, _ error) {
// Decode path: id.
if err := func() error {
param, err := url.PathUnescape(args[0])
if err != nil {
return errors.Wrap(err, "unescape path")
}
if len(param) > 0 {
d := uri.NewPathDecoder(uri.PathDecoderConfig{
Param: "id",
Value: param,
Style: uri.PathStyleSimple,
Explode: false,
})
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
params.ID = c
return nil
}(); err != nil {
return err
}
} else {
return validate.ErrFieldRequired
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "id",
In: "path",
Err: err,
}
}
return params, nil
}
// ReadUserParams is parameters of readUser operation.
type ReadUserParams struct {
// ID of the User.
ID int
}
func unpackReadUserParams(packed middleware.Parameters) (params ReadUserParams) {
{
key := middleware.ParameterKey{
Name: "id",
In: "path",
}
params.ID = packed[key].(int)
}
return params
}
func decodeReadUserParams(args [1]string, r *http.Request) (params ReadUserParams, _ error) {
// Decode path: id.
if err := func() error {
param, err := url.PathUnescape(args[0])
if err != nil {
return errors.Wrap(err, "unescape path")
}
if len(param) > 0 {
d := uri.NewPathDecoder(uri.PathDecoderConfig{
Param: "id",
Value: param,
Style: uri.PathStyleSimple,
Explode: false,
})
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
params.ID = c
return nil
}(); err != nil {
return err
}
} else {
return validate.ErrFieldRequired
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "id",
In: "path",
Err: err,
}
}
return params, nil
}
// UpdatePasswordTokenParams is parameters of updatePasswordToken operation.
type UpdatePasswordTokenParams struct {
// ID of the PasswordToken.
ID int
}
func unpackUpdatePasswordTokenParams(packed middleware.Parameters) (params UpdatePasswordTokenParams) {
{
key := middleware.ParameterKey{
Name: "id",
In: "path",
}
params.ID = packed[key].(int)
}
return params
}
func decodeUpdatePasswordTokenParams(args [1]string, r *http.Request) (params UpdatePasswordTokenParams, _ error) {
// Decode path: id.
if err := func() error {
param, err := url.PathUnescape(args[0])
if err != nil {
return errors.Wrap(err, "unescape path")
}
if len(param) > 0 {
d := uri.NewPathDecoder(uri.PathDecoderConfig{
Param: "id",
Value: param,
Style: uri.PathStyleSimple,
Explode: false,
})
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
params.ID = c
return nil
}(); err != nil {
return err
}
} else {
return validate.ErrFieldRequired
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "id",
In: "path",
Err: err,
}
}
return params, nil
}
// UpdateUserParams is parameters of updateUser operation.
type UpdateUserParams struct {
// ID of the User.
ID int
}
func unpackUpdateUserParams(packed middleware.Parameters) (params UpdateUserParams) {
{
key := middleware.ParameterKey{
Name: "id",
In: "path",
}
params.ID = packed[key].(int)
}
return params
}
func decodeUpdateUserParams(args [1]string, r *http.Request) (params UpdateUserParams, _ error) {
// Decode path: id.
if err := func() error {
param, err := url.PathUnescape(args[0])
if err != nil {
return errors.Wrap(err, "unescape path")
}
if len(param) > 0 {
d := uri.NewPathDecoder(uri.PathDecoderConfig{
Param: "id",
Value: param,
Style: uri.PathStyleSimple,
Explode: false,
})
if err := func() error {
val, err := d.DecodeValue()
if err != nil {
return err
}
c, err := conv.ToInt(val)
if err != nil {
return err
}
params.ID = c
return nil
}(); err != nil {
return err
}
} else {
return validate.ErrFieldRequired
}
return nil
}(); err != nil {
return params, &ogenerrors.DecodeParamError{
Name: "id",
In: "path",
Err: err,
}
}
return params, nil
}

View file

@ -1,268 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"io"
"mime"
"net/http"
"github.com/go-faster/errors"
"github.com/go-faster/jx"
"go.uber.org/multierr"
"github.com/ogen-go/ogen/ogenerrors"
"github.com/ogen-go/ogen/validate"
)
func (s *Server) decodeCreatePasswordTokenRequest(r *http.Request) (
req *CreatePasswordTokenReq,
close func() error,
rerr error,
) {
var closers []func() error
close = func() error {
var merr error
// Close in reverse order, to match defer behavior.
for i := len(closers) - 1; i >= 0; i-- {
c := closers[i]
merr = multierr.Append(merr, c())
}
return merr
}
defer func() {
if rerr != nil {
rerr = multierr.Append(rerr, close())
}
}()
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
if err != nil {
return req, close, errors.Wrap(err, "parse media type")
}
switch {
case ct == "application/json":
if r.ContentLength == 0 {
return req, close, validate.ErrBodyRequired
}
buf, err := io.ReadAll(r.Body)
if err != nil {
return req, close, err
}
if len(buf) == 0 {
return req, close, validate.ErrBodyRequired
}
d := jx.DecodeBytes(buf)
var request CreatePasswordTokenReq
if err := func() error {
if err := request.Decode(d); err != nil {
return err
}
if err := d.Skip(); err != io.EOF {
return errors.New("unexpected trailing data")
}
return nil
}(); err != nil {
err = &ogenerrors.DecodeBodyError{
ContentType: ct,
Body: buf,
Err: err,
}
return req, close, err
}
return &request, close, nil
default:
return req, close, validate.InvalidContentType(ct)
}
}
func (s *Server) decodeCreateUserRequest(r *http.Request) (
req *CreateUserReq,
close func() error,
rerr error,
) {
var closers []func() error
close = func() error {
var merr error
// Close in reverse order, to match defer behavior.
for i := len(closers) - 1; i >= 0; i-- {
c := closers[i]
merr = multierr.Append(merr, c())
}
return merr
}
defer func() {
if rerr != nil {
rerr = multierr.Append(rerr, close())
}
}()
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
if err != nil {
return req, close, errors.Wrap(err, "parse media type")
}
switch {
case ct == "application/json":
if r.ContentLength == 0 {
return req, close, validate.ErrBodyRequired
}
buf, err := io.ReadAll(r.Body)
if err != nil {
return req, close, err
}
if len(buf) == 0 {
return req, close, validate.ErrBodyRequired
}
d := jx.DecodeBytes(buf)
var request CreateUserReq
if err := func() error {
if err := request.Decode(d); err != nil {
return err
}
if err := d.Skip(); err != io.EOF {
return errors.New("unexpected trailing data")
}
return nil
}(); err != nil {
err = &ogenerrors.DecodeBodyError{
ContentType: ct,
Body: buf,
Err: err,
}
return req, close, err
}
return &request, close, nil
default:
return req, close, validate.InvalidContentType(ct)
}
}
func (s *Server) decodeUpdatePasswordTokenRequest(r *http.Request) (
req *UpdatePasswordTokenReq,
close func() error,
rerr error,
) {
var closers []func() error
close = func() error {
var merr error
// Close in reverse order, to match defer behavior.
for i := len(closers) - 1; i >= 0; i-- {
c := closers[i]
merr = multierr.Append(merr, c())
}
return merr
}
defer func() {
if rerr != nil {
rerr = multierr.Append(rerr, close())
}
}()
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
if err != nil {
return req, close, errors.Wrap(err, "parse media type")
}
switch {
case ct == "application/json":
if r.ContentLength == 0 {
return req, close, validate.ErrBodyRequired
}
buf, err := io.ReadAll(r.Body)
if err != nil {
return req, close, err
}
if len(buf) == 0 {
return req, close, validate.ErrBodyRequired
}
d := jx.DecodeBytes(buf)
var request UpdatePasswordTokenReq
if err := func() error {
if err := request.Decode(d); err != nil {
return err
}
if err := d.Skip(); err != io.EOF {
return errors.New("unexpected trailing data")
}
return nil
}(); err != nil {
err = &ogenerrors.DecodeBodyError{
ContentType: ct,
Body: buf,
Err: err,
}
return req, close, err
}
return &request, close, nil
default:
return req, close, validate.InvalidContentType(ct)
}
}
func (s *Server) decodeUpdateUserRequest(r *http.Request) (
req *UpdateUserReq,
close func() error,
rerr error,
) {
var closers []func() error
close = func() error {
var merr error
// Close in reverse order, to match defer behavior.
for i := len(closers) - 1; i >= 0; i-- {
c := closers[i]
merr = multierr.Append(merr, c())
}
return merr
}
defer func() {
if rerr != nil {
rerr = multierr.Append(rerr, close())
}
}()
ct, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
if err != nil {
return req, close, errors.Wrap(err, "parse media type")
}
switch {
case ct == "application/json":
if r.ContentLength == 0 {
return req, close, validate.ErrBodyRequired
}
buf, err := io.ReadAll(r.Body)
if err != nil {
return req, close, err
}
if len(buf) == 0 {
return req, close, validate.ErrBodyRequired
}
d := jx.DecodeBytes(buf)
var request UpdateUserReq
if err := func() error {
if err := request.Decode(d); err != nil {
return err
}
if err := d.Skip(); err != io.EOF {
return errors.New("unexpected trailing data")
}
return nil
}(); err != nil {
err = &ogenerrors.DecodeBodyError{
ContentType: ct,
Body: buf,
Err: err,
}
return req, close, err
}
return &request, close, nil
default:
return req, close, validate.InvalidContentType(ct)
}
}

View file

@ -1,68 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"bytes"
"net/http"
"github.com/go-faster/jx"
ht "github.com/ogen-go/ogen/http"
)
func encodeCreatePasswordTokenRequest(
req *CreatePasswordTokenReq,
r *http.Request,
) error {
const contentType = "application/json"
e := jx.GetEncoder()
{
req.Encode(e)
}
encoded := e.Bytes()
ht.SetBody(r, bytes.NewReader(encoded), contentType)
return nil
}
func encodeCreateUserRequest(
req *CreateUserReq,
r *http.Request,
) error {
const contentType = "application/json"
e := jx.GetEncoder()
{
req.Encode(e)
}
encoded := e.Bytes()
ht.SetBody(r, bytes.NewReader(encoded), contentType)
return nil
}
func encodeUpdatePasswordTokenRequest(
req *UpdatePasswordTokenReq,
r *http.Request,
) error {
const contentType = "application/json"
e := jx.GetEncoder()
{
req.Encode(e)
}
encoded := e.Bytes()
ht.SetBody(r, bytes.NewReader(encoded), contentType)
return nil
}
func encodeUpdateUserRequest(
req *UpdateUserReq,
r *http.Request,
) error {
const contentType = "application/json"
e := jx.GetEncoder()
{
req.Encode(e)
}
encoded := e.Bytes()
ht.SetBody(r, bytes.NewReader(encoded), contentType)
return nil
}

File diff suppressed because it is too large Load diff

View file

@ -1,780 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"net/http"
"github.com/go-faster/errors"
"github.com/go-faster/jx"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)
func encodeCreatePasswordTokenResponse(response CreatePasswordTokenRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *PasswordTokenCreate:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeCreateUserResponse(response CreateUserRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *UserCreate:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeDeletePasswordTokenResponse(response DeletePasswordTokenRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *DeletePasswordTokenNoContent:
w.WriteHeader(204)
span.SetStatus(codes.Ok, http.StatusText(204))
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeDeleteUserResponse(response DeleteUserRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *DeleteUserNoContent:
w.WriteHeader(204)
span.SetStatus(codes.Ok, http.StatusText(204))
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeListPasswordTokenResponse(response ListPasswordTokenRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *ListPasswordTokenOKApplicationJSON:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeListUserResponse(response ListUserRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *ListUserOKApplicationJSON:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeListUserOwnerResponse(response ListUserOwnerRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *ListUserOwnerOKApplicationJSON:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeReadPasswordTokenResponse(response ReadPasswordTokenRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *PasswordTokenRead:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeReadPasswordTokenUserResponse(response ReadPasswordTokenUserRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *PasswordTokenUserRead:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeReadUserResponse(response ReadUserRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *UserRead:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeUpdatePasswordTokenResponse(response UpdatePasswordTokenRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *PasswordTokenUpdate:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}
func encodeUpdateUserResponse(response UpdateUserRes, w http.ResponseWriter, span trace.Span) error {
switch response := response.(type) {
case *UserUpdate:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
span.SetStatus(codes.Ok, http.StatusText(200))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R400:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(400)
span.SetStatus(codes.Error, http.StatusText(400))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R404:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(404)
span.SetStatus(codes.Error, http.StatusText(404))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R409:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(409)
span.SetStatus(codes.Error, http.StatusText(409))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
case *R500:
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(500)
span.SetStatus(codes.Error, http.StatusText(500))
e := jx.GetEncoder()
response.Encode(e)
if _, err := e.WriteTo(w); err != nil {
return errors.Wrap(err, "write")
}
return nil
default:
return errors.Errorf("unexpected response type: %T", response)
}
}

View file

@ -1,489 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"net/http"
"net/url"
"strings"
"github.com/ogen-go/ogen/uri"
)
// ServeHTTP serves http request as defined by OpenAPI v3 specification,
// calling handler that matches the path or returning not found error.
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
elem := r.URL.Path
if rawPath := r.URL.RawPath; rawPath != "" {
if normalized, ok := uri.NormalizeEscapedPath(rawPath); ok {
elem = normalized
}
}
if prefix := s.cfg.Prefix; len(prefix) > 0 {
if strings.HasPrefix(elem, prefix) {
// Cut prefix from the path.
elem = strings.TrimPrefix(elem, prefix)
} else {
// Prefix doesn't match.
s.notFound(w, r)
return
}
}
if len(elem) == 0 {
s.notFound(w, r)
return
}
args := [1]string{}
// Static code generated router with unwrapped path search.
switch {
default:
if len(elem) == 0 {
break
}
switch elem[0] {
case '/': // Prefix: "/"
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
break
}
switch elem[0] {
case 'p': // Prefix: "password-tokens"
if l := len("password-tokens"); len(elem) >= l && elem[0:l] == "password-tokens" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
switch r.Method {
case "GET":
s.handleListPasswordTokenRequest([0]string{}, w, r)
case "POST":
s.handleCreatePasswordTokenRequest([0]string{}, w, r)
default:
s.notAllowed(w, r, "GET,POST")
}
return
}
switch elem[0] {
case '/': // Prefix: "/"
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
elem = elem[l:]
} else {
break
}
// Param: "id"
// Match until "/"
idx := strings.IndexByte(elem, '/')
if idx < 0 {
idx = len(elem)
}
args[0] = elem[:idx]
elem = elem[idx:]
if len(elem) == 0 {
switch r.Method {
case "DELETE":
s.handleDeletePasswordTokenRequest([1]string{
args[0],
}, w, r)
case "GET":
s.handleReadPasswordTokenRequest([1]string{
args[0],
}, w, r)
case "PATCH":
s.handleUpdatePasswordTokenRequest([1]string{
args[0],
}, w, r)
default:
s.notAllowed(w, r, "DELETE,GET,PATCH")
}
return
}
switch elem[0] {
case '/': // Prefix: "/user"
if l := len("/user"); len(elem) >= l && elem[0:l] == "/user" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
// Leaf node.
switch r.Method {
case "GET":
s.handleReadPasswordTokenUserRequest([1]string{
args[0],
}, w, r)
default:
s.notAllowed(w, r, "GET")
}
return
}
}
}
case 'u': // Prefix: "users"
if l := len("users"); len(elem) >= l && elem[0:l] == "users" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
switch r.Method {
case "GET":
s.handleListUserRequest([0]string{}, w, r)
case "POST":
s.handleCreateUserRequest([0]string{}, w, r)
default:
s.notAllowed(w, r, "GET,POST")
}
return
}
switch elem[0] {
case '/': // Prefix: "/"
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
elem = elem[l:]
} else {
break
}
// Param: "id"
// Match until "/"
idx := strings.IndexByte(elem, '/')
if idx < 0 {
idx = len(elem)
}
args[0] = elem[:idx]
elem = elem[idx:]
if len(elem) == 0 {
switch r.Method {
case "DELETE":
s.handleDeleteUserRequest([1]string{
args[0],
}, w, r)
case "GET":
s.handleReadUserRequest([1]string{
args[0],
}, w, r)
case "PATCH":
s.handleUpdateUserRequest([1]string{
args[0],
}, w, r)
default:
s.notAllowed(w, r, "DELETE,GET,PATCH")
}
return
}
switch elem[0] {
case '/': // Prefix: "/owner"
if l := len("/owner"); len(elem) >= l && elem[0:l] == "/owner" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
// Leaf node.
switch r.Method {
case "GET":
s.handleListUserOwnerRequest([1]string{
args[0],
}, w, r)
default:
s.notAllowed(w, r, "GET")
}
return
}
}
}
}
}
}
s.notFound(w, r)
}
// Route is route object.
type Route struct {
name string
operationID string
pathPattern string
count int
args [1]string
}
// Name returns ogen operation name.
//
// It is guaranteed to be unique and not empty.
func (r Route) Name() string {
return r.name
}
// OperationID returns OpenAPI operationId.
func (r Route) OperationID() string {
return r.operationID
}
// PathPattern returns OpenAPI path.
func (r Route) PathPattern() string {
return r.pathPattern
}
// Args returns parsed arguments.
func (r Route) Args() []string {
return r.args[:r.count]
}
// FindRoute finds Route for given method and path.
//
// Note: this method does not unescape path or handle reserved characters in path properly. Use FindPath instead.
func (s *Server) FindRoute(method, path string) (Route, bool) {
return s.FindPath(method, &url.URL{Path: path})
}
// FindPath finds Route for given method and URL.
func (s *Server) FindPath(method string, u *url.URL) (r Route, _ bool) {
var (
elem = u.Path
args = r.args
)
if rawPath := u.RawPath; rawPath != "" {
if normalized, ok := uri.NormalizeEscapedPath(rawPath); ok {
elem = normalized
}
defer func() {
for i, arg := range r.args[:r.count] {
if unescaped, err := url.PathUnescape(arg); err == nil {
r.args[i] = unescaped
}
}
}()
}
// Static code generated router with unwrapped path search.
switch {
default:
if len(elem) == 0 {
break
}
switch elem[0] {
case '/': // Prefix: "/"
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
break
}
switch elem[0] {
case 'p': // Prefix: "password-tokens"
if l := len("password-tokens"); len(elem) >= l && elem[0:l] == "password-tokens" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
switch method {
case "GET":
r.name = "ListPasswordToken"
r.operationID = "listPasswordToken"
r.pathPattern = "/password-tokens"
r.args = args
r.count = 0
return r, true
case "POST":
r.name = "CreatePasswordToken"
r.operationID = "createPasswordToken"
r.pathPattern = "/password-tokens"
r.args = args
r.count = 0
return r, true
default:
return
}
}
switch elem[0] {
case '/': // Prefix: "/"
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
elem = elem[l:]
} else {
break
}
// Param: "id"
// Match until "/"
idx := strings.IndexByte(elem, '/')
if idx < 0 {
idx = len(elem)
}
args[0] = elem[:idx]
elem = elem[idx:]
if len(elem) == 0 {
switch method {
case "DELETE":
r.name = "DeletePasswordToken"
r.operationID = "deletePasswordToken"
r.pathPattern = "/password-tokens/{id}"
r.args = args
r.count = 1
return r, true
case "GET":
r.name = "ReadPasswordToken"
r.operationID = "readPasswordToken"
r.pathPattern = "/password-tokens/{id}"
r.args = args
r.count = 1
return r, true
case "PATCH":
r.name = "UpdatePasswordToken"
r.operationID = "updatePasswordToken"
r.pathPattern = "/password-tokens/{id}"
r.args = args
r.count = 1
return r, true
default:
return
}
}
switch elem[0] {
case '/': // Prefix: "/user"
if l := len("/user"); len(elem) >= l && elem[0:l] == "/user" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
switch method {
case "GET":
// Leaf: ReadPasswordTokenUser
r.name = "ReadPasswordTokenUser"
r.operationID = "readPasswordTokenUser"
r.pathPattern = "/password-tokens/{id}/user"
r.args = args
r.count = 1
return r, true
default:
return
}
}
}
}
case 'u': // Prefix: "users"
if l := len("users"); len(elem) >= l && elem[0:l] == "users" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
switch method {
case "GET":
r.name = "ListUser"
r.operationID = "listUser"
r.pathPattern = "/users"
r.args = args
r.count = 0
return r, true
case "POST":
r.name = "CreateUser"
r.operationID = "createUser"
r.pathPattern = "/users"
r.args = args
r.count = 0
return r, true
default:
return
}
}
switch elem[0] {
case '/': // Prefix: "/"
if l := len("/"); len(elem) >= l && elem[0:l] == "/" {
elem = elem[l:]
} else {
break
}
// Param: "id"
// Match until "/"
idx := strings.IndexByte(elem, '/')
if idx < 0 {
idx = len(elem)
}
args[0] = elem[:idx]
elem = elem[idx:]
if len(elem) == 0 {
switch method {
case "DELETE":
r.name = "DeleteUser"
r.operationID = "deleteUser"
r.pathPattern = "/users/{id}"
r.args = args
r.count = 1
return r, true
case "GET":
r.name = "ReadUser"
r.operationID = "readUser"
r.pathPattern = "/users/{id}"
r.args = args
r.count = 1
return r, true
case "PATCH":
r.name = "UpdateUser"
r.operationID = "updateUser"
r.pathPattern = "/users/{id}"
r.args = args
r.count = 1
return r, true
default:
return
}
}
switch elem[0] {
case '/': // Prefix: "/owner"
if l := len("/owner"); len(elem) >= l && elem[0:l] == "/owner" {
elem = elem[l:]
} else {
break
}
if len(elem) == 0 {
switch method {
case "GET":
// Leaf: ListUserOwner
r.name = "ListUserOwner"
r.operationID = "listUserOwner"
r.pathPattern = "/users/{id}/owner"
r.args = args
r.count = 1
return r, true
default:
return
}
}
}
}
}
}
}
return r, false
}

File diff suppressed because it is too large Load diff

View file

@ -1,102 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"context"
)
// Handler handles operations described by OpenAPI v3 specification.
type Handler interface {
// CreatePasswordToken implements createPasswordToken operation.
//
// Creates a new PasswordToken and persists it to storage.
//
// POST /password-tokens
CreatePasswordToken(ctx context.Context, req *CreatePasswordTokenReq) (CreatePasswordTokenRes, error)
// CreateUser implements createUser operation.
//
// Creates a new User and persists it to storage.
//
// POST /users
CreateUser(ctx context.Context, req *CreateUserReq) (CreateUserRes, error)
// DeletePasswordToken implements deletePasswordToken operation.
//
// Deletes the PasswordToken with the requested ID.
//
// DELETE /password-tokens/{id}
DeletePasswordToken(ctx context.Context, params DeletePasswordTokenParams) (DeletePasswordTokenRes, error)
// DeleteUser implements deleteUser operation.
//
// Deletes the User with the requested ID.
//
// DELETE /users/{id}
DeleteUser(ctx context.Context, params DeleteUserParams) (DeleteUserRes, error)
// ListPasswordToken implements listPasswordToken operation.
//
// List PasswordTokens.
//
// GET /password-tokens
ListPasswordToken(ctx context.Context, params ListPasswordTokenParams) (ListPasswordTokenRes, error)
// ListUser implements listUser operation.
//
// List Users.
//
// GET /users
ListUser(ctx context.Context, params ListUserParams) (ListUserRes, error)
// ListUserOwner implements listUserOwner operation.
//
// List attached Owners.
//
// GET /users/{id}/owner
ListUserOwner(ctx context.Context, params ListUserOwnerParams) (ListUserOwnerRes, error)
// ReadPasswordToken implements readPasswordToken operation.
//
// Finds the PasswordToken with the requested ID and returns it.
//
// GET /password-tokens/{id}
ReadPasswordToken(ctx context.Context, params ReadPasswordTokenParams) (ReadPasswordTokenRes, error)
// ReadPasswordTokenUser implements readPasswordTokenUser operation.
//
// Find the attached User of the PasswordToken with the given ID.
//
// GET /password-tokens/{id}/user
ReadPasswordTokenUser(ctx context.Context, params ReadPasswordTokenUserParams) (ReadPasswordTokenUserRes, error)
// ReadUser implements readUser operation.
//
// Finds the User with the requested ID and returns it.
//
// GET /users/{id}
ReadUser(ctx context.Context, params ReadUserParams) (ReadUserRes, error)
// UpdatePasswordToken implements updatePasswordToken operation.
//
// Updates a PasswordToken and persists changes to storage.
//
// PATCH /password-tokens/{id}
UpdatePasswordToken(ctx context.Context, req *UpdatePasswordTokenReq, params UpdatePasswordTokenParams) (UpdatePasswordTokenRes, error)
// UpdateUser implements updateUser operation.
//
// Updates a User and persists changes to storage.
//
// PATCH /users/{id}
UpdateUser(ctx context.Context, req *UpdateUserReq, params UpdateUserParams) (UpdateUserRes, error)
}
// Server implements http server based on OpenAPI v3 specification and
// calls Handler to handle requests.
type Server struct {
h Handler
baseServer
}
// NewServer creates new Server.
func NewServer(h Handler, opts ...ServerOption) (*Server, error) {
s, err := newServerConfig(opts...).baseServer()
if err != nil {
return nil, err
}
return &Server{
h: h,
baseServer: s,
}, nil
}

View file

@ -1,122 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"context"
ht "github.com/ogen-go/ogen/http"
)
// UnimplementedHandler is no-op Handler which returns http.ErrNotImplemented.
type UnimplementedHandler struct{}
var _ Handler = UnimplementedHandler{}
// CreatePasswordToken implements createPasswordToken operation.
//
// Creates a new PasswordToken and persists it to storage.
//
// POST /password-tokens
func (UnimplementedHandler) CreatePasswordToken(ctx context.Context, req *CreatePasswordTokenReq) (r CreatePasswordTokenRes, _ error) {
return r, ht.ErrNotImplemented
}
// CreateUser implements createUser operation.
//
// Creates a new User and persists it to storage.
//
// POST /users
func (UnimplementedHandler) CreateUser(ctx context.Context, req *CreateUserReq) (r CreateUserRes, _ error) {
return r, ht.ErrNotImplemented
}
// DeletePasswordToken implements deletePasswordToken operation.
//
// Deletes the PasswordToken with the requested ID.
//
// DELETE /password-tokens/{id}
func (UnimplementedHandler) DeletePasswordToken(ctx context.Context, params DeletePasswordTokenParams) (r DeletePasswordTokenRes, _ error) {
return r, ht.ErrNotImplemented
}
// DeleteUser implements deleteUser operation.
//
// Deletes the User with the requested ID.
//
// DELETE /users/{id}
func (UnimplementedHandler) DeleteUser(ctx context.Context, params DeleteUserParams) (r DeleteUserRes, _ error) {
return r, ht.ErrNotImplemented
}
// ListPasswordToken implements listPasswordToken operation.
//
// List PasswordTokens.
//
// GET /password-tokens
func (UnimplementedHandler) ListPasswordToken(ctx context.Context, params ListPasswordTokenParams) (r ListPasswordTokenRes, _ error) {
return r, ht.ErrNotImplemented
}
// ListUser implements listUser operation.
//
// List Users.
//
// GET /users
func (UnimplementedHandler) ListUser(ctx context.Context, params ListUserParams) (r ListUserRes, _ error) {
return r, ht.ErrNotImplemented
}
// ListUserOwner implements listUserOwner operation.
//
// List attached Owners.
//
// GET /users/{id}/owner
func (UnimplementedHandler) ListUserOwner(ctx context.Context, params ListUserOwnerParams) (r ListUserOwnerRes, _ error) {
return r, ht.ErrNotImplemented
}
// ReadPasswordToken implements readPasswordToken operation.
//
// Finds the PasswordToken with the requested ID and returns it.
//
// GET /password-tokens/{id}
func (UnimplementedHandler) ReadPasswordToken(ctx context.Context, params ReadPasswordTokenParams) (r ReadPasswordTokenRes, _ error) {
return r, ht.ErrNotImplemented
}
// ReadPasswordTokenUser implements readPasswordTokenUser operation.
//
// Find the attached User of the PasswordToken with the given ID.
//
// GET /password-tokens/{id}/user
func (UnimplementedHandler) ReadPasswordTokenUser(ctx context.Context, params ReadPasswordTokenUserParams) (r ReadPasswordTokenUserRes, _ error) {
return r, ht.ErrNotImplemented
}
// ReadUser implements readUser operation.
//
// Finds the User with the requested ID and returns it.
//
// GET /users/{id}
func (UnimplementedHandler) ReadUser(ctx context.Context, params ReadUserParams) (r ReadUserRes, _ error) {
return r, ht.ErrNotImplemented
}
// UpdatePasswordToken implements updatePasswordToken operation.
//
// Updates a PasswordToken and persists changes to storage.
//
// PATCH /password-tokens/{id}
func (UnimplementedHandler) UpdatePasswordToken(ctx context.Context, req *UpdatePasswordTokenReq, params UpdatePasswordTokenParams) (r UpdatePasswordTokenRes, _ error) {
return r, ht.ErrNotImplemented
}
// UpdateUser implements updateUser operation.
//
// Updates a User and persists changes to storage.
//
// PATCH /users/{id}
func (UnimplementedHandler) UpdateUser(ctx context.Context, req *UpdateUserReq, params UpdateUserParams) (r UpdateUserRes, _ error) {
return r, ht.ErrNotImplemented
}

View file

@ -1,26 +0,0 @@
// Code generated by ogen, DO NOT EDIT.
package ogent
import (
"github.com/go-faster/errors"
)
func (s ListPasswordTokenOKApplicationJSON) Validate() error {
if s == nil {
return errors.New("nil is invalid value")
}
return nil
}
func (s ListUserOKApplicationJSON) Validate() error {
if s == nil {
return errors.New("nil is invalid value")
}
return nil
}
func (s ListUserOwnerOKApplicationJSON) Validate() error {
if s == nil {
return errors.New("nil is invalid value")
}
return nil
}

View file

@ -1,264 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ogent
import (
"context"
"github.com/go-faster/jx"
"github.com/mikestefanello/pagoda/ent"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
)
// OgentHandler implements the ogen generated Handler interface and uses Ent as data layer.
type OgentHandler struct {
client *ent.Client
}
// NewOgentHandler returns a new OgentHandler.
func NewOgentHandler(c *ent.Client) *OgentHandler { return &OgentHandler{c} }
// rawError renders err as json string.
func rawError(err error) jx.Raw {
var e jx.Encoder
e.Str(err.Error())
return e.Bytes()
}
// CreatePasswordToken handles POST /password-tokens requests.
func (h *OgentHandler) CreatePasswordToken(ctx context.Context, req *CreatePasswordTokenReq) (CreatePasswordTokenRes, error) {
b := h.client.PasswordToken.Create()
// Add all fields.
b.SetHash(req.Hash)
b.SetCreatedAt(req.CreatedAt)
// Add all edges.
b.SetUserID(req.User)
// Persist to storage.
e, err := b.Save(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
// Reload the entity to attach all eager-loaded edges.
q := h.client.PasswordToken.Query().Where(passwordtoken.ID(e.ID))
e, err = q.Only(ctx)
if err != nil {
// This should never happen.
return nil, err
}
return NewPasswordTokenCreate(e), nil
}
// ReadPasswordToken handles GET /password-tokens/{id} requests.
func (h *OgentHandler) ReadPasswordToken(ctx context.Context, params ReadPasswordTokenParams) (ReadPasswordTokenRes, error) {
q := h.client.PasswordToken.Query().Where(passwordtoken.IDEQ(params.ID))
e, err := q.Only(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
return NewPasswordTokenRead(e), nil
}
// UpdatePasswordToken handles PATCH /password-tokens/{id} requests.
func (h *OgentHandler) UpdatePasswordToken(ctx context.Context, req *UpdatePasswordTokenReq, params UpdatePasswordTokenParams) (UpdatePasswordTokenRes, error) {
b := h.client.PasswordToken.UpdateOneID(params.ID)
// Add all fields.
if v, ok := req.Hash.Get(); ok {
b.SetHash(v)
}
if v, ok := req.CreatedAt.Get(); ok {
b.SetCreatedAt(v)
}
// Add all edges.
if v, ok := req.User.Get(); ok {
b.SetUserID(v)
}
// Persist to storage.
e, err := b.Save(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
// Reload the entity to attach all eager-loaded edges.
q := h.client.PasswordToken.Query().Where(passwordtoken.ID(e.ID))
e, err = q.Only(ctx)
if err != nil {
// This should never happen.
return nil, err
}
return NewPasswordTokenUpdate(e), nil
}
// DeletePasswordToken handles DELETE /password-tokens/{id} requests.
func (h *OgentHandler) DeletePasswordToken(ctx context.Context, params DeletePasswordTokenParams) (DeletePasswordTokenRes, error) {
err := h.client.PasswordToken.DeleteOneID(params.ID).Exec(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
return new(DeletePasswordTokenNoContent), nil
}
// ListPasswordToken handles GET /password-tokens requests.
func (h *OgentHandler) ListPasswordToken(ctx context.Context, params ListPasswordTokenParams) (ListPasswordTokenRes, error) {
q := h.client.PasswordToken.Query()
page := 1
if v, ok := params.Page.Get(); ok {
page = v
}
itemsPerPage := 30
if v, ok := params.ItemsPerPage.Get(); ok {
itemsPerPage = v
}
q.Limit(itemsPerPage).Offset((page - 1) * itemsPerPage)
es, err := q.All(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
r := NewPasswordTokenLists(es)
return (*ListPasswordTokenOKApplicationJSON)(&r), nil
}
// ReadPasswordTokenUser handles GET /password-tokens/{id}/user requests.
func (h *OgentHandler) ReadPasswordTokenUser(ctx context.Context, params ReadPasswordTokenUserParams) (ReadPasswordTokenUserRes, error) {
q := h.client.PasswordToken.Query().Where(passwordtoken.IDEQ(params.ID)).QueryUser()
e, err := q.Only(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
return NewPasswordTokenUserRead(e), nil
}
// CreateUser handles POST /users requests.
func (h *OgentHandler) CreateUser(ctx context.Context, req *CreateUserReq) (CreateUserRes, error) {
b := h.client.User.Create()
// Add all fields.
b.SetName(req.Name)
b.SetEmail(req.Email)
b.SetPassword(req.Password)
b.SetVerified(req.Verified)
b.SetCreatedAt(req.CreatedAt)
// Add all edges.
b.AddOwnerIDs(req.Owner...)
// Persist to storage.
e, err := b.Save(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
// Reload the entity to attach all eager-loaded edges.
q := h.client.User.Query().Where(user.ID(e.ID))
e, err = q.Only(ctx)
if err != nil {
// This should never happen.
return nil, err
}
return NewUserCreate(e), nil
}
// ReadUser handles GET /users/{id} requests.
func (h *OgentHandler) ReadUser(ctx context.Context, params ReadUserParams) (ReadUserRes, error) {
q := h.client.User.Query().Where(user.IDEQ(params.ID))
e, err := q.Only(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
return NewUserRead(e), nil
}
// UpdateUser handles PATCH /users/{id} requests.
func (h *OgentHandler) UpdateUser(ctx context.Context, req *UpdateUserReq, params UpdateUserParams) (UpdateUserRes, error) {
b := h.client.User.UpdateOneID(params.ID)
// Add all fields.
if v, ok := req.Name.Get(); ok {
b.SetName(v)
}
if v, ok := req.Email.Get(); ok {
b.SetEmail(v)
}
if v, ok := req.Password.Get(); ok {
b.SetPassword(v)
}
if v, ok := req.Verified.Get(); ok {
b.SetVerified(v)
}
// Add all edges.
if req.Owner != nil {
b.ClearOwner().AddOwnerIDs(req.Owner...)
}
// Persist to storage.
e, err := b.Save(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
// Reload the entity to attach all eager-loaded edges.
q := h.client.User.Query().Where(user.ID(e.ID))
e, err = q.Only(ctx)
if err != nil {
// This should never happen.
return nil, err
}
return NewUserUpdate(e), nil
}
// DeleteUser handles DELETE /users/{id} requests.
func (h *OgentHandler) DeleteUser(ctx context.Context, params DeleteUserParams) (DeleteUserRes, error) {
err := h.client.User.DeleteOneID(params.ID).Exec(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
return new(DeleteUserNoContent), nil
}
// ListUser handles GET /users requests.
func (h *OgentHandler) ListUser(ctx context.Context, params ListUserParams) (ListUserRes, error) {
q := h.client.User.Query()
page := 1
if v, ok := params.Page.Get(); ok {
page = v
}
itemsPerPage := 30
if v, ok := params.ItemsPerPage.Get(); ok {
itemsPerPage = v
}
q.Limit(itemsPerPage).Offset((page - 1) * itemsPerPage)
es, err := q.All(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
r := NewUserLists(es)
return (*ListUserOKApplicationJSON)(&r), nil
}
// ListUserOwner handles GET /users/{id}/owner requests.
func (h *OgentHandler) ListUserOwner(ctx context.Context, params ListUserOwnerParams) (ListUserOwnerRes, error) {
q := h.client.User.Query().Where(user.IDEQ(params.ID)).QueryOwner()
page := 1
if v, ok := params.Page.Get(); ok {
page = v
}
itemsPerPage := 30
if v, ok := params.ItemsPerPage.Get(); ok {
itemsPerPage = v
}
q.Limit(itemsPerPage).Offset((page - 1) * itemsPerPage)
es, err := q.All(ctx)
if err != nil {
// Let the server handle the error.
return nil, err
}
r := NewUserOwnerLists(es)
return (*ListUserOwnerOKApplicationJSON)(&r), nil
}

View file

@ -1,300 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ogent
import "github.com/mikestefanello/pagoda/ent"
func NewPasswordTokenCreate(e *ent.PasswordToken) *PasswordTokenCreate {
if e == nil {
return nil
}
var ret PasswordTokenCreate
ret.ID = e.ID
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewPasswordTokenCreates(es []*ent.PasswordToken) []PasswordTokenCreate {
if len(es) == 0 {
return nil
}
r := make([]PasswordTokenCreate, len(es))
for i, e := range es {
r[i] = NewPasswordTokenCreate(e).Elem()
}
return r
}
func (pt *PasswordTokenCreate) Elem() PasswordTokenCreate {
if pt == nil {
return PasswordTokenCreate{}
}
return *pt
}
func NewPasswordTokenList(e *ent.PasswordToken) *PasswordTokenList {
if e == nil {
return nil
}
var ret PasswordTokenList
ret.ID = e.ID
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewPasswordTokenLists(es []*ent.PasswordToken) []PasswordTokenList {
if len(es) == 0 {
return nil
}
r := make([]PasswordTokenList, len(es))
for i, e := range es {
r[i] = NewPasswordTokenList(e).Elem()
}
return r
}
func (pt *PasswordTokenList) Elem() PasswordTokenList {
if pt == nil {
return PasswordTokenList{}
}
return *pt
}
func NewPasswordTokenRead(e *ent.PasswordToken) *PasswordTokenRead {
if e == nil {
return nil
}
var ret PasswordTokenRead
ret.ID = e.ID
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewPasswordTokenReads(es []*ent.PasswordToken) []PasswordTokenRead {
if len(es) == 0 {
return nil
}
r := make([]PasswordTokenRead, len(es))
for i, e := range es {
r[i] = NewPasswordTokenRead(e).Elem()
}
return r
}
func (pt *PasswordTokenRead) Elem() PasswordTokenRead {
if pt == nil {
return PasswordTokenRead{}
}
return *pt
}
func NewPasswordTokenUpdate(e *ent.PasswordToken) *PasswordTokenUpdate {
if e == nil {
return nil
}
var ret PasswordTokenUpdate
ret.ID = e.ID
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewPasswordTokenUpdates(es []*ent.PasswordToken) []PasswordTokenUpdate {
if len(es) == 0 {
return nil
}
r := make([]PasswordTokenUpdate, len(es))
for i, e := range es {
r[i] = NewPasswordTokenUpdate(e).Elem()
}
return r
}
func (pt *PasswordTokenUpdate) Elem() PasswordTokenUpdate {
if pt == nil {
return PasswordTokenUpdate{}
}
return *pt
}
func NewPasswordTokenUserRead(e *ent.User) *PasswordTokenUserRead {
if e == nil {
return nil
}
var ret PasswordTokenUserRead
ret.ID = e.ID
ret.Name = e.Name
ret.Email = e.Email
ret.Verified = e.Verified
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewPasswordTokenUserReads(es []*ent.User) []PasswordTokenUserRead {
if len(es) == 0 {
return nil
}
r := make([]PasswordTokenUserRead, len(es))
for i, e := range es {
r[i] = NewPasswordTokenUserRead(e).Elem()
}
return r
}
func (u *PasswordTokenUserRead) Elem() PasswordTokenUserRead {
if u == nil {
return PasswordTokenUserRead{}
}
return *u
}
func NewUserCreate(e *ent.User) *UserCreate {
if e == nil {
return nil
}
var ret UserCreate
ret.ID = e.ID
ret.Name = e.Name
ret.Email = e.Email
ret.Verified = e.Verified
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewUserCreates(es []*ent.User) []UserCreate {
if len(es) == 0 {
return nil
}
r := make([]UserCreate, len(es))
for i, e := range es {
r[i] = NewUserCreate(e).Elem()
}
return r
}
func (u *UserCreate) Elem() UserCreate {
if u == nil {
return UserCreate{}
}
return *u
}
func NewUserList(e *ent.User) *UserList {
if e == nil {
return nil
}
var ret UserList
ret.ID = e.ID
ret.Name = e.Name
ret.Email = e.Email
ret.Verified = e.Verified
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewUserLists(es []*ent.User) []UserList {
if len(es) == 0 {
return nil
}
r := make([]UserList, len(es))
for i, e := range es {
r[i] = NewUserList(e).Elem()
}
return r
}
func (u *UserList) Elem() UserList {
if u == nil {
return UserList{}
}
return *u
}
func NewUserRead(e *ent.User) *UserRead {
if e == nil {
return nil
}
var ret UserRead
ret.ID = e.ID
ret.Name = e.Name
ret.Email = e.Email
ret.Verified = e.Verified
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewUserReads(es []*ent.User) []UserRead {
if len(es) == 0 {
return nil
}
r := make([]UserRead, len(es))
for i, e := range es {
r[i] = NewUserRead(e).Elem()
}
return r
}
func (u *UserRead) Elem() UserRead {
if u == nil {
return UserRead{}
}
return *u
}
func NewUserUpdate(e *ent.User) *UserUpdate {
if e == nil {
return nil
}
var ret UserUpdate
ret.ID = e.ID
ret.Name = e.Name
ret.Email = e.Email
ret.Verified = e.Verified
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewUserUpdates(es []*ent.User) []UserUpdate {
if len(es) == 0 {
return nil
}
r := make([]UserUpdate, len(es))
for i, e := range es {
r[i] = NewUserUpdate(e).Elem()
}
return r
}
func (u *UserUpdate) Elem() UserUpdate {
if u == nil {
return UserUpdate{}
}
return *u
}
func NewUserOwnerList(e *ent.PasswordToken) *UserOwnerList {
if e == nil {
return nil
}
var ret UserOwnerList
ret.ID = e.ID
ret.CreatedAt = e.CreatedAt
return &ret
}
func NewUserOwnerLists(es []*ent.PasswordToken) []UserOwnerList {
if len(es) == 0 {
return nil
}
r := make([]UserOwnerList, len(es))
for i, e := range es {
r[i] = NewUserOwnerList(e).Elem()
}
return r
}
func (pt *UserOwnerList) Elem() UserOwnerList {
if pt == nil {
return UserOwnerList{}
}
return *pt
}

View file

@ -1,16 +0,0 @@
package ogent
import (
"time"
)
type Datetime time.Time
func (d *Datetime) UnmarshalParam(param string) error {
t, err := time.Parse(`2006-01-02 15:04:05 MST`, param)
if err != nil {
return err
}
*d = Datetime(t)
return nil
}

File diff suppressed because it is too large Load diff

21
go.mod
View file

@ -5,8 +5,6 @@ go 1.24.0
require (
entgo.io/ent v0.14.3
github.com/PuerkitoBio/goquery v1.10.2
github.com/go-faster/errors v0.6.1
github.com/go-faster/jx v0.42.0-alpha.1
github.com/go-playground/validator/v10 v10.25.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/gorilla/context v1.1.2
@ -15,37 +13,24 @@ require (
github.com/mattn/go-sqlite3 v1.14.24
github.com/maypok86/otter v1.2.4
github.com/mikestefanello/backlite v0.3.0
github.com/ogen-go/ogen v0.59.0
github.com/spf13/afero v1.14.0
github.com/spf13/viper v1.20.0
github.com/stretchr/testify v1.10.0
go.opentelemetry.io/otel v1.13.0
go.opentelemetry.io/otel/metric v0.36.0
go.opentelemetry.io/otel/trace v1.13.0
go.uber.org/multierr v1.11.0
golang.org/x/crypto v0.36.0
maragu.dev/gomponents v1.1.0
)
require (
ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83 // indirect
ariga.io/ogent v0.0.0-20230621041143-ed3e5d4da458 // indirect
entgo.io/contrib v0.6.0 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dlclark/regexp2 v1.8.0 // indirect
github.com/dolthub/maphash v0.1.0 // indirect
github.com/fatih/color v1.14.1 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/gammazero/deque v0.2.1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-faster/yamlx v0.4.1 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/inflect v0.21.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
@ -63,7 +48,6 @@ require (
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
@ -72,9 +56,7 @@ require (
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
github.com/zclconf/go-cty-yaml v1.1.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/net v0.37.0 // indirect
golang.org/x/sync v0.12.0 // indirect
@ -83,6 +65,5 @@ require (
golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.30.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

47
go.sum
View file

@ -1,9 +1,5 @@
ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83 h1:nX4HXncwIdvQ8/8sIUIf1nyCkK8qdBaHQ7EtzPpuiGE=
ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w=
ariga.io/ogent v0.0.0-20230621041143-ed3e5d4da458 h1:FShFeMszKX8VcySiTRgshmj98jQWMv2GjQgMJcHJJi4=
ariga.io/ogent v0.0.0-20230621041143-ed3e5d4da458/go.mod h1:95vCbvAYAW6NsWUrSL23k2SQykuf/yjellmwV1X+svI=
entgo.io/contrib v0.6.0 h1:xfo4TbJE7sJZWx7BV7YrpSz7IPFvS8MzL3fnfzZjKvQ=
entgo.io/contrib v0.6.0/go.mod h1:3qWIseJ/9Wx2Hu5zVh15FDzv7d/UvKNcYKdViywWCQg=
entgo.io/ent v0.14.3 h1:wokAV/kIlH9TeklJWGGS7AYJdVckr0DloWjIcO9iIIQ=
entgo.io/ent v0.14.3/go.mod h1:aDPE/OziPEu8+OWbzy4UlvWmD2/kbRuWfK2A40hcxJM=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
@ -16,18 +12,12 @@ github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kk
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.8.0 h1:rJD5HeGIT/2b5CDk63FVCwZA3qgYElfg+oQK7uH5pfE=
github.com/dlclark/regexp2 v1.8.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ=
github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4=
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
@ -36,19 +26,6 @@ github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3G
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0=
github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI=
github.com/go-faster/errors v0.6.1/go.mod h1:5MGV2/2T9yvlrbhe9pD9LO5Z/2zCSq2T8j+Jpi2LAyY=
github.com/go-faster/jx v0.42.0-alpha.1 h1:KRu+ofEoozOsq2qpjwIp2R08vw9w2VqfbV4wtybQZ9U=
github.com/go-faster/jx v0.42.0-alpha.1/go.mod h1:fTSMeBYBKUmGFJaA6EkF658Rrco40FHenmq9fOBpYuM=
github.com/go-faster/yamlx v0.4.1 h1:00RQkZopoLDF1SgBDJVHuN6epTOK7T0TkN427vbvEBk=
github.com/go-faster/yamlx v0.4.1/go.mod h1:QXr/i3Z00jRhskgyWkoGsEdseebd/ZbZEpGS6DJv8oo=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk=
github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@ -105,20 +82,14 @@ github.com/mikestefanello/backlite v0.3.0 h1:C6hYoXoIJ7RyRfapZJdW95V3ao/g3tW8dWZ
github.com/mikestefanello/backlite v0.3.0/go.mod h1:oTT4WWGP2EDfgCfjA3PODuIz4YfA/QROEAh4o6+SlsI=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/ogen-go/ogen v0.59.0 h1:9aSSZ1KCLJIcRyjkO7IHrG0vAI6l1BO877LwTbMcX+k=
github.com/ogen-go/ogen v0.59.0/go.mod h1:0MHLcWEbxwdvR+R9E05paQSRh/2vHtVSJgKqmwYyW8M=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
@ -129,8 +100,6 @@ github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY=
github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
@ -146,20 +115,8 @@ github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY3
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0=
github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs=
go.opentelemetry.io/otel v1.13.0 h1:1ZAKnNQKwBBxFtww/GwxNUyTf0AxkZzrukO8MeXqe4Y=
go.opentelemetry.io/otel v1.13.0/go.mod h1:FH3RtdZCzRkJYFTCsAKDy9l/XYjMdNv6QrkFFB8DvVg=
go.opentelemetry.io/otel/metric v0.36.0 h1:t0lgGI+L68QWt3QtOIlqM9gXoxqxWLhZ3R/e5oOAY0Q=
go.opentelemetry.io/otel/metric v0.36.0/go.mod h1:wKVw57sd2HdSZAzyfOM9gTqqE8v7CbqWsYL6AyrH9qk=
go.opentelemetry.io/otel/trace v1.13.0 h1:CBgRZ6ntv+Amuj1jDsMhZtlAPT6gbyIRdaIzFhfBSdY=
go.opentelemetry.io/otel/trace v1.13.0/go.mod h1:muCvmmO9KKpvuXSf3KKAXXB2ygNYHQ+ZfI5X08d3tds=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
@ -168,8 +125,6 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg=
golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@ -246,8 +201,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maragu.dev/gomponents v1.1.0 h1:iCybZZChHr1eSlvkWp/JP3CrZGzctLudQ/JI3sBcO4U=

View file

@ -6,19 +6,16 @@ import (
"net/http"
"strconv"
"strings"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/entc/gen"
"entgo.io/ent/entc/load"
"github.com/labstack/echo/v4"
"github.com/mikestefanello/pagoda/ent"
"github.com/mikestefanello/pagoda/ent/ogent"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
"github.com/mikestefanello/pagoda/ent/admin"
"github.com/mikestefanello/pagoda/pkg/msg"
"github.com/mikestefanello/pagoda/pkg/pager"
"github.com/mikestefanello/pagoda/pkg/redirect"
"github.com/mikestefanello/pagoda/pkg/routenames"
"github.com/mikestefanello/pagoda/pkg/services"
"github.com/mikestefanello/pagoda/pkg/ui/pages"
)
@ -28,9 +25,10 @@ const entityContextKey = "admin:entity"
const entityIDContextKey = "admin:entity_id"
type Admin struct {
orm *ent.Client
graph *gen.Graph
ogent *ogent.OgentHandler
orm *ent.Client
graph *gen.Graph
admin *admin.Handler
itemsPerPage int
}
func init() {
@ -38,9 +36,10 @@ func init() {
}
func (h *Admin) Init(c *services.Container) error {
h.itemsPerPage = 25
h.graph = c.Graph
h.orm = c.ORM
h.ogent = ogent.NewOgentHandler(h.orm)
h.admin = admin.NewHandler(h.orm, h.itemsPerPage)
return nil
}
@ -48,21 +47,24 @@ func (h *Admin) Routes(g *echo.Group) {
// TODO admin user status middleware
entities := g.Group("/admin/content")
for _, p := range h.getEntityPlugins() {
pg := entities.Group(fmt.Sprintf("/%s", strings.ToLower(p.ID)))
pg.GET("", h.EntityList(p)).Name = p.RouteNameList()
pg.POST("", h.EntityList(p)).Name = p.RouteNameListSubmit()
pg.GET("/add", h.EntityAdd(p)).Name = p.RouteNameAdd()
pg.POST("/add", h.EntityAddSubmit(p)).Name = p.RouteNameAddSubmit()
pg.GET("/:id/edit", h.EntityEdit(p), h.entityPluginMiddleware(p)).Name = p.RouteNameEdit()
pg.POST("/:id/edit", h.EntityEditSubmit(p), h.entityPluginMiddleware(p)).Name = p.RouteNameEditSubmit()
pg.GET("/:id/delete", h.EntityDelete(p), h.entityPluginMiddleware(p)).Name = p.RouteNameDelete()
pg.POST("/:id/delete", h.EntityDeleteSubmit(p), h.entityPluginMiddleware(p)).Name = p.RouteNameDeleteSubmit()
// TODO: can we generate something we can loop instead?
for _, n := range h.graph.Nodes {
ng := entities.Group(fmt.Sprintf("/%s", strings.ToLower(n.Name)))
ng.GET("", h.EntityList(n)).Name = routenames.AdminEntityList(n.Name)
ng.POST("", h.EntityList(n)).Name = routenames.AdminEntityListSubmit(n.Name)
ng.GET("/add", h.EntityAdd(n)).Name = routenames.AdminEntityAdd(n.Name)
ng.POST("/add", h.EntityAddSubmit(n)).Name = routenames.AdminEntityAddSubmit(n.Name)
//ng.GET("/:id/edit", h.EntityEdit(n), h.entityPluginMiddleware(n.Name)).Name = RouteNameEdit(n.Name)
//ng.POST("/:id/edit", h.EntityEditSubmit(n), h.entityPluginMiddleware(n.Name)).Name = RouteNameEditSubmit(n.Name)
ng.GET("/:id/delete", h.EntityDelete(n), h.middlewareEntityLoad(n)).
Name = routenames.AdminEntityDelete(n.Name)
ng.POST("/:id/delete", h.EntityDeleteSubmit(n), h.middlewareEntityLoad(n)).
Name = routenames.AdminEntityDeleteSubmit(n.Name)
}
}
// TODO, maybe this can be used outside of admin stuff as well?
func (h *Admin) entityPluginMiddleware(plugin AdminEntityPlugin) echo.MiddlewareFunc {
func (h *Admin) middlewareEntityLoad(n *gen.Type) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(ctx echo.Context) error {
id, err := strconv.Atoi(ctx.Param("id"))
@ -70,11 +72,11 @@ func (h *Admin) entityPluginMiddleware(plugin AdminEntityPlugin) echo.Middleware
return echo.NewHTTPError(http.StatusBadRequest, "invalid entity ID")
}
entity, err := plugin.Load(ctx, h.orm, id)
err = h.admin.Get(ctx, n.Name, id)
switch {
case err == nil:
ctx.Set(entityIDContextKey, id)
ctx.Set(entityContextKey, entity)
//ctx.Set(entityContextKey, entity) // TODO
return next(ctx)
case errors.Is(err, new(ent.NotFoundError)):
return echo.NewHTTPError(http.StatusNotFound, "entity not found")
@ -85,228 +87,85 @@ func (h *Admin) entityPluginMiddleware(plugin AdminEntityPlugin) echo.Middleware
}
}
func (h *Admin) EntityList(p AdminEntityPlugin) echo.HandlerFunc {
func (h *Admin) EntityList(n *gen.Type) echo.HandlerFunc {
return func(ctx echo.Context) error {
var err error
pgr := pager.NewPager(ctx, 25)
params := pages.AdminEntityListParams{
Title: p.LabelPlural,
Headers: p.Heading,
EditRoute: p.RouteNameEdit(), // todo remove, pass in plugin
DeleteRoute: p.RouteNameDelete(), // todo remove, pass in plugin
Pager: pgr,
}
params.Rows, err = p.List(ctx, h.orm, pgr)
list, err := h.admin.List(ctx, n.Name)
if err != nil {
return fail(err, fmt.Sprintf("failed to query %s", p.ID))
return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
}
return pages.AdminEntityList(ctx, params)
return pages.AdminEntityList(ctx, pages.AdminEntityListParams{
EntityType: n,
EntityList: list,
Pager: pager.NewPager(ctx, h.itemsPerPage),
})
}
}
func (h *Admin) EntityAdd(p AdminEntityPlugin) echo.HandlerFunc {
func (h *Admin) EntityAdd(n *gen.Type) echo.HandlerFunc {
return func(ctx echo.Context) error {
var schema *load.Schema
for _, s := range h.graph.Schemas {
if s.Name == p.ID {
schema = s
}
}
return pages.AdminEntityAdd(ctx, schema)
return pages.AdminEntityAdd(ctx, h.getEntitySchema(n))
}
}
func (h *Admin) EntityAddSubmit(p AdminEntityPlugin) echo.HandlerFunc {
func (h *Admin) EntityAddSubmit(n *gen.Type) echo.HandlerFunc {
return func(ctx echo.Context) error {
var v ogent.CreatePasswordTokenReq // TODO type
err := ctx.Bind(&v)
if err != nil {
return fail(err, fmt.Sprintf("failed to bind create password token request body"))
}
res, err := h.ogent.CreatePasswordToken(ctx.Request().Context(), &v)
err := h.admin.Create(ctx, n.Name)
if err != nil {
msg.Danger(ctx, err.Error())
return h.EntityAdd(p)(ctx)
// TODO : hold state
return h.EntityAdd(n)(ctx)
}
fmt.Printf("%+v\n", res)
msg.Success(ctx, fmt.Sprintf("Successfully added %s.", strings.ToLower(p.Label)))
msg.Success(ctx, fmt.Sprintf("Successfully added %s.", n.Name))
return redirect.
New(ctx).
Route(p.RouteNameList()).
Route(routenames.AdminEntityList(n.Name)).
Go()
}
}
func (h *Admin) EntityEdit(p AdminEntityPlugin) echo.HandlerFunc {
//
//func (h *Admin) EntityEdit(p AdminEntityPlugin) echo.HandlerFunc {
// return func(ctx echo.Context) error {
// return nil
// }
//}
//
//func (h *Admin) EntityEditSubmit(p AdminEntityPlugin) echo.HandlerFunc {
// return func(ctx echo.Context) error {
// return nil
// }
//}
//
func (h *Admin) EntityDelete(n *gen.Type) echo.HandlerFunc {
return func(ctx echo.Context) error {
return nil
return pages.AdminEntityDelete(ctx, n.Name)
}
}
func (h *Admin) EntityEditSubmit(p AdminEntityPlugin) echo.HandlerFunc {
return func(ctx echo.Context) error {
return nil
}
}
func (h *Admin) EntityDelete(p AdminEntityPlugin) echo.HandlerFunc {
return func(ctx echo.Context) error {
return pages.AdminEntityDelete(ctx)
}
}
func (h *Admin) EntityDeleteSubmit(p AdminEntityPlugin) echo.HandlerFunc {
func (h *Admin) EntityDeleteSubmit(n *gen.Type) echo.HandlerFunc {
return func(ctx echo.Context) error {
id := ctx.Get(entityIDContextKey).(int)
if err := p.Delete(ctx, h.orm, id); err != nil {
return fail(err, fmt.Sprintf("failed to delete %s (ID: %d)", p.ID, id))
if err := h.admin.Delete(ctx, n.Name, id); err != nil {
return fail(err, fmt.Sprintf("failed to delete %s (ID: %d)", n.Name, id))
}
msg.Success(ctx, fmt.Sprintf("Successfully deleted %s.", strings.ToLower(p.Label)))
msg.Success(ctx, fmt.Sprintf("Successfully deleted %s ID %d.", n.Name, id))
return redirect.
New(ctx).
Route(p.RouteNameList()).
Route(routenames.AdminEntityList(n.Name)).
Go()
}
}
// TODO inject orm? move to separate package?
type AdminEntityPlugin struct {
ID string
Label string
LabelPlural string
Heading []string
List func(ctx echo.Context, orm *ent.Client, pgr pager.Pager) ([]pages.AdminEntityListRow, error)
Load func(ctx echo.Context, orm *ent.Client, id int) (any, error)
Delete func(ctx echo.Context, orm *ent.Client, id int) error
}
func (p *AdminEntityPlugin) RouteNameList() string {
return fmt.Sprintf("admin:%s_list", p.ID)
}
func (p *AdminEntityPlugin) RouteNameListSubmit() string {
return fmt.Sprintf("admin:%s_list.submit", p.ID)
}
func (p *AdminEntityPlugin) RouteNameAdd() string {
return fmt.Sprintf("admin:%s_add", p.ID)
}
func (p *AdminEntityPlugin) RouteNameEdit() string {
return fmt.Sprintf("admin:%s_edit", p.ID)
}
func (p *AdminEntityPlugin) RouteNameDelete() string {
return fmt.Sprintf("admin:%s_delete", p.ID)
}
func (p *AdminEntityPlugin) RouteNameAddSubmit() string {
return fmt.Sprintf("admin:%s_add.submit", p.ID)
}
func (p *AdminEntityPlugin) RouteNameEditSubmit() string {
return fmt.Sprintf("admin:%s_edit.submit", p.ID)
}
func (p *AdminEntityPlugin) RouteNameDeleteSubmit() string {
return fmt.Sprintf("admin:%s_delete.submit", p.ID)
}
func (h *Admin) getEntityPlugins() []AdminEntityPlugin {
return []AdminEntityPlugin{
{
ID: "User",
Label: "User",
LabelPlural: "Users",
Heading: []string{
"ID",
"Name",
"Email",
"Created at",
},
List: func(ctx echo.Context, client *ent.Client, pgr pager.Pager) ([]pages.AdminEntityListRow, error) {
users, err := client.User.
Query().
Limit(pgr.ItemsPerPage).
Offset(pgr.GetOffset()).
Order(user.ByCreatedAt(sql.OrderDesc())).
All(ctx.Request().Context())
if err != nil {
return nil, err
}
rows := make([]pages.AdminEntityListRow, 0, len(users))
for _, u := range users {
rows = append(rows, pages.AdminEntityListRow{
ID: u.ID,
Columns: []string{
fmt.Sprint(u.ID),
u.Name,
u.Email,
u.CreatedAt.Format(time.RFC822),
},
})
}
return rows, nil
},
Load: func(ctx echo.Context, orm *ent.Client, id int) (any, error) {
return orm.User.Get(ctx.Request().Context(), id)
},
Delete: func(ctx echo.Context, orm *ent.Client, id int) error {
return orm.User.DeleteOneID(id).Exec(ctx.Request().Context())
},
},
{
ID: "PasswordToken",
Label: "Password token",
LabelPlural: "Password tokens",
Heading: []string{
"ID",
"Hash",
"Created at",
},
List: func(ctx echo.Context, client *ent.Client, pgr pager.Pager) ([]pages.AdminEntityListRow, error) {
tokens, err := client.PasswordToken.
Query().
Limit(pgr.ItemsPerPage).
Offset(pgr.GetOffset()).
Order(passwordtoken.ByCreatedAt(sql.OrderDesc())).
All(ctx.Request().Context())
if err != nil {
return nil, err
}
rows := make([]pages.AdminEntityListRow, 0, len(tokens))
for _, t := range tokens {
rows = append(rows, pages.AdminEntityListRow{
ID: t.ID,
Columns: []string{
fmt.Sprint(t.ID),
t.Hash,
t.CreatedAt.Format(time.RFC822),
},
})
}
return rows, nil
},
Load: func(ctx echo.Context, orm *ent.Client, id int) (any, error) {
return orm.PasswordToken.Get(ctx.Request().Context(), id)
},
Delete: func(ctx echo.Context, orm *ent.Client, id int) error {
return orm.PasswordToken.DeleteOneID(id).Exec(ctx.Request().Context())
},
},
func (h *Admin) getEntitySchema(n *gen.Type) *load.Schema {
for _, s := range h.graph.Schemas {
if s.Name == n.Name {
return s
}
}
return nil
}

View file

@ -1,5 +1,9 @@
package routenames
import (
"fmt"
)
const (
Home = "home"
About = "about"
@ -23,3 +27,35 @@ const (
Files = "files"
FilesSubmit = "files.submit"
)
func AdminEntityList(entityTypeName string) string {
return fmt.Sprintf("admin:%s_list", entityTypeName)
}
func AdminEntityListSubmit(entityTypeName string) string {
return fmt.Sprintf("admin:%s_list.submit", entityTypeName)
}
func AdminEntityAdd(entityTypeName string) string {
return fmt.Sprintf("admin:%s_add", entityTypeName)
}
func AdminEntityEdit(entityTypeName string) string {
return fmt.Sprintf("admin:%s_edit", entityTypeName)
}
func AdminEntityDelete(entityTypeName string) string {
return fmt.Sprintf("admin:%s_delete", entityTypeName)
}
func AdminEntityAddSubmit(entityTypeName string) string {
return fmt.Sprintf("admin:%s_add.submit", entityTypeName)
}
func AdminEntityEditSubmit(entityTypeName string) string {
return fmt.Sprintf("admin:%s_edit.submit", entityTypeName)
}
func AdminEntityDeleteSubmit(entityTypeName string) string {
return fmt.Sprintf("admin:%s_delete.submit", entityTypeName)
}

View file

@ -51,8 +51,8 @@ func adminMenu(r *ui.Request) Node {
),
Ul(
Class("menu-list"),
MenuLink(r, "Users", "admin:user_list"),
MenuLink(r, "Tokens", "admin:passwordtoken_list"),
MenuLink(r, "User", routenames.AdminEntityList("User")),
MenuLink(r, "PasswordToken", routenames.AdminEntityList("PasswordToken")),
),
P(
Class("menu-label"),

View file

@ -7,10 +7,13 @@ import (
"time"
"unicode"
"entgo.io/ent/entc/gen"
"entgo.io/ent/entc/load"
"entgo.io/ent/schema/field"
"github.com/labstack/echo/v4"
"github.com/mikestefanello/pagoda/ent/admin"
"github.com/mikestefanello/pagoda/pkg/pager"
"github.com/mikestefanello/pagoda/pkg/routenames"
"github.com/mikestefanello/pagoda/pkg/ui"
. "github.com/mikestefanello/pagoda/pkg/ui/components"
"github.com/mikestefanello/pagoda/pkg/ui/layouts"
@ -22,14 +25,14 @@ func Entity(ctx echo.Context) error {
return ui.NewRequest(ctx).Render(layouts.Admin, Div(Text("abc")))
}
func AdminEntityDelete(ctx echo.Context) error {
func AdminEntityDelete(ctx echo.Context, entityTypeName string) error {
r := ui.NewRequest(ctx)
form := Form(
Method(http.MethodPost),
H2(Text("Are you sure you want to delete this entity?")),
H2(Textf("Are you sure you want to delete this %s?", entityTypeName)),
ControlGroup(
FormButton("is-link", "Delete"),
ButtonLink("/", "is-secondary", "Cancel"),
ButtonLink(r.Path(routenames.AdminEntityList(entityTypeName)), "is-secondary", "Cancel"),
),
CSRF(r),
)
@ -39,7 +42,7 @@ func AdminEntityDelete(ctx echo.Context) error {
func AdminEntityAdd(ctx echo.Context, schema *load.Schema) error {
r := ui.NewRequest(ctx)
r.Title = fmt.Sprintf("Add %s", "entity") // TODO
r.Title = fmt.Sprintf("Add %s", schema.Name) // TODO
nodes := make(Group, 0)
@ -88,7 +91,7 @@ func AdminEntityAdd(ctx echo.Context, schema *load.Schema) error {
nodes = append(nodes, ControlGroup(
FormButton("is-primary", "Submit"),
ButtonLink("/", "is-secondary", "Cancel"), // todo
ButtonLink(r.Path(routenames.AdminEntityList(schema.Name)), "is-secondary", "Cancel"),
), CSRF(r))
return r.Render(layouts.Admin, Form(
@ -98,12 +101,9 @@ func AdminEntityAdd(ctx echo.Context, schema *load.Schema) error {
}
type AdminEntityListParams struct {
Title string
Headers []string
Rows []AdminEntityListRow
EditRoute string
DeleteRoute string
Pager pager.Pager
EntityType *gen.Type
EntityList *admin.EntityList
Pager pager.Pager
}
type AdminEntityListRow struct {
@ -113,37 +113,40 @@ type AdminEntityListRow struct {
func AdminEntityList(ctx echo.Context, params AdminEntityListParams) error {
r := ui.NewRequest(ctx)
r.Title = params.Title
r.Title = params.EntityType.Name
genHeader := func() Node {
g := make(Group, 0, len(params.Headers)+2)
for _, h := range params.Headers {
g := make(Group, 0, len(params.EntityList.Columns)+3)
g = append(g, Th(Text("ID")))
for _, h := range params.EntityList.Columns {
g = append(g, Th(Text(h)))
}
g = append(g, Th(), Th())
return g
}
genRow := func(row AdminEntityListRow) Node {
g := make(Group, 0, len(row.Columns)+2)
for _, h := range row.Columns {
genRow := func(row admin.EntityValues) Node {
g := make(Group, 0, len(row.Values)+3)
g = append(g, Th(Text(fmt.Sprint(row.ID))))
for _, h := range row.Values {
g = append(g, Td(Text(h)))
}
g = append(g,
Td(A(Href(r.Path(params.EditRoute, row.ID)), Text("Edit"))),
Td(A(Href(r.Path(params.DeleteRoute, row.ID)), Text("Delete"))),
Td(A(Href(r.Path(routenames.AdminEntityEdit(params.EntityType.Name), row.ID)), Text("Edit"))),
Td(A(Href(r.Path(routenames.AdminEntityDelete(params.EntityType.Name), row.ID)), Text("Delete"))),
)
return g
}
genRows := func() Node {
g := make(Group, 0, len(params.Rows))
for _, row := range params.Rows {
g := make(Group, 0, len(params.EntityList.Entities))
for _, row := range params.EntityList.Entities {
g = append(g, Tr(genRow(row)))
}
return g
}
// TODO pager
return r.Render(layouts.Admin, Table(
Class("table"),
THead(