From 51e44a57a15b2dd0bfc09e35fdeef1302b4a6e0f Mon Sep 17 00:00:00 2001 From: mikestefanello Date: Thu, 10 Feb 2022 08:56:07 -0500 Subject: [PATCH] Lint check adjustments. --- README.md | 14 +++++++------- config/config.go | 29 ++++++++++++++++++++--------- config/config_test.go | 2 +- msg/msg.go | 12 ++++++++++-- routes/about.go | 18 +++++++++--------- routes/contact.go | 14 +++++++------- routes/error.go | 4 ++-- routes/forgot_password.go | 14 +++++++------- routes/home.go | 12 ++++++------ routes/login.go | 14 +++++++------- routes/logout.go | 4 ++-- routes/register.go | 16 ++++++++-------- routes/reset_password.go | 14 +++++++------- routes/router.go | 22 +++++++++++----------- routes/search.go | 10 +++++----- routes/verify_email.go | 4 ++-- services/container.go | 4 ++++ tests/tests.go | 5 +++++ 18 files changed, 120 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index e1e9b60..3804d05 100644 --- a/README.md +++ b/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`: ```go -type Home struct { +type home struct { 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: ```go -home := Home{Controller: controller.NewController(c)} +home := home{Controller: controller.NewController(c)} g.GET("/", home.Get).Name = "home" 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: ```go -func (c *Home) Get(ctx echo.Context) error { +func (c *home) Get(ctx echo.Context) error { 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()`: ```go -func (c *Home) Get(ctx echo.Context) error { +func (c *home) Get(ctx echo.Context) error { page := controller.NewPage(ctx) page.Layout = "main" 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: ```go -func (c *Home) Get(ctx echo.Context) error { +func (c *home) Get(ctx echo.Context) error { ctx.Logger().Info("something happened") if err := someOperation(); err != nil { diff --git a/config/config.go b/config/config.go index 4e7b5b2..f5c10eb 100644 --- a/config/config.go +++ b/config/config.go @@ -21,21 +21,32 @@ const ( StaticPrefix = "files" ) -type Environment string +type environment string const ( - EnvLocal Environment = "local" - EnvTest Environment = "test" - EnvDevelop Environment = "dev" - EnvStaging Environment = "staging" - EnvQA Environment = "qa" - EnvProduction Environment = "prod" + // EnvLocal represents the local environment + EnvLocal environment = "local" + + // EnvTest represents the test environment + EnvTest environment = "test" + + // 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 // currently running in. // 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 { panic(err) } @@ -68,7 +79,7 @@ type ( // AppConfig stores application configuration AppConfig struct { 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 EncryptionKey string `env:"APP_ENCRYPTION_KEY,default=?E(G+KbPeShVmYq3t6w9z$C&F)J@McQf"` Timeout time.Duration `env:"APP_TIMEOUT,default=20s"` diff --git a/config/config_test.go b/config/config_test.go index 103e368..1404f7c 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -11,7 +11,7 @@ func TestGetConfig(t *testing.T) { _, err := GetConfig() require.NoError(t, err) - var env Environment + var env environment env = "abc" SwitchEnvironment(env) cfg, err := GetConfig() diff --git a/msg/msg.go b/msg/msg.go index 65626c2..50de881 100644 --- a/msg/msg.go +++ b/msg/msg.go @@ -6,13 +6,21 @@ import ( "github.com/labstack/echo/v4" ) +// Type is a message type type Type string const ( + // TypeSuccess represents a success message type TypeSuccess Type = "success" - TypeInfo Type = "info" + + // TypeInfo represents a info message type + TypeInfo Type = "info" + + // TypeWarning represents a warning message type TypeWarning Type = "warning" - TypeDanger Type = "danger" + + // TypeDanger represents a danger message type + TypeDanger Type = "danger" ) const ( diff --git a/routes/about.go b/routes/about.go index bdd809d..f9665ae 100644 --- a/routes/about.go +++ b/routes/about.go @@ -9,23 +9,23 @@ import ( ) type ( - About struct { + about struct { controller.Controller } - AboutData struct { + aboutData struct { ShowCacheWarning bool - FrontendTabs []AboutTab - BackendTabs []AboutTab + FrontendTabs []aboutTab + BackendTabs []aboutTab } - AboutTab struct { + aboutTab struct { Title string Body template.HTML } ) -func (c *About) Get(ctx echo.Context) error { +func (c *about) Get(ctx echo.Context) error { page := controller.NewPage(ctx) page.Layout = "main" 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 // even though you wouldn't normally send markup like this - page.Data = AboutData{ + page.Data = aboutData{ ShowCacheWarning: true, - FrontendTabs: []AboutTab{ + FrontendTabs: []aboutTab{ { Title: "HTMX", Body: template.HTML(`Completes HTML as a hypertext by providing attributes to AJAXify anything and much more. Visit htmx.org 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 bulma.io to learn more.`), }, }, - BackendTabs: []AboutTab{ + BackendTabs: []aboutTab{ { Title: "Echo", Body: template.HTML(`High performance, extensible, minimalist Go web framework. Visit echo.labstack.com to learn more.`), diff --git a/routes/contact.go b/routes/contact.go index 0ae07d9..4a7ac99 100644 --- a/routes/contact.go +++ b/routes/contact.go @@ -10,33 +10,33 @@ import ( ) type ( - Contact struct { + contact struct { controller.Controller } - ContactForm struct { + contactForm struct { Email string `form:"email" validate:"required,email"` Message string `form:"message" validate:"required"` Submission controller.FormSubmission } ) -func (c *Contact) Get(ctx echo.Context) error { +func (c *contact) Get(ctx echo.Context) error { page := controller.NewPage(ctx) page.Layout = "main" page.Name = "contact" page.Title = "Contact us" - page.Form = ContactForm{} + page.Form = contactForm{} if form := ctx.Get(context.FormKey); form != nil { - page.Form = form.(*ContactForm) + page.Form = form.(*contactForm) } return c.RenderPage(ctx, page) } -func (c *Contact) Post(ctx echo.Context) error { - var form ContactForm +func (c *contact) Post(ctx echo.Context) error { + var form contactForm ctx.Set(context.FormKey, &form) // Parse the form values diff --git a/routes/error.go b/routes/error.go index 50e2bfc..d6f2270 100644 --- a/routes/error.go +++ b/routes/error.go @@ -9,11 +9,11 @@ import ( "github.com/labstack/echo/v4" ) -type Error struct { +type errorHandler struct { 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) { return } diff --git a/routes/forgot_password.go b/routes/forgot_password.go index d380079..52243fc 100644 --- a/routes/forgot_password.go +++ b/routes/forgot_password.go @@ -14,32 +14,32 @@ import ( ) type ( - ForgotPassword struct { + forgotPassword struct { controller.Controller } - ForgotPasswordForm struct { + forgotPasswordForm struct { Email string `form:"email" validate:"required,email"` Submission controller.FormSubmission } ) -func (c *ForgotPassword) Get(ctx echo.Context) error { +func (c *forgotPassword) Get(ctx echo.Context) error { page := controller.NewPage(ctx) page.Layout = "auth" page.Name = "forgot-password" page.Title = "Forgot password" - page.Form = ForgotPasswordForm{} + page.Form = forgotPasswordForm{} if form := ctx.Get(context.FormKey); form != nil { - page.Form = form.(*ForgotPasswordForm) + page.Form = form.(*forgotPasswordForm) } return c.RenderPage(ctx, page) } -func (c *ForgotPassword) Post(ctx echo.Context) error { - var form ForgotPasswordForm +func (c *forgotPassword) Post(ctx echo.Context) error { + var form forgotPasswordForm ctx.Set(context.FormKey, &form) succeed := func() error { diff --git a/routes/home.go b/routes/home.go index 20ae798..721d97b 100644 --- a/routes/home.go +++ b/routes/home.go @@ -9,17 +9,17 @@ import ( ) type ( - Home struct { + home struct { controller.Controller } - Post struct { + post struct { Title string Body string } ) -func (c *Home) Get(ctx echo.Context) error { +func (c *home) Get(ctx echo.Context) error { page := controller.NewPage(ctx) page.Layout = "main" 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 -func (c *Home) fetchPosts(pager *controller.Pager) []Post { +func (c *home) fetchPosts(pager *controller.Pager) []post { pager.SetItems(20) - posts := make([]Post, 20) + posts := make([]post, 20) for k := range posts { - posts[k] = Post{ + posts[k] = post{ 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), } diff --git a/routes/login.go b/routes/login.go index b7cc415..a8e60bd 100644 --- a/routes/login.go +++ b/routes/login.go @@ -14,33 +14,33 @@ import ( ) type ( - Login struct { + login struct { controller.Controller } - LoginForm struct { + loginForm struct { Email string `form:"email" validate:"required,email"` Password string `form:"password" validate:"required"` Submission controller.FormSubmission } ) -func (c *Login) Get(ctx echo.Context) error { +func (c *login) Get(ctx echo.Context) error { page := controller.NewPage(ctx) page.Layout = "auth" page.Name = "login" page.Title = "Log in" - page.Form = LoginForm{} + page.Form = loginForm{} if form := ctx.Get(context.FormKey); form != nil { - page.Form = form.(*LoginForm) + page.Form = form.(*loginForm) } return c.RenderPage(ctx, page) } -func (c *Login) Post(ctx echo.Context) error { - var form LoginForm +func (c *login) Post(ctx echo.Context) error { + var form loginForm ctx.Set(context.FormKey, &form) authFailed := func() error { diff --git a/routes/logout.go b/routes/logout.go index 78cc051..70a9cb8 100644 --- a/routes/logout.go +++ b/routes/logout.go @@ -7,11 +7,11 @@ import ( "github.com/labstack/echo/v4" ) -type Logout struct { +type logout struct { 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 { msg.Success(c, "You have been logged out successfully.") } else { diff --git a/routes/register.go b/routes/register.go index dde596d..ecadccd 100644 --- a/routes/register.go +++ b/routes/register.go @@ -12,11 +12,11 @@ import ( ) type ( - Register struct { + register struct { controller.Controller } - RegisterForm struct { + registerForm struct { Name string `form:"name" validate:"required"` Email string `form:"email" validate:"required,email"` 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.Layout = "auth" page.Name = "register" page.Title = "Register" - page.Form = RegisterForm{} + page.Form = registerForm{} if form := ctx.Get(context.FormKey); form != nil { - page.Form = form.(*RegisterForm) + page.Form = form.(*registerForm) } return c.RenderPage(ctx, page) } -func (c *Register) Post(ctx echo.Context) error { - var form RegisterForm +func (c *register) Post(ctx echo.Context) error { + var form registerForm ctx.Set(context.FormKey, &form) // Parse the form values @@ -96,7 +96,7 @@ func (c *Register) Post(ctx echo.Context) error { 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 token, err := c.Container.Auth.GenerateEmailVerificationToken(usr.Email) if err != nil { diff --git a/routes/reset_password.go b/routes/reset_password.go index 577e6b7..d32d290 100644 --- a/routes/reset_password.go +++ b/routes/reset_password.go @@ -10,33 +10,33 @@ import ( ) type ( - ResetPassword struct { + resetPassword struct { controller.Controller } - ResetPasswordForm struct { + resetPasswordForm struct { Password string `form:"password" validate:"required"` ConfirmPassword string `form:"password-confirm" validate:"required,eqfield=Password"` Submission controller.FormSubmission } ) -func (c *ResetPassword) Get(ctx echo.Context) error { +func (c *resetPassword) Get(ctx echo.Context) error { page := controller.NewPage(ctx) page.Layout = "auth" page.Name = "reset-password" page.Title = "Reset password" - page.Form = ResetPasswordForm{} + page.Form = resetPasswordForm{} if form := ctx.Get(context.FormKey); form != nil { - page.Form = form.(*ResetPasswordForm) + page.Form = form.(*resetPasswordForm) } return c.RenderPage(ctx, page) } -func (c *ResetPassword) Post(ctx echo.Context) error { - var form ResetPasswordForm +func (c *resetPassword) Post(ctx echo.Context) error { + var form resetPasswordForm ctx.Set(context.FormKey, &form) // Parse the form values diff --git a/routes/router.go b/routes/router.go index b6d3972..ca5c0b1 100644 --- a/routes/router.go +++ b/routes/router.go @@ -56,7 +56,7 @@ func BuildRouter(c *services.Container) { ctr := controller.NewController(c) // Error handler - err := Error{Controller: ctr} + err := errorHandler{Controller: ctr} c.Web.HTTPErrorHandler = err.Get // Example routes @@ -65,37 +65,37 @@ func BuildRouter(c *services.Container) { } 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" - search := Search{Controller: ctr} + search := search{Controller: ctr} g.GET("/search", search.Get).Name = "search" - about := About{Controller: ctr} + about := about{Controller: ctr} g.GET("/about", about.Get).Name = "about" - contact := Contact{Controller: ctr} + contact := contact{Controller: ctr} g.GET("/contact", contact.Get).Name = "contact" g.POST("/contact", contact.Post).Name = "contact.post" } 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" - verifyEmail := VerifyEmail{Controller: ctr} + verifyEmail := verifyEmail{Controller: ctr} g.GET("/email/verify/:token", verifyEmail.Get).Name = "verify_email" noAuth := g.Group("/user", middleware.RequireNoAuthentication()) - login := Login{Controller: ctr} + login := login{Controller: ctr} noAuth.GET("/login", login.Get).Name = "login" noAuth.POST("/login", login.Post).Name = "login.post" - register := Register{Controller: ctr} + register := register{Controller: ctr} noAuth.GET("/register", register.Get).Name = "register" 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.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.LoadValidPasswordToken(c.Auth), ) - reset := ResetPassword{Controller: ctr} + reset := resetPassword{Controller: ctr} 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" } diff --git a/routes/search.go b/routes/search.go index 3292f5a..ca99b3b 100644 --- a/routes/search.go +++ b/routes/search.go @@ -10,29 +10,29 @@ import ( ) type ( - Search struct { + search struct { controller.Controller } - SearchResult struct { + searchResult struct { Title string URL string } ) -func (c *Search) Get(ctx echo.Context) error { +func (c *search) Get(ctx echo.Context) error { page := controller.NewPage(ctx) page.Layout = "main" page.Name = "search" // Fake search results - var results []SearchResult + var results []searchResult if search := ctx.QueryParam("query"); search != "" { for i := 0; i < 5; i++ { title := "Lorem ipsum example ddolor sit amet" index := rand.Intn(len(title)) title = title[:index] + search + title[index:] - results = append(results, SearchResult{ + results = append(results, searchResult{ Title: title, URL: fmt.Sprintf("https://www.%s.com", search), }) diff --git a/routes/verify_email.go b/routes/verify_email.go index 59d137c..6bd88f9 100644 --- a/routes/verify_email.go +++ b/routes/verify_email.go @@ -9,11 +9,11 @@ import ( "github.com/mikestefanello/pagoda/msg" ) -type VerifyEmail struct { +type verifyEmail struct { controller.Controller } -func (c *VerifyEmail) Get(ctx echo.Context) error { +func (c *verifyEmail) Get(ctx echo.Context) error { var usr *ent.User // Validate the token diff --git a/services/container.go b/services/container.go index 977572c..87543fa 100644 --- a/services/container.go +++ b/services/container.go @@ -8,12 +8,16 @@ import ( "entgo.io/ent/dialect" entsql "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/schema" + + // Required by ent _ "github.com/jackc/pgx/v4/stdlib" "github.com/labstack/echo/v4" "github.com/labstack/gommon/log" "github.com/mikestefanello/pagoda/config" "github.com/mikestefanello/pagoda/ent" + + // Require by ent _ "github.com/mikestefanello/pagoda/ent/runtime" ) diff --git a/tests/tests.go b/tests/tests.go index d5127c5..aa43980 100644 --- a/tests/tests.go +++ b/tests/tests.go @@ -20,17 +20,20 @@ import ( "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) { req := httptest.NewRequest(http.MethodGet, url, strings.NewReader("")) rec := httptest.NewRecorder() return e.NewContext(req, rec), rec } +// InitSession initializes a session for a given Echo context func InitSession(ctx echo.Context) { mw := session.Middleware(sessions.NewCookieStore([]byte("secret"))) _ = ExecuteMiddleware(ctx, mw) } +// ExecuteMiddleware executes a middleware function on a given Echo context func ExecuteMiddleware(ctx echo.Context, mw echo.MiddlewareFunc) error { handler := mw(func(c echo.Context) error { return nil @@ -38,12 +41,14 @@ func ExecuteMiddleware(ctx echo.Context, mw echo.MiddlewareFunc) error { return handler(ctx) } +// AssertHTTPErrorCode asserts an HTTP status code on a given Echo HTTP error func AssertHTTPErrorCode(t *testing.T, err error, code int) { httpError, ok := err.(*echo.HTTPError) require.True(t, ok) assert.Equal(t, code, httpError.Code) } +// CreateUser creates a random user entity func CreateUser(orm *ent.Client) (*ent.User, error) { seed := fmt.Sprintf("%d-%d", time.Now().UnixMilli(), rand.Intn(1000000)) return orm.User.