/
login.go
95 lines (83 loc) · 2.56 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
// Itero - Online iterative vote application
// Copyright (C) 2020 Joseph Boudou
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package handlers
import (
"bytes"
"context"
"database/sql"
"errors"
"net/http"
"strings"
"github.com/JBoudou/Itero/mid/db"
"github.com/JBoudou/Itero/mid/root"
"github.com/JBoudou/Itero/mid/server"
)
type ProfileInfo struct {
Verified bool
}
type userInfo struct {
Id uint32
Passwd []byte
Verified bool
}
func getUserInfo(ctx context.Context, login string) (info userInfo, err error) {
const (
qName = `SELECT Id, Passwd, Verified FROM Users WHERE Name = ?`
qEmail = `SELECT Id, Passwd, Verified FROM Users WHERE Email = ?`
)
query := qName
if strings.ContainsRune(login, '@') {
query = qEmail
}
row := db.DB.QueryRowContext(ctx, query, login)
err = row.Scan(&info.Id, &info.Passwd, &info.Verified)
if err != nil && errors.Is(err, sql.ErrNoRows) {
err = server.UnauthorizedHttpError("User not found")
}
return
}
// LoginHandler starts a new session for an existing user.
func LoginHandler(ctx context.Context, response server.Response, request *server.Request) {
if err := request.CheckPOST(ctx); err != nil {
response.SendError(ctx, err)
return
}
var loginQuery struct {
User string
Passwd string
}
if err := request.UnmarshalJSONBody(&loginQuery); err != nil {
err = server.WrapError(http.StatusBadRequest, "Wrong request", err)
response.SendError(ctx, err)
return
}
userInfo, err := getUserInfo(ctx, loginQuery.User)
must(err)
hashFct, err := root.PasswdHash()
if err != nil {
response.SendError(ctx, err)
return
}
hashFct.Write([]byte(loginQuery.Passwd))
hashPwd := hashFct.Sum(nil)
if !bytes.Equal(hashPwd, userInfo.Passwd) {
response.SendError(ctx, server.UnauthorizedHttpError("Wrong password"))
return
}
response.SendLoginAccepted(ctx, server.User{Name: loginQuery.User, Id: userInfo.Id, Logged: true},
request, ProfileInfo{Verified: userInfo.Verified})
return
}