-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
133 additions
and
240 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,4 +6,6 @@ [email protected] | |
SMTP_SERVER=smtp.example.com | ||
SMTP_PORT=587 | ||
SMTP_PASSWORD=password | ||
JWT_SECRET=jwtSecret | ||
JWT_SECRET=jwtSecret | ||
VERIFY_URL=http://example.com/verify | ||
RESET_EMAIL_URL=http://example.com/reset-email |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package emails | ||
|
||
import ( | ||
"fmt" | ||
"net/smtp" | ||
"os" | ||
"strconv" | ||
) | ||
|
||
func SendResetPasswordEmail(to, resetPasswordLink string) error { | ||
|
||
var ( | ||
smtpServer = os.Getenv("SMTP_SERVER") | ||
smtpPort = os.Getenv("SMTP_PORT") | ||
username = os.Getenv("EMAIL_FROM") | ||
password = os.Getenv("SMTP_PASSWORD") | ||
from = os.Getenv("EMAIL_FROM") | ||
) | ||
|
||
if smtpServer == "" || smtpPort == "" || username == "" || password == "" || from == "" { | ||
return fmt.Errorf("environment variable not set: SMTP_SERVER, SMTP_PORT, EMAIL_FROM, or SMTP_PASSWORD") | ||
} | ||
|
||
port, err := strconv.Atoi(smtpPort) | ||
if err != nil { | ||
return fmt.Errorf("failed to convert smtpPort to int: %v", err) | ||
} | ||
|
||
body := fmt.Sprintf(` | ||
<html> | ||
<body> | ||
<p> | ||
Hello! | ||
</p> | ||
<p> | ||
We received a request to reset your password. If you did not make this request, please ignore this email. | ||
</p> | ||
<p> | ||
Please click the following link to reset your password: | ||
<br /> | ||
<a href="%s">%s</a> | ||
</p> | ||
<p> | ||
<button style="background-color: #4CAF50; color: white; padding: 14px 20px; margin: 8px 0; border: none; cursor: pointer; width: 100%%;">Verify</button> | ||
</p> | ||
<p> | ||
Best regards, | ||
<br /> | ||
The Team | ||
</p> | ||
</body> | ||
</html> | ||
`, resetPasswordLink, resetPasswordLink) | ||
msg := []byte(fmt.Sprintf("From: %s\r\nTo: %s\r\nSubject: Welcome\r\nContent-Type: text/html\r\n\r\n%s", from, to, body)) | ||
auth := smtp.PlainAuth("", username, password, smtpServer) | ||
if err := smtp.SendMail(fmt.Sprintf("%s:%d", smtpServer, port), auth, from, []string{to}, msg); err != nil { | ||
return fmt.Errorf("failed to send email: %v", err) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package email | ||
package emails | ||
|
||
import ( | ||
"fmt" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Your request headers, e.g. | ||
GET http://localhost:8080/check-username?username=bkawk | ||
Content-Type: application/json | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,54 @@ | ||
package handlers | ||
|
||
import ( | ||
"net/http" | ||
|
||
"bkawk/go-echo/api/models" | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/labstack/echo/v4" | ||
"go.mongodb.org/mongo-driver/bson" | ||
"go.mongodb.org/mongo-driver/mongo" | ||
) | ||
|
||
// RegisterEndpoint handles user registration requests | ||
func ForgotPasswordPost(c echo.Context) error { | ||
// bind the incoming request body to a User struct | ||
|
||
// Get database connection from context | ||
db := c.Get("db").(*mongo.Database) | ||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||
defer cancel() | ||
|
||
// Validate input | ||
u := new(models.User) | ||
if err := c.Bind(u); err != nil { | ||
return err | ||
return c.JSON(http.StatusInternalServerError, echo.Map{"error": "Failed to bind request body"}) | ||
} | ||
|
||
// validate user input | ||
if u.Username == "" || u.Password == "" || u.Email == "" { | ||
return c.JSON(http.StatusBadRequest, map[string]string{ | ||
"error": "invalid request body", | ||
}) | ||
var user models.User | ||
collection := db.Collection("users") | ||
filter := bson.M{"email": u.Email} | ||
|
||
if err := collection.FindOne(ctx, filter).Decode(&user); err != nil { | ||
if err == mongo.ErrNoDocuments { | ||
return echo.NewHTTPError(http.StatusNotFound, "Email not found") | ||
} | ||
return echo.NewHTTPError(http.StatusInternalServerError, "Error fetching user") | ||
} | ||
|
||
if time.Since(time.Unix(user.ForgotPassword, 0)) < (5 * time.Minute) { | ||
waitTime := 5*time.Minute - time.Since(time.Unix(user.ForgotPassword, 0)) | ||
return echo.NewHTTPError(http.StatusTooManyRequests, fmt.Sprintf("Try again in %d minutes and %d seconds", int(waitTime.Minutes()), int(waitTime.Seconds())%60)) | ||
} | ||
|
||
// add the new user to the database | ||
// (this is a dummy implementation and would be replaced in a real application) | ||
// ... | ||
// send email logic | ||
fmt.Println("Sending forgot password email to", u.Email) | ||
|
||
user.ForgotPassword = time.Now().Unix() | ||
if _, err := collection.ReplaceOne(ctx, filter, user); err != nil { | ||
return echo.NewHTTPError(http.StatusInternalServerError, "Error updating user") | ||
} | ||
|
||
// return a success response | ||
return c.JSON(http.StatusOK, map[string]string{ | ||
"message": "user registered successfully", | ||
}) | ||
return c.JSON(http.StatusOK, "Forgot password email sent!") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Your request headers, e.g. | ||
POST http://localhost:8080/forgot-password | ||
Content-Type: application/json | ||
|
||
# The request body, if any | ||
{ | ||
"email": "[email protected]" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
package models | ||
|
||
type User struct { | ||
ID string `json:"id" bson:"_id" validate:"required"` | ||
Email string `json:"email" bson:"email" validate:"required,email,max=100"` | ||
Username string `json:"username" bson:"username" validate:"required,min=4,max=12"` | ||
Password string `json:"password" bson:"password" validate:"required,max=64,min=8"` | ||
RefreshToken string `json:"refreshToken,omitempty" bson:"refreshToken,omitempty"` | ||
CreatedAt int64 `json:"createdAt" bson:"createdAt"` | ||
VerificationCode string `json:"verificationCode,omitempty" bson:"verificationCode,omitempty"` | ||
LastSeen int64 `json:"lastSeen,omitempty" bson:"lastSeen,omitempty"` | ||
IsVerified bool `bson:"isVerified"` | ||
ID string `json:"id" bson:"_id" validate:"required"` | ||
Email string `json:"email" bson:"email" validate:"required,email,max=100"` | ||
Username string `json:"username" bson:"username" validate:"min=4,max=12"` | ||
Password string `json:"password" bson:"password" validate:"max=64,min=8"` | ||
RefreshToken string `json:"refreshToken,omitempty" bson:"refreshToken,omitempty"` | ||
CreatedAt int64 `json:"createdAt" bson:"createdAt"` | ||
VerificationCode string `json:"verificationCode,omitempty" bson:"verificationCode,omitempty"` | ||
PasswordResetToken string `json:"passwordResetToken,omitempty" bson:"passwordResetToken,omitempty"` | ||
LastSeen int64 `json:"lastSeen,omitempty" bson:"lastSeen,omitempty"` | ||
IsVerified bool `bson:"isVerified"` | ||
ForgotPassword int64 `json:"forgotPassword,omitempty" bson:"forgotPassword,omitempty"` | ||
} |
Oops, something went wrong.