Lint check adjustments.
This commit is contained in:
parent
944a4d941a
commit
51e44a57a1
14
README.md
14
README.md
@ -401,19 +401,19 @@ These patterns are not required, but were designed to make development as easy a
|
|||||||
To declare a new route that will have methods to handle a GET and POST request, for example, start with a new _struct_ type, that embeds the `Controller`:
|
To declare a new route that will have methods to handle a GET and POST request, for example, start with a new _struct_ type, that embeds the `Controller`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Home struct {
|
type home struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Home) Get(ctx echo.Context) error {}
|
func (c *home) Get(ctx echo.Context) error {}
|
||||||
|
|
||||||
func (c *Home) Post(ctx echo.Context) error {}
|
func (c *home) Post(ctx echo.Context) error {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then create the route and add to the router:
|
Then create the route and add to the router:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
home := Home{Controller: controller.NewController(c)}
|
home := home{Controller: controller.NewController(c)}
|
||||||
g.GET("/", home.Get).Name = "home"
|
g.GET("/", home.Get).Name = "home"
|
||||||
g.POST("/", home.Post).Name = "home.post"
|
g.POST("/", home.Post).Name = "home.post"
|
||||||
```
|
```
|
||||||
@ -485,7 +485,7 @@ As you develop your application, the `Page` can be easily extended to include wh
|
|||||||
Initializing a new page is simple:
|
Initializing a new page is simple:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Home) Get(ctx echo.Context) error {
|
func (c *home) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -814,7 +814,7 @@ If [CSRF](#csrf) protection is enabled, the token value will automatically be pa
|
|||||||
Once your `Page` is fully built, rendering it via the embedded `Controller` in your _route_ can be done simply by calling `RenderPage()`:
|
Once your `Page` is fully built, rendering it via the embedded `Controller` in your _route_ can be done simply by calling `RenderPage()`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Home) Get(ctx echo.Context) error {
|
func (c *home) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "main"
|
page.Layout = "main"
|
||||||
page.Name = "home"
|
page.Name = "home"
|
||||||
@ -1191,7 +1191,7 @@ To use _Let's Encrypt_ follow [this guide](https://echo.labstack.com/cookbook/au
|
|||||||
Logging is provided by [Echo](https://echo.labstack.com/guide/customization/#logging) and is accessible within the _Echo_ instance, which is located in the `Web` field of the `Container`, or within any of the _context_ parameters, for example:
|
Logging is provided by [Echo](https://echo.labstack.com/guide/customization/#logging) and is accessible within the _Echo_ instance, which is located in the `Web` field of the `Container`, or within any of the _context_ parameters, for example:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func (c *Home) Get(ctx echo.Context) error {
|
func (c *home) Get(ctx echo.Context) error {
|
||||||
ctx.Logger().Info("something happened")
|
ctx.Logger().Info("something happened")
|
||||||
|
|
||||||
if err := someOperation(); err != nil {
|
if err := someOperation(); err != nil {
|
||||||
|
@ -21,21 +21,32 @@ const (
|
|||||||
StaticPrefix = "files"
|
StaticPrefix = "files"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Environment string
|
type environment string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EnvLocal Environment = "local"
|
// EnvLocal represents the local environment
|
||||||
EnvTest Environment = "test"
|
EnvLocal environment = "local"
|
||||||
EnvDevelop Environment = "dev"
|
|
||||||
EnvStaging Environment = "staging"
|
// EnvTest represents the test environment
|
||||||
EnvQA Environment = "qa"
|
EnvTest environment = "test"
|
||||||
EnvProduction Environment = "prod"
|
|
||||||
|
// EnvDevelop represents the development environment
|
||||||
|
EnvDevelop environment = "dev"
|
||||||
|
|
||||||
|
// EnvStaging represents the staging environment
|
||||||
|
EnvStaging environment = "staging"
|
||||||
|
|
||||||
|
// EnvQA represents the qa environment
|
||||||
|
EnvQA environment = "qa"
|
||||||
|
|
||||||
|
// EnvProduction represents the production environment
|
||||||
|
EnvProduction environment = "prod"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SwitchEnvironment sets the environment variable used to dictate which environment the application is
|
// SwitchEnvironment sets the environment variable used to dictate which environment the application is
|
||||||
// currently running in.
|
// currently running in.
|
||||||
// This must be called prior to loading the configuration in order for it to take effect.
|
// This must be called prior to loading the configuration in order for it to take effect.
|
||||||
func SwitchEnvironment(env Environment) {
|
func SwitchEnvironment(env environment) {
|
||||||
if err := os.Setenv("APP_ENVIRONMENT", string(env)); err != nil {
|
if err := os.Setenv("APP_ENVIRONMENT", string(env)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -68,7 +79,7 @@ type (
|
|||||||
// AppConfig stores application configuration
|
// AppConfig stores application configuration
|
||||||
AppConfig struct {
|
AppConfig struct {
|
||||||
Name string `env:"APP_NAME,default=Pagoda"`
|
Name string `env:"APP_NAME,default=Pagoda"`
|
||||||
Environment Environment `env:"APP_ENVIRONMENT,default=local"`
|
Environment environment `env:"APP_ENVIRONMENT,default=local"`
|
||||||
// THIS MUST BE OVERRIDDEN ON ANY LIVE ENVIRONMENTS
|
// THIS MUST BE OVERRIDDEN ON ANY LIVE ENVIRONMENTS
|
||||||
EncryptionKey string `env:"APP_ENCRYPTION_KEY,default=?E(G+KbPeShVmYq3t6w9z$C&F)J@McQf"`
|
EncryptionKey string `env:"APP_ENCRYPTION_KEY,default=?E(G+KbPeShVmYq3t6w9z$C&F)J@McQf"`
|
||||||
Timeout time.Duration `env:"APP_TIMEOUT,default=20s"`
|
Timeout time.Duration `env:"APP_TIMEOUT,default=20s"`
|
||||||
|
@ -11,7 +11,7 @@ func TestGetConfig(t *testing.T) {
|
|||||||
_, err := GetConfig()
|
_, err := GetConfig()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var env Environment
|
var env environment
|
||||||
env = "abc"
|
env = "abc"
|
||||||
SwitchEnvironment(env)
|
SwitchEnvironment(env)
|
||||||
cfg, err := GetConfig()
|
cfg, err := GetConfig()
|
||||||
|
12
msg/msg.go
12
msg/msg.go
@ -6,13 +6,21 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Type is a message type
|
||||||
type Type string
|
type Type string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// TypeSuccess represents a success message type
|
||||||
TypeSuccess Type = "success"
|
TypeSuccess Type = "success"
|
||||||
TypeInfo Type = "info"
|
|
||||||
|
// TypeInfo represents a info message type
|
||||||
|
TypeInfo Type = "info"
|
||||||
|
|
||||||
|
// TypeWarning represents a warning message type
|
||||||
TypeWarning Type = "warning"
|
TypeWarning Type = "warning"
|
||||||
TypeDanger Type = "danger"
|
|
||||||
|
// TypeDanger represents a danger message type
|
||||||
|
TypeDanger Type = "danger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -9,23 +9,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
About struct {
|
about struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
AboutData struct {
|
aboutData struct {
|
||||||
ShowCacheWarning bool
|
ShowCacheWarning bool
|
||||||
FrontendTabs []AboutTab
|
FrontendTabs []aboutTab
|
||||||
BackendTabs []AboutTab
|
BackendTabs []aboutTab
|
||||||
}
|
}
|
||||||
|
|
||||||
AboutTab struct {
|
aboutTab struct {
|
||||||
Title string
|
Title string
|
||||||
Body template.HTML
|
Body template.HTML
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *About) Get(ctx echo.Context) error {
|
func (c *about) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "main"
|
page.Layout = "main"
|
||||||
page.Name = "about"
|
page.Name = "about"
|
||||||
@ -37,9 +37,9 @@ func (c *About) Get(ctx echo.Context) error {
|
|||||||
|
|
||||||
// A simple example of how the Data field can contain anything you want to send to the templates
|
// A simple example of how the Data field can contain anything you want to send to the templates
|
||||||
// even though you wouldn't normally send markup like this
|
// even though you wouldn't normally send markup like this
|
||||||
page.Data = AboutData{
|
page.Data = aboutData{
|
||||||
ShowCacheWarning: true,
|
ShowCacheWarning: true,
|
||||||
FrontendTabs: []AboutTab{
|
FrontendTabs: []aboutTab{
|
||||||
{
|
{
|
||||||
Title: "HTMX",
|
Title: "HTMX",
|
||||||
Body: template.HTML(`Completes HTML as a hypertext by providing attributes to AJAXify anything and much more. Visit <a href="https://htmx.org/">htmx.org</a> to learn more.`),
|
Body: template.HTML(`Completes HTML as a hypertext by providing attributes to AJAXify anything and much more. Visit <a href="https://htmx.org/">htmx.org</a> to learn more.`),
|
||||||
@ -53,7 +53,7 @@ func (c *About) Get(ctx echo.Context) error {
|
|||||||
Body: template.HTML(`Ready-to-use frontend components that you can easily combine to build responsive web interfaces with no JavaScript requirements. Visit <a href="https://bulma.io/">bulma.io</a> to learn more.`),
|
Body: template.HTML(`Ready-to-use frontend components that you can easily combine to build responsive web interfaces with no JavaScript requirements. Visit <a href="https://bulma.io/">bulma.io</a> to learn more.`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
BackendTabs: []AboutTab{
|
BackendTabs: []aboutTab{
|
||||||
{
|
{
|
||||||
Title: "Echo",
|
Title: "Echo",
|
||||||
Body: template.HTML(`High performance, extensible, minimalist Go web framework. Visit <a href="https://echo.labstack.com/">echo.labstack.com</a> to learn more.`),
|
Body: template.HTML(`High performance, extensible, minimalist Go web framework. Visit <a href="https://echo.labstack.com/">echo.labstack.com</a> to learn more.`),
|
||||||
|
@ -10,33 +10,33 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Contact struct {
|
contact struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactForm struct {
|
contactForm struct {
|
||||||
Email string `form:"email" validate:"required,email"`
|
Email string `form:"email" validate:"required,email"`
|
||||||
Message string `form:"message" validate:"required"`
|
Message string `form:"message" validate:"required"`
|
||||||
Submission controller.FormSubmission
|
Submission controller.FormSubmission
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Contact) Get(ctx echo.Context) error {
|
func (c *contact) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "main"
|
page.Layout = "main"
|
||||||
page.Name = "contact"
|
page.Name = "contact"
|
||||||
page.Title = "Contact us"
|
page.Title = "Contact us"
|
||||||
page.Form = ContactForm{}
|
page.Form = contactForm{}
|
||||||
|
|
||||||
if form := ctx.Get(context.FormKey); form != nil {
|
if form := ctx.Get(context.FormKey); form != nil {
|
||||||
page.Form = form.(*ContactForm)
|
page.Form = form.(*contactForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.RenderPage(ctx, page)
|
return c.RenderPage(ctx, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Contact) Post(ctx echo.Context) error {
|
func (c *contact) Post(ctx echo.Context) error {
|
||||||
var form ContactForm
|
var form contactForm
|
||||||
ctx.Set(context.FormKey, &form)
|
ctx.Set(context.FormKey, &form)
|
||||||
|
|
||||||
// Parse the form values
|
// Parse the form values
|
||||||
|
@ -9,11 +9,11 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Error struct {
|
type errorHandler struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Error) Get(err error, ctx echo.Context) {
|
func (e *errorHandler) Get(err error, ctx echo.Context) {
|
||||||
if ctx.Response().Committed || context.IsCanceledError(err) {
|
if ctx.Response().Committed || context.IsCanceledError(err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -14,32 +14,32 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ForgotPassword struct {
|
forgotPassword struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
ForgotPasswordForm struct {
|
forgotPasswordForm struct {
|
||||||
Email string `form:"email" validate:"required,email"`
|
Email string `form:"email" validate:"required,email"`
|
||||||
Submission controller.FormSubmission
|
Submission controller.FormSubmission
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ForgotPassword) Get(ctx echo.Context) error {
|
func (c *forgotPassword) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "auth"
|
page.Layout = "auth"
|
||||||
page.Name = "forgot-password"
|
page.Name = "forgot-password"
|
||||||
page.Title = "Forgot password"
|
page.Title = "Forgot password"
|
||||||
page.Form = ForgotPasswordForm{}
|
page.Form = forgotPasswordForm{}
|
||||||
|
|
||||||
if form := ctx.Get(context.FormKey); form != nil {
|
if form := ctx.Get(context.FormKey); form != nil {
|
||||||
page.Form = form.(*ForgotPasswordForm)
|
page.Form = form.(*forgotPasswordForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.RenderPage(ctx, page)
|
return c.RenderPage(ctx, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ForgotPassword) Post(ctx echo.Context) error {
|
func (c *forgotPassword) Post(ctx echo.Context) error {
|
||||||
var form ForgotPasswordForm
|
var form forgotPasswordForm
|
||||||
ctx.Set(context.FormKey, &form)
|
ctx.Set(context.FormKey, &form)
|
||||||
|
|
||||||
succeed := func() error {
|
succeed := func() error {
|
||||||
|
@ -9,17 +9,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Home struct {
|
home struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
Post struct {
|
post struct {
|
||||||
Title string
|
Title string
|
||||||
Body string
|
Body string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Home) Get(ctx echo.Context) error {
|
func (c *home) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "main"
|
page.Layout = "main"
|
||||||
page.Name = "home"
|
page.Name = "home"
|
||||||
@ -32,12 +32,12 @@ func (c *Home) Get(ctx echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fetchPosts is an mock example of fetching posts to illustrate how paging works
|
// fetchPosts is an mock example of fetching posts to illustrate how paging works
|
||||||
func (c *Home) fetchPosts(pager *controller.Pager) []Post {
|
func (c *home) fetchPosts(pager *controller.Pager) []post {
|
||||||
pager.SetItems(20)
|
pager.SetItems(20)
|
||||||
posts := make([]Post, 20)
|
posts := make([]post, 20)
|
||||||
|
|
||||||
for k := range posts {
|
for k := range posts {
|
||||||
posts[k] = Post{
|
posts[k] = post{
|
||||||
Title: fmt.Sprintf("Post example #%d", k+1),
|
Title: fmt.Sprintf("Post example #%d", k+1),
|
||||||
Body: fmt.Sprintf("Lorem ipsum example #%d ddolor sit amet, consectetur adipiscing elit. Nam elementum vulputate tristique.", k+1),
|
Body: fmt.Sprintf("Lorem ipsum example #%d ddolor sit amet, consectetur adipiscing elit. Nam elementum vulputate tristique.", k+1),
|
||||||
}
|
}
|
||||||
|
@ -14,33 +14,33 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Login struct {
|
login struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
LoginForm struct {
|
loginForm struct {
|
||||||
Email string `form:"email" validate:"required,email"`
|
Email string `form:"email" validate:"required,email"`
|
||||||
Password string `form:"password" validate:"required"`
|
Password string `form:"password" validate:"required"`
|
||||||
Submission controller.FormSubmission
|
Submission controller.FormSubmission
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Login) Get(ctx echo.Context) error {
|
func (c *login) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "auth"
|
page.Layout = "auth"
|
||||||
page.Name = "login"
|
page.Name = "login"
|
||||||
page.Title = "Log in"
|
page.Title = "Log in"
|
||||||
page.Form = LoginForm{}
|
page.Form = loginForm{}
|
||||||
|
|
||||||
if form := ctx.Get(context.FormKey); form != nil {
|
if form := ctx.Get(context.FormKey); form != nil {
|
||||||
page.Form = form.(*LoginForm)
|
page.Form = form.(*loginForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.RenderPage(ctx, page)
|
return c.RenderPage(ctx, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Login) Post(ctx echo.Context) error {
|
func (c *login) Post(ctx echo.Context) error {
|
||||||
var form LoginForm
|
var form loginForm
|
||||||
ctx.Set(context.FormKey, &form)
|
ctx.Set(context.FormKey, &form)
|
||||||
|
|
||||||
authFailed := func() error {
|
authFailed := func() error {
|
||||||
|
@ -7,11 +7,11 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Logout struct {
|
type logout struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logout) Get(c echo.Context) error {
|
func (l *logout) Get(c echo.Context) error {
|
||||||
if err := l.Container.Auth.Logout(c); err == nil {
|
if err := l.Container.Auth.Logout(c); err == nil {
|
||||||
msg.Success(c, "You have been logged out successfully.")
|
msg.Success(c, "You have been logged out successfully.")
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,11 +12,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Register struct {
|
register struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterForm struct {
|
registerForm struct {
|
||||||
Name string `form:"name" validate:"required"`
|
Name string `form:"name" validate:"required"`
|
||||||
Email string `form:"email" validate:"required,email"`
|
Email string `form:"email" validate:"required,email"`
|
||||||
Password string `form:"password" validate:"required"`
|
Password string `form:"password" validate:"required"`
|
||||||
@ -25,22 +25,22 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Register) Get(ctx echo.Context) error {
|
func (c *register) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "auth"
|
page.Layout = "auth"
|
||||||
page.Name = "register"
|
page.Name = "register"
|
||||||
page.Title = "Register"
|
page.Title = "Register"
|
||||||
page.Form = RegisterForm{}
|
page.Form = registerForm{}
|
||||||
|
|
||||||
if form := ctx.Get(context.FormKey); form != nil {
|
if form := ctx.Get(context.FormKey); form != nil {
|
||||||
page.Form = form.(*RegisterForm)
|
page.Form = form.(*registerForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.RenderPage(ctx, page)
|
return c.RenderPage(ctx, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Register) Post(ctx echo.Context) error {
|
func (c *register) Post(ctx echo.Context) error {
|
||||||
var form RegisterForm
|
var form registerForm
|
||||||
ctx.Set(context.FormKey, &form)
|
ctx.Set(context.FormKey, &form)
|
||||||
|
|
||||||
// Parse the form values
|
// Parse the form values
|
||||||
@ -96,7 +96,7 @@ func (c *Register) Post(ctx echo.Context) error {
|
|||||||
return c.Redirect(ctx, "home")
|
return c.Redirect(ctx, "home")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Register) sendVerificationEmail(ctx echo.Context, usr *ent.User) {
|
func (c *register) sendVerificationEmail(ctx echo.Context, usr *ent.User) {
|
||||||
// Generate a token
|
// Generate a token
|
||||||
token, err := c.Container.Auth.GenerateEmailVerificationToken(usr.Email)
|
token, err := c.Container.Auth.GenerateEmailVerificationToken(usr.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,33 +10,33 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ResetPassword struct {
|
resetPassword struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetPasswordForm struct {
|
resetPasswordForm struct {
|
||||||
Password string `form:"password" validate:"required"`
|
Password string `form:"password" validate:"required"`
|
||||||
ConfirmPassword string `form:"password-confirm" validate:"required,eqfield=Password"`
|
ConfirmPassword string `form:"password-confirm" validate:"required,eqfield=Password"`
|
||||||
Submission controller.FormSubmission
|
Submission controller.FormSubmission
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ResetPassword) Get(ctx echo.Context) error {
|
func (c *resetPassword) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "auth"
|
page.Layout = "auth"
|
||||||
page.Name = "reset-password"
|
page.Name = "reset-password"
|
||||||
page.Title = "Reset password"
|
page.Title = "Reset password"
|
||||||
page.Form = ResetPasswordForm{}
|
page.Form = resetPasswordForm{}
|
||||||
|
|
||||||
if form := ctx.Get(context.FormKey); form != nil {
|
if form := ctx.Get(context.FormKey); form != nil {
|
||||||
page.Form = form.(*ResetPasswordForm)
|
page.Form = form.(*resetPasswordForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.RenderPage(ctx, page)
|
return c.RenderPage(ctx, page)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ResetPassword) Post(ctx echo.Context) error {
|
func (c *resetPassword) Post(ctx echo.Context) error {
|
||||||
var form ResetPasswordForm
|
var form resetPasswordForm
|
||||||
ctx.Set(context.FormKey, &form)
|
ctx.Set(context.FormKey, &form)
|
||||||
|
|
||||||
// Parse the form values
|
// Parse the form values
|
||||||
|
@ -56,7 +56,7 @@ func BuildRouter(c *services.Container) {
|
|||||||
ctr := controller.NewController(c)
|
ctr := controller.NewController(c)
|
||||||
|
|
||||||
// Error handler
|
// Error handler
|
||||||
err := Error{Controller: ctr}
|
err := errorHandler{Controller: ctr}
|
||||||
c.Web.HTTPErrorHandler = err.Get
|
c.Web.HTTPErrorHandler = err.Get
|
||||||
|
|
||||||
// Example routes
|
// Example routes
|
||||||
@ -65,37 +65,37 @@ func BuildRouter(c *services.Container) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func navRoutes(c *services.Container, g *echo.Group, ctr controller.Controller) {
|
func navRoutes(c *services.Container, g *echo.Group, ctr controller.Controller) {
|
||||||
home := Home{Controller: ctr}
|
home := home{Controller: ctr}
|
||||||
g.GET("/", home.Get).Name = "home"
|
g.GET("/", home.Get).Name = "home"
|
||||||
|
|
||||||
search := Search{Controller: ctr}
|
search := search{Controller: ctr}
|
||||||
g.GET("/search", search.Get).Name = "search"
|
g.GET("/search", search.Get).Name = "search"
|
||||||
|
|
||||||
about := About{Controller: ctr}
|
about := about{Controller: ctr}
|
||||||
g.GET("/about", about.Get).Name = "about"
|
g.GET("/about", about.Get).Name = "about"
|
||||||
|
|
||||||
contact := Contact{Controller: ctr}
|
contact := contact{Controller: ctr}
|
||||||
g.GET("/contact", contact.Get).Name = "contact"
|
g.GET("/contact", contact.Get).Name = "contact"
|
||||||
g.POST("/contact", contact.Post).Name = "contact.post"
|
g.POST("/contact", contact.Post).Name = "contact.post"
|
||||||
}
|
}
|
||||||
|
|
||||||
func userRoutes(c *services.Container, g *echo.Group, ctr controller.Controller) {
|
func userRoutes(c *services.Container, g *echo.Group, ctr controller.Controller) {
|
||||||
logout := Logout{Controller: ctr}
|
logout := logout{Controller: ctr}
|
||||||
g.GET("/logout", logout.Get, middleware.RequireAuthentication()).Name = "logout"
|
g.GET("/logout", logout.Get, middleware.RequireAuthentication()).Name = "logout"
|
||||||
|
|
||||||
verifyEmail := VerifyEmail{Controller: ctr}
|
verifyEmail := verifyEmail{Controller: ctr}
|
||||||
g.GET("/email/verify/:token", verifyEmail.Get).Name = "verify_email"
|
g.GET("/email/verify/:token", verifyEmail.Get).Name = "verify_email"
|
||||||
|
|
||||||
noAuth := g.Group("/user", middleware.RequireNoAuthentication())
|
noAuth := g.Group("/user", middleware.RequireNoAuthentication())
|
||||||
login := Login{Controller: ctr}
|
login := login{Controller: ctr}
|
||||||
noAuth.GET("/login", login.Get).Name = "login"
|
noAuth.GET("/login", login.Get).Name = "login"
|
||||||
noAuth.POST("/login", login.Post).Name = "login.post"
|
noAuth.POST("/login", login.Post).Name = "login.post"
|
||||||
|
|
||||||
register := Register{Controller: ctr}
|
register := register{Controller: ctr}
|
||||||
noAuth.GET("/register", register.Get).Name = "register"
|
noAuth.GET("/register", register.Get).Name = "register"
|
||||||
noAuth.POST("/register", register.Post).Name = "register.post"
|
noAuth.POST("/register", register.Post).Name = "register.post"
|
||||||
|
|
||||||
forgot := ForgotPassword{Controller: ctr}
|
forgot := forgotPassword{Controller: ctr}
|
||||||
noAuth.GET("/password", forgot.Get).Name = "forgot_password"
|
noAuth.GET("/password", forgot.Get).Name = "forgot_password"
|
||||||
noAuth.POST("/password", forgot.Post).Name = "forgot_password.post"
|
noAuth.POST("/password", forgot.Post).Name = "forgot_password.post"
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ func userRoutes(c *services.Container, g *echo.Group, ctr controller.Controller)
|
|||||||
middleware.LoadUser(c.ORM),
|
middleware.LoadUser(c.ORM),
|
||||||
middleware.LoadValidPasswordToken(c.Auth),
|
middleware.LoadValidPasswordToken(c.Auth),
|
||||||
)
|
)
|
||||||
reset := ResetPassword{Controller: ctr}
|
reset := resetPassword{Controller: ctr}
|
||||||
resetGroup.GET("/token/:user/:password_token/:token", reset.Get).Name = "reset_password"
|
resetGroup.GET("/token/:user/:password_token/:token", reset.Get).Name = "reset_password"
|
||||||
resetGroup.POST("/token/:user/:password_token/:token", reset.Post).Name = "reset_password.post"
|
resetGroup.POST("/token/:user/:password_token/:token", reset.Post).Name = "reset_password.post"
|
||||||
}
|
}
|
||||||
|
@ -10,29 +10,29 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Search struct {
|
search struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchResult struct {
|
searchResult struct {
|
||||||
Title string
|
Title string
|
||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Search) Get(ctx echo.Context) error {
|
func (c *search) Get(ctx echo.Context) error {
|
||||||
page := controller.NewPage(ctx)
|
page := controller.NewPage(ctx)
|
||||||
page.Layout = "main"
|
page.Layout = "main"
|
||||||
page.Name = "search"
|
page.Name = "search"
|
||||||
|
|
||||||
// Fake search results
|
// Fake search results
|
||||||
var results []SearchResult
|
var results []searchResult
|
||||||
if search := ctx.QueryParam("query"); search != "" {
|
if search := ctx.QueryParam("query"); search != "" {
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
title := "Lorem ipsum example ddolor sit amet"
|
title := "Lorem ipsum example ddolor sit amet"
|
||||||
index := rand.Intn(len(title))
|
index := rand.Intn(len(title))
|
||||||
title = title[:index] + search + title[index:]
|
title = title[:index] + search + title[index:]
|
||||||
results = append(results, SearchResult{
|
results = append(results, searchResult{
|
||||||
Title: title,
|
Title: title,
|
||||||
URL: fmt.Sprintf("https://www.%s.com", search),
|
URL: fmt.Sprintf("https://www.%s.com", search),
|
||||||
})
|
})
|
||||||
|
@ -9,11 +9,11 @@ import (
|
|||||||
"github.com/mikestefanello/pagoda/msg"
|
"github.com/mikestefanello/pagoda/msg"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VerifyEmail struct {
|
type verifyEmail struct {
|
||||||
controller.Controller
|
controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *VerifyEmail) Get(ctx echo.Context) error {
|
func (c *verifyEmail) Get(ctx echo.Context) error {
|
||||||
var usr *ent.User
|
var usr *ent.User
|
||||||
|
|
||||||
// Validate the token
|
// Validate the token
|
||||||
|
@ -8,12 +8,16 @@ import (
|
|||||||
"entgo.io/ent/dialect"
|
"entgo.io/ent/dialect"
|
||||||
entsql "entgo.io/ent/dialect/sql"
|
entsql "entgo.io/ent/dialect/sql"
|
||||||
"entgo.io/ent/dialect/sql/schema"
|
"entgo.io/ent/dialect/sql/schema"
|
||||||
|
|
||||||
|
// Required by ent
|
||||||
_ "github.com/jackc/pgx/v4/stdlib"
|
_ "github.com/jackc/pgx/v4/stdlib"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
|
|
||||||
"github.com/mikestefanello/pagoda/config"
|
"github.com/mikestefanello/pagoda/config"
|
||||||
"github.com/mikestefanello/pagoda/ent"
|
"github.com/mikestefanello/pagoda/ent"
|
||||||
|
|
||||||
|
// Require by ent
|
||||||
_ "github.com/mikestefanello/pagoda/ent/runtime"
|
_ "github.com/mikestefanello/pagoda/ent/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,17 +20,20 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewContext creates a new Echo context for tests using an HTTP test request and response recorder
|
||||||
func NewContext(e *echo.Echo, url string) (echo.Context, *httptest.ResponseRecorder) {
|
func NewContext(e *echo.Echo, url string) (echo.Context, *httptest.ResponseRecorder) {
|
||||||
req := httptest.NewRequest(http.MethodGet, url, strings.NewReader(""))
|
req := httptest.NewRequest(http.MethodGet, url, strings.NewReader(""))
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
return e.NewContext(req, rec), rec
|
return e.NewContext(req, rec), rec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InitSession initializes a session for a given Echo context
|
||||||
func InitSession(ctx echo.Context) {
|
func InitSession(ctx echo.Context) {
|
||||||
mw := session.Middleware(sessions.NewCookieStore([]byte("secret")))
|
mw := session.Middleware(sessions.NewCookieStore([]byte("secret")))
|
||||||
_ = ExecuteMiddleware(ctx, mw)
|
_ = ExecuteMiddleware(ctx, mw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecuteMiddleware executes a middleware function on a given Echo context
|
||||||
func ExecuteMiddleware(ctx echo.Context, mw echo.MiddlewareFunc) error {
|
func ExecuteMiddleware(ctx echo.Context, mw echo.MiddlewareFunc) error {
|
||||||
handler := mw(func(c echo.Context) error {
|
handler := mw(func(c echo.Context) error {
|
||||||
return nil
|
return nil
|
||||||
@ -38,12 +41,14 @@ func ExecuteMiddleware(ctx echo.Context, mw echo.MiddlewareFunc) error {
|
|||||||
return handler(ctx)
|
return handler(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AssertHTTPErrorCode asserts an HTTP status code on a given Echo HTTP error
|
||||||
func AssertHTTPErrorCode(t *testing.T, err error, code int) {
|
func AssertHTTPErrorCode(t *testing.T, err error, code int) {
|
||||||
httpError, ok := err.(*echo.HTTPError)
|
httpError, ok := err.(*echo.HTTPError)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
assert.Equal(t, code, httpError.Code)
|
assert.Equal(t, code, httpError.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateUser creates a random user entity
|
||||||
func CreateUser(orm *ent.Client) (*ent.User, error) {
|
func CreateUser(orm *ent.Client) (*ent.User, error) {
|
||||||
seed := fmt.Sprintf("%d-%d", time.Now().UnixMilli(), rand.Intn(1000000))
|
seed := fmt.Sprintf("%d-%d", time.Now().UnixMilli(), rand.Intn(1000000))
|
||||||
return orm.User.
|
return orm.User.
|
||||||
|
Loading…
Reference in New Issue
Block a user