Skip to content

Commit bda3d21

Browse files
committed
update referral CA
1 parent f7cc3ef commit bda3d21

File tree

11 files changed

+97
-26
lines changed

11 files changed

+97
-26
lines changed

app.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ passport.use(
4545
app.get(
4646
"/api/v1/Oauth2/google",
4747
(req, res, next) => {
48+
const { referralCode } = req.query;
4849
const frontendUrl = req.headers.referer;
49-
const state = JSON.stringify({ frontendUrl });
50+
const state = JSON.stringify({ frontendUrl, referralCode });
5051
const authUrl = passport.authenticate("google", {
5152
scope: ["profile", "email"],
5253
state,

controllers/auth.js

+31-9
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import jwt from "jsonwebtoken";
77
import { generateOTP, sendVerification } from "../utils/sendVerification.js";
88
import { Verification } from "../models/verification.js";
99
import validator from "validator";
10+
import { CARequest } from "../models/ca_request.js";
1011

1112
export const signup = async (req, res, next) => {
1213
try {
13-
const { name, email, password } = req.body;
14+
const { name, email, password, referralCode } = req.body;
1415

1516
if (!validator.isLength(name, { min: 2, max: 50 })) {
1617
return next(
@@ -30,16 +31,12 @@ export const signup = async (req, res, next) => {
3031

3132
let user = await User.findOne({ email });
3233
if (user) {
33-
return next(new ErrorHandler("User Already Exist", 400));
34+
return next(new ErrorHandler("User Already Exists", 400));
3435
}
3536

3637
const hashedpswd = await bcrypt.hash(password, 10);
3738

38-
await sendVerification(email, generateOTP(), name, hashedpswd);
39-
return res.status(200).json({
40-
status: "success",
41-
message: "Email sent for verification",
42-
});
39+
sendVerification(email, generateOTP(), name, hashedpswd, referralCode, res);
4340
} catch (error) {
4441
next(error);
4542
}
@@ -65,12 +62,17 @@ export const createGoogleUser = async (
6562

6663
export const googleCallback = async (user, req, res, next) => {
6764
try {
68-
const frontendUrl = req.frontendUrl;
65+
const { frontendUrl, referralCode } = req;
6966
const email = user.emails[0].value;
7067
let googleUser = await User.findOne({ email }).select("+password");
7168

72-
if (!googleUser.password)
69+
if (!googleUser.password) {
70+
if (referralCode) {
71+
googleUser.referredBy = referralCode
72+
await googleUser.save();
73+
}
7374
res.redirect(`${frontendUrl}setPassword?email=${email}`);
75+
}
7476
else {
7577
const refreshToken = await generateRefreshToken(googleUser);
7678
const token = jwt.sign({ _id: googleUser._id }, process.env.JWT_SECRET, {
@@ -138,6 +140,16 @@ export const passwordSetter = async (req, res, next) => {
138140

139141
const hashedpswd = await bcrypt.hash(password, 10);
140142

143+
const referralCode = user.referredBy;
144+
if (referralCode) {
145+
const ca = await CARequest.findOne({ referralCode });
146+
if (ca && ca.status === 'approved') {
147+
const points = 10;
148+
ca.points += points;
149+
await ca.save();
150+
}
151+
}
152+
141153
user.password = hashedpswd;
142154
await user.save();
143155

@@ -203,10 +215,20 @@ export const verifyEmail = async (req, res, next) => {
203215
const verification = await Verification.findOne({ email });
204216
if (!verification || verification.code != otp)
205217
return next(new ErrorHandler("OTP Invalid or Expired", 400));
218+
219+
if (verification.referralCode) {
220+
const ca = await CARequest.findOne({ referralCode: verification.referralCode });
221+
if (ca && ca.status === "approved") {
222+
const points = 10;
223+
ca.points += points;
224+
await ca.save();
225+
}
226+
}
206227
const user = await User.create({
207228
name: verification.name,
208229
email: verification.email,
209230
password: verification.password,
231+
referredBy: verification.referralCode
210232
});
211233
const refreshToken = await generateRefreshToken(user);
212234
await Verification.deleteOne({ email });

controllers/ca.js

+21-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import ErrorHandler from "../middlewares/error.js";
22
import { CARequest } from "../models/ca_request.js";
33
import { User } from "../models/user.js";
4+
import { generateCAReferral } from "../utils/features.js";
45

56
export const register = async (req, res, next) => {
67
try {
78
const request = await CARequest.findOne({ user: req.user._id });
89
if (request)
910
return next(new ErrorHandler("CA Request already exists", 400));
1011
const { institute, userDescription, ca_brought_by, branch, graduation_year, contact_number, whatsapp_number } = req.body;
12+
13+
const referralCode = await generateCAReferral();
1114
const newRequest = await CARequest.create({
1215
user: req.user._id,
1316
institute,
@@ -16,7 +19,8 @@ export const register = async (req, res, next) => {
1619
branch,
1720
graduation_year,
1821
contact_number,
19-
whatsapp_number
22+
whatsapp_number,
23+
referralCode
2024
});
2125
res.status(201).json(newRequest);
2226
} catch (error) {
@@ -61,13 +65,6 @@ export const updateRequest = async (req, res, next) => {
6165
);
6266
}
6367
if (status) {
64-
if (req.user.role === "admin" && status === "approved") {
65-
await User.findByIdAndUpdate(request.user, { role: "ca" });
66-
}
67-
68-
if (req.user.role === "admin" && status !== "approved" && request.status === "approved") {
69-
await User.findByIdAndUpdate(request.user, { role: "user" });
70-
}
7168
request.status = status;
7269
}
7370

@@ -91,3 +88,19 @@ export const updateRequest = async (req, res, next) => {
9188
next(error);
9289
}
9390
};
91+
92+
export const getCALeaderboard = async (req, res, next) => {
93+
try {
94+
const ca_requests = await CARequest.find({ status: "approved" }).populate("user", "name").sort({ points: -1 });
95+
const ca_leaderboard = ca_requests.map(request => {
96+
return {
97+
name: request.user.name,
98+
institute: request.institute,
99+
points: request.points
100+
}
101+
})
102+
res.status(200).json(ca_leaderboard)
103+
} catch (error) {
104+
next(error)
105+
}
106+
}

controllers/user.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const updateUser = async (req, res, next) => {
2424
)
2525
);
2626
const { role, institute, phone_num } = req.body;
27-
if (role && role !== "user" && role !== "ca" && role !== "admin")
27+
if (role && role !== "user" && role !== "admin")
2828
return next(new ErrorHandler("Invalid role", 400));
2929

3030
let user = await User.findById(id);

middlewares/auth.js

+2
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ export const isAuthenticated = async (req, res, next) => {
2727
export const cbMiddleware = (req, res, next) => {
2828
const state = JSON.parse(req.query.state || "{}");
2929
const frontend = state.frontendUrl || frontendUrl;
30+
const referralCode = state.referralCode || "";
3031
const callBack = passport.authenticate("google", {
3132
failureRedirect: `${frontend}backend_redirect?error=unknown`,
3233
session: false,
3334
});
3435
req.frontendUrl = frontend;
36+
req.referralCode = referralCode;
3537
callBack(req, res, next);
3638
}

models/ca_request.js

+8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ const schema = new mongoose.Schema({
2626
adminMessage: {
2727
type: String,
2828
},
29+
referralCode: {
30+
type: String,
31+
unique: true
32+
},
33+
points: {
34+
type: Number,
35+
default: 0,
36+
}
2937
});
3038

3139
export const CARequest = mongoose.model("CARequest", schema);

models/user.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const schema = new mongoose.Schema({
1616
},
1717
role: {
1818
type: String,
19-
enum: ["user", "ca", "admin"],
19+
enum: ["user", "admin"],
2020
default: "user",
2121
},
2222
institute: {
@@ -25,6 +25,7 @@ const schema = new mongoose.Schema({
2525
phone_num: {
2626
type: String,
2727
},
28+
referredBy: String,
2829
createdAt: {
2930
type: Date,
3031
default: Date.now,

models/verification.js

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const schema = new mongoose.Schema({
2121
type: Date,
2222
required: true,
2323
},
24+
referralCode: String
2425
});
2526

2627
schema.index({ expiry: 1 }, { expireAfterSeconds: 0 });

routes/ca.js

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
getMyRequest,
66
register,
77
updateRequest,
8+
getCALeaderboard
89
} from "../controllers/ca.js";
910

1011
const router = express.Router();
@@ -13,5 +14,6 @@ router.post("/", isAuthenticated, register);
1314
router.get("/my", isAuthenticated, getMyRequest);
1415
router.patch("/:id", isAuthenticated, updateRequest);
1516
router.get("/all", isAuthenticated, getAllRequests);
17+
router.get("/leaderboard", getCALeaderboard);
1618

1719
export default router;

utils/features.js

+17
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Session } from "../models/session.js";
33
import { Team } from "../models/team.js";
44
import fs from "fs"
55
import YAML from "yamljs";
6+
import { CARequest } from "../models/ca_request.js";
67

78
export const sendJwt = async (
89
user,
@@ -62,6 +63,22 @@ export const generateRandomCode = async () => {
6263
return result;
6364
};
6465

66+
export const generateCAReferral = async () => {
67+
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
68+
let result = "";
69+
70+
do {
71+
result = "";
72+
for (let i = 0; i < 8; i++) {
73+
result += characters.charAt(
74+
Math.floor(Math.random() * characters.length)
75+
);
76+
}
77+
} while (await CARequest.findOne({ referralCode: result }));
78+
79+
return result;
80+
};
81+
6582
export const loadSwaggerWithDynamicUrl = (filePath) => {
6683
let swaggerYaml = fs.readFileSync(filePath, 'utf8');
6784

utils/sendVerification.js

+10-6
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ export function generateOTP() {
66
return otp;
77
}
88

9-
export const sendVerification = async (to, otp, name, password) => {
9+
export const sendVerification = async (to, otp, name, password, referralCode, res) => {
1010
const transporter = nodemailer.createTransport({
1111
service: "gmail",
1212
auth: {
13-
13+
user: process.env.SMTP_EMAIL_ID,
1414
pass: process.env.SMTP_APP_PASS,
1515
},
1616
});
1717

18-
const image_url = "https://iili.io/2cwlabs.png";
19-
const from = "[email protected]";
18+
const image_url = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTP63mBXmRPHkCh88H6n2upFPU-8ibISHho3A&s";
19+
const from = process.env.SMTP_EMAIL_ID;
2020
const mailOptions = {
2121
from,
2222
to,
@@ -69,7 +69,7 @@ export const sendVerification = async (to, otp, name, password) => {
6969
`,
7070
};
7171

72-
await transporter.sendMail(mailOptions, async (error, info) => {
72+
transporter.sendMail(mailOptions, async (error, info) => {
7373
if (error) {
7474
console.error("Error sending email:", error);
7575
throw new Error("Error sending email:", error);
@@ -82,9 +82,13 @@ export const sendVerification = async (to, otp, name, password) => {
8282
code: otp,
8383
password,
8484
expiry: new Date(Date.now() + 60 * 60 * 1000),
85+
referralCode
8586
},
8687
{ upsert: true }
8788
);
88-
89+
res.status(200).json({
90+
status: "success",
91+
message: "Email sent for verification",
92+
});
8993
});
9094
};

0 commit comments

Comments
 (0)