forked from kataras/iris
/
user_controller.go
171 lines (140 loc) 路 4.5 KB
/
user_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// file: controllers/user_controller.go
package controllers
import (
"github.com/kataras/iris/_examples/mvc/login/datamodels"
"github.com/kataras/iris/_examples/mvc/login/services"
"github.com/kataras/iris"
"github.com/kataras/iris/mvc"
"github.com/kataras/iris/sessions"
)
// UserController is our /user controller.
// UserController is responsible to handle the following requests:
// GET /user/register
// POST /user/register
// GET /user/login
// POST /user/login
// GET /user/me
// All HTTP Methods /user/logout
type UserController struct {
// context is auto-binded by Iris on each request,
// remember that on each incoming request iris creates a new UserController each time,
// so all fields are request-scoped by-default, only dependency injection is able to set
// custom fields like the Service which is the same for all requests (static binding)
// and the Session which depends on the current context (dynamic binding).
Ctx iris.Context
// Our UserService, it's an interface which
// is binded from the main application.
Service services.UserService
// Session, binded using dependency injection from the main.go.
Session *sessions.Session
}
const userIDKey = "UserID"
func (c *UserController) getCurrentUserID() int64 {
userID := c.Session.GetInt64Default(userIDKey, 0)
return userID
}
func (c *UserController) isLoggedIn() bool {
return c.getCurrentUserID() > 0
}
func (c *UserController) logout() {
c.Session.Destroy()
}
var registerStaticView = mvc.View{
Name: "user/register.html",
Data: iris.Map{"Title": "User Registration"},
}
// GetRegister handles GET: http://localhost:8080/user/register.
func (c *UserController) GetRegister() mvc.Result {
if c.isLoggedIn() {
c.logout()
}
return registerStaticView
}
// PostRegister handles POST: http://localhost:8080/user/register.
func (c *UserController) PostRegister() mvc.Result {
// get firstname, username and password from the form.
var (
firstname = c.Ctx.FormValue("firstname")
username = c.Ctx.FormValue("username")
password = c.Ctx.FormValue("password")
)
// create the new user, the password will be hashed by the service.
u, err := c.Service.Create(password, datamodels.User{
Username: username,
Firstname: firstname,
})
// set the user's id to this session even if err != nil,
// the zero id doesn't matters because .getCurrentUserID() checks for that.
// If err != nil then it will be shown, see below on mvc.Response.Err: err.
c.Session.Set(userIDKey, u.ID)
return mvc.Response{
// if not nil then this error will be shown instead.
Err: err,
// redirect to /user/me.
Path: "/user/me",
// When redirecting from POST to GET request you -should- use this HTTP status code,
// however there're some (complicated) alternatives if you
// search online or even the HTTP RFC.
// Status "See Other" RFC 7231, however iris can automatically fix that
// but it's good to know you can set a custom code;
// Code: 303,
}
}
var loginStaticView = mvc.View{
Name: "user/login.html",
Data: iris.Map{"Title": "User Login"},
}
// GetLogin handles GET: http://localhost:8080/user/login.
func (c *UserController) GetLogin() mvc.Result {
if c.isLoggedIn() {
// if it's already logged in then destroy the previous session.
c.logout()
}
return loginStaticView
}
// PostLogin handles POST: http://localhost:8080/user/register.
func (c *UserController) PostLogin() mvc.Result {
var (
username = c.Ctx.FormValue("username")
password = c.Ctx.FormValue("password")
)
u, found := c.Service.GetByUsernameAndPassword(username, password)
if !found {
return mvc.Response{
Path: "/user/register",
}
}
c.Session.Set(userIDKey, u.ID)
return mvc.Response{
Path: "/user/me",
}
}
// GetMe handles GET: http://localhost:8080/user/me.
func (c *UserController) GetMe() mvc.Result {
if !c.isLoggedIn() {
// if it's not logged in then redirect user to the login page.
return mvc.Response{Path: "/user/login"}
}
u, found := c.Service.GetByID(c.getCurrentUserID())
if !found {
// if the session exists but for some reason the user doesn't exist in the "database"
// then logout and re-execute the function, it will redirect the client to the
// /user/login page.
c.logout()
return c.GetMe()
}
return mvc.View{
Name: "user/me.html",
Data: iris.Map{
"Title": "Profile of " + u.Username,
"User": u,
},
}
}
// AnyLogout handles All/Any HTTP Methods for: http://localhost:8080/user/logout.
func (c *UserController) AnyLogout() {
if c.isLoggedIn() {
c.logout()
}
c.Ctx.Redirect("/user/login")
}