Skip to content

Commit fb2cfdb

Browse files
authored
Merge pull request #23 from atlp-rwanda/profile-page-settings-#184359076
feat(profile-page): created models to use in profile setup
2 parents 552e91a + fbd6a77 commit fb2cfdb

File tree

12 files changed

+474
-11
lines changed

12 files changed

+474
-11
lines changed

package-lock.json

+27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"bcrypt": "^5.1.0",
3434
"connect-redis": "^6.1.3",
3535
"cookie-parser": "^1.4.6",
36+
"country-data-list": "^1.2.3",
3637
"crypto": "^1.0.1",
3738
"dotenv": "^16.0.3",
3839
"express": "^4.18.2",

src/app.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import {config} from 'dotenv'
33
import swaggerDocs from './docs/swagger'
44
import connectdb from './db/database'
55
import authRoutes from './routes/authroutes'
6-
6+
import profileRoutes from "./routes/profileroutes"
77
const app: Application = express()
88

99
config()
1010
//middleware section
1111
app.use(express.json())
1212

1313
app.use(authRoutes)
14-
14+
app.use(profileRoutes)
1515
console.log('Hello Team emma This backend API')
1616

1717
const PORT = process.env.PORT || 3000

src/controllers/authController.ts

+19-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import bcrypt from 'bcrypt'
1313

1414
const RedisStore = connectRedis(session)
1515
import { object } from 'joi'
16+
import PROFILE from '../models/profilemodels/profile'
17+
import ADDRESS from '../models/profilemodels/Address'
18+
import BILLINGADDRESS from '../models/profilemodels/BillingAdress'
1619
config()
1720

1821
const account_sid = process.env.TWILIO_ACCOUNT_SID
@@ -97,17 +100,31 @@ class auth {
97100
firstName,
98101
lastName,
99102
email,
100-
role: 'User',
101103
password,
102104
})
105+
//create profile
106+
// BILLINGADDRESS.drop()
107+
// ADDRESS.drop()
108+
109+
if(createData){
110+
const profiledata={
111+
firstName: createData.firstName,
112+
lastName: createData.lastName,
113+
email: createData.email,
114+
userId: createData.id
115+
}
116+
await PROFILE.create({...profiledata})
117+
118+
}
119+
//create pofile
103120
const user = await USER.findOne({
104121
where: { email: email },
105122
attributes: ['id', 'firstName', 'lastName', 'email', 'role'],
106123
})
107124
res.status(200).json({
108125
status: 200,
109126
message: 'account created successfully',
110-
token: encode({ id: createData.id, email: createData.email }),
127+
token: encode({ id: createData.id, email: createData.email , role : createData.role}),//changed the token to keep same fields as login
111128
})
112129
}
113130
} catch (error: any) {
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import PROFILE from "../models/profilemodels/profile";
2+
import ADDRESS from "../models/profilemodels/Address";
3+
import BILLINGADRESS from "../models/profilemodels/BillingAdress";
4+
import { Request , Response } from "express";
5+
import { CustomRequest } from "../middlewares/verifyToken";
6+
/* eslint-disable @typescript-eslint/no-explicit-any */
7+
8+
9+
class Profiles{
10+
static async getprofile(req: Request , res: Response){
11+
try {
12+
const profilepage: any = await PROFILE.findOne({where:{userId: req.params.userId},
13+
include: [{ model: BILLINGADRESS , as: 'billingAddress' },{ model: ADDRESS , as: 'Address' }]
14+
15+
})
16+
res.status(200).json({
17+
statusCode: 200,
18+
message: "succesfully retrieved profile data",
19+
data: profilepage
20+
21+
})
22+
} catch (error) {
23+
console.log()
24+
}
25+
}
26+
27+
static async edit(req: CustomRequest , res: Response){
28+
const loggedinuser:any = req.user
29+
console.log(loggedinuser)
30+
const profile:any = await PROFILE.findOne({where: {userId : loggedinuser.id}})
31+
const profileId = profile.id
32+
33+
try {
34+
35+
const foundProfile: any = await PROFILE.findOne({where:{id: profileId}})
36+
if(foundProfile){
37+
const bAddress= req.body.billingAddress
38+
const profileDetails= req.body.profileDetails
39+
const Address = req.body.address
40+
if(profileDetails){
41+
await PROFILE.update(profileDetails,{where:{id: profileId}})
42+
}
43+
if(bAddress){
44+
const BA = await BILLINGADRESS.findOne({where: {id: profileId}})
45+
if(BA){
46+
await BILLINGADRESS.update(bAddress,{where: {profileId}})
47+
}else {
48+
await BILLINGADRESS.create({...bAddress, profileId})
49+
}
50+
}
51+
if(Address){
52+
const AD = await ADDRESS.findOne({where: {profileId}})
53+
if(AD){
54+
await ADDRESS.update(Address,{where: {profileId}})
55+
}else{
56+
await ADDRESS.create({...Address, profileId})
57+
}
58+
}
59+
res.status(200).json({
60+
statusCode: 200,
61+
message: `updated profile for ${foundProfile.firstName}`,
62+
63+
})
64+
}
65+
} catch (error: any) {
66+
res.status(400).json({
67+
StatusCode: 400,
68+
message: error.message
69+
})
70+
71+
}
72+
73+
74+
}
75+
static async getall(req: Request , res: Response){
76+
try {
77+
78+
const profiles = await PROFILE.findAll( {attributes: [ "id","email", "firstName" , "lastName", "userId"]} )
79+
res.status(200).json({
80+
statusCode: 200,
81+
message: "sucessfully retreived the profiles",
82+
data: profiles
83+
84+
})
85+
86+
} catch (error: any ) {
87+
res.status(200).json({
88+
statusCode: 400,
89+
message: error.message
90+
})
91+
92+
}
93+
94+
}
95+
}
96+
export default Profiles

src/middlewares/verifyToken.ts

+30-6
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,56 @@
11
import { Request,Response,NextFunction } from 'express';
22
import jwt from "jsonwebtoken";
33
import dotenv from "dotenv";
4-
import { any, string } from 'joi';
4+
import { RequestHandler } from 'express';
55
dotenv.config();
66

7-
const verifyToken=async(req:Request, res:Response, next:NextFunction)=>{
7+
/* eslint-disable @typescript-eslint/no-explicit-any */
8+
9+
interface User {
10+
id: number;
11+
email: string;
12+
role: string;
13+
}
14+
export interface CustomRequest extends Request {
15+
user?: User;
16+
[key: string]: any;
17+
}
18+
19+
const verifyToken: RequestHandler<CustomRequest> =async(req :CustomRequest, res:Response, next: NextFunction)=>{
820
try {
921

1022
const token=req.headers['authorization'] as string
23+
if(token){
1124
const auth = token.split(" ")[1]
1225
// const token=authHeader && authHeader.split('')[1]
1326
if (!auth) {
1427
return res.status(403).send("A token is required for authentication");
1528
}
1629
try {
17-
const decoded = jwt.verify(auth, process.env.JWT_SECRET as string);
18-
// req.user = decoded;
30+
const decoded: any = jwt.verify(auth, process.env.JWT_SECRET as string);
31+
req.user = {
32+
id: decoded.id,
33+
email: decoded.email,
34+
role: decoded.role
35+
}
36+
next()
37+
38+
;
1939
} catch (err) {
2040

2141
console.log(err)
42+
}}else{
43+
res.status(401).json({
44+
statusCode: 401,
45+
message: "you are not logged"
46+
})
2247
}
23-
return next();
48+
2449

2550
} catch (error) {
2651
return res.status(403).send("Token not provided");
2752

2853
}
29-
3054

3155
}
3256

src/models/User.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { sequelizedb } from "../db/database";
22
import {DataTypes} from "sequelize";
33
import bcrypt from "bcrypt"
4+
import Profile from "./profilemodels/profile";
45
const USER = sequelizedb.define('user', {
56
firstName: {
67
type: DataTypes.STRING,
@@ -33,4 +34,6 @@ const USER = sequelizedb.define('user', {
3334
})
3435
USER.sync()
3536

36-
export default USER
37+
USER.hasOne(Profile, { foreignKey: 'userId', as: 'profile' });
38+
Profile.belongsTo(Profile, { foreignKey: 'userId' });
39+
export default USER

src/models/profilemodels/Address.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { DataTypes } from "sequelize";
2+
import { sequelizedb } from "../../db/database";
3+
import countrylist from "country-data-list"
4+
5+
// console.log(countrylist.languages.all)
6+
// const countries = countrylist.countries
7+
8+
9+
const Address = sequelizedb.define('Addresses',{
10+
streetAddress: {
11+
type: DataTypes.STRING,
12+
allowNull: true,
13+
},
14+
city: {
15+
type: DataTypes.STRING,
16+
allowNull: false,
17+
},
18+
stateOrProvince: {
19+
type: DataTypes.STRING,
20+
allowNull: false,
21+
},
22+
zipOrPostalCode: {
23+
type: DataTypes.STRING,
24+
allowNull: true,
25+
},
26+
country: {
27+
type: DataTypes.STRING,
28+
allowNull: false,
29+
},
30+
profileId: {
31+
type: DataTypes.INTEGER,
32+
allowNull: false,
33+
references: {
34+
model: 'profiles',
35+
key: 'id'
36+
}}
37+
38+
})
39+
Address.sync()
40+
export default Address
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { sequelizedb } from "../../db/database";
2+
import { DataTypes } from "sequelize";
3+
import countrylist from "country-data-list"
4+
5+
6+
// const countries = countrylist.countries.all
7+
8+
9+
10+
const BillingAddress = sequelizedb.define('BillingAddress',
11+
{
12+
streetAddress: {
13+
type: DataTypes.STRING,
14+
allowNull: true,
15+
},
16+
city: {
17+
type: DataTypes.STRING,
18+
allowNull: false,
19+
},
20+
stateOrProvince: {
21+
type: DataTypes.STRING,
22+
allowNull: false,
23+
},
24+
zipOrPostalCode: {
25+
type: DataTypes.STRING,
26+
allowNull: true,
27+
},
28+
country: {
29+
type: DataTypes.STRING,
30+
allowNull: false,
31+
} ,
32+
profileId: {
33+
type: DataTypes.INTEGER,
34+
allowNull: false,
35+
references: {
36+
model: 'profiles',
37+
key: 'id'
38+
}}
39+
40+
})
41+
BillingAddress.sync()
42+
//billing address
43+
export default BillingAddress

0 commit comments

Comments
 (0)