mirror of
https://github.com/kataras/iris.git
synced 2025-03-22 00:36:29 +01:00
111 lines
3.1 KiB
Go
111 lines
3.1 KiB
Go
package user
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/kataras/iris"
|
|
"github.com/kataras/iris/mvc"
|
|
"github.com/kataras/iris/sessions"
|
|
)
|
|
|
|
const sessionIDKey = "UserID"
|
|
|
|
// paths
|
|
var (
|
|
PathLogin = mvc.Response{Path: "/user/login"}
|
|
PathLogout = mvc.Response{Path: "/user/logout"}
|
|
)
|
|
|
|
// AuthController is the user authentication controller, a custom shared controller.
|
|
type AuthController struct {
|
|
// context is auto-binded if struct depends on this,
|
|
// in this controller we don't we do everything with mvc-style,
|
|
// and that's neither the 30% of its features.
|
|
// Ctx iris.Context
|
|
|
|
Source *DataSource
|
|
Session *sessions.Session
|
|
|
|
// the whole controller is request-scoped because we already depend on Session, so
|
|
// this will be new for each new incoming request, BeginRequest sets that based on the session.
|
|
UserID int64
|
|
}
|
|
|
|
// BeginRequest saves login state to the context, the user id.
|
|
func (c *AuthController) BeginRequest(ctx iris.Context) {
|
|
c.UserID, _ = c.Session.GetInt64(sessionIDKey)
|
|
}
|
|
|
|
// EndRequest is here just to complete the BaseController
|
|
// in order to be tell iris to call the `BeginRequest` before the main method.
|
|
func (c *AuthController) EndRequest(ctx iris.Context) {}
|
|
|
|
func (c *AuthController) fireError(err error) mvc.View {
|
|
return mvc.View{
|
|
Code: iris.StatusBadRequest,
|
|
Name: "shared/error.html",
|
|
Data: iris.Map{"Title": "User Error", "Message": strings.ToUpper(err.Error())},
|
|
}
|
|
}
|
|
|
|
func (c *AuthController) redirectTo(id int64) mvc.Response {
|
|
return mvc.Response{Path: "/user/" + strconv.Itoa(int(id))}
|
|
}
|
|
|
|
func (c *AuthController) createOrUpdate(firstname, username, password string) (user Model, err error) {
|
|
username = strings.Trim(username, " ")
|
|
if username == "" || password == "" || firstname == "" {
|
|
return user, errors.New("empty firstname, username or/and password")
|
|
}
|
|
|
|
userToInsert := Model{
|
|
Firstname: firstname,
|
|
Username: username,
|
|
password: password,
|
|
} // password is hashed by the Source.
|
|
|
|
newUser, err := c.Source.InsertOrUpdate(userToInsert)
|
|
if err != nil {
|
|
return user, err
|
|
}
|
|
|
|
return newUser, nil
|
|
}
|
|
|
|
func (c *AuthController) isLoggedIn() bool {
|
|
// we don't search by session, we have the user id
|
|
// already by the `BeginRequest` middleware.
|
|
return c.UserID > 0
|
|
}
|
|
|
|
func (c *AuthController) verify(username, password string) (user Model, err error) {
|
|
if username == "" || password == "" {
|
|
return user, errors.New("please fill both username and password fields")
|
|
}
|
|
|
|
u, found := c.Source.GetByUsername(username)
|
|
if !found {
|
|
// if user found with that username not found at all.
|
|
return user, errors.New("user with that username does not exist")
|
|
}
|
|
|
|
if ok, err := ValidatePassword(password, u.HashedPassword); err != nil || !ok {
|
|
// if user found but an error occurred or the password is not valid.
|
|
return user, errors.New("please try to login with valid credentials")
|
|
}
|
|
|
|
return u, nil
|
|
}
|
|
|
|
// if logged in then destroy the session
|
|
// and redirect to the login page
|
|
// otherwise redirect to the registration page.
|
|
func (c *AuthController) logout() mvc.Response {
|
|
if c.isLoggedIn() {
|
|
c.Session.Destroy()
|
|
}
|
|
return PathLogin
|
|
}
|