@feardread/fear 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FEAR.js +76 -63
- package/FEARServer.js +290 -20
- package/controllers/address.js +9 -0
- package/controllers/auth/index.js +498 -92
- package/controllers/auth/password.js +237 -0
- package/controllers/order.js +0 -1
- package/controllers/payment.js +5 -142
- package/libs/db/index.js +5 -0
- package/libs/emailer/info.js +22 -34
- package/libs/emailer/smtp.js +511 -65
- package/libs/passport/index.js +137 -0
- package/libs/passport.js +22 -0
- package/libs/paypal/index.js +82 -0
- package/libs/stripe/index.js +306 -0
- package/libs/validator/index.js +2 -2
- package/models/address.js +37 -0
- package/models/blog.js +947 -17
- package/models/brand.js +205 -8
- package/models/category.js +498 -7
- package/models/events.js +1 -0
- package/models/order.js +29 -154
- package/models/payment.js +18 -79
- package/models/user.js +116 -49
- package/package.json +1 -1
- package/routes/address.js +16 -0
- package/routes/auth.js +9 -3
- package/routes/mail.js +10 -165
- package/routes/order.js +7 -4
- package/routes/password.js +17 -0
- package/routes/payment.js +4 -7
- package/routes/paypal.js +12 -0
- package/routes/stripe.js +27 -0
- package/libs/passport/passport.js +0 -109
- /package/routes/{events.js → event.js} +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const User = require('../../models/user');
|
|
3
|
+
//const { validateMongoDbId } = require('../utils/validateMongoDbId');
|
|
4
|
+
|
|
5
|
+
// Response helper
|
|
6
|
+
const response = {
|
|
7
|
+
success: (res, data, statusCode = 200, message = "Operation successful") => {
|
|
8
|
+
return res.status(statusCode).json({
|
|
9
|
+
success: true,
|
|
10
|
+
message,
|
|
11
|
+
data
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
error: (res, statusCode, message, error = null) => {
|
|
16
|
+
const responseObj = { success: false, message };
|
|
17
|
+
if (error && process.env.NODE_ENV === "development") {
|
|
18
|
+
responseObj.error = error;
|
|
19
|
+
}
|
|
20
|
+
return res.status(statusCode).json(responseObj);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Update password for authenticated user
|
|
25
|
+
exports.updatePassword = (req, res) => {
|
|
26
|
+
const { _id } = req.user;
|
|
27
|
+
const { currentPassword, newPassword } = req.body;
|
|
28
|
+
|
|
29
|
+
//validateMongoDbId(_id);
|
|
30
|
+
|
|
31
|
+
if (!currentPassword || !newPassword) {
|
|
32
|
+
return response.error(res, 400, 'Current password and new password are required');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
User.findById(_id)
|
|
36
|
+
.then((user) => {
|
|
37
|
+
if (!user) {
|
|
38
|
+
return response.error(res, 404, 'User not found');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Verify current password
|
|
42
|
+
return user.isPasswordMatched(currentPassword)
|
|
43
|
+
.then((isMatch) => {
|
|
44
|
+
if (!isMatch) {
|
|
45
|
+
return response.error(res, 401, 'Current password is incorrect');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
user.password = newPassword;
|
|
49
|
+
return user.save();
|
|
50
|
+
})
|
|
51
|
+
.then((updatedUser) => {
|
|
52
|
+
// Send confirmation email
|
|
53
|
+
const mailService = req.app.get('mailService');
|
|
54
|
+
|
|
55
|
+
return mailService.sendEmail({
|
|
56
|
+
to: updatedUser.email,
|
|
57
|
+
subject: 'Password Changed Successfully',
|
|
58
|
+
html: mailService.templates.passwordResetSuccessTemplate(updatedUser.email),
|
|
59
|
+
text: mailService.templates.generatePlainText({ email: updatedUser.email }, 'passwordResetSuccess')
|
|
60
|
+
})
|
|
61
|
+
.then(() => {
|
|
62
|
+
const userResponse = updatedUser.toJSON();
|
|
63
|
+
return response.success(res, { user: userResponse }, 200, 'Password updated successfully');
|
|
64
|
+
})
|
|
65
|
+
.catch((emailError) => {
|
|
66
|
+
// Log error but don't fail the password update
|
|
67
|
+
console.error('Failed to send confirmation email:', emailError);
|
|
68
|
+
const userResponse = updatedUser.toJSON();
|
|
69
|
+
return response.success(res, { user: userResponse }, 200, 'Password updated successfully');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
})
|
|
73
|
+
.catch((error) => {
|
|
74
|
+
return response.error(res, 500, 'Error updating password', error.message);
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Request password reset token
|
|
79
|
+
exports.forgotPasswordToken = (req, res) => {
|
|
80
|
+
const { email } = req.body;
|
|
81
|
+
|
|
82
|
+
if (!email) {
|
|
83
|
+
return response.error(res, 400, 'Email is required');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
User.findOne({ email })
|
|
87
|
+
.then((user) => {
|
|
88
|
+
if (!user) {
|
|
89
|
+
return response.error(res, 404, 'User not found with this email');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Create reset token
|
|
93
|
+
return user.createPasswordResetToken()
|
|
94
|
+
.then((token) => {
|
|
95
|
+
return user.save()
|
|
96
|
+
.then(() => ({ user, token }));
|
|
97
|
+
});
|
|
98
|
+
})
|
|
99
|
+
.then(({ user, token }) => {
|
|
100
|
+
// Construct reset URL
|
|
101
|
+
const resetURL = `${req.protocol}://${req.get('host')}/reset-password/${token}`;
|
|
102
|
+
|
|
103
|
+
// Send email
|
|
104
|
+
const mailService = req.app.get('mailService');
|
|
105
|
+
|
|
106
|
+
return mailService.sendEmail({
|
|
107
|
+
to: user.email,
|
|
108
|
+
subject: 'Password Reset Request',
|
|
109
|
+
html: mailService.templates.passwordResetTemplate(resetURL, user.email),
|
|
110
|
+
text: mailService.templates.generatePlainText({ resetURL, email: user.email }, 'passwordReset')
|
|
111
|
+
})
|
|
112
|
+
.then(() => {
|
|
113
|
+
return response.success(
|
|
114
|
+
res,
|
|
115
|
+
{
|
|
116
|
+
message: 'Password reset link sent to email',
|
|
117
|
+
expiresIn: '10 minutes'
|
|
118
|
+
},
|
|
119
|
+
200,
|
|
120
|
+
'Password reset email sent successfully'
|
|
121
|
+
);
|
|
122
|
+
})
|
|
123
|
+
.catch((emailError) => {
|
|
124
|
+
// Clear reset token if email fails
|
|
125
|
+
user.passwordResetToken = undefined;
|
|
126
|
+
user.passwordResetExpires = undefined;
|
|
127
|
+
return user.save()
|
|
128
|
+
.then(() => {
|
|
129
|
+
return response.error(res, 500, 'Error sending password reset email', emailError.message);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
})
|
|
133
|
+
.catch((error) => {
|
|
134
|
+
return response.error(res, 500, 'Error processing password reset request', error.message);
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Reset password with token
|
|
139
|
+
exports.resetPassword = (req, res) => {
|
|
140
|
+
const { password } = req.body;
|
|
141
|
+
const { token } = req.params;
|
|
142
|
+
|
|
143
|
+
if (!password) {
|
|
144
|
+
return response.error(res, 400, 'New password is required');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!token) {
|
|
148
|
+
return response.error(res, 400, 'Reset token is required');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const hashedToken = crypto.createHash("sha256").update(token).digest("hex");
|
|
152
|
+
|
|
153
|
+
User.findOne({
|
|
154
|
+
passwordResetToken: hashedToken,
|
|
155
|
+
passwordResetExpires: { $gt: Date.now() }
|
|
156
|
+
})
|
|
157
|
+
.then((user) => {
|
|
158
|
+
if (!user) {
|
|
159
|
+
return response.error(res, 400, 'Token expired or invalid. Please try again');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Update password and clear reset token
|
|
163
|
+
user.password = password;
|
|
164
|
+
user.passwordResetToken = undefined;
|
|
165
|
+
user.passwordResetExpires = undefined;
|
|
166
|
+
|
|
167
|
+
return user.save();
|
|
168
|
+
})
|
|
169
|
+
.then((updatedUser) => {
|
|
170
|
+
// Send confirmation email
|
|
171
|
+
const mailService = req.app.get('mailService');
|
|
172
|
+
|
|
173
|
+
return mailService.sendEmail({
|
|
174
|
+
to: updatedUser.email,
|
|
175
|
+
subject: 'Password Changed Successfully',
|
|
176
|
+
html: mailService.templates.passwordResetSuccessTemplate(updatedUser.email),
|
|
177
|
+
text: mailService.templates.generatePlainText({ email: updatedUser.email }, 'passwordResetSuccess')
|
|
178
|
+
})
|
|
179
|
+
.then(() => {
|
|
180
|
+
const userResponse = updatedUser.toJSON();
|
|
181
|
+
return response.success(
|
|
182
|
+
res,
|
|
183
|
+
{ user: userResponse },
|
|
184
|
+
200,
|
|
185
|
+
'Password reset successfully'
|
|
186
|
+
);
|
|
187
|
+
})
|
|
188
|
+
.catch((emailError) => {
|
|
189
|
+
// Log error but don't fail the password reset
|
|
190
|
+
console.error('Failed to send confirmation email:', emailError);
|
|
191
|
+
const userResponse = updatedUser.toJSON();
|
|
192
|
+
return response.success(
|
|
193
|
+
res,
|
|
194
|
+
{ user: userResponse },
|
|
195
|
+
200,
|
|
196
|
+
'Password reset successfully'
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
})
|
|
200
|
+
.catch((error) => {
|
|
201
|
+
return response.error(res, 500, 'Error resetting password', error.message);
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// Verify reset token validity (optional)
|
|
206
|
+
exports.verifyResetToken = (req, res) => {
|
|
207
|
+
const { token } = req.params;
|
|
208
|
+
|
|
209
|
+
if (!token) {
|
|
210
|
+
return response.error(res, 400, 'Reset token is required');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const hashedToken = crypto.createHash("sha256").update(token).digest("hex");
|
|
214
|
+
|
|
215
|
+
User.findOne({
|
|
216
|
+
passwordResetToken: hashedToken,
|
|
217
|
+
passwordResetExpires: { $gt: Date.now() }
|
|
218
|
+
})
|
|
219
|
+
.then((user) => {
|
|
220
|
+
if (!user) {
|
|
221
|
+
return response.error(res, 400, 'Token expired or invalid');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return response.success(
|
|
225
|
+
res,
|
|
226
|
+
{
|
|
227
|
+
valid: true,
|
|
228
|
+
email: user.email.replace(/(.{2})(.*)(@.*)/, '$1***$3') // Partially masked email
|
|
229
|
+
},
|
|
230
|
+
200,
|
|
231
|
+
'Token is valid'
|
|
232
|
+
);
|
|
233
|
+
})
|
|
234
|
+
.catch((error) => {
|
|
235
|
+
return response.error(res, 500, 'Error verifying token', error.message);
|
|
236
|
+
});
|
|
237
|
+
};
|
package/controllers/order.js
CHANGED
package/controllers/payment.js
CHANGED
|
@@ -1,148 +1,11 @@
|
|
|
1
|
-
const
|
|
2
|
-
const paypal = require("@paypal/checkout-server-sdk");
|
|
3
|
-
const Payment = require("../models/payment");
|
|
1
|
+
const Payment = require('../models/payment');
|
|
4
2
|
const methods = require("./crud");
|
|
5
3
|
|
|
6
|
-
const instance = new Razorpay({
|
|
7
|
-
key_id: "rzp_test_HSSeDI22muUrLR",
|
|
8
|
-
key_secret: "sRO0YkBxvgMg0PvWHJN16Uf7",
|
|
9
|
-
});
|
|
10
4
|
|
|
11
|
-
//
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
// PayPal environment setup
|
|
18
|
-
const paypalEnvironment = () => {
|
|
19
|
-
const clientId = process.env.PAYPAL_CLIENT_ID || "YOUR_PAYPAL_CLIENT_ID";
|
|
20
|
-
const clientSecret = process.env.PAYPAL_CLIENT_SECRET || "YOUR_PAYPAL_CLIENT_SECRET";
|
|
21
|
-
|
|
22
|
-
// Use sandbox for testing, live for production
|
|
23
|
-
return new paypal.core.SandboxEnvironment(clientId, clientSecret);
|
|
24
|
-
// For production: return new paypal.core.LiveEnvironment(clientId, clientSecret);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const paypalClient = () => {
|
|
28
|
-
return new paypal.core.PayPalHttpClient(paypalEnvironment());
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
exports.checkout = async (req, res) => {
|
|
32
|
-
try {
|
|
33
|
-
const { amount } = req.body;
|
|
34
|
-
const option = {
|
|
35
|
-
amount: amount * 100,
|
|
36
|
-
currency: "INR",
|
|
37
|
-
};
|
|
38
|
-
const order = await razorpayInstance.orders.create(option);
|
|
39
|
-
res.json({
|
|
40
|
-
success: true,
|
|
41
|
-
order,
|
|
42
|
-
});
|
|
43
|
-
} catch (error) {
|
|
44
|
-
res.status(500).json({
|
|
45
|
-
success: false,
|
|
46
|
-
message: "Error creating Razorpay order",
|
|
47
|
-
error: error.message,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
exports.paymentVerification = async (req, res) => {
|
|
53
|
-
try {
|
|
54
|
-
const { razorpayOrderId, razorpayPaymentId, razorpaySignature } = req.body;
|
|
55
|
-
|
|
56
|
-
// Verify signature for security
|
|
57
|
-
const crypto = require("crypto");
|
|
58
|
-
const generatedSignature = crypto
|
|
59
|
-
.createHmac("sha256", "sRO0YkBxvgMg0PvWHJN16Uf7")
|
|
60
|
-
.update(`${razorpayOrderId}|${razorpayPaymentId}`)
|
|
61
|
-
.digest("hex");
|
|
62
|
-
|
|
63
|
-
if (generatedSignature === razorpaySignature) {
|
|
64
|
-
res.json({
|
|
65
|
-
success: true,
|
|
66
|
-
razorpayOrderId,
|
|
67
|
-
razorpayPaymentId,
|
|
68
|
-
verified: true,
|
|
69
|
-
});
|
|
70
|
-
} else {
|
|
71
|
-
res.status(400).json({
|
|
72
|
-
success: false,
|
|
73
|
-
message: "Payment verification failed",
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
} catch (error) {
|
|
77
|
-
res.status(500).json({
|
|
78
|
-
success: false,
|
|
79
|
-
message: "Error verifying payment",
|
|
80
|
-
error: error.message,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
// ============ PAYPAL METHODS ============
|
|
86
|
-
|
|
87
|
-
const createPayPalOrder = async (req, res) => {
|
|
88
|
-
try {
|
|
89
|
-
const { amount, currency = "USD" } = req.body;
|
|
90
|
-
|
|
91
|
-
const request = new paypal.orders.OrdersCreateRequest();
|
|
92
|
-
request.prefer("return=representation");
|
|
93
|
-
request.requestBody({
|
|
94
|
-
intent: "CAPTURE",
|
|
95
|
-
purchase_units: [{
|
|
96
|
-
amount: {
|
|
97
|
-
currency_code: currency,
|
|
98
|
-
value: amount.toString(),
|
|
99
|
-
},
|
|
100
|
-
}],
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const order = await paypalClient().execute(request);
|
|
104
|
-
|
|
105
|
-
res.json({
|
|
106
|
-
success: true,
|
|
107
|
-
orderId: order.result.id,
|
|
108
|
-
order: order.result,
|
|
109
|
-
});
|
|
110
|
-
} catch (error) {
|
|
111
|
-
res.status(500).json({
|
|
112
|
-
success: false,
|
|
113
|
-
message: "Error creating PayPal order",
|
|
114
|
-
error: error.message,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const capturePayPalOrder = async (req, res) => {
|
|
120
|
-
try {
|
|
121
|
-
const { orderId } = req.body;
|
|
122
|
-
|
|
123
|
-
const request = new paypal.orders.OrdersCaptureRequest(orderId);
|
|
124
|
-
request.requestBody({});
|
|
125
|
-
|
|
126
|
-
const capture = await paypalClient().execute(request);
|
|
127
|
-
|
|
128
|
-
res.json({
|
|
129
|
-
success: true,
|
|
130
|
-
captureId: capture.result.id,
|
|
131
|
-
status: capture.result.status,
|
|
132
|
-
capture: capture.result,
|
|
133
|
-
});
|
|
134
|
-
} catch (error) {
|
|
135
|
-
res.status(500).json({
|
|
136
|
-
success: false,
|
|
137
|
-
message: "Error capturing PayPal order",
|
|
138
|
-
error: error.message,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const crud = methods.crudController( Payment );
|
|
144
|
-
for(prop in crud) {
|
|
145
|
-
if(crud.hasOwnProperty(prop)) {
|
|
5
|
+
// Extend with CRUD methods
|
|
6
|
+
const crud = methods.crudController(Payment);
|
|
7
|
+
for (const prop in crud) {
|
|
8
|
+
if (crud.hasOwnProperty(prop)) {
|
|
146
9
|
module.exports[prop] = crud[prop];
|
|
147
10
|
}
|
|
148
11
|
}
|
package/libs/db/index.js
CHANGED
package/libs/emailer/info.js
CHANGED
|
@@ -1,41 +1,29 @@
|
|
|
1
1
|
require("dotenv").config({ path: "backend/.env" });
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"user": process.env.SMTP_MAIL,
|
|
10
|
-
"pass": process.env.SMTP_PASS
|
|
11
|
-
},
|
|
12
|
-
"apps": {
|
|
13
|
-
"gfolio": {
|
|
14
|
-
"auth": {
|
|
15
|
-
"user": process.env.SMTP_MAIL,
|
|
16
|
-
"pass": process.env.SMTP_PASS
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
"gdrea": {
|
|
20
|
-
"auth": {
|
|
21
|
-
"user": process.env.SMTP_MAIL,
|
|
22
|
-
"pass": process.env.SMTP_PASS
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
"jbird": {
|
|
26
|
-
"auth": {
|
|
27
|
-
"user": process.env.SMTP_MAIL,
|
|
28
|
-
"pass": process.env.SMTP_PASS
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
}
|
|
4
|
+
mailgun: {
|
|
5
|
+
domain: "fear.dedyn.io",
|
|
6
|
+
region: 'US',
|
|
7
|
+
apikey: process.env.MG_API_KEY,
|
|
8
|
+
sandbox: "sandbox933b4315c0164f209bbf0bc7fb908598.mailgun.org"
|
|
32
9
|
},
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
10
|
+
smtp: {
|
|
11
|
+
secure: process.env.SMTP_SECURE === 'true',
|
|
12
|
+
mailgun: {
|
|
13
|
+
host: process.env.MG_SMTP_HOST,
|
|
14
|
+
port: parseInt(process.env.SMTP_PORT),
|
|
15
|
+
auth: {
|
|
16
|
+
user: process.env.MG_SMTP_USER,
|
|
17
|
+
pass: process.env.MG_SMTP_PASS
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
google: {
|
|
21
|
+
host: process.env.GOOGLE_SMTP_HOST,
|
|
22
|
+
port: parseInt(process.env.SMTP_PORT),
|
|
23
|
+
auth: {
|
|
24
|
+
user: process.env.GOOGLE_SMTP_USER,
|
|
25
|
+
pass: process.env.GOOGLE_SMTP_PASS
|
|
26
|
+
}
|
|
39
27
|
}
|
|
40
28
|
}
|
|
41
29
|
}
|