@feardread/fear 1.0.1
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 +459 -0
- package/FEARServer.js +280 -0
- package/controllers/agent.js +438 -0
- package/controllers/auth/index.js +345 -0
- package/controllers/auth/token.js +50 -0
- package/controllers/blog.js +105 -0
- package/controllers/brand.js +10 -0
- package/controllers/cart.js +425 -0
- package/controllers/category.js +9 -0
- package/controllers/coupon.js +63 -0
- package/controllers/crud/crud.js +508 -0
- package/controllers/crud/index.js +36 -0
- package/controllers/email.js +34 -0
- package/controllers/enquiry.js +65 -0
- package/controllers/events.js +9 -0
- package/controllers/order.js +125 -0
- package/controllers/payment.js +31 -0
- package/controllers/product.js +147 -0
- package/controllers/review.js +247 -0
- package/controllers/tag.js +10 -0
- package/controllers/task.js +10 -0
- package/controllers/upload.js +41 -0
- package/controllers/user.js +401 -0
- package/index.js +7 -0
- package/libs/agent/index.js +561 -0
- package/libs/agent/modules/ai/ai.js +285 -0
- package/libs/agent/modules/ai/chat.js +518 -0
- package/libs/agent/modules/ai/config.js +688 -0
- package/libs/agent/modules/ai/operations.js +787 -0
- package/libs/agent/modules/analyze/api.js +546 -0
- package/libs/agent/modules/analyze/dorks.js +395 -0
- package/libs/agent/modules/ccard/README.md +454 -0
- package/libs/agent/modules/ccard/audit.js +479 -0
- package/libs/agent/modules/ccard/checker.js +674 -0
- package/libs/agent/modules/ccard/payment-processors.json +16 -0
- package/libs/agent/modules/ccard/validator.js +629 -0
- package/libs/agent/modules/code/analyzer.js +303 -0
- package/libs/agent/modules/code/jquery.js +1093 -0
- package/libs/agent/modules/code/react.js +1536 -0
- package/libs/agent/modules/code/refactor.js +499 -0
- package/libs/agent/modules/crypto/exchange.js +564 -0
- package/libs/agent/modules/net/proxy.js +409 -0
- package/libs/agent/modules/security/cve.js +442 -0
- package/libs/agent/modules/security/monitor.js +360 -0
- package/libs/agent/modules/security/scanner.js +300 -0
- package/libs/agent/modules/security/vulnerability.js +506 -0
- package/libs/agent/modules/security/web.js +465 -0
- package/libs/agent/modules/utils/browser.js +492 -0
- package/libs/agent/modules/utils/colorizer.js +285 -0
- package/libs/agent/modules/utils/manager.js +478 -0
- package/libs/cloud/index.js +228 -0
- package/libs/config/db.js +21 -0
- package/libs/config/validator.js +82 -0
- package/libs/db/index.js +318 -0
- package/libs/emailer/imap.js +126 -0
- package/libs/emailer/info.js +41 -0
- package/libs/emailer/smtp.js +77 -0
- package/libs/handler/async.js +3 -0
- package/libs/handler/error.js +66 -0
- package/libs/handler/index.js +161 -0
- package/libs/logger/index.js +49 -0
- package/libs/logger/morgan.js +24 -0
- package/libs/passport/passport.js +109 -0
- package/libs/search/api.js +384 -0
- package/libs/search/features.js +219 -0
- package/libs/search/service.js +64 -0
- package/libs/swagger/config.js +18 -0
- package/libs/swagger/index.js +35 -0
- package/libs/validator/index.js +254 -0
- package/models/blog.js +31 -0
- package/models/brand.js +12 -0
- package/models/cart.js +14 -0
- package/models/category.js +11 -0
- package/models/coupon.js +9 -0
- package/models/customer.js +0 -0
- package/models/enquiry.js +29 -0
- package/models/events.js +13 -0
- package/models/order.js +94 -0
- package/models/product.js +32 -0
- package/models/review.js +14 -0
- package/models/tag.js +10 -0
- package/models/task.js +11 -0
- package/models/user.js +68 -0
- package/package.json +12 -0
- package/routes/agent.js +615 -0
- package/routes/auth.js +13 -0
- package/routes/blog.js +19 -0
- package/routes/brand.js +15 -0
- package/routes/cart.js +105 -0
- package/routes/category.js +16 -0
- package/routes/coupon.js +15 -0
- package/routes/enquiry.js +14 -0
- package/routes/events.js +16 -0
- package/routes/mail.js +170 -0
- package/routes/order.js +19 -0
- package/routes/product.js +22 -0
- package/routes/review.js +11 -0
- package/routes/task.js +12 -0
- package/routes/user.js +17 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
const connectDB = async () => {
|
|
4
|
+
try {
|
|
5
|
+
const uri = process.env.MONGO_URI || "mongodb://localhost/bags-ecommerce";
|
|
6
|
+
await mongoose
|
|
7
|
+
.connect(uri, {
|
|
8
|
+
useNewUrlParser: true,
|
|
9
|
+
useCreateIndex: true,
|
|
10
|
+
useUnifiedTopology: true,
|
|
11
|
+
})
|
|
12
|
+
.catch((error) => console.log(error));
|
|
13
|
+
const connection = mongoose.connection;
|
|
14
|
+
console.log("MONGODB CONNECTED SUCCESSFULLY!");
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.log(error);
|
|
17
|
+
return error;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
module.exports = connectDB;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const { check, validationResult } = require("express-validator");
|
|
2
|
+
|
|
3
|
+
const userSignUpValidationRules = () => {
|
|
4
|
+
return [
|
|
5
|
+
check("name", "Name is required").not().isEmpty(),
|
|
6
|
+
check("email", "Invalid email").not().isEmpty().isEmail(),
|
|
7
|
+
check("password", "Please enter a password with 4 or more characters")
|
|
8
|
+
.not()
|
|
9
|
+
.isEmpty()
|
|
10
|
+
.isLength({ min: 4 }),
|
|
11
|
+
];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const userSignInValidationRules = () => {
|
|
15
|
+
return [
|
|
16
|
+
check("email", "Invalid email").not().isEmpty().isEmail(),
|
|
17
|
+
check("password", "Invalid password").not().isEmpty().isLength({ min: 4 }),
|
|
18
|
+
];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const userContactUsValidationRules = () => {
|
|
22
|
+
return [
|
|
23
|
+
check("name", "Please enter a name").not().isEmpty(),
|
|
24
|
+
check("email", "Please enter a valid email address")
|
|
25
|
+
.not()
|
|
26
|
+
.isEmpty()
|
|
27
|
+
.isEmail(),
|
|
28
|
+
check("message", "Please enter a message with at least 10 words")
|
|
29
|
+
.not()
|
|
30
|
+
.isEmpty()
|
|
31
|
+
.isLength({ min: 10 }),
|
|
32
|
+
];
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const validateSignup = (req, res, next) => {
|
|
36
|
+
const errors = validationResult(req);
|
|
37
|
+
if (!errors.isEmpty()) {
|
|
38
|
+
var messages = [];
|
|
39
|
+
errors.array().forEach((error) => {
|
|
40
|
+
messages.push(error.msg);
|
|
41
|
+
});
|
|
42
|
+
req.flash("error", messages);
|
|
43
|
+
return res.redirect("/user/signup");
|
|
44
|
+
}
|
|
45
|
+
next();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const validateSignin = (req, res, next) => {
|
|
49
|
+
const errors = validationResult(req);
|
|
50
|
+
if (!errors.isEmpty()) {
|
|
51
|
+
var messages = [];
|
|
52
|
+
errors.array().forEach((error) => {
|
|
53
|
+
messages.push(error.msg);
|
|
54
|
+
});
|
|
55
|
+
req.flash("error", messages);
|
|
56
|
+
return res.redirect("/user/signin");
|
|
57
|
+
}
|
|
58
|
+
next();
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const validateContactUs = (req, res, next) => {
|
|
62
|
+
const errors = validationResult(req);
|
|
63
|
+
if (!errors.isEmpty()) {
|
|
64
|
+
var messages = [];
|
|
65
|
+
errors.array().forEach((error) => {
|
|
66
|
+
messages.push(error.msg);
|
|
67
|
+
});
|
|
68
|
+
console.log(messages);
|
|
69
|
+
req.flash("error", messages);
|
|
70
|
+
return res.redirect("/pages/contact-us");
|
|
71
|
+
}
|
|
72
|
+
next();
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
userSignUpValidationRules,
|
|
77
|
+
userSignInValidationRules,
|
|
78
|
+
userContactUsValidationRules,
|
|
79
|
+
validateSignup,
|
|
80
|
+
validateSignin,
|
|
81
|
+
validateContactUs,
|
|
82
|
+
};
|
package/libs/db/index.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
const mongoose = require("mongoose");
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MongoDB connection utility module
|
|
5
|
+
* Provides connection management and ObjectId utilities
|
|
6
|
+
*/
|
|
7
|
+
class DatabaseManager {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.isConnected = false;
|
|
10
|
+
this.currentDbName = null;
|
|
11
|
+
this._setupEventListeners();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Setup mongoose connection event listeners
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
_setupEventListeners() {
|
|
19
|
+
mongoose.connection.on('connected', () => {
|
|
20
|
+
this.isConnected = true;
|
|
21
|
+
console.log(`✅ MongoDB connected successfully to: ${this.currentDbName}`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
mongoose.connection.on('error', (err) => {
|
|
25
|
+
this.isConnected = false;
|
|
26
|
+
console.error('❌ MongoDB connection error:', err);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
mongoose.connection.on('disconnected', () => {
|
|
30
|
+
this.isConnected = false;
|
|
31
|
+
console.log(`🔌 MongoDB disconnected from: ${this.currentDbName || 'database'}`);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
mongoose.connection.on('reconnected', () => {
|
|
35
|
+
this.isConnected = true;
|
|
36
|
+
console.log(`🔄 MongoDB reconnected to: ${this.currentDbName}`);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Graceful shutdown handling
|
|
40
|
+
process.on('SIGINT', async () => {
|
|
41
|
+
await this.close();
|
|
42
|
+
process.exit(0);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Connect to MongoDB database
|
|
48
|
+
* @param {Object} env - Environment configuration object
|
|
49
|
+
* @param {string} env.DB_LINK - MongoDB connection string
|
|
50
|
+
* @param {string} env.DB_NAME - Database name
|
|
51
|
+
* @param {Function} [callback] - Optional callback function
|
|
52
|
+
* @param {Object} [options] - Additional mongoose connection options
|
|
53
|
+
* @returns {Promise<void>}
|
|
54
|
+
*/
|
|
55
|
+
async connect(env, callback = null, options = {}) {
|
|
56
|
+
try {
|
|
57
|
+
// Validate required environment variables
|
|
58
|
+
if (!env.DB_LINK) {
|
|
59
|
+
throw new Error('DB_LINK is required in environment configuration');
|
|
60
|
+
}
|
|
61
|
+
if (!env.DB_NAME) {
|
|
62
|
+
throw new Error('DB_NAME is required in environment configuration');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check if already connected to the same database
|
|
66
|
+
if (this.isConnected && this.currentDbName === env.DB_NAME) {
|
|
67
|
+
console.log(`📋 Already connected to MongoDB: ${env.DB_NAME}`);
|
|
68
|
+
if (callback) callback();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Close existing connection if connected to different database
|
|
73
|
+
if (this.isConnected && this.currentDbName !== env.DB_NAME) {
|
|
74
|
+
await this.close();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Set mongoose configuration
|
|
78
|
+
mongoose.set("strictQuery", false);
|
|
79
|
+
|
|
80
|
+
// Default connection options
|
|
81
|
+
const defaultOptions = {
|
|
82
|
+
dbName: env.DB_NAME,
|
|
83
|
+
maxPoolSize: 10,
|
|
84
|
+
serverSelectionTimeoutMS: 5000,
|
|
85
|
+
socketTimeoutMS: 45000,
|
|
86
|
+
bufferCommands: false,
|
|
87
|
+
...options
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
this.currentDbName = env.DB_NAME;
|
|
91
|
+
|
|
92
|
+
// Connect to MongoDB
|
|
93
|
+
await mongoose.connect(env.DB_LINK, defaultOptions);
|
|
94
|
+
|
|
95
|
+
// Execute callback if provided
|
|
96
|
+
if (callback) callback();
|
|
97
|
+
|
|
98
|
+
} catch (error) {
|
|
99
|
+
this.isConnected = false;
|
|
100
|
+
console.error('❌ Failed to connect to MongoDB:', error.message);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Disconnect from MongoDB
|
|
107
|
+
* @param {Function} [callback] - Optional callback function
|
|
108
|
+
* @returns {Promise<void>}
|
|
109
|
+
*/
|
|
110
|
+
async close(callback = null) {
|
|
111
|
+
try {
|
|
112
|
+
if (!this.isConnected) {
|
|
113
|
+
console.log('📋 MongoDB is not connected');
|
|
114
|
+
if (callback) callback();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
await mongoose.disconnect();
|
|
119
|
+
this.isConnected = false;
|
|
120
|
+
|
|
121
|
+
if (callback) callback();
|
|
122
|
+
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error('❌ Error disconnecting from MongoDB:', error.message);
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get connection status
|
|
131
|
+
* @returns {Object} Connection status information
|
|
132
|
+
*/
|
|
133
|
+
getConnectionStatus() {
|
|
134
|
+
return {
|
|
135
|
+
isConnected: this.isConnected,
|
|
136
|
+
readyState: mongoose.connection.readyState,
|
|
137
|
+
dbName: this.currentDbName,
|
|
138
|
+
host: mongoose.connection.host,
|
|
139
|
+
port: mongoose.connection.port
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Wait for database connection to be ready
|
|
145
|
+
* @param {number} [timeout=10000] - Timeout in milliseconds
|
|
146
|
+
* @returns {Promise<void>}
|
|
147
|
+
*/
|
|
148
|
+
async waitForConnection(timeout = 10000) {
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
if (this.isConnected) {
|
|
151
|
+
resolve();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const timeoutId = setTimeout(() => {
|
|
156
|
+
reject(new Error(`Connection timeout after ${timeout}ms`));
|
|
157
|
+
}, timeout);
|
|
158
|
+
|
|
159
|
+
mongoose.connection.once('connected', () => {
|
|
160
|
+
clearTimeout(timeoutId);
|
|
161
|
+
resolve();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
mongoose.connection.once('error', (error) => {
|
|
165
|
+
clearTimeout(timeoutId);
|
|
166
|
+
reject(error);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Create singleton instance
|
|
173
|
+
const dbManager = new DatabaseManager();
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* ObjectId utility functions
|
|
177
|
+
*/
|
|
178
|
+
const ObjectIdUtils = {
|
|
179
|
+
/**
|
|
180
|
+
* Create new ObjectId from string or return existing ObjectId
|
|
181
|
+
* @param {string|mongoose.Types.ObjectId} id - ID to wrap
|
|
182
|
+
* @returns {mongoose.Types.ObjectId} ObjectId instance
|
|
183
|
+
*/
|
|
184
|
+
wrapId(id) {
|
|
185
|
+
if (!id) {
|
|
186
|
+
throw new Error('ID parameter is required');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (mongoose.Types.ObjectId.isValid(id)) {
|
|
190
|
+
return new mongoose.Types.ObjectId(id);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
throw new Error(`Invalid ObjectId format: ${id}`);
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Validate if string is a valid ObjectId
|
|
198
|
+
* @param {string} id - ID to validate
|
|
199
|
+
* @param {boolean} [throwError=true] - Whether to throw error on invalid ID
|
|
200
|
+
* @returns {boolean} True if valid ObjectId
|
|
201
|
+
*/
|
|
202
|
+
validate(id, throwError = true) {
|
|
203
|
+
if (!id) {
|
|
204
|
+
if (throwError) {
|
|
205
|
+
throw new Error('ID parameter is required');
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const isValid = mongoose.Types.ObjectId.isValid(id);
|
|
211
|
+
|
|
212
|
+
if (!isValid && throwError) {
|
|
213
|
+
throw new Error(`Invalid ObjectId format: ${id}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return isValid;
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Generate new ObjectId
|
|
221
|
+
* @returns {mongoose.Types.ObjectId} New ObjectId
|
|
222
|
+
*/
|
|
223
|
+
generate() {
|
|
224
|
+
return new mongoose.Types.ObjectId();
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Convert ObjectId to string
|
|
229
|
+
* @param {mongoose.Types.ObjectId} objectId - ObjectId to convert
|
|
230
|
+
* @returns {string} String representation of ObjectId
|
|
231
|
+
*/
|
|
232
|
+
toString(objectId) {
|
|
233
|
+
if (!objectId) {
|
|
234
|
+
throw new Error('ObjectId parameter is required');
|
|
235
|
+
}
|
|
236
|
+
return objectId.toString();
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Check if two ObjectIds are equal
|
|
241
|
+
* @param {string|mongoose.Types.ObjectId} id1 - First ID
|
|
242
|
+
* @param {string|mongoose.Types.ObjectId} id2 - Second ID
|
|
243
|
+
* @returns {boolean} True if IDs are equal
|
|
244
|
+
*/
|
|
245
|
+
areEqual(id1, id2) {
|
|
246
|
+
if (!id1 || !id2) return false;
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
const objId1 = this.wrapId(id1);
|
|
250
|
+
const objId2 = this.wrapId(id2);
|
|
251
|
+
return objId1.equals(objId2);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Legacy compatibility functions (backwards compatibility)
|
|
260
|
+
*/
|
|
261
|
+
const legacyAPI = {
|
|
262
|
+
/**
|
|
263
|
+
* Legacy run function for backwards compatibility
|
|
264
|
+
* @deprecated Use dbManager.connect() instead
|
|
265
|
+
*/
|
|
266
|
+
async run(env, callback) {
|
|
267
|
+
console.warn('⚠️ Warning: run() is deprecated. Use connect() instead.');
|
|
268
|
+
return await dbManager.connect(env, callback);
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Legacy close function for backwards compatibility
|
|
273
|
+
* @deprecated Use dbManager.close() instead
|
|
274
|
+
*/
|
|
275
|
+
async close(callback) {
|
|
276
|
+
console.warn('⚠️ Warning: close() is deprecated. Use disconnect() instead.');
|
|
277
|
+
return await dbManager.disconnect(callback);
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Legacy store function (placeholder)
|
|
282
|
+
* @deprecated This function was not implemented in original code
|
|
283
|
+
*/
|
|
284
|
+
store() {
|
|
285
|
+
console.warn('⚠️ Warning: store() function is not implemented');
|
|
286
|
+
return null;
|
|
287
|
+
},
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Legacy wrapId function for backwards compatibility
|
|
291
|
+
* @deprecated Use ObjectIdUtils.wrapId() instead
|
|
292
|
+
*/
|
|
293
|
+
wrapId(id) {
|
|
294
|
+
console.warn('⚠️ Warning: wrapId() is deprecated. Use ObjectIdUtils.wrapId() instead.');
|
|
295
|
+
return ObjectIdUtils.wrapId(id);
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Legacy validate function for backwards compatibility
|
|
300
|
+
* @deprecated Use ObjectIdUtils.validate() instead
|
|
301
|
+
*/
|
|
302
|
+
validate(id) {
|
|
303
|
+
console.warn('⚠️ Warning: validate() is deprecated. Use ObjectIdUtils.validate() instead.');
|
|
304
|
+
return ObjectIdUtils.validate(id);
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
module.exports = {
|
|
309
|
+
// New recommended API
|
|
310
|
+
connect: (env, callback, options) => dbManager.connect(env, callback, options),
|
|
311
|
+
disconnect: (callback) => dbManager.close(callback),
|
|
312
|
+
getConnectionStatus: () => dbManager.getConnectionStatus(),
|
|
313
|
+
waitForConnection: (timeout) => dbManager.waitForConnection(timeout),
|
|
314
|
+
ObjectId: ObjectIdUtils,
|
|
315
|
+
dbManager,
|
|
316
|
+
mongoose,
|
|
317
|
+
...legacyAPI
|
|
318
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const ImapClient = require("emailjs-imap-client");
|
|
2
|
+
const { ParsedMail, simpleParser } = require("mailparser");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module.exports = class Worker {
|
|
6
|
+
constructor (mailinfo) {
|
|
7
|
+
this.mailinfo = mailinfo;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
connectToServer = async (req, res) => {
|
|
11
|
+
const client = new ImapClient.default(
|
|
12
|
+
this.mailinfo.imap.host,
|
|
13
|
+
this.mailinfo.imap.port,
|
|
14
|
+
{ auth: this.mailinfo.imap.auth }
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
client.logLevel = client.LOG_LEVEL_NONE; // keep the output logging
|
|
18
|
+
client.onerror = (error) => {
|
|
19
|
+
console.log("IMAP.Worker.listMailboxes(): Connection error", error);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
await client.connect();
|
|
23
|
+
|
|
24
|
+
return client;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
listMailboxes = async (req, res) => {
|
|
28
|
+
const client = await this.connectToServer();
|
|
29
|
+
const mailboxes = await client.listMailboxes();
|
|
30
|
+
await client.close();
|
|
31
|
+
|
|
32
|
+
const iterateChildren = (inArray) => {
|
|
33
|
+
|
|
34
|
+
inArray.forEach((inValue: any) => {
|
|
35
|
+
finalMailboxes.push({
|
|
36
|
+
name: inValue.name,
|
|
37
|
+
path: inValue.path
|
|
38
|
+
});
|
|
39
|
+
iterateChildren(inValue.children);
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
iterateChildren(mailboxes.children);
|
|
43
|
+
|
|
44
|
+
return finalMailboxes;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
listMessages = async (options) => {
|
|
48
|
+
const client = await this.connectToServer();
|
|
49
|
+
const mailbox = await client.selectMailbox(options.mailbox);
|
|
50
|
+
|
|
51
|
+
if (mailbox.exists === 0) {
|
|
52
|
+
await client.close();
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const messages = await client.listMessages(
|
|
57
|
+
options.mailbox, "1:*", ["uid", "envelope"]
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
await client.close();
|
|
61
|
+
const finalMessages = [];
|
|
62
|
+
messages.forEach((value) => {
|
|
63
|
+
finalMessages.push({
|
|
64
|
+
id: value.uid,
|
|
65
|
+
date: value.envelope.date,
|
|
66
|
+
from: value.envelope.from[0].address,
|
|
67
|
+
subject: value.envelope.subject
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return finalMessages;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Gets the plain text body of a single message.
|
|
77
|
+
*
|
|
78
|
+
* @param options An object implementing the ICallOptions interface.
|
|
79
|
+
* @return The plain text body of the message.
|
|
80
|
+
*/
|
|
81
|
+
getMessageBody = async (options) => {
|
|
82
|
+
const client = await this.connectToServer();
|
|
83
|
+
const messages = await client.listMessages(
|
|
84
|
+
options.mailbox,
|
|
85
|
+
options.id,
|
|
86
|
+
{ byUid: true }
|
|
87
|
+
);
|
|
88
|
+
const parsed = await simpleParser(messages[0]["body[]"]);
|
|
89
|
+
await client.close();
|
|
90
|
+
|
|
91
|
+
return parsed?.text;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Deletes a single message.
|
|
97
|
+
*
|
|
98
|
+
* @param options An object implementing the ICallOptions interface.
|
|
99
|
+
*/
|
|
100
|
+
deleteMessage = async (options) => {
|
|
101
|
+
const client = await this.connectToServer();
|
|
102
|
+
const messages = await client.listMessages(
|
|
103
|
+
options.mailbox,
|
|
104
|
+
options.id, // specifying a specific message ID
|
|
105
|
+
["uid"], // body can be in multiple parts, it’s actually an array
|
|
106
|
+
{ byUid: true } // listing messages based on a specific ID
|
|
107
|
+
);
|
|
108
|
+
if (options.mailbox !== 'Deleted'){
|
|
109
|
+
await client.copyMessages(
|
|
110
|
+
options.mailbox,
|
|
111
|
+
messages[0]['uid'],
|
|
112
|
+
'Deleted',
|
|
113
|
+
{ byUid: true } // tell the method that we are passing a unique ID
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
await client.deleteMessages(
|
|
117
|
+
options.mailbox,
|
|
118
|
+
messages[0]['uid'],
|
|
119
|
+
// inCallOptions.id,
|
|
120
|
+
{ byUid: true } // tell the method that we are passing a unique ID
|
|
121
|
+
);
|
|
122
|
+
await client.close(); // no return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require("dotenv").config({ path: "backend/.env" });
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
"smtp": {
|
|
5
|
+
"service": process.env.SMTP_SERVICE,
|
|
6
|
+
"host": process.env.SMTP_HOST,
|
|
7
|
+
"port": process.env.SMTP_PORT,
|
|
8
|
+
"auth": {
|
|
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
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"imap": {
|
|
34
|
+
"host": "mail.mydomain.com",
|
|
35
|
+
"port": 999,
|
|
36
|
+
"auth": {
|
|
37
|
+
"user": "user@domain.com",
|
|
38
|
+
"pass": "xxx"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const nodemailer = require("nodemailer");
|
|
2
|
+
|
|
3
|
+
module.exports = class Worker {
|
|
4
|
+
constructor(mailinfo) {
|
|
5
|
+
this.mailinfo = mailinfo;
|
|
6
|
+
this.email = mailinfo.smtp.auth.user;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Send a message.
|
|
11
|
+
*
|
|
12
|
+
* @param options An object containing to, from, subject and text properties (matches the IContact interface,
|
|
13
|
+
* but can't be used since the type comes from nodemailer, not app code).
|
|
14
|
+
* @return A Promise that eventually resolves to a string (null for success, error message for an error).
|
|
15
|
+
*/
|
|
16
|
+
sendMessage = async (options) => {
|
|
17
|
+
return new Promise((res, req) => {
|
|
18
|
+
const transport = nodemailer.createTransport(this.mailinfo.smtp);
|
|
19
|
+
|
|
20
|
+
transport.sendMail( options, (error, info) => {
|
|
21
|
+
if (error) return reject(error);
|
|
22
|
+
return resolve();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
sendProjectEmail = async (data) => {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
let transporter = nodemailer.createTransport(this.mailinfo.smtp);
|
|
30
|
+
|
|
31
|
+
const { $subject, fullname, company, email, phone, budget, about } = data;
|
|
32
|
+
|
|
33
|
+
const message = `Fullname: ${fullname}\n`
|
|
34
|
+
+ `Email: ${email}\n`
|
|
35
|
+
+ `Budget: ${budget}\n`
|
|
36
|
+
+ `Phone number: + ${phone}\n`
|
|
37
|
+
+ `Company: ${company}\n`
|
|
38
|
+
+ `About project: ${about}\n`
|
|
39
|
+
|
|
40
|
+
const options = {
|
|
41
|
+
from: email,
|
|
42
|
+
to: this.email,
|
|
43
|
+
subject: $subject || `Gfolio Contact Form Submission`,
|
|
44
|
+
text: message,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
transporter.sendMail(options, function(error, info) {
|
|
48
|
+
if (error) {
|
|
49
|
+
return reject({ message: `An error has occured: ${error}`});
|
|
50
|
+
}
|
|
51
|
+
return resolve({ message: 'Email sent succesfully!'})
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
sendContactEmail = async (data) => {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
let transport = nodemailer.createTransport(this.mailinfo.smtp);
|
|
59
|
+
const { $subject, $email, $message, $source } = data;
|
|
60
|
+
|
|
61
|
+
const options = {
|
|
62
|
+
from: $source,
|
|
63
|
+
to: this.email,
|
|
64
|
+
subject:"Contact Form :: " + $email,
|
|
65
|
+
text: $message,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
transport.sendMail(options, (error, info) => {
|
|
69
|
+
console.log('send contact email resp :: ', error);
|
|
70
|
+
|
|
71
|
+
if (error) return reject({ message: `An error has occured: ${error}`});
|
|
72
|
+
|
|
73
|
+
return resolve({ message: 'Email sent succesfully!'})
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
}
|