started login system
This commit is contained in:
parent
bd6fbb2bce
commit
c0d546b167
|
@ -1,3 +1,4 @@
|
|||
comics
|
||||
db.sqlite
|
||||
media
|
||||
media
|
||||
secret.key
|
44
comics.go
44
comics.go
|
@ -17,10 +17,10 @@ import (
|
|||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
var errlog *log.Logger = nil
|
||||
var db *sql.DB = nil
|
||||
var errlog *log.Logger = nil
|
||||
var db *sql.DB = nil
|
||||
|
||||
var options Options = Options{}
|
||||
var options Options = Options{}
|
||||
|
||||
var NoSuchComicErr Err = Err{msg: "no such comic found"}
|
||||
|
||||
|
@ -45,25 +45,27 @@ type Options struct {
|
|||
ImagePath string
|
||||
RunManager bool
|
||||
UploadSize int64
|
||||
SiteURL string
|
||||
SiteURL string
|
||||
SecretPath string
|
||||
}
|
||||
|
||||
type Comic struct {
|
||||
ID int
|
||||
DateTime string
|
||||
Title string
|
||||
Image string
|
||||
Description string
|
||||
Tags string
|
||||
ID int
|
||||
DateTime string
|
||||
Title string
|
||||
Image string
|
||||
Description string
|
||||
Tags string
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
Comics []struct{
|
||||
No int
|
||||
Title string
|
||||
Date string
|
||||
Image string
|
||||
}
|
||||
No int
|
||||
Title string
|
||||
Date string
|
||||
Image string
|
||||
}
|
||||
|
||||
Comic *Comic
|
||||
Current int
|
||||
Previous int
|
||||
|
@ -83,7 +85,7 @@ type Err struct {
|
|||
func (o * Options) Parse() error {
|
||||
flag.StringVar(&o.DBPath, "d", "./db.sqlite", "Sets path to database file")
|
||||
flag.StringVar(&o.MediaPath, "m", "./media/", "Sets path to media directory")
|
||||
flag.StringVar(&o.TemplatesPath, "t", "./templates/", "Sets path to templates directory")
|
||||
flag.StringVar(&o.TemplatesPath, "t", "./templates/", "Sets path to templates directory")
|
||||
flag.StringVar(&o.Address, "a", "127.0.0.1", "Defines the address the web server will listen to")
|
||||
flag.IntVar(&o.Port, "p", 8080, "Defines the port the web server will listen to")
|
||||
flag.BoolVar(&o.Publish, "u", false, "Creates new commics. Needs both -i and -l")
|
||||
|
@ -92,7 +94,8 @@ func (o * Options) Parse() error {
|
|||
flag.BoolVar(&o.RunManager, "r", false, "Runs the content manager instead of the site")
|
||||
flag.Int64Var(&o.UploadSize, "z", 10, "Max upload size for posts")
|
||||
flag.StringVar(&o.SiteURL, "0", "https://comics.blackram.works", "URL of the site once deployed")
|
||||
|
||||
flag.StringVar(&o.SecretPath, "s", "./secret.key", "Sets path to secret key file")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if _, err := os.Stat(o.TemplatesPath); errors.Is(err, os.ErrNotExist) {
|
||||
|
@ -100,12 +103,11 @@ func (o * Options) Parse() error {
|
|||
}
|
||||
|
||||
if _, err := os.Stat(o.MediaPath); errors.Is(err, os.ErrNotExist) {
|
||||
err := os.Mkdir(o.MediaPath, os.ModePerm)
|
||||
err := os.Mkdir(o.MediaPath, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -375,6 +377,10 @@ func returnError(w http.ResponseWriter, r * http.Request, status int) {
|
|||
err = t.Execute(w, &c)
|
||||
}
|
||||
|
||||
func return401(w http.ResponseWriter, r * http.Request) {
|
||||
returnError(w, r, http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
func return404(w http.ResponseWriter, r * http.Request) {
|
||||
returnError(w, r, http.StatusNotFound)
|
||||
}
|
||||
|
|
5
go.mod
5
go.mod
|
@ -3,3 +3,8 @@ module tildegit.com/drevil/comics
|
|||
go 1.19
|
||||
|
||||
require github.com/mattn/go-sqlite3 v1.14.16
|
||||
|
||||
require (
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
golang.org/x/crypto v0.10.0 // indirect
|
||||
)
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1,2 +1,6 @@
|
|||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
|
|
133
manager.go
133
manager.go
|
@ -11,16 +11,75 @@ import (
|
|||
"strings"
|
||||
"net/http"
|
||||
"math/rand"
|
||||
"database/sql"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
var seededRand *rand.Rand = nil
|
||||
var secretKey string = ""
|
||||
|
||||
const authSquema string = `
|
||||
CREATE TABLE IF NOT EXISTS user (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
name CHAR(20),
|
||||
password CHAR(100)
|
||||
);`
|
||||
|
||||
type User struct {
|
||||
ID int
|
||||
Name string
|
||||
Password string
|
||||
}
|
||||
|
||||
type ConfirmContext struct {
|
||||
Action string
|
||||
Message string
|
||||
OnYes string
|
||||
OnNo string
|
||||
Action string
|
||||
Message string
|
||||
OnYes string
|
||||
OnNo string
|
||||
}
|
||||
|
||||
|
||||
func (u *User) readRow(db * sql.Rows) error {
|
||||
return db.Scan(&u.ID, &u.Name, &u.Password)
|
||||
}
|
||||
|
||||
func generateToken(username string) (string, error) {
|
||||
token := jwt.New(jwt.SigningMethodEdDSA)
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
|
||||
claims["exp"] = time.Now().Add(10 * time.Minute)
|
||||
claims["authorized"] = true
|
||||
claims["user"] = username
|
||||
|
||||
tokenString, err := token.SignedString(secretKey)
|
||||
if err != nil {
|
||||
return "Signing Error", err
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
||||
|
||||
func getAllUsers() ([]User, error) {
|
||||
rows, err := db.Query("SELECT * FROM user ORDER BY id ASC")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
users := []User{}
|
||||
for rows.Next() {
|
||||
u := User{}
|
||||
err := u.readRow(rows)
|
||||
if err != nil {
|
||||
return users, err
|
||||
}
|
||||
users = append(users, u)
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func randomString(length int) string {
|
||||
|
@ -34,7 +93,7 @@ func randomString(length int) string {
|
|||
|
||||
func managerIndexView(w http.ResponseWriter, r * http.Request) {
|
||||
var err error
|
||||
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
errlog.Println(err)
|
||||
|
@ -167,12 +226,74 @@ func managerPublishView(w http.ResponseWriter, r * http.Request) {
|
|||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func loginView(w http.ResponseWriter, r * http.Request) {
|
||||
if r.Method != "POST" {
|
||||
return404(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
username := r.FormValue("username")
|
||||
password := r.FormValue("password")
|
||||
if username == "" || password == "" {
|
||||
return404(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if len(username) >= 20 {
|
||||
username = username[:20]
|
||||
}
|
||||
if len(password) >= 100 {
|
||||
password = password[:100]
|
||||
}
|
||||
|
||||
users, _ := getAllUsers()
|
||||
var user *User = nil
|
||||
for i, u := range(users) {
|
||||
if u.Name == username {
|
||||
user = &users[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
return401(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
|
||||
return401(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func managerEditView(w http.ResponseWriter, r * http.Request) {
|
||||
}
|
||||
|
||||
func startManager(address string, port int, dbPath string, mediaPath string) error {
|
||||
_, err := db.Exec(authSquema)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
seededRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
|
||||
_, err = os.Stat(options.SecretPath)
|
||||
if os.IsNotExist(err) {
|
||||
secretKey = randomString(100)
|
||||
err = os.WriteFile(options.SecretPath, []byte(secretKey), 0600)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("failed to create random key: %s", err))
|
||||
}
|
||||
} else {
|
||||
s, err := os.ReadFile(options.SecretPath)
|
||||
secretKey = string(s)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("failed to read random key: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
http.HandleFunc("/", managerIndexView)
|
||||
http.HandleFunc("/edit/", managerEditView)
|
||||
http.HandleFunc("/remove/", managerRemoveView)
|
||||
|
|
Loading…
Reference in New Issue