This commit is contained in:
venbaittech 2024-12-20 16:23:45 +05:30
parent 65eddf6fd8
commit 39862c0516

525
main.go
View File

@ -2,18 +2,22 @@ package main
import (
"crypto/rand"
"encoding/xml"
"fmt"
"io/ioutil"
"log"
"math/big"
"net/http"
"net/mail"
"os"
"strings"
"time"
"github.com/labstack/echo/v5"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/apis"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/tools/mailer"
"github.com/pocketbase/pocketbase/tools/types"
)
@ -29,80 +33,99 @@ type EmailConfigurationResponse struct {
} `json:"items"`
}
type GenericData struct {
XMLName xml.Name `xml:"GenericData"`
DataSet []Obs `xml:"DataSet>Obs"`
}
type Obs struct {
ObsKey []ObsKey `xml:"ObsKey>Value"` // Dynamic key-value pairs
ObsValue ObsValue `xml:"ObsValue"`
}
type ObsKey struct {
ID string `xml:"id,attr"` // Attribute for 'id'
Value string `xml:"value,attr"` // Attribute for 'value'
}
type ObsValue struct {
Value string `xml:"value,attr"` // Attribute for 'value'
}
// Helper function to map ObsKey into a dictionary
func mapObsKey(keys []ObsKey) map[string]string {
result := map[string]string{}
for _, key := range keys {
result[key.ID] = key.Value
}
return result
}
// Helper function to clean XML namespace prefixes
func removeNamespace(xmlBytes []byte) string {
return strings.ReplaceAll(string(xmlBytes), "generic:", "")
}
// Function to fetch XML from an API and convert it to JSON
func fetchAndConvertXMLToJSON(apiURL string) ([]map[string]interface{}, error) {
// Call the API and get the XML response
resp, err := http.Get(apiURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// Read the response body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// Clean the XML by removing namespace prefixes
cleanXML := []byte(removeNamespace(body))
// Parse the cleaned XML data
var data GenericData
err = xml.Unmarshal(cleanXML, &data)
if err != nil {
return nil, err
}
// Transform the data for JSON output
response := []map[string]interface{}{}
for _, obs := range data.DataSet {
obsMap := map[string]interface{}{
"ObsKey": mapObsKey(obs.ObsKey),
"ObsValue": obs.ObsValue,
}
response = append(response, obsMap)
}
return response, nil
}
var app *pocketbase.PocketBase
func main() {
// app := pocketbase.New()
app = pocketbase.New()
//send mail while status changed from app admin
app.OnRecordBeforeUpdateRequest().Add(func(e *core.RecordUpdateEvent) error {
if e.Collection.Name == "users" {
// Fetch the original record by ID
originalRecord, err := app.Dao().FindRecordById("users", e.Record.GetString("id"))
if err != nil {
return fmt.Errorf("failed to fetch original record: %v", err)
}
// Get the old status before the update
oldStatus := originalRecord.GetString("status")
newStatus := e.Record.GetString("status")
// If the status has changed, send an email
if newStatus != oldStatus {
userEmail := e.Record.GetString("email")
userName := e.Record.GetString("username")
if userEmail != "" {
var subject string
var body string
// Define the email content based on status
if newStatus == "Approved" {
subject = "Registration Approved FCSC"
body = fmt.Sprintf(`
<p>Dear %s,</p>
<p>We are pleased to inform you that your registration with FCSC has been approved. You can now log in using the credentials that you had created.</p>
<p>Please access your account using the following link: <a href="http://your-login-url.com">Login</a>.</p>
<p>If you have any questions, please feel free to contact us for further clarification.</p>
`, userName)
} else if newStatus == "Denied" {
subject = "Registration Update FCSC"
body = fmt.Sprintf(`
<p>Dear %s,</p>
<p>Thank you for registering with FCSC. After careful review, we regret to inform you that your registration has not been approved at this time.</p>
<p>If you have any questions or believe this decision was made in error, please feel free to contact us for further clarification.</p>
<p>We appreciate your understanding and thank you for your interest.</p>
<p>Best regards,</p>
`, userName)
} else {
// If the status is neither "Approved" nor "Denied", skip sending an email
return nil
}
// Create the email message
message := &mailer.Message{
From: mail.Address{
Name: "FCSC",
Address: app.Settings().Meta.SenderAddress, // Replace with your sender's email
},
To: []mail.Address{
{
Name: userName,
Address: userEmail,
},
},
Subject: subject,
HTML: body,
}
// Send the email
err = app.NewMailClient().Send(message)
if err != nil {
log.Printf("Failed to send status change email: %v", err)
return err
}
log.Println("Status change email sent successfully to:", userEmail)
// Check if the status has changed
if oldStatus != newStatus {
err := sendStatusChangeEmail(app, e.Record, newStatus)
if err != nil {
return err
}
}
}
@ -169,7 +192,7 @@ func main() {
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
e.Router.GET("/api/custom/approve", func(c echo.Context) error {
userId := c.QueryParam("userId") // Get userId from query parameters
userId := c.QueryParam("userId")
if userId == "" {
return c.JSON(400, map[string]interface{}{
"code": 400,
@ -177,7 +200,7 @@ func main() {
})
}
// Find the user record in PocketBase by userId
// Find the user record
record, err := app.Dao().FindRecordById("users", userId)
if err != nil {
return c.JSON(500, map[string]interface{}{
@ -186,8 +209,60 @@ func main() {
})
}
// Set the verified status to true
// Check if the email is already verified
if record.GetBool("reviewed") {
return c.HTML(http.StatusOK, `
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f0f8ff;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}
.message-container {
text-align: center;
background-color: #ffe0e0;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.message-container h1 {
font-size: 24px;
color: #b71c1c;
margin-bottom: 10px;
}
.message-container p {
font-size: 16px;
color: #880e4f;
}
.icon {
font-size: 50px;
color: #b71c1c;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="message-container">
<div class="icon">&#x2716;</div>
<h1>Your Already Reviewed</h1>
<p>You have already been reviewed. No further action is required.</p>
</div>
</body>
</html>
`)
}
// Update the status
newStatus := "Approved"
record.Set("verified", true)
record.Set("status", newStatus)
record.Set("reviewed", true)
if err := app.Dao().SaveRecord(record); err != nil {
return c.JSON(500, map[string]interface{}{
"code": 500,
@ -195,39 +270,8 @@ func main() {
})
}
// Prepare the email details
name := record.GetString("username")
email := record.GetString("email")
subject := "Registration Approved FCSC"
body := fmt.Sprintf(`
<html>
<body>
<p>Dear %s,</p>
<p>We are pleased to inform you that your registration with FCSC has been approved. You can now log in using the credentials that you had created.</p>
<p>Please access your account using the following link: <a href="http://your-login-url.com">Login</a>.</p>
<p>If you have any questions, please feel free to contact us for further clarification.</p>
</body>
</html>
`, name)
// Create the email message
message := &mailer.Message{
From: mail.Address{
Name: "FCSC",
Address: app.Settings().Meta.SenderAddress,
},
To: []mail.Address{
{
Name: name,
Address: email,
},
},
Subject: subject,
HTML: body,
}
// Send the approval email
err = app.NewMailClient().Send(message)
// Send the status change email
err = sendStatusChangeEmail(app, record, newStatus)
if err != nil {
return c.JSON(500, map[string]interface{}{
"code": 500,
@ -235,9 +279,8 @@ func main() {
})
}
// Render a success message as an HTML response
return c.HTML(http.StatusOK, `
<html>
<html>
<head>
<style>
body {
@ -290,7 +333,7 @@ func main() {
// Approve Endpoint
e.Router.GET("/api/custom/reject", func(c echo.Context) error {
userId := c.QueryParam("userId") // Get userId from query parameters
userId := c.QueryParam("userId")
if userId == "" {
return c.JSON(400, map[string]interface{}{
"code": 400,
@ -307,49 +350,77 @@ func main() {
})
}
// Set the verified status to false
record.Set("verified", false)
if err := app.Dao().SaveRecord(record); err != nil {
return c.JSON(500, map[string]interface{}{
"code": 500,
"message": "Failed to update user status.",
// Check if the email is already verified
if record.GetBool("reviewed") {
return c.HTML(http.StatusOK, `
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f0f8ff;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}
.message-container {
text-align: center;
background-color: #ffe0e0;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.message-container h1 {
font-size: 24px;
color: #b71c1c;
margin-bottom: 10px;
}
.message-container p {
font-size: 16px;
color: #880e4f;
}
.icon {
font-size: 50px;
color: #b71c1c;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="message-container">
<div class="icon">&#x2716;</div>
<h1>Your Already Reviewed</h1>
<p>You have already been reviewed. No further action is required.</p>
</div>
</body>
</html>
`)
}
// Check if the status is already "Denied" to avoid duplicate email
if record.GetString("status") == "Denied" {
return c.JSON(400, map[string]interface{}{
"code": 400,
"message": "User is already rejected.",
})
}
// Prepare the rejection email details
name := record.GetString("username")
email := record.GetString("email")
subject := "Registration Update FCSC"
body := fmt.Sprintf(`
<html>
<body>
<p>Dear %s,</p>
<p>Thank you for registering with FCSC. After careful review, we regret to inform you that your registration has not been approved at this time.</p>
<p>If you have any questions or believe this decision was made in error, please feel free to contact us for further clarification.</p>
<p>We appreciate your understanding and thank you for your interest.</p>
<p>Best regards,</p>
</body>
</html>
`, name)
// Create the rejection email message
message := &mailer.Message{
From: mail.Address{
Name: "FCSC",
Address: app.Settings().Meta.SenderAddress,
},
To: []mail.Address{
{
Name: name,
Address: email,
},
},
Subject: subject,
HTML: body,
// Update the status
newStatus := "Denied"
record.Set("verified", true)
record.Set("status", newStatus)
record.Set("reviewed", true)
if err := app.Dao().SaveRecord(record); err != nil {
return c.JSON(500, map[string]interface{}{
"code": 500,
"message": "Failed to verify user.",
})
}
// Send the rejection email
err = app.NewMailClient().Send(message)
// Send the status change email
err = sendStatusChangeEmail(app, record, newStatus)
if err != nil {
return c.JSON(500, map[string]interface{}{
"code": 500,
@ -359,44 +430,44 @@ func main() {
// Render a success message as an HTML response
return c.HTML(http.StatusOK, `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Rejected</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #ffe6e6; /* Light red background */
font-family: Arial, sans-serif;
}
.message-box {
text-align: center;
color: #d9534f; /* Bootstrap red */
}
.message-box i {
font-size: 48px;
margin-bottom: 20px;
}
.message-box p {
font-size: 18px;
}
</style>
</head>
<body>
<div class="message-box">
<i></i>
<h1>User Rejected</h1>
<p>Rejection email sent successfully.</p>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User Rejected</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #ffe6e6;
font-family: Arial, sans-serif;
}
.message-box {
text-align: center;
color: #d9534f;
}
.message-box i {
font-size: 48px;
margin-bottom: 20px;
}
.message-box p {
font-size: 18px;
}
</style>
</head>
<body>
<div class="message-box">
<i></i>
<h1>User Rejected</h1>
<p>Rejection email sent successfully.</p>
</div>
</body>
</html>
`)
})
@ -410,6 +481,7 @@ func main() {
return nil
})
//Feedback Mail Trigger
app.OnRecordAfterCreateRequest().Add(func(e *core.RecordCreateEvent) error {
if e.Record.Collection().Name == "feedback" {
// Retrieve feedback details
@ -635,6 +707,55 @@ func verifyEmailHandler(c echo.Context) error {
})
}
// Check if the email is already verified
if record.GetBool("user_mail_verify") {
return c.HTML(http.StatusOK, `
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f0f8ff;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}
.message-container {
text-align: center;
background-color: #ffe0e0;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.message-container h1 {
font-size: 24px;
color: #b71c1c;
margin-bottom: 10px;
}
.message-container p {
font-size: 16px;
color: #880e4f;
}
.icon {
font-size: 50px;
color: #b71c1c;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="message-container">
<div class="icon">&#x2716;</div>
<h1>Email Already Verified</h1>
<p>Your email has already been verified. No further action is required.</p>
</div>
</body>
</html>
`)
}
// Set the verified status to true
record.Set("user_mail_verify", true)
// log.Printf("Failed to verify user: %v", err)
@ -710,6 +831,7 @@ func verifyEmailHandler(c echo.Context) error {
func sendAdminEmail(app *pocketbase.PocketBase, userID, username, userEmail string) error {
adminName := "Admin"
subject := "New User Registration Pending Review"
body := fmt.Sprintf(`
<html>
<body>
@ -755,3 +877,60 @@ func sendAdminEmail(app *pocketbase.PocketBase, userID, username, userEmail stri
log.Println("Admin email sent successfully.")
return nil
}
func sendStatusChangeEmail(app *pocketbase.PocketBase, record *models.Record, newStatus string) error {
userEmail := record.GetString("email")
userName := record.GetString("username")
if userEmail == "" {
return fmt.Errorf("user email is empty")
}
var subject, body string
if newStatus == "Approved" {
subject = "Registration Approved FCSC"
body = fmt.Sprintf(`
<p>Dear %s,</p>
<p>We are pleased to inform you that your registration with FCSC has been approved. You can now log in using the credentials that you had created.</p>
<p>Please access your account using the following link: <a href="http://your-login-url.com">Login</a>.</p>
<p>If you have any questions, please feel free to contact us for further clarification.</p>
`, userName)
} else if newStatus == "Denied" {
subject = "Registration Update FCSC"
body = fmt.Sprintf(`
<p>Dear %s,</p>
<p>Thank you for registering with FCSC. After careful review, we regret to inform you that your registration has not been approved at this time.</p>
<p>If you have any questions or believe this decision was made in error, please feel free to contact us for further clarification.</p>
<p>We appreciate your understanding and thank you for your interest.</p>
<p>Best regards,</p>
`, userName)
} else {
// If the status is neither "Approved" nor "Denied", skip sending an email
return nil
}
// Create and send the email
message := &mailer.Message{
From: mail.Address{
Name: "FCSC",
Address: app.Settings().Meta.SenderAddress,
},
To: []mail.Address{
{
Name: userName,
Address: userEmail,
},
},
Subject: subject,
HTML: body,
}
err := app.NewMailClient().Send(message)
if err != nil {
return fmt.Errorf("failed to send email: %v", err)
}
log.Printf("Status change email sent successfully to: %s", userEmail)
return nil
}