form modified to send to backend only instead of email

This commit is contained in:
Jacob Delgado 2024-08-21 13:56:18 -07:00
parent 76ac941dc0
commit 46902a9e33
10 changed files with 156 additions and 27 deletions

Binary file not shown.

View File

@ -3,7 +3,64 @@ from config import app, db, bcrypt
from models import Contact, User, Orders
from werkzeug.utils import secure_filename
from werkzeug.exceptions import RequestEntityTooLarge
import os
import json, os
import logging
from pywebpush import webpush, WebPushException
DER_BASE64_ENCODED_PRIVATE_KEY_FILE_PATH = os.path.join(os.getcwd(),"private_key.txt")
DER_BASE64_ENCODED_PUBLIC_KEY_FILE_PATH = os.path.join(os.getcwd(),"public_key.txt")
VAPID_PRIVATE_KEY = open(DER_BASE64_ENCODED_PRIVATE_KEY_FILE_PATH, "r+").readline().strip("\n")
VAPID_PUBLIC_KEY = open(DER_BASE64_ENCODED_PUBLIC_KEY_FILE_PATH, "r+").read().strip("\n")
VAPID_CLAIMS = {
"sub": "mailto:arcjcb11p@gmail.com"
}
def send_web_push(subscription_information, message_body):
return webpush(
subscription_info=subscription_information,
data=message_body,
vapid_private_key=VAPID_PRIVATE_KEY,
vapid_claims=VAPID_CLAIMS
)
@app.route("/subscription/", methods=["GET", "POST"])
def subscription():
"""
POST creates a subscription
GET returns vapid public key which clients uses to send around push notification
"""
if request.method == "GET":
return Response(response=json.dumps({"public_key": VAPID_PUBLIC_KEY}),
headers={"Access-Control-Allow-Origin": "*"}, content_type="application/json")
subscription_token = request.get_json("subscription_token")
return Response(status=201, mimetype="application/json")
@app.route("/push_v1/",methods=['POST'])
def push_v1():
message = "Push Test v1"
print("is_json",request.is_json)
if not request.json or not request.json.get('sub_token'):
return jsonify({'failed':1})
print("request.json",request.json)
token = request.json.get('sub_token')
try:
token = json.loads(token)
send_web_push(token, message)
return jsonify({'success':1})
except Exception as e:
print("error",e)
return jsonify({'failed':str(e)})
@app.route('/')
@ -70,7 +127,7 @@ def serve_image(filename):
return send_from_directory(app.config['UPLOAD_DIRECTORY'], filename)
# Register User
# New Orders
@app.route("/new-order", methods=["POST"])
def register_user():
email = request.json["email"]

1
backend/private_key.txt Normal file
View File

@ -0,0 +1 @@
eQYEgHfr53K8YbTLdqSiTWT8XrFvUxpnxtT_3Z9gks4

2
backend/public_key.txt Normal file
View File

@ -0,0 +1,2 @@
BINa1y6A1wjwKg96cBGZ3uU7maveC_ifiuu9hW4E_Gx-m5ocB4zur5_wIpgQPq4cn26Q6cxAyYBR
dzp7FVtBPDU

4
backend/readme.md Normal file
View File

@ -0,0 +1,4 @@
# Install vapid keys
`openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem`
`openssl ec -in ./vapid_private.pem -outform DER|tail -c +8|head -c 32|base64|tr -d '=' |tr '/+' '_-' >> private_key.txt`
`openssl ec -in ./vapid_private.pem -pubout -outform DER|tail -c 65|base64|tr -d '=' |tr '/+' '_-' >> public_key.txt`

View File

@ -7,4 +7,8 @@ flask-session
redis
# Flask-Migrate
# flask_validator
# psycopg2-binary
# psycopg2-binary
py-vapid
pywebpush
cryptography
FLASK-API

View File

@ -7,7 +7,7 @@
<title>Kevos orders</title>
<style>
body{
background-color:#FBFAF4;
background-color: #D1D5DB;
}
table {
font-family: arial, sans-serif;
@ -21,7 +21,7 @@
}
tr:nth-child(even) {
background-color: #dddddd;
background-color: #D1D5DB;
}
</style>
</head>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Push Notification | Raturi</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
<script defer src="https://code.getmdl.io/1.2.1/material.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='index.css') }}">
</head>
<body>
<header>
<h1>WebPush Notification</h1>
</header>
<main>
<p>Welcome to the webpush notification. The button below needs to be
fixed to support subscribing to push.</p>
<p>
<button disabled class="js-push-btn mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect">
Enable Push Messaging
</button>
</p>
<section class="subscription-details js-subscription-details is-invisible">
<p>Once you've subscribed your user, you'd send their subscription to your
server to store in a database so that when you want to send a message
you can lookup the subscription and send a message to it.</p>
<pre><code class="js-subscription-json"></code></pre>
<hr>
<p>You can test push notification below.</p>
<button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" onclick="push_message()">Test Push Notification</button>
</section>
</main>
<script src="{{ url_for('static',filename='main.js') }}"></script>
<script src="https://code.getmdl.io/1.2.1/material.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHkGBIB36+dyvGG0y3akok1k/F6xb1MaZ8bU/92fYJLOoAoGCCqGSM49
AwEHoUQDQgAEg1rXLoDXCPAqD3pwEZne5TuZq94L+J+K672FbgT8bH6bmhwHjO6v
n/AimBA+rhyfbpDpzEDJgFF3OnsVW0E8NQ==
-----END EC PRIVATE KEY-----

View File

@ -9,6 +9,7 @@ import ClientPortal from "@/components/ClientPortal/ClientPortal";
import styles from "@/styles/Home.module.css";
import { Poppins } from "next/font/google";
import { sendEmail } from "./actions/sendEmail";
import { createEmptyCacheNode } from "next/dist/client/components/app-router";
const Popp = Poppins({ weight: "400", subsets: ["latin"] });
@ -17,31 +18,35 @@ const Popp = Poppins({ weight: "400", subsets: ["latin"] });
export default function Home() {
const [email, setEmail] = React.useState<string>("");
const [order, setOrder] = React.useState<string>("");
const [isOpen, setIsOpen] = React.useState(false);
const [showPortal, setShowPortal] = React.useState(false);
const handleModal = () => {
setShowPortal(!showPortal);
};
// const registerUser = async () => {
// console.log(email, password);
// try {
// const res = await httpAxios.post("http://127.0.0.1:5080/register", {
// email,
// password,
// });
// console.log(res)
// router.push("/LandingPage")
// } catch (error: any) {
// if (error.response.status === 401) {
// alert("Invalid Credentials");
// }
// }
// };
async function newOrder(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
const response = await fetch("http://192.168.50.107:5580/new-order", {
method: "POST",
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify({email:email, order:order }),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});
}
return (
<main className="flex min-h-screen flex-col px-20 bg-[#F5F5F5">
<main className="flex min-h-screen flex-col px-20">
{/* Title */}
<div className="text-4xl w-full justify-center text-center items-center flex flex-col gap-4 py-12 font-medium text-orange-600">
<span className={`${Popp.className}`}>Kevo&#39;s Attire</span>
@ -64,15 +69,16 @@ export default function Home() {
<form
className="mt-10 flex flex-col w-full items-center gap-4"
action={async (formData) => {
await sendEmail(formData);
}}
// action={async (formData) => {
// await sendEmail(formData);
// }}
onSubmit={newOrder}
>
<h2 className="text-orange-600 text-2xl">Order Form</h2>
<input
className="h-14 px-4 rounded-lg border-black bg-slate-600 lg:w-1/3 md:w-1/2 text-[#EEEEEE]"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
maxLength={500}
placeholder="Your email"
@ -82,7 +88,7 @@ export default function Home() {
<textarea
className="h-52 my-3 rounded-lg lg:w-1/3 md:w-1/2 bg-slate-600 p-4 text-[#EEEEEE]"
name="order"
value={order}
onChange={(e) => setOrder(e.target.value)}
placeholder="Your order"
required
maxLength={500}