diff --git a/backend/instance/mydatabase.db b/backend/instance/mydatabase.db
index c2ae9eb..7e8c98f 100644
Binary files a/backend/instance/mydatabase.db and b/backend/instance/mydatabase.db differ
diff --git a/backend/main.py b/backend/main.py
index 89dfffd..c23e910 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -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"]
diff --git a/backend/private_key.txt b/backend/private_key.txt
new file mode 100644
index 0000000..1ac27d5
--- /dev/null
+++ b/backend/private_key.txt
@@ -0,0 +1 @@
+eQYEgHfr53K8YbTLdqSiTWT8XrFvUxpnxtT_3Z9gks4
diff --git a/backend/public_key.txt b/backend/public_key.txt
new file mode 100644
index 0000000..470dd76
--- /dev/null
+++ b/backend/public_key.txt
@@ -0,0 +1,2 @@
+BINa1y6A1wjwKg96cBGZ3uU7maveC_ifiuu9hW4E_Gx-m5ocB4zur5_wIpgQPq4cn26Q6cxAyYBR
+dzp7FVtBPDU
diff --git a/backend/readme.md b/backend/readme.md
new file mode 100644
index 0000000..7090cd5
--- /dev/null
+++ b/backend/readme.md
@@ -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`
\ No newline at end of file
diff --git a/backend/requirements.txt b/backend/requirements.txt
index 49a248a..00fed51 100644
--- a/backend/requirements.txt
+++ b/backend/requirements.txt
@@ -7,4 +7,8 @@ flask-session
redis
# Flask-Migrate
# flask_validator
-# psycopg2-binary
\ No newline at end of file
+# psycopg2-binary
+py-vapid
+pywebpush
+cryptography
+FLASK-API
\ No newline at end of file
diff --git a/backend/templates/orders.html b/backend/templates/orders.html
index 381b40e..362ca97 100644
--- a/backend/templates/orders.html
+++ b/backend/templates/orders.html
@@ -7,7 +7,7 @@
Kevos orders
diff --git a/backend/templates/pushnotifications.html b/backend/templates/pushnotifications.html
new file mode 100644
index 0000000..3ce27ca
--- /dev/null
+++ b/backend/templates/pushnotifications.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+ Push Notification | Raturi
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Welcome to the webpush notification. The button below needs to be
+ fixed to support subscribing to push.
+
+
+ Enable Push Messaging
+
+
+
+ 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.
+
+
+
+ You can test push notification below.
+ Test Push Notification
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/backend/vapid_private.pem b/backend/vapid_private.pem
new file mode 100644
index 0000000..3fd37a6
--- /dev/null
+++ b/backend/vapid_private.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIHkGBIB36+dyvGG0y3akok1k/F6xb1MaZ8bU/92fYJLOoAoGCCqGSM49
+AwEHoUQDQgAEg1rXLoDXCPAqD3pwEZne5TuZq94L+J+K672FbgT8bH6bmhwHjO6v
+n/AimBA+rhyfbpDpzEDJgFF3OnsVW0E8NQ==
+-----END EC PRIVATE KEY-----
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index ab5ed77..8900bb4 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -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("");
const [order, setOrder] = React.useState("");
-
+
+
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) {
+ 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 (
-
+
{/* Title */}
Kevo's Attire
@@ -64,15 +69,16 @@ export default function Home() {