Add login endpoint and generate a valid token
This commit is contained in:
parent
83a2d2a31f
commit
9b6f7cbdcc
6 changed files with 89 additions and 11 deletions
|
@ -1,10 +1,24 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (a *API) Login(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "FROM API")
|
||||
body := ParseBody(r)
|
||||
username := body.String("username")
|
||||
password := body.String("password")
|
||||
|
||||
token, err := a.App.Login(username, password)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if token == "" {
|
||||
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write([]byte(token))
|
||||
}
|
||||
|
|
28
server/app/auth.go
Normal file
28
server/app/auth.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"git.ctrlz.es/mgdelacroix/craban/utils"
|
||||
)
|
||||
|
||||
func (a *App) Login(username, password string) (string, error) {
|
||||
user, err := a.store.User().GetByUsername(username)
|
||||
if err == sql.ErrNoRows {
|
||||
return "", nil
|
||||
} else if err != nil {
|
||||
return "", fmt.Errorf("cannot get user by username: %w", err)
|
||||
}
|
||||
|
||||
if !utils.CheckHash(user.Password, password) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
token, err := utils.GenerateToken(user.ID, *a.config.Secret)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot generate token: %w", err)
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
|
@ -5,11 +5,11 @@ import (
|
|||
)
|
||||
|
||||
type User struct {
|
||||
ID int
|
||||
Name string
|
||||
Mail string
|
||||
Username string
|
||||
Password string
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Mail string `json:"mail"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"-"`
|
||||
}
|
||||
|
||||
func (u *User) IsValid() error {
|
||||
|
|
|
@ -68,6 +68,29 @@ func (us *UserStore) GetByID(id int) (*model.User, error) {
|
|||
return users[0], nil
|
||||
}
|
||||
|
||||
func (us *UserStore) GetByUsername(username string) (*model.User, error) {
|
||||
query := us.Q().Select(userColumns...).
|
||||
From("users").
|
||||
Where(sq.Eq{"username": username})
|
||||
|
||||
rows, err := query.Query()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
users, err := us.usersFromRows(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(users) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
|
||||
return users[0], nil
|
||||
}
|
||||
|
||||
func (us *UserStore) Create(user *model.User) (*model.User, error) {
|
||||
query := us.Q().Insert("users").
|
||||
Columns(userColumns[1:]...).
|
||||
|
|
|
@ -5,7 +5,13 @@ export class Client {
|
|||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password })
|
||||
}).then(r => r.text()).then(token => {
|
||||
}).then(r => {
|
||||
if (r.status === 200) {
|
||||
return r.text()
|
||||
}
|
||||
console.error("INVALID")
|
||||
throw new Error("invalid credentials")
|
||||
}).then(token => {
|
||||
localStorage.setItem('token', token)
|
||||
return token
|
||||
})
|
||||
|
|
|
@ -18,12 +18,17 @@ const Login = () => {
|
|||
|
||||
const [username, setUsername] = useState("")
|
||||
const [password, setPassword] = useState("")
|
||||
const [error, setError] = useState("")
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
client.login(username, password).then(token => {
|
||||
client.login(username, password)
|
||||
.then(token => {
|
||||
setToken(token)
|
||||
})
|
||||
.catch(e => {
|
||||
setError(e.toString())
|
||||
})
|
||||
}
|
||||
|
||||
const handleChange = (setFn) => {
|
||||
|
@ -52,6 +57,8 @@ const Login = () => {
|
|||
onChange={handleChange(setPassword)}
|
||||
/>
|
||||
|
||||
{error !== "" && <p style={{color: 'red'}}>{error}</p>}
|
||||
|
||||
<Button variant="contained" color="primary" onClick={handleSubmit}>Login</Button>
|
||||
</Box>
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue