mirror of
https://github.com/adanrsantos/ThePlaceHolders.git
synced 2024-12-16 05:50:39 -06:00
Merge branch 'main' of https://github.com/adanrsantos/ThePlaceHolders
This commit is contained in:
commit
73866b79f4
|
@ -17,6 +17,9 @@ let image = new ImageData(DATA_SIZE, DATA_SIZE);
|
||||||
let bitmap = null;
|
let bitmap = null;
|
||||||
|
|
||||||
window.addEventListener("load", async (e) => {
|
window.addEventListener("load", async (e) => {
|
||||||
|
for (let x = 0; x < DATA_SIZE * DATA_SIZE * 4; x++) {
|
||||||
|
image.data[x] = 255;
|
||||||
|
}
|
||||||
// Create drawable image, update it every half second
|
// Create drawable image, update it every half second
|
||||||
await redraw();
|
await redraw();
|
||||||
setInterval(redraw, 500);
|
setInterval(redraw, 500);
|
||||||
|
@ -46,17 +49,28 @@ function draw() {
|
||||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mousePosition(e) {
|
||||||
|
let x = e.clientX - canvas.getBoundingClientRect().left;
|
||||||
|
let y = e.clientY - canvas.getBoundingClientRect().top;
|
||||||
|
let cx = Math.round(x / (CANVAS_SIZE * scale) * DATA_SIZE - offx - 0.5);
|
||||||
|
let cy = Math.round(y / (CANVAS_SIZE * scale) * DATA_SIZE - offy - 0.5);
|
||||||
|
return {x: cx, y: cy};
|
||||||
|
}
|
||||||
|
|
||||||
canvas.addEventListener("wheel", async (e) => {
|
canvas.addEventListener("wheel", async (e) => {
|
||||||
|
let mouse = mousePosition(e);
|
||||||
|
console.log(mouse);
|
||||||
let oldScale = scale;
|
let oldScale = scale;
|
||||||
if (e.deltaY < 0) {
|
if (e.deltaY < 0) {
|
||||||
scale += 0.1;
|
scale += 0.1;
|
||||||
} else if (e.deltaY > 0) {
|
} else if (e.deltaY > 0) {
|
||||||
scale -= 0.1;
|
scale -= 0.1;
|
||||||
}
|
}
|
||||||
/*
|
let diff = (CANVAS_SIZE / oldScale) - (CANVAS_SIZE / scale);
|
||||||
offX += (DATA_SIZE * scale - DATA_SIZE * oldScale) / 2;
|
let ratiox = (mouse.x - (CANVAS_SIZE / 2)) / CANVAS_SIZE;
|
||||||
offY += (DATA_SIZE * scale - DATA_SIZE * oldScale) / 2;
|
let ratioy = (mouse.y - (CANVAS_SIZE / 2)) / CANVAS_SIZE;
|
||||||
*/
|
offx += diff * ratiox;
|
||||||
|
offy += diff * ratioy;
|
||||||
draw(image);
|
draw(image);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -77,17 +91,12 @@ canvas.addEventListener("mousedown", async (e) => {
|
||||||
canvas.addEventListener("mouseup", async (e) => {
|
canvas.addEventListener("mouseup", async (e) => {
|
||||||
if (e.button == 0 && mouseClicked) {
|
if (e.button == 0 && mouseClicked) {
|
||||||
mouseClicked = false;
|
mouseClicked = false;
|
||||||
|
|
||||||
clickx = e.clientX;
|
clickx = e.clientX;
|
||||||
clicky = e.clientY;
|
clicky = e.clientY;
|
||||||
|
let mouse = mousePosition(e);
|
||||||
let x = e.clientX - canvas.getBoundingClientRect().left;
|
let cx = mouse.x;
|
||||||
let y = e.clientY - canvas.getBoundingClientRect().top;
|
let cy = mouse.y;
|
||||||
|
|
||||||
let cx = Math.round(x / (CANVAS_SIZE * scale) * DATA_SIZE - offx);
|
|
||||||
let cy = Math.round(y / (CANVAS_SIZE * scale) * DATA_SIZE - offy);
|
|
||||||
|
|
||||||
console.log(cx, cy);
|
|
||||||
if (cx < 0 || cx > CANVAS_SIZE || cy < 0 || cy > CANVAS_SIZE) {
|
if (cx < 0 || cx > CANVAS_SIZE || cy < 0 || cy > CANVAS_SIZE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
55
static/contact.css
Normal file
55
static/contact.css
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
*, *:before, *:after {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
float: left;
|
||||||
|
width: 33.3%;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section {
|
||||||
|
padding: 30px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #bf7016;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container::after, .row::after {
|
||||||
|
content: "";
|
||||||
|
clear: both;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 650px) {
|
||||||
|
.column {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
95
static/contact.html
Normal file
95
static/contact.html
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Contact</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
<link href="./contact.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="about-section">
|
||||||
|
<h1>About Us / Contact Page</h1>
|
||||||
|
<p>Who are we??</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 style="text-align:center">Team</h2>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<img src="/image.png" alt="Joe" style="width:100%">
|
||||||
|
<div class="container">
|
||||||
|
<h2>Joe</h2>
|
||||||
|
<p class="role">back-end</p>
|
||||||
|
<p>Lorem ipsum dolor sit amet.</p>
|
||||||
|
<p>joe@Placeholders.com</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<img src="meow.jpg" alt="Joe2" style="width:100%">
|
||||||
|
<div class="container">
|
||||||
|
<h2>Joe 2</h2>
|
||||||
|
<p class="role">front-end</p>
|
||||||
|
<p>Lorem ipsum dolor sit amet.</p>
|
||||||
|
<p>joe2@Placeholders.com</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<img src="/woof.jpg" alt="Joe3" style="width:100%">
|
||||||
|
<div class="container">
|
||||||
|
<h2>Joe 3</h2>
|
||||||
|
<p class="role">stinky</p>
|
||||||
|
<p>Lorem ipsum dolor sit amet.</p>
|
||||||
|
<p>joe3@Placeholders.com</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<img src="/image.png" alt="Joe4" style="width:100%">
|
||||||
|
<div class="container">
|
||||||
|
<h2>Joe4</h2>
|
||||||
|
<p class="role">back-end</p>
|
||||||
|
<p>Lorem ipsum dolor sit amet.</p>
|
||||||
|
<p>joe@Placeholders.com</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<img src="meow.jpg" alt="Joe5" style="width:100%">
|
||||||
|
<div class="container">
|
||||||
|
<h2>Joe 5</h2>
|
||||||
|
<p class="role">front-end</p>
|
||||||
|
<p>Lorem ipsum dolor sit amet.</p>
|
||||||
|
<p>joe2@Placeholders.com</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<img src="/woof.jpg" alt="Joe6" style="width:100%">
|
||||||
|
<div class="container">
|
||||||
|
<h2>Joe 6</h2>
|
||||||
|
<p class="role">stinky</p>
|
||||||
|
<p>Lorem ipsum dolor sit amet.</p>
|
||||||
|
<p>joe3@Placeholders.com</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -16,7 +16,6 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="./register.html"> Register </a>
|
<a href="./register.html"> Register </a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="./login.html"> Login </a>
|
<a href="./login.html"> Login </a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -37,6 +36,9 @@
|
||||||
</li>
|
</li>
|
||||||
<a href="./secret"> Secret </a>
|
<a href="./secret"> Secret </a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="/contact.html"> Contact </a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
37
users.go
37
users.go
|
@ -11,10 +11,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const SESSION_COOKIE_NAME = "utsa-place-session"
|
const SESSION_COOKIE_NAME = "utsa-place-session"
|
||||||
|
const SESSION_EMAIL = "email"
|
||||||
const SESSION_AUTH = "auth"
|
const SESSION_AUTH = "auth"
|
||||||
const SESSION_STARTED = "age"
|
const SESSION_STARTED = "age"
|
||||||
const SESSION_CONFIRMED = "confirmed"
|
|
||||||
const SESSION_CONFIRM_KEY = "confirm-key"
|
|
||||||
|
|
||||||
const ENCRYPTION_STRENGTH = 14
|
const ENCRYPTION_STRENGTH = 14
|
||||||
|
|
||||||
|
@ -23,11 +22,13 @@ type UserData struct {
|
||||||
Password string
|
Password string
|
||||||
AccountCreated time.Time
|
AccountCreated time.Time
|
||||||
LastLogin time.Time
|
LastLogin time.Time
|
||||||
|
EmailCode string
|
||||||
|
Verified bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func validate_email(email string) (string, bool) {
|
func validate_email(email string) (string, bool) {
|
||||||
email = strings.ToLower(email)
|
email = strings.ToLower(email)
|
||||||
regex := regexp.MustCompile("^[a-z]+.[a-z]+@(my.)?utsa.edu")
|
regex := regexp.MustCompile("^[a-z0-9]+.[a-z0-9]+@(my.)?utsa.edu")
|
||||||
ok := regex.MatchString(email)
|
ok := regex.MatchString(email)
|
||||||
return email, ok
|
return email, ok
|
||||||
}
|
}
|
||||||
|
@ -51,7 +52,7 @@ func (s *Server) handle_login(w http.ResponseWriter, r *http.Request) {
|
||||||
http.ServeFile(w, r, "./static/login.html")
|
http.ServeFile(w, r, "./static/login.html")
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
// Get data from form
|
// Get data from form
|
||||||
email := r.FormValue("email")
|
email := strings.ToLower(r.FormValue("email"))
|
||||||
password := r.FormValue("password")
|
password := r.FormValue("password")
|
||||||
// Get user from database
|
// Get user from database
|
||||||
user, ok := s.Users[email]
|
user, ok := s.Users[email]
|
||||||
|
@ -75,9 +76,15 @@ func (s *Server) handle_login(w http.ResponseWriter, r *http.Request) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
session.Values[SESSION_AUTH] = true
|
session.Values[SESSION_AUTH] = true
|
||||||
session.Values[SESSION_STARTED] = now.String()
|
session.Values[SESSION_STARTED] = now.String()
|
||||||
|
session.Values[SESSION_EMAIL] = user.Email
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
// Update last-login on DB
|
// Update last-login on DB
|
||||||
user.LastLogin = now
|
user.LastLogin = now
|
||||||
|
// If email not verified, go to verified page
|
||||||
|
if user.Verified {
|
||||||
|
s.handle_confirmation(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
s.Users[email] = user
|
s.Users[email] = user
|
||||||
// Redirect to index.html
|
// Redirect to index.html
|
||||||
fmt.Println("Logged in user: ", email)
|
fmt.Println("Logged in user: ", email)
|
||||||
|
@ -124,12 +131,13 @@ func (s *Server) handle_register(w http.ResponseWriter, r *http.Request) {
|
||||||
Password: hash_password(password),
|
Password: hash_password(password),
|
||||||
AccountCreated: now,
|
AccountCreated: now,
|
||||||
LastLogin: now,
|
LastLogin: now,
|
||||||
|
EmailCode: "123456",
|
||||||
|
Verified: false,
|
||||||
}
|
}
|
||||||
// Make session valid
|
// Make session valid
|
||||||
session.Values[SESSION_AUTH] = true
|
session.Values[SESSION_AUTH] = true
|
||||||
session.Values[SESSION_STARTED] = now.String()
|
session.Values[SESSION_STARTED] = now.String()
|
||||||
session.Values[SESSION_CONFIRMED] = false
|
session.Values[SESSION_EMAIL] = email
|
||||||
session.Values[SESSION_CONFIRM_KEY] = "asdf"
|
|
||||||
// Send session token to browser
|
// Send session token to browser
|
||||||
session.Save(r, w)
|
session.Save(r, w)
|
||||||
// Redirect to index.html
|
// Redirect to index.html
|
||||||
|
@ -147,17 +155,26 @@ func (s *Server) handle_confirmation(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Redirect(w, r, "/register", http.StatusFound)
|
http.Redirect(w, r, "/register", http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
email := session.Values[SESSION_EMAIL].(string)
|
||||||
|
user, ok := s.Users[email]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
switch r.Method {
|
switch r.Method {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
confirmed := session.Values[SESSION_CONFIRMED].(bool)
|
fmt.Println("User email confirmed: ", user.Verified)
|
||||||
fmt.Println("User email confirmed: ", confirmed)
|
if user.Verified {
|
||||||
if confirmed {
|
|
||||||
http.Redirect(w, r, "/", http.StatusFound)
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
} else {
|
} else {
|
||||||
http.ServeFile(w, r, "./static/confirmation.html")
|
http.ServeFile(w, r, "./static/confirmation.html")
|
||||||
}
|
}
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
default:
|
code := r.FormValue("code")
|
||||||
|
if user.EmailCode == code {
|
||||||
|
http.Redirect(w, r, "/", http.StatusAccepted)
|
||||||
|
} else {
|
||||||
|
http.Redirect(w, r, "/confirm-email", http.StatusForbidden)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue