chore(backend): polish things up a little
This commit is contained in:
parent
950fe47f52
commit
f800cafb1d
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -10,19 +11,26 @@ type App struct {
|
||||||
UserHandler *UserHandler
|
UserHandler *UserHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define the serve function
|
||||||
func (h *App) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
func (h *App) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||||
var head string
|
var head string
|
||||||
head, req.URL.Path = ShiftPath(req.URL.Path)
|
head, req.URL.Path = ShiftPath(req.URL.Path)
|
||||||
switch head {
|
switch head {
|
||||||
|
// Start the user handler should the requested user be found
|
||||||
case "user":
|
case "user":
|
||||||
h.UserHandler.Handle(res, req)
|
h.UserHandler.Handle(res, req)
|
||||||
|
// Return a `Not Found` if the user is not found
|
||||||
default:
|
default:
|
||||||
http.Error(res, "Not Found", http.StatusNotFound)
|
http.Error(res, "Not Found", http.StatusNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run the server
|
||||||
func main() {
|
func main() {
|
||||||
|
// Initialise the user handler
|
||||||
user_handler, err := NewUserHandler()
|
user_handler, err := NewUserHandler()
|
||||||
|
|
||||||
|
// Log any errors
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
@ -35,6 +43,7 @@ func main() {
|
||||||
if port == "" {
|
if port == "" {
|
||||||
port = "7741"
|
port = "7741"
|
||||||
}
|
}
|
||||||
log.Println("Ambition going strong at port 7741")
|
// Log that the program has successfully started listening to the port
|
||||||
|
log.Println(fmt.Sprintf("Ambition backend listening to port %v", port))
|
||||||
http.ListenAndServe(":"+port, a)
|
http.ListenAndServe(":"+port, a)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
// The standard stuff
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
// Encryption
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
@ -14,31 +16,39 @@ import (
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
|
// SQL databasing
|
||||||
"database/sql"
|
"database/sql"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Define the user handler struct
|
||||||
type UserHandler struct {
|
type UserHandler struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
jwt_secret *ecdsa.PrivateKey
|
jwt_secret *ecdsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define the user request struct
|
||||||
type UserRequest struct {
|
type UserRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define the function to create user handlers
|
||||||
func NewUserHandler() (*UserHandler, error) {
|
func NewUserHandler() (*UserHandler, error) {
|
||||||
|
// Initialise the database using the database file
|
||||||
db, err := sql.Open("sqlite3", "users.db")
|
db, err := sql.Open("sqlite3", "users.db")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define the JSON web token
|
||||||
jwt_secret, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
jwt_secret, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
// Return any errors
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the user handler struct
|
||||||
return &UserHandler{
|
return &UserHandler{
|
||||||
db: db,
|
db: db,
|
||||||
jwt_secret: jwt_secret,
|
jwt_secret: jwt_secret,
|
||||||
|
@ -53,6 +63,7 @@ func (h *UserHandler) Handle(res http.ResponseWriter, req *http.Request) {
|
||||||
h.updateUser(res, req)
|
h.updateUser(res, req)
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
h.deleteUser(res, req)
|
h.deleteUser(res, req)
|
||||||
|
// Return an error message should an invalid method be used
|
||||||
default:
|
default:
|
||||||
http.Error(res, "Only POST, PUT, and DELETE are valid methods", http.StatusMethodNotAllowed)
|
http.Error(res, "Only POST, PUT, and DELETE are valid methods", http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
|
@ -78,14 +89,14 @@ func (h *UserHandler) createUser(res http.ResponseWriter, req *http.Request) {
|
||||||
password := []byte(user_request.Password)
|
password := []byte(user_request.Password)
|
||||||
|
|
||||||
// Password checks
|
// Password checks
|
||||||
// -------------------
|
|
||||||
row := h.db.QueryRow("SELECT pwdhash FROM users WHERE name=?", name)
|
row := h.db.QueryRow("SELECT pwdhash FROM users WHERE name=?", name)
|
||||||
var db_pwdhash string
|
var db_pwdhash string
|
||||||
|
|
||||||
if err = row.Scan(&db_pwdhash); err != nil {
|
if err = row.Scan(&db_pwdhash); err != nil {
|
||||||
// If no user found with name, create the user
|
// If no user is found with the requested name, create the user
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
pwdhash_bytes, err := bcrypt.GenerateFromPassword(password, 12)
|
pwdhash_bytes, err := bcrypt.GenerateFromPassword(password, 12)
|
||||||
|
// Log any errors
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(res, fmt.Sprintf("user: failed to generate password hash (%s)", err), http.StatusInternalServerError)
|
http.Error(res, fmt.Sprintf("user: failed to generate password hash (%s)", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|
Reference in a new issue