mirror of
https://github.com/simon987/task_tracker.git
synced 2025-04-19 18:16:45 +00:00
some work on auth/sessions
This commit is contained in:
parent
d3188c512d
commit
9e09246a29
53
api/auth.go
Normal file
53
api/auth.go
Normal file
@ -0,0 +1,53 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/kataras/go-sessions"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
)
|
||||
|
||||
type LoginRequest struct {
|
||||
Username []byte
|
||||
Password []byte
|
||||
}
|
||||
|
||||
type LoginResponse struct {
|
||||
Ok bool
|
||||
Message string
|
||||
Manager *storage.Manager
|
||||
}
|
||||
|
||||
func (api *WebAPI) Login(r *Request) {
|
||||
|
||||
req := &LoginRequest{}
|
||||
err := json.Unmarshal(r.Ctx.Request.Body(), req)
|
||||
|
||||
if err != nil {
|
||||
r.Json(LoginResponse{
|
||||
Ok: false,
|
||||
Message: "Could not parse request",
|
||||
}, 400)
|
||||
return
|
||||
}
|
||||
|
||||
manager, err := api.Database.ValidateCredentials(req.Username, req.Password)
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithFields(logrus.Fields{
|
||||
"username": string(manager.Username),
|
||||
}).Warning("Login attempt")
|
||||
|
||||
r.Json(LoginResponse{
|
||||
Ok: false,
|
||||
Message: "Invalid username/password",
|
||||
}, 403)
|
||||
return
|
||||
}
|
||||
|
||||
sess := sessions.StartFasthttp(r.Ctx)
|
||||
sess.Set("manager", manager)
|
||||
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"username": string(manager.Username),
|
||||
}).Info("Logged in")
|
||||
}
|
@ -7,10 +7,10 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"github.com/valyala/fasthttp"
|
||||
"hash"
|
||||
"src/task_tracker/config"
|
||||
"src/task_tracker/storage"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -4,9 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"github.com/valyala/fasthttp"
|
||||
"src/task_tracker/config"
|
||||
"src/task_tracker/storage"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
11
api/main.go
11
api/main.go
@ -4,15 +4,17 @@ import (
|
||||
"fmt"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/buaazp/fasthttprouter"
|
||||
"github.com/kataras/go-sessions"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"github.com/valyala/fasthttp"
|
||||
"src/task_tracker/config"
|
||||
"src/task_tracker/storage"
|
||||
)
|
||||
|
||||
type WebAPI struct {
|
||||
server *fasthttp.Server
|
||||
router *fasthttprouter.Router
|
||||
Database *storage.Database
|
||||
SessionConfig *sessions.Config
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
@ -36,6 +38,11 @@ func New() *WebAPI {
|
||||
|
||||
api.router = &fasthttprouter.Router{}
|
||||
|
||||
api.SessionConfig = &sessions.Config{
|
||||
Cookie: config.Cfg.SessionCookieName,
|
||||
Expires: config.Cfg.SessionCookieExpiration,
|
||||
}
|
||||
|
||||
api.server = &fasthttp.Server{
|
||||
Handler: api.router.Handler,
|
||||
Name: info.Name,
|
||||
|
@ -3,7 +3,7 @@ package api
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"src/task_tracker/storage"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"errors"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/dchest/siphash"
|
||||
"src/task_tracker/storage"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
@ -3,8 +3,8 @@ package api
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"math/rand"
|
||||
"src/task_tracker/storage"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ package config
|
||||
import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Cfg struct {
|
||||
@ -13,6 +14,8 @@ var Cfg struct {
|
||||
WebHookSigHeader string
|
||||
LogLevel logrus.Level
|
||||
DbLogLevels []logrus.Level
|
||||
SessionCookieName string
|
||||
SessionCookieExpiration time.Duration
|
||||
}
|
||||
|
||||
func SetupConfig() {
|
||||
@ -35,4 +38,7 @@ func SetupConfig() {
|
||||
newLevel, _ := logrus.ParseLevel(level)
|
||||
Cfg.DbLogLevels = append(Cfg.DbLogLevels, newLevel)
|
||||
}
|
||||
Cfg.SessionCookieName = viper.GetString("session.cookie_name")
|
||||
Cfg.SessionCookieExpiration, err = time.ParseDuration(viper.GetString("session.expiration"))
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"math/rand"
|
||||
"src/task_tracker/api"
|
||||
"src/task_tracker/config"
|
||||
"src/task_tracker/storage"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
16
schema.sql
16
schema.sql
@ -1,5 +1,5 @@
|
||||
DROP TABLE IF EXISTS worker_identity, worker, project, task, log_entry,
|
||||
worker_has_access_to_project;
|
||||
worker_has_access_to_project, manager, manager_has_role_on_project;
|
||||
DROP TYPE IF EXISTS status;
|
||||
DROP TYPE IF EXISTS log_level;
|
||||
|
||||
@ -63,3 +63,17 @@ CREATE TABLE log_entry
|
||||
timestamp INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE manager
|
||||
(
|
||||
id SERIAL PRIMARY KEY,
|
||||
username TEXT,
|
||||
password TEXT,
|
||||
website_admin BOOLEAN
|
||||
);
|
||||
|
||||
CREATE TABLE manager_has_role_on_project
|
||||
(
|
||||
manager INTEGER REFERENCES manager (id),
|
||||
role SMALLINT,
|
||||
project INTEGER REFERENCES project (id)
|
||||
);
|
121
storage/auth.go
Normal file
121
storage/auth.go
Normal file
@ -0,0 +1,121 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"errors"
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ManagerRole int
|
||||
|
||||
const (
|
||||
ROLE_READ ManagerRole = 1
|
||||
ROLE_EDIT ManagerRole = 2
|
||||
ROLE_MANAGE_ACCESS ManagerRole = 3
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
Id int `json:"id"`
|
||||
Username string `json:"username"`
|
||||
WebsiteAdmin bool `json:"website_admin"`
|
||||
}
|
||||
|
||||
func (database *Database) ValidateCredentials(username []byte, password []byte) (*Manager, error) {
|
||||
|
||||
db := database.getDB()
|
||||
|
||||
row := db.QueryRow(`SELECT id, password, website_admin FROM manager WHERE username=$1`,
|
||||
username)
|
||||
|
||||
manager := &Manager{}
|
||||
var passwordHash []byte
|
||||
err := row.Scan(&manager.Id, &passwordHash, &manager.WebsiteAdmin)
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithFields(logrus.Fields{
|
||||
"username": username,
|
||||
}).Warning("Database.ValidateCredentials: user not found")
|
||||
|
||||
return nil, errors.New("username not found")
|
||||
}
|
||||
|
||||
hash := crypto.SHA512.New()
|
||||
hash.Write([]byte(password))
|
||||
hash.Write([]byte(username))
|
||||
|
||||
if bytes.Compare(passwordHash, hash.Sum(nil)) != 0 {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"username": username,
|
||||
}).Warning("Database.ValidateCredentials: password does not match")
|
||||
|
||||
return nil, errors.New("password does not match")
|
||||
}
|
||||
|
||||
manager.Username = string(username)
|
||||
|
||||
return manager, nil
|
||||
}
|
||||
|
||||
func (database *Database) SaveManager(manager *Manager, password []byte) error {
|
||||
|
||||
db := database.getDB()
|
||||
|
||||
hash := crypto.SHA512.New()
|
||||
hash.Write(password)
|
||||
hashedPassword := hash.Sum(nil)
|
||||
|
||||
row := db.QueryRow(`INSERT INTO manager (username, password, website_admin)
|
||||
VALUES ($1,$2,$3) RETURNING ID`,
|
||||
manager.Username, hashedPassword, manager.WebsiteAdmin)
|
||||
|
||||
err := row.Scan(manager.Id)
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithFields(logrus.Fields{
|
||||
"username": manager,
|
||||
}).Warning("Database.SaveManager INSERT error")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"manager": manager,
|
||||
}).Info("Database.SaveManager INSERT")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (database *Database) UpdateManager(manager *Manager) {
|
||||
|
||||
db := database.getDB()
|
||||
|
||||
res, err := db.Exec(`UPDATE manager SET website_admin=$1 WHERE id=$2`,
|
||||
manager.WebsiteAdmin, manager.Id)
|
||||
handleErr(err)
|
||||
|
||||
rowsAffected, _ := res.RowsAffected()
|
||||
|
||||
logrus.WithError(err).WithFields(logrus.Fields{
|
||||
"rowsAffected": rowsAffected,
|
||||
"manager": manager,
|
||||
}).Warning("Database.UpdateManager UPDATE")
|
||||
}
|
||||
|
||||
func (database *Database) UpdateManagerPassword(id int64, newPassword []byte) {
|
||||
|
||||
hash := crypto.SHA512.New()
|
||||
hash.Write(newPassword)
|
||||
hashedPassword := hash.Sum(nil)
|
||||
|
||||
db := database.getDB()
|
||||
|
||||
res, err := db.Exec(`UPDATE manager SET password=$1 WHERE id=$2`,
|
||||
hashedPassword, id)
|
||||
handleErr(err)
|
||||
|
||||
rowsAffected, _ := res.RowsAffected()
|
||||
|
||||
logrus.WithError(err).WithFields(logrus.Fields{
|
||||
"rowsAffected": rowsAffected,
|
||||
"id": id,
|
||||
}).Warning("Database.UpdateManagerPassword UPDATE")
|
||||
}
|
@ -4,9 +4,9 @@ import (
|
||||
"database/sql"
|
||||
"github.com/Sirupsen/logrus"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"src/task_tracker/config"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
|
@ -3,7 +3,7 @@ package storage
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"src/task_tracker/config"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
)
|
||||
|
||||
type LogEntry struct {
|
||||
|
@ -5,9 +5,9 @@ import (
|
||||
"crypto"
|
||||
"crypto/hmac"
|
||||
"encoding/hex"
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"net/http"
|
||||
"src/task_tracker/api"
|
||||
"src/task_tracker/config"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -2,8 +2,8 @@ package test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"io/ioutil"
|
||||
"src/task_tracker/api"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -4,9 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"io/ioutil"
|
||||
"src/task_tracker/api"
|
||||
"src/task_tracker/storage"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
@ -3,9 +3,9 @@ package test
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"src/task_tracker/api"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"src/task_tracker/api"
|
||||
"src/task_tracker/config"
|
||||
"src/task_tracker/storage"
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
@ -50,23 +50,3 @@ func BenchmarkCreateTask(b *testing.B) {
|
||||
_ = db.SaveTask(&storage.Task{}, project, 0)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTest(t *testing.T) {
|
||||
|
||||
config.SetupConfig()
|
||||
db := storage.Database{}
|
||||
|
||||
project, _ := db.SaveProject(&storage.Project{
|
||||
Priority: 1,
|
||||
Id: 1,
|
||||
Version: "bmcreatetask",
|
||||
Public: true,
|
||||
Motd: "bmcreatetask",
|
||||
Name: "BenchmarkCreateTask",
|
||||
GitRepo: "benchmark_test",
|
||||
})
|
||||
|
||||
for i := 0; i < 1000000; i++ {
|
||||
_ = db.SaveTask(&storage.Task{}, project, 0)
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ package test
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"io/ioutil"
|
||||
"src/task_tracker/api"
|
||||
"src/task_tracker/storage"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -3,10 +3,10 @@ package test
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"src/task_tracker/api"
|
||||
"src/task_tracker/storage"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -7,11 +7,11 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"github.com/simon987/task_tracker/storage"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"src/task_tracker/config"
|
||||
"src/task_tracker/storage"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
@ -3,8 +3,8 @@ server:
|
||||
|
||||
database:
|
||||
conn_str: "user=task_tracker dbname=task_tracker_test sslmode=disable"
|
||||
# log_levels: ["debug", "error"]
|
||||
log_levels: ["debug", "error", "trace", "info", "warning"]
|
||||
log_levels: ["debug", "error"]
|
||||
# log_levels: ["debug", "error", "trace", "info", "warning"]
|
||||
|
||||
git:
|
||||
webhook_secret: "very_secret_secret"
|
||||
@ -13,3 +13,7 @@ git:
|
||||
|
||||
log:
|
||||
level: "trace"
|
||||
|
||||
session:
|
||||
cookie_name: "tt"
|
||||
expiration: "25m"
|
@ -1,8 +1,8 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"src/task_tracker/api"
|
||||
"src/task_tracker/config"
|
||||
"github.com/simon987/task_tracker/api"
|
||||
"github.com/simon987/task_tracker/config"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
@ -1,5 +1,5 @@
|
||||
DROP TABLE IF EXISTS worker_identity, worker, project, task, log_entry,
|
||||
worker_has_access_to_project;
|
||||
worker_has_access_to_project, manager, manager_has_role_on_project;
|
||||
DROP TYPE IF EXISTS status;
|
||||
DROP TYPE IF EXISTS log_level;
|
||||
|
||||
@ -63,3 +63,17 @@ CREATE TABLE log_entry
|
||||
timestamp INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE manager
|
||||
(
|
||||
id SERIAL PRIMARY KEY,
|
||||
username TEXT,
|
||||
password TEXT,
|
||||
website_admin BOOLEAN
|
||||
);
|
||||
|
||||
CREATE TABLE manager_has_role_on_project
|
||||
(
|
||||
manager INTEGER REFERENCES manager (id),
|
||||
role SMALLINT,
|
||||
project INTEGER REFERENCES project (id)
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user