package routes import ( "fmt" "strings" "github.com/mikestefanello/pagoda/context" "github.com/mikestefanello/pagoda/controller" "github.com/mikestefanello/pagoda/ent" "github.com/mikestefanello/pagoda/ent/user" "github.com/mikestefanello/pagoda/msg" "github.com/labstack/echo/v4" ) type ( Login struct { controller.Controller } 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 { page := controller.NewPage(ctx) page.Layout = "auth" page.Name = "login" page.Title = "Log in" page.Form = LoginForm{} if form := ctx.Get(context.FormKey); form != nil { page.Form = form.(*LoginForm) } return c.RenderPage(ctx, page) } func (c *Login) Post(ctx echo.Context) error { var form LoginForm ctx.Set(context.FormKey, &form) authFailed := func() error { form.Submission.SetFieldError("Email", "") form.Submission.SetFieldError("Password", "") msg.Danger(ctx, "Invalid credentials. Please try again.") return c.Get(ctx) } // Parse the form values if err := ctx.Bind(&form); err != nil { return c.Fail(ctx, err, "unable to parse login form") } if err := form.Submission.Process(ctx, form); err != nil { return c.Fail(ctx, err, "unable to process form submission") } if form.Submission.HasErrors() { return c.Get(ctx) } // Attempt to load the user u, err := c.Container.ORM.User. Query(). Where(user.Email(strings.ToLower(form.Email))). Only(ctx.Request().Context()) switch err.(type) { case *ent.NotFoundError: return authFailed() case nil: default: return c.Fail(ctx, err, "error querying user during login") } // Check if the password is correct err = c.Container.Auth.CheckPassword(form.Password, u.Password) if err != nil { return authFailed() } // Log the user in err = c.Container.Auth.Login(ctx, u.ID) if err != nil { return c.Fail(ctx, err, "unable to log in user") } msg.Success(ctx, fmt.Sprintf("Welcome back, %s. You are now logged in.", u.Name)) return c.Redirect(ctx, "home") }