Skip to content

Commit fdd6f53

Browse files
committed
Cleanup
1 parent e49eb96 commit fdd6f53

File tree

7 files changed

+137
-64
lines changed

7 files changed

+137
-64
lines changed

Diff for: models/update.go

+20-19
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package models
22

33
import (
44
"fmt"
5+
"strconv"
56
)
67

78
type Update struct {
8-
key string
9+
id int64
910
}
1011

1112
func NewUpdate(userId int64, body string) (*Update, error) {
@@ -24,46 +25,46 @@ func NewUpdate(userId int64, body string) (*Update, error) {
2425
if err != nil {
2526
return nil, err
2627
}
27-
return &Update{key}, nil
28+
return &Update{id}, nil
2829
}
2930

3031
func (update *Update) GetBody() (string, error) {
31-
return client.HGet(update.key, "body").Result()
32+
key := fmt.Sprintf("update:%d", update.id)
33+
return client.HGet(key, "body").Result()
3234
}
3335

3436
func (update *Update) GetUser() (*User, error) {
35-
userId, err := client.HGet(update.key, "user_id").Int64()
37+
key := fmt.Sprintf("update:%d", update.id)
38+
userId, err := client.HGet(key, "user_id").Int64()
3639
if err != nil {
3740
return nil, err
3841
}
3942
return GetUserById(userId)
4043
}
4144

42-
func GetAllUpdates() ([]*Update, error) {
43-
updateIds, err := client.LRange("updates", 0, 10).Result()
45+
func queryUpdates(key string) ([]*Update, error) {
46+
updateIds, err := client.LRange(key, 0, 10).Result()
4447
if err != nil {
4548
return nil, err
4649
}
4750
updates := make([]*Update, len(updateIds))
48-
for i, id := range updateIds {
49-
key := "update:" + id
50-
updates[i] = &Update{key}
51+
for i, strId := range updateIds {
52+
id, err := strconv.Atoi(strId)
53+
if err != nil {
54+
return nil, err
55+
}
56+
updates[i] = &Update{int64(id)}
5157
}
5258
return updates, nil
5359
}
5460

61+
func GetAllUpdates() ([]*Update, error) {
62+
return queryUpdates("updates")
63+
}
64+
5565
func GetUpdates(userId int64) ([]*Update, error) {
5666
key := fmt.Sprintf("user:%d:updates", userId)
57-
updateIds, err := client.LRange(key, 0, 10).Result()
58-
if err != nil {
59-
return nil, err
60-
}
61-
updates := make([]*Update, len(updateIds))
62-
for i, id := range updateIds {
63-
key := "update:" + id
64-
updates[i] = &Update{key}
65-
}
66-
return updates, nil
67+
return queryUpdates(key)
6768
}
6869

6970
func PostUpdate(userId int64, body string) error {

Diff for: models/user.go

+13-7
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@ import (
1010
var (
1111
ErrUserNotFound = errors.New("user not found")
1212
ErrInvalidLogin = errors.New("invalid login")
13+
ErrUsernameTaken = errors.New("username taken")
1314
)
1415

1516
type User struct {
16-
key string
17+
id int64
1718
}
1819

1920
func NewUser(username string, hash []byte) (*User, error) {
21+
exists, err := client.HExists("user:by-username", username).Result()
22+
if exists {
23+
return nil, ErrUsernameTaken
24+
}
2025
id, err := client.Incr("user:next-id").Result()
2126
if err != nil {
2227
return nil, err
@@ -31,19 +36,21 @@ func NewUser(username string, hash []byte) (*User, error) {
3136
if err != nil {
3237
return nil, err
3338
}
34-
return &User{key}, nil
39+
return &User{id}, nil
3540
}
3641

3742
func (user *User) GetId() (int64, error) {
38-
return client.HGet(user.key, "id").Int64()
43+
return user.id, nil
3944
}
4045

4146
func (user *User) GetUsername() (string, error) {
42-
return client.HGet(user.key, "username").Result()
47+
key := fmt.Sprintf("user:%d", user.id)
48+
return client.HGet(key, "username").Result()
4349
}
4450

4551
func (user *User) GetHash() ([]byte, error) {
46-
return client.HGet(user.key, "hash").Bytes()
52+
key := fmt.Sprintf("user:%d", user.id)
53+
return client.HGet(key, "hash").Bytes()
4754
}
4855

4956
func (user *User) Authenticate(password string) error {
@@ -59,8 +66,7 @@ func (user *User) Authenticate(password string) error {
5966
}
6067

6168
func GetUserById(id int64) (*User, error) {
62-
key := fmt.Sprintf("user:%d", id)
63-
return &User{key}, nil
69+
return &User{id}, nil
6470
}
6571

6672
func GetUserByUsername(username string) (*User, error) {

Diff for: routes/routes.go

+33-20
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func NewRouter() *mux.Router {
1515
r.HandleFunc("/", middleware.AuthRequired(indexPostHandler)).Methods("POST")
1616
r.HandleFunc("/login", loginGetHandler).Methods("GET")
1717
r.HandleFunc("/login", loginPostHandler).Methods("POST")
18+
r.HandleFunc("/logout", logoutGetHandler).Methods("GET")
1819
r.HandleFunc("/register", registerGetHandler).Methods("GET")
1920
r.HandleFunc("/register", registerPostHandler).Methods("POST")
2021
fs := http.FileServer(http.Dir("./static/"))
@@ -27,16 +28,17 @@ func NewRouter() *mux.Router {
2728
func indexGetHandler(w http.ResponseWriter, r *http.Request) {
2829
updates, err := models.GetAllUpdates()
2930
if err != nil {
30-
w.WriteHeader(http.StatusInternalServerError)
31-
w.Write([]byte("Internal server error"))
31+
utils.InternalServerError(w)
3232
return
3333
}
3434
utils.ExecuteTemplate(w, "index.html", struct {
3535
Title string
3636
Updates []*models.Update
37+
DisplayForm bool
3738
} {
3839
Title: "All updates",
3940
Updates: updates,
41+
DisplayForm: true,
4042
})
4143
}
4244

@@ -45,48 +47,52 @@ func indexPostHandler(w http.ResponseWriter, r *http.Request) {
4547
untypedUserId := session.Values["user_id"]
4648
userId, ok := untypedUserId.(int64)
4749
if !ok {
48-
w.WriteHeader(http.StatusInternalServerError)
49-
w.Write([]byte("Internal server error"))
50+
utils.InternalServerError(w)
5051
return
5152
}
5253
r.ParseForm()
5354
body := r.PostForm.Get("update")
5455
err := models.PostUpdate(userId, body)
5556
if err != nil {
56-
w.WriteHeader(http.StatusInternalServerError)
57-
w.Write([]byte("Internal server error"))
57+
utils.InternalServerError(w)
5858
return
5959
}
6060
http.Redirect(w, r, "/", 302)
6161
}
6262

6363
func userGetHandler(w http.ResponseWriter, r *http.Request) {
64+
session, _ := sessions.Store.Get(r, "session")
65+
untypedUserId := session.Values["user_id"]
66+
currentUserId, ok := untypedUserId.(int64)
67+
if !ok {
68+
utils.InternalServerError(w)
69+
return
70+
}
6471
vars := mux.Vars(r)
6572
username := vars["username"]
6673
user, err := models.GetUserByUsername(username)
6774
if err != nil {
68-
w.WriteHeader(http.StatusInternalServerError)
69-
w.Write([]byte("Internal server error"))
75+
utils.InternalServerError(w)
7076
return
7177
}
7278
userId, err := user.GetId()
7379
if err != nil {
74-
w.WriteHeader(http.StatusInternalServerError)
75-
w.Write([]byte("Internal server error"))
80+
utils.InternalServerError(w)
7681
return
7782
}
7883
updates, err := models.GetUpdates(userId)
7984
if err != nil {
80-
w.WriteHeader(http.StatusInternalServerError)
81-
w.Write([]byte("Internal server error"))
85+
utils.InternalServerError(w)
8286
return
8387
}
8488
utils.ExecuteTemplate(w, "index.html", struct {
8589
Title string
8690
Updates []*models.Update
87-
} {
91+
DisplayForm bool
92+
} {
8893
Title: username,
8994
Updates: updates,
95+
DisplayForm: currentUserId == userId,
9096
})
9197
}
9298

@@ -106,15 +112,13 @@ func loginPostHandler(w http.ResponseWriter, r *http.Request) {
106112
case models.ErrInvalidLogin:
107113
utils.ExecuteTemplate(w, "login.html", "invalid login")
108114
default:
109-
w.WriteHeader(http.StatusInternalServerError)
110-
w.Write([]byte("Internal server error"))
115+
utils.InternalServerError(w)
111116
}
112117
return
113118
}
114119
userId, err := user.GetId()
115120
if err != nil {
116-
w.WriteHeader(http.StatusInternalServerError)
117-
w.Write([]byte("Internal server error"))
121+
utils.InternalServerError(w)
118122
return
119123
}
120124
session, _ := sessions.Store.Get(r, "session")
@@ -123,6 +127,13 @@ func loginPostHandler(w http.ResponseWriter, r *http.Request) {
123127
http.Redirect(w, r, "/", 302)
124128
}
125129

130+
func logoutGetHandler(w http.ResponseWriter, r *http.Request) {
131+
session, _ := sessions.Store.Get(r, "session")
132+
delete(session.Values, "user_id")
133+
session.Save(r, w)
134+
http.Redirect(w, r, "/login", 302)
135+
}
136+
126137
func registerGetHandler(w http.ResponseWriter, r *http.Request) {
127138
utils.ExecuteTemplate(w, "register.html", nil)
128139
}
@@ -132,9 +143,11 @@ func registerPostHandler(w http.ResponseWriter, r *http.Request) {
132143
username := r.PostForm.Get("username")
133144
password := r.PostForm.Get("password")
134145
err := models.RegisterUser(username, password)
135-
if err != nil {
136-
w.WriteHeader(http.StatusInternalServerError)
137-
w.Write([]byte("Internal server error"))
146+
if err == models.ErrUsernameTaken {
147+
utils.ExecuteTemplate(w, "register.html", "username taken")
148+
return
149+
} else if err != nil {
150+
utils.InternalServerError(w)
138151
return
139152
}
140153
http.Redirect(w, r, "/login", 302)

Diff for: static/index.css

+36-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
1-
body > div {
1+
* {
2+
margin: 0;
3+
padding: 0;
4+
}
5+
6+
body {
7+
background: #f0f0f0;
8+
}
9+
10+
nav {
211
padding: 0.5em;
3-
width: 200px;
4-
margin: 1em 0em;
5-
background: #ccc;
12+
background: #fff;
13+
border-bottom: 1px solid #aaa;
14+
text-align: right;
15+
}
16+
17+
main {
18+
margin: 0 auto;
19+
max-width: 640px;
20+
}
21+
22+
main > .update {
23+
padding: 0.5em;
24+
background: #fff;
625
border: 1px solid #aaa;
7-
}
26+
margin-bottom: 1em;
27+
}
28+
29+
#update-form {
30+
text-align: right;
31+
margin-bottom: 1em;
32+
}
33+
34+
#update-form textarea {
35+
width: 100%;
36+
margin-bottom: 0.5em;
37+
resize: vertical;
38+
}

Diff for: templates/index.html

+22-13
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,29 @@
44
<link rel="stylesheet" type="text/css" href="/static/index.css">
55
</head>
66
<body>
7-
<h1>{{ .Title }}</h1>
8-
<form method="POST">
9-
<textarea name="update"></textarea>
10-
<div>
11-
<button type="submit">Post Update</button>
7+
<nav>
8+
<a href="/logout">logout</a>
9+
</nav>
10+
<main>
11+
<h1>{{ .Title }}</h1>
12+
{{ if .DisplayForm }}
13+
<div id="update-form">
14+
<form action="/" method="POST">
15+
<textarea name="update"></textarea>
16+
<div>
17+
<button type="submit">Post Update</button>
18+
</div>
19+
</form>
1220
</div>
13-
</form>
14-
{{ range .Updates }}
15-
<div>
16-
<div>
17-
<strong>{{ .GetUser.GetUsername }} wrote:</strong>
21+
{{ end }}
22+
{{ range .Updates }}
23+
<div class="update">
24+
<div>
25+
<strong><a href="/{{ .GetUser.GetUsername }}">{{ .GetUser.GetUsername }}</a> wrote:</strong>
26+
</div>
27+
<div>{{ .GetBody }}</div>
1828
</div>
19-
<div>{{ .GetBody }}</div>
20-
</div>
21-
{{ end }}
29+
{{ end }}
30+
</main>
2231
</body>
2332
</html>

Diff for: templates/register.html

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
<title>Register</title>
44
</head>
55
<body>
6+
{{ if . }}
7+
<div class="error">{{ . }}</div>
8+
{{ end }}
69
<form method="POST">
710
<div>Username: <input name="username"></div>
811
<div>Password: <input name="password"></div>

Diff for: utils/errors.go

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package utils
2+
3+
import (
4+
"net/http"
5+
)
6+
7+
func InternalServerError(w http.ResponseWriter) {
8+
w.WriteHeader(http.StatusInternalServerError)
9+
w.Write([]byte("Internal server error"))
10+
}

0 commit comments

Comments
 (0)