squash all commits and fix service worker (file has to be at this specific path by convention):

Added pwa subscription storage for publishers
This commit is contained in:
Dobromir Popov
2024-05-07 10:28:54 +03:00
parent 7d1d529037
commit 03dcf5e755
18 changed files with 1053 additions and 288 deletions

View File

@ -86,9 +86,9 @@ export const authOptions: NextAuthOptions = {
// // Return null if user data could not be retrieved
// return null
const users = [
{ id: "1", name: "admin", email: "admin@example.com", password: "admin123", role: "ADMIN" },
{ id: "2", name: "krasi", email: "krasi@example.com", password: "krasi123", role: "ADMIN" },
{ id: "3", name: "popov", email: "popov@example.com", password: "popov123", role: "ADMIN" }
{ id: "1", name: "admin", email: "admin@example.com", password: "admin123", role: "ADMIN", static: true },
{ id: "2", name: "krasi", email: "krasi@example.com", password: "krasi123", role: "ADMIN", static: true },
{ id: "3", name: "popov", email: "popov@example.com", password: "popov123", role: "ADMIN", static: true }
];
const user = users.find(user =>
@ -174,6 +174,10 @@ export const authOptions: NextAuthOptions = {
callbacks: {
// https://codevoweb.com/implement-authentication-with-nextauth-in-nextjs-14/
async signIn({ user, account, profile }) {
if (account.provider === 'credentials' && user?.static) {
return true;
}
var prisma = common.getPrismaClient();
console.log("[nextauth] signIn:", account.provider, user.email)

View File

@ -1,33 +1,95 @@
const webPush = require('web-push')
import common from '../../src/helpers/common';
//generate and store VAPID keys in .env.local if not already done
if (!process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY || !process.env.WEB_PUSH_PRIVATE_KEY) {
const { publicKey, privateKey } = webPush.generateVAPIDKeys()
console.log('VAPID keys generated:')
console.log('Public key:', publicKey)
console.log('Private key:', privateKey)
console.log('Store these keys in your .env.local file:')
console.log('NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY=', publicKey)
console.log('WEB_PUSH_PRIVATE_KEY=', privateKey)
process.exit(0)
}
webPush.setVapidDetails(
`mailto:${process.env.WEB_PUSH_EMAIL}`,
process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY,
process.env.VAPID_PRIVATE_KEY
process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY,
process.env.WEB_PUSH_PRIVATE_KEY
)
const Notification = (req, res) => {
if (req.method == 'POST') {
const { subscription } = req.body
const Notification = async (req, res) => {
if (req.method == 'GET') {
res.statusCode = 200
res.setHeader('Allow', 'POST')
// send the public key in the response headers
//res.setHeader('Content-Type', 'text/plain')
res.end(process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY)
res.end()
}
if (req.method == 'PUT') {
// store the subscription object in the database
// publisher.pushSubscription = subscription
const prisma = common.getPrismaClient();
const { subscription, id } = req.body
const publisher = await prisma.publisher.update({
where: { id },
data: { pushSubscription: subscription }
})
console.log('Subscription for publisher', id, 'updated:', subscription)
res.statusCode = 200
res.end()
}
if (req.method == 'DELETE') {
// remove the subscription object from the database
// publisher.pushSubscription = null
const prisma = common.getPrismaClient();
const { id } = req.body
const publisher = await prisma.publisher.update({
where: { id },
data: { pushSubscription: null }
})
console.log('Subscription for publisher', id, 'deleted')
res.statusCode = 200
res.end()
}
webPush
.sendNotification(
subscription,
JSON.stringify({ title: 'Hello Web Push', message: 'Your web push notification is here!' })
)
.then(response => {
res.writeHead(response.statusCode, response.headers).end(response.body)
})
.catch(err => {
if ('statusCode' in err) {
res.writeHead(err.statusCode, err.headers).end(err.body)
} else {
console.error(err)
res.statusCode = 500
res.end()
}
})
if (req.method == 'POST') {
const { subscription, id, broadcast, title = 'Hello Web Push', message = 'Your web push notification is here!' } = req.body
if (broadcast) {
await broadcastPush(title, message)
res.statusCode = 200
res.end()
return
}
else if (id) {
await sendPush(id, title, message)
res.statusCode = 200
res.end()
return
} else if (subscription) {
await webPush
.sendNotification(
subscription,
JSON.stringify({ title, message })
)
.then(response => {
res.writeHead(response.statusCode, response.headers).end(response.body)
})
.catch(err => {
if ('statusCode' in err) {
res.writeHead(err.statusCode, err.headers).end(err.body)
} else {
console.error(err)
res.statusCode = 500
res.end()
}
})
}
} else {
res.statusCode = 405
res.end()
@ -35,3 +97,48 @@ const Notification = (req, res) => {
}
export default Notification
//export pushNotification(userId or email) for use in other files
export const sendPush = async (id, title, message) => {
const prisma = common.getPrismaClient();
const publisher = await prisma.publisher.findUnique({
where: { id }
})
if (!publisher.pushSubscription) {
console.log('No push subscription found for publisher', id)
return
}
await webPush
.sendNotification(
publisher.pushSubscription,
JSON.stringify({ title, message })
)
.then(response => {
console.log('Push notification sent to publisher', id)
})
.catch(err => {
console.error('Error sending push notification to publisher', id, ':', err)
})
}
//export breoadcastNotification for use in other files
export const broadcastPush = async (title, message) => {
const prisma = common.getPrismaClient();
const publishers = await prisma.publisher.findMany({
where: { pushSubscription: { not: null } }
})
for (const publisher of publishers) {
await webPush
.sendNotification(
publisher.pushSubscription,
JSON.stringify({ title, message })
)
.then(response => {
console.log('Push notification sent to publisher', publisher.id)
})
.catch(err => {
console.error('Error sending push notification to publisher', publisher.id, ':', err)
})
}
}