-
Notifications
You must be signed in to change notification settings - Fork 0
/
login.go
139 lines (119 loc) · 3.74 KB
/
login.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
package piplayer
import (
"log"
"net/http"
"github.com/gorilla/sessions"
"golang.org/x/crypto/bcrypt"
)
// Login holds the credentials to the single user in the system.
type Login struct {
Username string
Password string
}
var store = sessions.NewCookieStore([]byte("ip-player-session-secret"))
// newLogin creates the default login credentials if none are found
func newLogin() (Login, error) {
p, err := hash("admin")
if err != nil {
return Login{}, err
}
return Login{Username: "admin", Password: p}, nil
}
func hash(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
return string(bytes), err
}
func checkHash(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
// CheckLogin checks if the user is logged in
func CheckLogin(w http.ResponseWriter, r *http.Request) (*sessions.Session, bool, error) {
session, err := store.Get(r, "piplayer-session")
if err != nil {
return nil, false, err
}
return session, session.Values["x-forwarded-for"] != nil, nil
}
// LoginHandler handles login requests
func LoginHandler(conf *Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session, loggedIn, err := CheckLogin(w, r)
if err != nil {
log.Println("error trying to retrieve session on login page:", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// if already logged in the user has already been redirected.
// rest of logic can be ignored.
if loggedIn {
http.Redirect(w, r, "/control", http.StatusFound)
return
}
if r.Method == "GET" {
tempControl := TemplateHandler{
filename: "login.html",
data: map[string]interface{}{
"location": conf.Location,
},
}
tempControl.ServeHTTP(w, r)
return
} else if r.Method != "POST" {
log.Println("Unsuported request type for Settings page:", r.Method)
return
}
// process POST request
xForward := r.Header.Get("x-forwarded-for")
if conf.Debug {
log.Println("attempted login request from:", xForward, r.RemoteAddr)
}
if err := r.ParseForm(); err != nil {
log.Println("Error trying to parse form in login page.\n", err)
}
username := r.PostFormValue("username")
password := r.PostFormValue("password")
// if there's no login entry in the config file, add the default login details
if conf.Login.Username == "" {
if conf.Debug {
log.Println("no login details found in config file, creating default login details now.")
}
var err error
if conf.Login, err = newLogin(); err != nil {
log.Println("error trying to save default username and password")
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := conf.Save(""); err != nil {
log.Println("error trying to save config file:", err)
}
}
if username == conf.Login.Username && checkHash(password, conf.Login.Password) {
// user successfully logged in
session.Values["x-forwarded-for"] = xForward
session.Save(r, w)
http.Redirect(w, r, "/control", http.StatusFound)
return
}
tempControl := TemplateHandler{
filename: "login.html",
data: map[string]interface{}{
"location": conf.Location,
"flashMessage": "Incorrect username or password",
},
}
tempControl.ServeHTTP(w, r)
}
}
// LogoutHandler logs a user out and redirects them to the login page
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "piplayer-session")
if err != nil {
log.Println("error trying to get session in logout page")
}
session.Options.MaxAge = -1
if err := session.Save(r, w); err != nil {
log.Println("error trying to set MaxAge on session to logout")
}
http.Redirect(w, r, "/login", http.StatusFound)
}