Skip to content

Commit

Permalink
External wallet SOCIAL NETWORKS ( METAMASK ) (#369)
Browse files Browse the repository at this point in the history
### PR Description:

Hello team,

This PR introduces a comprehensive system for external users,
specifically those utilizing Metamask wallets. With this enhancement,
users can seamlessly connect their Metamask wallets to our application
and link their social network accounts, including Facebook, YouTube,
LinkedIn, TikTok, and Twitter.

### Changes Made:

- Metamask Integration:

1- Added functionality to allow users to connect their Metamask wallets
to our application.
2- Implemented a smooth authentication process for Metamask users.


- Social Network Account Linking:

1-Users with connected Metamask wallets can now link their social
network accounts (Facebook, YouTube, LinkedIn, TikTok, Twitter) within
our application.


- New Routes and Controllers for External Users:

1-Created new routes and controllers specifically designed for external
users.


### Notes for Reviewers:

Please review the changes made in this PR to confirm that the Metamask
integration and the introduction of the external user system have been
correctly implemented. Test the new routes and controllers to ensure
they seamlessly handle tasks for external users, such as campaign
creation and application processes.

Your attention and contributions are highly appreciated. Feel free to
provide any feedback or suggestions you may have.

Best regards,
Louay HICHRI
  • Loading branch information
ksibisamir authored Nov 30, 2023
2 parents 6d0755d + c9322c4 commit 7247c6a
Show file tree
Hide file tree
Showing 10 changed files with 389 additions and 60 deletions.
283 changes: 283 additions & 0 deletions controllers/external.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
const { responseHandler } = require('../helpers/response-handler')
const makeResponseData = responseHandler.makeResponseData
const makeResponseError = responseHandler.makeResponseError
const {
GoogleProfile,
LinkedinProfile,
TwitterProfile,
FbPage,
TikTokProfile,
UserExternalWallet
} = require('../model/index')


exports.createUserFromExternalWallet = async (req, res) =>{
try {
const userExist = await UserExternalWallet.findOne({walletId: req.body.wallet});
if(!userExist) {
const workerId = process.pid
const currentDate = new Date().getTime();
const uniqueId = parseInt(workerId + currentDate);
const user = new UserExternalWallet({UserId: uniqueId,walletId: req.body.wallet});
const savedUser = await user.save();
return makeResponseData(res, 200, 'User created successfully', savedUser);
} else return makeResponseData(res, 200, 'User signed In successfully', userExist);

} catch(err){
return makeResponseError(res, 500, err.message ? err.message : err.error);
}
}


exports.externalSocialAccounts = async (req, res) => {
try {
const user = await UserExternalWallet.findOne({walletId: req.address});

let UserId = user.UserId;
let networks = {}
let [channelsGoogle, channelsTwitter] = await Promise.all([
GoogleProfile.find({ UserId }, { accessToken: 0, refreshToken: 0 }),
TwitterProfile.find(
{ UserId },
{ _raw: 0, access_token_key: 0, access_token_secret: 0 }
),
])
let channelsFacebook = await FbPage.find({ UserId }, { token: 0 })
let channelsLinkedin = await LinkedinProfile.find({ userId: UserId })
let channelsTiktok = await TikTokProfile.find(
{ userId: UserId },
{ accessToken: 0, refreshToken: 0 }
)
networks.google = channelsGoogle
networks.twitter = channelsTwitter
networks.facebook = channelsFacebook
networks.linkedin = channelsLinkedin?.flatMap((item) =>
item?.pages.map((elem) => {
elem = elem.toJSON()
elem.linkedinId = item.linkedinId
return elem
})
)

networks.tikTok = channelsTiktok || []
if (
!channelsGoogle?.length &&
!channelsLinkedin?.length &&
!channelsTwitter?.length &&
!channelsFacebook?.length &&
!channelsTiktok?.length
) {
return makeResponseError(res, 204, 'No channel found')
}
return makeResponseData(res, 200, 'success', networks)
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteTiktokChannel = async (req,res) => {
try {
let user = await UserExternalWallet.findOne({walletId: req.address})

let tiktokProfiles = await TikTokProfile.find({ userId: user.UserId })

if (tiktokProfiles.length === 0)
return makeResponseError(res, 204, 'No channel found')
else {
await TikTokProfile.deleteMany({ userId: user.UserId })
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteTiktokChannels = async (req, res) => {
try {
let user = await UserExternalWallet.findOne({walletId: req.address})

let tiktokProfiles = await TikTokProfile.find({ userId: user.UserId })

if (tiktokProfiles.length === 0)
return makeResponseError(res, 204, 'No channel found')
else {
await TikTokProfile.deleteMany({ userId: user.UserId })
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteGoogleChannel = async (req, res) => {
try {
const UserId = await UserExternalWallet.findOne({walletId: req.address})
let _id = req.params.id
let googleProfile = await GoogleProfile.findOne({ _id }).lean()
if (googleProfile?.UserId !== UserId.UserId)
return makeResponseError(res, 401, 'unauthorized')
else {
await GoogleProfile.deleteOne({ _id })
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteGoogleChannels = async (req, res) => {
try {
const user = await UserExternalWallet.findOne({walletId: req.address})
const result = await GoogleProfile.deleteMany({ UserId: user.UserId })
if (result.deletedCount === 0) {
return makeResponseError(res, 204, 'No channel found')
} else {
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
console.log({err})
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteFacebookChannels = async (req, res) => {
try {
const user = await UserExternalWallet.findOne({walletId: req.address})
const result = await FbPage.deleteMany({ UserId: user.UserId })
if (result.deletedCount === 0) {
return makeResponseError(res, 204, 'No channel found')
} else {
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteFacebookChannel = async (req, res) => {
try {
const user = await UserExternalWallet.findOne({walletId: req.address})
let _id = req.params.id
let facebookProfile = await FbPage.findOne({ _id })
if (facebookProfile?.UserId !== user.UserId)
return makeResponseError(res, 401, 'unauthorized')
else {
await FbPage.deleteOne({ _id })
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteLinkedinChannels = async (req, res) => {
try {
const user = await UserExternalWallet.findOne({walletId: req.address})
const result = await LinkedinProfile.deleteMany({ userId: user.UserId })
if (result.deletedCount === 0) {
return makeResponseError(res, 204, 'No channel found')
} else {
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteLinkedinChannel = async (req, res) => {
try {
const user = await UserExternalWallet.findOne({walletId: req.address})
let { organization, linkedinId } = req.params
let linkedinProfile = await LinkedinProfile.findOne(
{ userId: user.UserId, linkedinId },
{ pages: 1 }
).lean()
if (!linkedinProfile) return makeResponseError(res, 401, 'unauthorized')
if (linkedinProfile.pages.length === 1) {
await LinkedinProfile.deleteOne({ userId: user.UserId, linkedinId })
} else {
await LinkedinProfile.updateOne(
{ userId: user.UserId, linkedinId },
{ $pull: { pages: { organization } } }
)
}
return makeResponseData(res, 200, 'deleted successfully')
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}


exports.externalDeleteTwitterChannels = async (req, res) => {
try {
const user = await UserExternalWallet.findOne({walletId: req.address})
const result = await TwitterProfile.deleteMany({ UserId: user.UserId })
if (result.deletedCount === 0) {
return makeResponseError(res, 204, 'No channel found')
} else {
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}

exports.externalDeleteTwitterChannel = async (req, res) => {
try {
const user = await UserExternalWallet.findOne({walletId: req.address})
let _id = req.params.id
let twitterProfile = await TwitterProfile.findOne({ _id })
if (twitterProfile?.UserId !== user.UserId)
return makeResponseError(res, 401, 'unauthorized')
else {
await TwitterProfile.deleteOne({ UserId: user.UserId })
return makeResponseData(res, 200, 'deleted successfully')
}
} catch (err) {
return makeResponseError(
res,
500,
err.message ? err.message : err.error
)
}
}
25 changes: 1 addition & 24 deletions controllers/wallet.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var bip32 = require('bip32')
var bip38 = require('bip38')
const { ethers } = require('ethers');

const UserExternalWallet = require('./../model/userxternalwallet.model.js'); // Adjust the path as needed


const Web3 = require('web3')
const {
Expand Down Expand Up @@ -1019,29 +1019,6 @@ exports.createNewWalletV2 = async (req, res) => {
}
}


exports.createUserFromExternalWallet = async (req, res) =>{

try{

const newUserWallet = new UserExternalWallet({
_id: req.body.wallet, // Replace with the actual user ID
});

await newUserWallet.save()

return responseHandler.makeResponseData(res, 200, 'User created successfully', newUserWallet);

}
catch(err){
return responseHandler.makeResponseError(res, 500, err.message ? err.message : err.error);

}


}


exports.addTronWalletToExistingAccount = async (req, res) => {
try {
let account = await Wallet.findOne({ UserId: req.user._id })
Expand Down
15 changes: 15 additions & 0 deletions middleware/verifySignature.middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const verifySignature = require('./../web3/verifySignature')

const verifySignatureMiddleware = (req, res, next) => {
const signature = req.header('X-Signature');
const address = req.header('X-Address');
const message = req.header('X-Message')
if (verifySignature(message, signature, address)) {
req.address = address;
return next();
} else {
return res.status(401).json({ message: 'Invalid signature' });
}
}

module.exports = verifySignatureMiddleware
4 changes: 3 additions & 1 deletion model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var Request = require('../model/request.model')
var Captcha = require('../model/captcha.model')
var UserArchived = require('../model/UserArchive.model')
const WalletUserNode = require('../model/walletUserNode.model')
const UserExternalWallet = require('../model/userExternalWallet.model.js');

module.exports = {
UserArchived,
Expand All @@ -36,5 +37,6 @@ module.exports = {
FbPage,
Wallet,
CustomToken,
WalletUserNode
WalletUserNode,
UserExternalWallet
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const mongoose = require('mongoose');
const { mongoConnection } = require('../conf/config');

const db = mongoose.createConnection(mongoConnection(), {
useNewUrlParser: true,
useUnifiedTopology: true,
Expand All @@ -9,7 +8,12 @@ const db = mongoose.createConnection(mongoConnection(), {
});

const userExternalWalletSchema = new mongoose.Schema({
_id: {
UserId: {
type: Number,
required: true,
unique:true
},
walletId: {
type: String,
required: true,
},
Expand Down
4 changes: 4 additions & 0 deletions route-setup/routeSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const loginRoutes = require('../routes/login.routes')
const walletRoutes = require('../routes/wallet.routes')
const profileRoutes = require('../routes/profile.routes')
const campaignRoutes = require('../routes/campaign.routes')
const externalRoutes = require('../routes/external.routes')
const {swaggerUi, swaggerSpec, cssOptions} = require('../conf/swaggerSetup');
const {errorHandler, handleEndpointNotFound} = require('../middleware/errorHandler.middleware');

Expand All @@ -19,6 +20,9 @@ const setupRoutes = (app) => {
// CAPAIGN ROUTES
app.use('/campaign', campaignRoutes);

// EXTERNAL ROUTES FOR DAPP
app.use('/external', externalRoutes)

// SWAGGER DOCS
app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, cssOptions));

Expand Down
Loading

0 comments on commit 7247c6a

Please sign in to comment.