Skip to content

Commit afa0b94

Browse files
committed
Define CRUD operation for feature flag
1 parent 4fe73d2 commit afa0b94

File tree

7 files changed

+473
-386
lines changed

7 files changed

+473
-386
lines changed

controllers/featureFlags.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const featureFlagQuery = require('../models/featureFlags')
2+
3+
/**
4+
* Fetches all the featureFlag
5+
*
6+
* @param req {Object} - Express request object
7+
* @param res {Object} - Express response object
8+
*/
9+
10+
const getFeatureFlags = async (req, res) => {
11+
try {
12+
const allFeatureFlags = await featureFlagQuery.fetchFeatureFlag()
13+
return res.json({
14+
message: 'All feature-flags returned successfully',
15+
featureflags: allFeatureFlags.length > 0 ? allFeatureFlags : []
16+
})
17+
} catch (err) {
18+
logger.error(`Error while fetching tasks ${err}`)
19+
return res.boom.badImplementation('An internal server error occurred')
20+
}
21+
}
22+
23+
/**
24+
* Posts the data of the featureFlag
25+
*
26+
* @param req {Object} - Express request object
27+
* @param res {Object} - Express response object
28+
*/
29+
30+
const addFeatureFlag = async (req, res) => {
31+
try {
32+
const featureFlag = await featureFlagQuery.addFeatureFlags(req.body, req.userData.username)
33+
return res.json({
34+
message: 'FeatureFlag added successfully',
35+
featureFlag
36+
})
37+
} catch (err) {
38+
logger.error(`Error while adding featureFlag info: ${err}`)
39+
return res.boom.badImplementation('Something went wrong please contact admin')
40+
}
41+
}
42+
43+
/**
44+
* Update the data of the featureFlag
45+
*
46+
* @param req {Object} - Express request object
47+
* @param res {Object} - Express response object
48+
*/
49+
50+
const updateFeatureFlag = async (req, res) => {
51+
try {
52+
const result = await featureFlagQuery.updateFeatureFlags(req.body, req.params.id)
53+
if (result.isUpdated) {
54+
return res.json({ message: 'FeatureFlag updated successfully!' })
55+
}
56+
return res.boom.notFound('FeatureFlag doesn\'t exist')
57+
} catch (err) {
58+
logger.error(`Error while updating featureFlag info: ${err}`)
59+
return res.boom.badImplementation('Something went wrong please contact admin')
60+
}
61+
}
62+
63+
/**
64+
* Delete featureFlag
65+
*
66+
* @param req {Object} - Express request object
67+
* @param res {Object} - Express response object
68+
*/
69+
70+
const deleteFeatureFlag = async (req, res) => {
71+
try {
72+
const result = await featureFlagQuery.deleteFeatureFlag(req.params.id)
73+
if (result.isDeleted) {
74+
return res.json({
75+
message: 'FeatureFlag deleted successfully!!'
76+
})
77+
}
78+
return res.boom.notFound('featureFlag doesn\'t exist')
79+
} catch (err) {
80+
logger.error(`Error while deleting featureFlag info: ${err}`)
81+
return res.boom.badImplementation('Something went wrong please contact admin')
82+
}
83+
}
84+
85+
module.exports = {
86+
getFeatureFlags,
87+
addFeatureFlag,
88+
updateFeatureFlag,
89+
deleteFeatureFlag
90+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const joi = require('joi')
2+
3+
const validateFeatureFlag = async (req, res, next) => {
4+
const schema = joi.object().keys({
5+
name: joi.string().required(),
6+
title: joi.string().required(),
7+
created_at: joi.number().optional(),
8+
updated_at: joi.number().optional(),
9+
config: joi.object().required(),
10+
launched_at: joi.number().optional()
11+
})
12+
13+
try {
14+
await schema.validateAsync(req.body)
15+
next()
16+
} catch (error) {
17+
logger.error(`Error in validating featureFlag data: ${error}`)
18+
res.boom.badRequest(error.details[0].message)
19+
}
20+
}
21+
22+
const updateFeatureFlags = async (req, res, next) => {
23+
const schema = joi.object().keys({
24+
title: joi.string().optional(),
25+
config: joi.object().required()
26+
})
27+
try {
28+
await schema.validateAsync(req.body)
29+
next()
30+
} catch (error) {
31+
logger.error(`Error in validating featureFlag data: ${error}`)
32+
res.boom.badRequest(error.details[0].message)
33+
}
34+
}
35+
36+
module.exports = {
37+
validateFeatureFlag,
38+
updateFeatureFlags
39+
}

models/featureFlags.js

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
const firestore = require('../utils/firestore')
2+
const featureFlagModel = firestore.collection('featureFlags')
3+
const userModel = require('./users')
4+
5+
/**
6+
* Fetch all tasks
7+
*
8+
* @return {Promise<featureFlags|Array>}
9+
*/
10+
const fetchFeatureFlag = async () => {
11+
try {
12+
const snapshot = await featureFlagModel.get()
13+
const featureFlags = []
14+
snapshot.forEach((doc) => {
15+
featureFlags.push({
16+
id: doc.id,
17+
...doc.data()
18+
})
19+
})
20+
const users = []
21+
const result = {}
22+
23+
featureFlags.forEach((item) => {
24+
if (!users.includes(item.owner)) { users.push(item.owner) }
25+
})
26+
27+
const getImage = async (usersData) => {
28+
return await userModel.fetchUserImage(usersData)
29+
}
30+
31+
let start = 0
32+
let end = 10
33+
34+
for (let i = 0; i < Math.ceil(users.length / 10); i++) {
35+
const usersData = users.slice(start, end)
36+
start = end
37+
end += 10
38+
const image = await getImage(usersData)
39+
Object.assign(result, image)
40+
}
41+
42+
featureFlags.forEach((item) => {
43+
item.owner = {
44+
username: item.owner,
45+
img: result[item.owner]
46+
}
47+
})
48+
return featureFlags
49+
} catch (err) {
50+
logger.error('error getting featureFlags', err)
51+
throw err
52+
}
53+
}
54+
55+
/**
56+
* Add the feature flag data
57+
*
58+
* @param featureFlagData { Object }: featureFlag data object to be stored in DB
59+
* @param username { String }: Username String to be used to add owner in feature flag object
60+
* @return {Promise<{featureFlagData:object}>}
61+
*/
62+
const addFeatureFlags = async (featureFlag, username) => {
63+
try {
64+
featureFlag.created_at = Date.now()
65+
featureFlag.updated_at = featureFlag.created_at
66+
featureFlag.owner = username
67+
const { id } = await featureFlagModel.add(featureFlag)
68+
const featureFlagData = (await featureFlagModel.doc(id).get()).data()
69+
featureFlagData.id = id
70+
return featureFlagData
71+
} catch (err) {
72+
logger.error('Error in adding featureFlag', err)
73+
throw err
74+
}
75+
}
76+
77+
/**
78+
* Adds or updates the feature flag data
79+
*
80+
* @param featureFlag { Object }: feature flag data object to be stored in DB
81+
* @param featureFlagId { String }: feature flag Id String to be used to update the feature Flag
82+
* @return {Promise<{isUpdated: boolean}>}
83+
*/
84+
const updateFeatureFlags = async (featureFlag, featureFlagId) => {
85+
try {
86+
const doc = await featureFlagModel.doc(featureFlagId).get()
87+
if (!doc.data()) {
88+
return {
89+
isUpdated: false
90+
}
91+
}
92+
if (doc.data()) {
93+
featureFlag.updated_at = Date.now()
94+
featureFlag.launched_at = Date.now()
95+
await featureFlagModel.doc(featureFlagId).set({
96+
...doc.data(),
97+
...featureFlag
98+
})
99+
}
100+
return {
101+
isUpdated: true
102+
}
103+
} catch (err) {
104+
logger.error('Error in updating featureFlag', err)
105+
throw err
106+
}
107+
}
108+
109+
/**
110+
* Delete the feature flag data
111+
*
112+
* @param featureFlagId { String }: feature flag Id String to be used to delete the feature Flag
113+
* @return {Promise<{isDeleted: boolean}>}
114+
*/
115+
const deleteFeatureFlag = async (featureFlagId) => {
116+
try {
117+
const doc = await featureFlagModel.doc(featureFlagId).get()
118+
if (!doc.exists) {
119+
return {
120+
isDeleted: false
121+
}
122+
}
123+
return {
124+
isDeleted: true
125+
}
126+
} catch (err) {
127+
logger.error('Error in deleting featureFlag', err)
128+
throw err
129+
}
130+
}
131+
132+
module.exports = {
133+
fetchFeatureFlag,
134+
addFeatureFlags,
135+
updateFeatureFlags,
136+
deleteFeatureFlag
137+
}

models/users.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,27 @@ const updateUserPicture = async (image, userId) => {
167167
}
168168
}
169169

170+
/**
171+
* fetch the users image by passing array of users
172+
*
173+
* @param users {array}
174+
*/
175+
const fetchUserImage = async (users) => {
176+
const data = await userModel.where('username', 'in', users).get()
177+
const hash = {}
178+
data.forEach((item) => {
179+
hash[item.data().username] = item.data().img
180+
})
181+
// console.log(hash)
182+
return hash
183+
}
184+
170185
module.exports = {
171186
addOrUpdate,
172187
fetchUsers,
173188
fetchUser,
174189
setIncompleteUserDetails,
175190
initializeUser,
176-
updateUserPicture
191+
updateUserPicture,
192+
fetchUserImage
177193
}

0 commit comments

Comments
 (0)