Added authentication system

This commit is contained in:
Logan 2024-09-26 01:11:22 -05:00
parent b66de955cf
commit 0e7d1a43e2
7 changed files with 139 additions and 36 deletions

View file

@ -2,9 +2,15 @@
"UTSA Place" Collaborate website canvas that allows students to place a pixel
within a restricted amount of time to make art.
## How to run
1. Install [Go](https://go.dev/dl/)
2. Run the command `go run .` inside this folder
3. View the website at [127.0.0.1:8080](http://127.0.0.1:8080/)
## Backend Source
Our back-end is written in [Go](https://go.dev/) using the standard library.
* [Server](server.go)
* [Request handling](server.go)
* [User registration/login](users.go)
## Frontend Source
Our front-end is written in vanilla JavaScript, using the [Bootstrap](https://getbootstrap.com/)

Binary file not shown.

6
go.mod
View file

@ -1,3 +1,7 @@
module github.com/adanrsantos/ThePlaceHolders
go 1.23.1
go 1.23
require github.com/gorilla/sessions v1.4.0
require github.com/gorilla/securecookie v1.1.2 // indirect

6
go.sum Normal file
View file

@ -0,0 +1,6 @@
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=

View file

@ -1,58 +1,51 @@
package main
import (
"crypto/rand"
"fmt"
"log"
"net/http"
"github.com/gorilla/sessions"
)
const ADDRESS = "127.0.0.1"
const PORT = "8080"
type UserForm struct {
Email string
Password string
}
func extract_user_data(r *http.Request) UserForm {
return UserForm{
Email: r.FormValue("email"),
Password: r.FormValue("password"),
}
}
func handle_login(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
return
}
data := extract_user_data(r)
fmt.Fprintln(w, data.Email)
fmt.Fprintln(w, data.Password)
}
func handle_register(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
return
}
data := extract_user_data(r)
fmt.Fprintln(w, data.Email)
fmt.Fprintln(w, data.Password)
type Server struct {
Users map[string]UserData
Sessions *sessions.CookieStore
}
func main() {
// Set up encryption for session tokens
fmt.Print("Generating encryption key... ")
secret := make([]byte, 32)
_, err := rand.Read(secret)
if err != nil {
fmt.Println("Error generating key:")
log.Fatal(err)
return
}
fmt.Println("Done!")
// Create server object
server := Server{
Users: make(map[string]UserData),
Sessions: sessions.NewCookieStore(secret),
}
// Host static files
static_files := http.FileServer(http.Dir("static/"))
http.Handle("/", static_files)
// Response generated by code
http.HandleFunc("/handle-register", handle_register)
http.HandleFunc("/handle-login", handle_login)
http.HandleFunc("/handle-register", server.handle_register)
http.HandleFunc("/handle-login", server.handle_login)
// Start web server at 127.0.0.1:8080
fmt.Printf("Listening to %s on port %s...\n", ADDRESS, PORT)
e := http.ListenAndServe(ADDRESS+":"+PORT, nil)
// Print any errors
if e != nil {
fmt.Println(e)
} else {
fmt.Println("Started server successfully")
fmt.Println("Error starting server:")
log.Fatal(e)
}
}

91
users.go Normal file
View file

@ -0,0 +1,91 @@
package main
import (
"net/http"
"time"
)
const SESSION_COOKIE_NAME = "utsa-place-session"
const SESSION_AUTH = "auth"
type UserData struct {
Email string `json:"email"`
Password string `json:"password"`
AccountCreated time.Time `json:"account-created"`
LastLogin time.Time `json:"last-login"`
}
func (s *Server) handle_login(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// Get data from form
email := r.FormValue("email")
password := r.FormValue("password")
// Get user from database
user, ok := s.Users[email]
// If user does not exist
if !ok {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// If password does not match
if password != user.Password {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// Generate session
session, err := s.Sessions.Get(r, SESSION_COOKIE_NAME)
if err != nil {
http.Error(w, "Internal Error", http.StatusInternalServerError)
return
}
session.Values[SESSION_AUTH] = true
if err := session.Save(r, w); err != nil {
http.Error(w, "Internal Error", http.StatusInternalServerError)
return
}
// Update last-login on DB
user.LastLogin = time.Now()
s.Users[email] = user
// Redirect to index.html
http.Redirect(w, r, "/", http.StatusFound)
}
func (s *Server) handle_register(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// Get data from form
email := r.FormValue("email")
password := r.FormValue("password")
// Check that this email is not already registered
if _, ok := s.Users[email]; ok {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
// Generate session
session, err := s.Sessions.Get(r, SESSION_COOKIE_NAME)
if err != nil {
http.Error(w, "Internal Error", http.StatusInternalServerError)
return
}
// Save user information to DB
s.Users[email] = UserData{
Email: email,
Password: password,
AccountCreated: time.Now(),
LastLogin: time.Now(),
}
// Make session valid
session.Values[SESSION_AUTH] = true
// Send session token to browser
if err := session.Save(r, w); err != nil {
http.Error(w, "Internal Error", http.StatusInternalServerError)
return
}
// Redirect to index.html
http.Redirect(w, r, "/", http.StatusFound)
}

3
users.json Normal file
View file

@ -0,0 +1,3 @@
{
"users" = {}
}