Skip to content

Commit 6e656d4

Browse files
committed
feat!: remove Pinterest OAuth and API integration
Pinterest's API v5 has significantly reduced functionality, only allowing users to manage their own content without access to public data. This makes it not good candidate for the intent of hackathon-starter. Changes: - Remove Pinterest OAuth2 authentication - Remove Pinterest API example endpoints and views - Remove related configuration and documentation
1 parent a0274af commit 6e656d4

File tree

11 files changed

+13
-213
lines changed

11 files changed

+13
-213
lines changed

.env.example

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ NYT_KEY=9548be6f3a64163d23e1539f067fcabd:5:68537648
6161
PAYPAL_ID=AdGE8hDyixVoHmbhASqAThfbBcrbcgiJPBwlAM7u7Kfq3YU-iPGc6BXaTppt
6262
PAYPAL_SECRET=EPN0WxB5PaRaumTB1ZpCuuTqLqIlF6_EWUcAbZV99Eu86YeNBVm9KVsw_Ez5
6363

64-
PINTEREST_ID=4819282851912494691
65-
PINTEREST_SECRET=b32f578ad83d94c058c6682329220feda7e5817e043a1cc4a5a1e28f51c70301
66-
6764
QUICKBOOKS_CLIENT_ID=ABQSXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxnIxiz
6865
QUICKBOOKS_CLIENT_SECRET=Kux3xxxxxxxxxxxxxxxxxxxxxxxxxxxxj58mqYCD
6966

README.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ I also tried to make it as **generic** and **reusable** as possible to cover mos
8585
- Contact Form (powered by SMTP via Sendgrid, Mailgun, AWS SES, etc.)
8686
- File upload
8787
- **API Examples**
88-
- Facebook, Foursquare, Tumblr (OAuth 1.0a example), Pinterest, Github, Steam, Quickbooks, Paypal, Stripe, Twilio (text messaging), Lob (USPS Mail), HERE Maps, Google Maps, Google Drive, Google Sheets, Alpha Vantage (stocks and finance info) with ChartJS, Last.fm, New York Times, Web Scraping
88+
- Facebook, Foursquare, Tumblr (OAuth 1.0a example), Github, Steam, Quickbooks, Paypal, Stripe, Twilio (text messaging), Lob (USPS Mail), HERE Maps, Google Maps, Google Drive, Google Sheets, Alpha Vantage (stocks and finance info) with ChartJS, Last.fm, New York Times, Web Scraping
8989
- Flash notifications
9090
- reCaPTCHA and rate limit protection
9191
- CSRF protection
@@ -162,7 +162,7 @@ _What to get and configure:_
162162
- Set TRANSACTION_EMAIL as the "From" address for emails sent to users thru the lost password or email verification emails to users. You may set this to the same address as SITE_CONTACT_EMAIL.
163163

164164
- ngrok and HTTPS
165-
If you want to use some API that needs HTTPS to work (for example Pinterest or Facebook),
165+
If you want to use some API that needs HTTPS to work (for example Github or Facebook),
166166
you will need to download [ngrok](https://ngrok.com/). Start ngrok, set your BASE_URL to the forwarding address (i.e `https://3ccb-1234-abcd.ngrok-free.app` ), and use the forwarding address to access your application. If you are using a proxy like ngrok, you may get a CSRF mismatch error if you try to access the app at `http://localhost:8080` instead of the https://...ngrok-free.app address.
167167

168168
After installing or downloading the standalone ngrok client you can start ngrok to intercept the data exchanged on port 8080 with `./ngrok http 8080` in Linux or `ngrok http 8080` in Windows.
@@ -243,11 +243,11 @@ Obtain SMTP credentials from a provider for transactional emails. Set the SMTP_U
243243
- Visit <a href="https://cloud.google.com/console/project" target="_blank">Google Cloud Console</a>
244244
- Click on the **Create Project** button
245245
- Enter _Project Name_, then click on **Create** button
246-
- Then click on _APIs & auth_ in the sidebar and select _API_ tab
247-
- Click on **Google+ API** under _Social APIs_, then click **Enable API**
248-
- Click on **Google Drive API** under _G Suite_, then click **Enable API**
249-
- Click on **Google Sheets API** under _G Suite_, then click **Enable API**
250-
- Next, under _APIs & auth_ in the sidebar click on _Credentials_ tab
246+
- Then click on _APIs & auth_ in the sidebar and select _API_ tab and based on your usage add:
247+
- Login by Google: Click on **Google+ API** under _Social APIs_, then click **Enable API**
248+
- Google Drive: Click on **Google Drive API** under _G Suite_, then click **Enable API**
249+
- Google Sheets: Click on **Google Sheets API** under _G Suite_, then click **Enable API**
250+
- Next, under _APIs & auth_ in the sidebar click on the _Credentials_ tab
251251
- Click on **Create new Client ID** button
252252
- Select _Web Application_ and click on **Configure Consent Screen**
253253
- Fill out the required fields then click on **Save**
@@ -258,6 +258,10 @@ Obtain SMTP credentials from a provider for transactional emails. Set the SMTP_U
258258
- Click on **Create Client ID** button
259259
- Copy and paste _Client ID_ and _Client secret_ keys into `.env`
260260

261+
**Warning:** Restrict your **Google Maps API key** to the "Maps JavaScript API" and the specific domain name you are using (for example, your ngrok development domain). Avoid using "localhost" or leaving the key unrestricted, because your Maps API key will be publicly exposed through the web application. This exposure could allow unauthorized users to misuse your key, potentially resulting in charges to your GCP account and credit card.
262+
263+
- Google Maps API Key: To use the "Maps JavaScript API," you must activate your Google Cloud Platform account with a valid credit card. If your account hasn't been activated yet, this process will also trigger the countdown for the expiration of your free credits if any. If you'd prefer to avoid this, consider using **HERE Maps** as an alternative. To get a key add the Search for "Maps Platform API Key" in your GCP Console and select the appropriate option. Then get your key and add your domain as the Website restriction for it.
264+
261265
<hr>
262266

263267
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c7/HERE_logo.svg" height="75">

app.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,6 @@ app.get('/api/paypal/cancel', apiController.getPayPalCancel);
200200
app.get('/api/lob', apiController.getLob);
201201
app.get('/api/upload', lusca({ csrf: true }), apiController.getFileUpload);
202202
app.post('/api/upload', apiController.uploadMiddleware, lusca({ csrf: true }), apiController.postFileUpload);
203-
app.get('/api/pinterest', passportConfig.isAuthenticated, passportConfig.isAuthorized, apiController.getPinterest);
204-
app.post('/api/pinterest', passportConfig.isAuthenticated, passportConfig.isAuthorized, apiController.postPinterest);
205203
app.get('/api/here-maps', apiController.getHereMaps);
206204
app.get('/api/google-maps', apiController.getGoogleMaps);
207205
app.get('/api/google/drive', passportConfig.isAuthenticated, passportConfig.isAuthorized, apiController.getGoogleDrive);
@@ -248,10 +246,6 @@ app.get('/auth/steam', passport.authorize('steam-openid'));
248246
app.get('/auth/steam/callback', passport.authorize('steam-openid', { failureRedirect: '/api' }), (req, res) => {
249247
res.redirect(req.session.returnTo);
250248
});
251-
app.get('/auth/pinterest', passport.authorize('pinterest'));
252-
app.get('/auth/pinterest/callback', passport.authorize('pinterest', { failureRedirect: '/login' }), (req, res) => {
253-
res.redirect(req.session.returnTo);
254-
});
255249
app.get('/auth/quickbooks', passport.authorize('quickbooks'));
256250
app.get('/auth/quickbooks/callback', passport.authorize('quickbooks', { failureRedirect: '/login' }), (req, res) => {
257251
res.redirect(req.session.returnTo);

config/passport.js

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -693,60 +693,6 @@ passport.use(
693693
),
694694
);
695695

696-
/**
697-
* Pinterest API OAuth.
698-
*/
699-
const pinterestStrategyConfig = new OAuth2Strategy(
700-
{
701-
authorizationURL: 'https://www.pinterest.com/oauth',
702-
tokenURL: 'https://api.pinterest.com/v5/oauth/token',
703-
clientID: process.env.PINTEREST_ID,
704-
clientSecret: process.env.PINTEREST_SECRET,
705-
callbackURL: `${process.env.BASE_URL}/auth/pinterest/callback`,
706-
passReqToCallback: true,
707-
state: generateState(),
708-
scope: ['user_accounts:read', 'pins:read', 'pins:write', 'boards:read'],
709-
customHeaders: {
710-
Authorization: `Basic ${Buffer.from(`${process.env.PINTEREST_ID}:${process.env.PINTEREST_SECRET}`).toString('base64')}`,
711-
},
712-
},
713-
async (req, accessToken, refreshToken, params, profile, done) => {
714-
try {
715-
const user = await User.findById(req.user._id);
716-
if (!user.pinterest) {
717-
const pinterestUserResponse = await fetch('https://api.pinterest.com/v5/user_account', {
718-
headers: {
719-
Authorization: `Bearer ${accessToken}`,
720-
},
721-
});
722-
if (!pinterestUserResponse.ok) {
723-
throw new Error(`HTTP error! status: ${pinterestUserResponse.status}`);
724-
}
725-
const pinterestUser = await pinterestUserResponse.json();
726-
user.pinterest = pinterestUser.id;
727-
if (pinterestUser.website_url) {
728-
user.profile.website = pinterestUser.website_url;
729-
}
730-
if (
731-
!user.profile.picture &&
732-
// && pinterestUser.account_type === 'PINNER'
733-
pinterestUser.profile_image &&
734-
!pinterestUser.profile_image.includes('default')
735-
) {
736-
user.profile.picture = pinterestUser.profile_image;
737-
}
738-
}
739-
const updatedUser = await saveOAuth2UserTokens(req, accessToken, refreshToken, params.expires_in, params.refresh_token_expires_in, 'pinterest');
740-
await user.save();
741-
return done(null, updatedUser);
742-
} catch (err) {
743-
return done(err);
744-
}
745-
},
746-
);
747-
passport.use('pinterest', pinterestStrategyConfig);
748-
refresh.use('pinterest', pinterestStrategyConfig);
749-
750696
/**
751697
* Intuit/QuickBooks API OAuth.
752698
*/

controllers/api.js

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,87 +1115,6 @@ exports.uploadMiddleware = (req, res, next) => {
11151115
});
11161116
};
11171117

1118-
/**
1119-
* GET /api/pinterest
1120-
* Pinterest API example.
1121-
*/
1122-
exports.getPinterest = (req, res, next) => {
1123-
const token = req.user.tokens.find((token) => token.kind === 'pinterest');
1124-
const headers = { Authorization: `Bearer ${token.accessToken}` };
1125-
1126-
fetch('https://api.pinterest.com/v5/boards', {
1127-
method: 'GET',
1128-
headers,
1129-
})
1130-
.then(async (response) => {
1131-
if (!response.ok) {
1132-
const errorData = await response.json();
1133-
throw new Error(errorData.message || 'An error occurred.');
1134-
}
1135-
return response.json();
1136-
})
1137-
.then((data) => {
1138-
res.render('api/pinterest', {
1139-
title: 'Pinterest API',
1140-
boards: data.items,
1141-
});
1142-
})
1143-
.catch((error) => {
1144-
next(error);
1145-
});
1146-
};
1147-
1148-
/**
1149-
* POST /api/pinterest
1150-
* Create a pin.
1151-
*/
1152-
exports.postPinterest = (req, res, next) => {
1153-
const validationErrors = [];
1154-
if (validator.isEmpty(req.body.board)) validationErrors.push({ msg: 'Board is required.' });
1155-
if (validator.isEmpty(req.body.note)) validationErrors.push({ msg: 'Note cannot be blank.' });
1156-
if (validator.isEmpty(req.body.image_url)) validationErrors.push({ msg: 'Image URL cannot be blank.' });
1157-
1158-
if (validationErrors.length) {
1159-
req.flash('errors', validationErrors);
1160-
return res.redirect('/api/pinterest');
1161-
}
1162-
1163-
const token = req.user.tokens.find((token) => token.kind === 'pinterest');
1164-
const headers = { Authorization: `Bearer ${token.accessToken}`, 'Content-Type': 'application/json' };
1165-
const formData = {
1166-
board_id: req.body.board,
1167-
title: req.body.note,
1168-
media: {
1169-
media_type: 'image',
1170-
url: req.body.image_url,
1171-
},
1172-
link: req.body.link,
1173-
};
1174-
1175-
fetch('https://api.pinterest.com/v5/pins', {
1176-
method: 'POST',
1177-
headers,
1178-
body: JSON.stringify(formData),
1179-
})
1180-
.then(async (response) => {
1181-
if (!response.ok) {
1182-
const errorData = await response.json();
1183-
throw new Error(errorData.message || 'An error occurred.');
1184-
}
1185-
return response.json();
1186-
})
1187-
.then(() => {
1188-
req.flash('success', { msg: 'Pin created' });
1189-
res.redirect('/api/pinterest');
1190-
})
1191-
.catch((error) => {
1192-
req.flash('errors', {
1193-
msg: error.message || 'An error occurred.',
1194-
});
1195-
res.redirect('/api/pinterest');
1196-
});
1197-
};
1198-
11991118
exports.getHereMaps = (req, res) => {
12001119
res.render('api/here-maps', {
12011120
apikey: process.env.HERE_API_KEY,

models/User.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ const userSchema = new mongoose.Schema(
1919
steam: String,
2020
twitch: String,
2121
quickbooks: String,
22-
pinterest: String,
2322
tumblr: String,
2423
tokens: Array,
2524

test/.env.test

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ NYT_KEY=test_nyt_key
4949
PAYPAL_ID=test_paypal_id
5050
PAYPAL_SECRET=test_paypal_secret
5151

52-
PINTEREST_ID=test_pinterest_id
53-
PINTEREST_SECRET=test_pinterest_secret
54-
5552
QUICKBOOKS_CLIENT_ID=test_quickbooks_client_id
5653
QUICKBOOKS_CLIENT_SECRET=test_quickbooks_client_secret
5754

test/passport.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ describe('Passport Config', () => {
254254
const refreshToken = 'refresh-token';
255255
const accessTokenExpiration = 2592000;
256256
const refreshTokenExpiration = 31536000;
257-
const providerName = 'pinterest';
257+
const providerName = 'quickbooks';
258258

259259
_saveOAuth2UserTokens(req, accessToken, refreshToken, accessTokenExpiration, refreshTokenExpiration, providerName)
260260
.then(() => {
@@ -468,7 +468,7 @@ describe('Passport Config', () => {
468468
const refreshToken = 'refresh-token';
469469
const accessTokenExpiration = 2592000;
470470
const refreshTokenExpiration = 31536000;
471-
const providerName = 'pinterest';
471+
const providerName = 'quickbooks';
472472
const tokenConfig = {};
473473

474474
_saveOAuth2UserTokens(req, accessToken, refreshToken, accessTokenExpiration, refreshTokenExpiration, providerName, tokenConfig)

views/account/profile.pug

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,6 @@ block content
141141
p.mb-1: a.text-danger(href='/account/unlink/quickbooks') Unlink your QuickBooks account
142142
else
143143
p.mb-1: a(href='/auth/quickbooks') Link your QuickBooks account
144-
.offset-sm-3.col-md-7.pl-2
145-
if user.pinterest
146-
p.mb-1: a.text-danger(href='/account/unlink/pinterest') Unlink your Pinterest account
147-
else
148-
p.mb-1: a(href='/auth/pinterest') Link your Pinterest account
149144
.offset-sm-3.col-md-7.pl-2
150145
if user.tumblr
151146
p.mb-1: a.text-danger(href='/account/unlink/tumblr') Unlink your Tumblr account

views/api/index.pug

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,6 @@ block content
9595
.card-body
9696
img(src='https://i.imgur.com/UPTzIdC.png', height=40, style='padding: 0px 10px 0px 0px')
9797
| File Upload
98-
.col-md-4
99-
a(href='/api/pinterest', style='color: #fff')
100-
.card.text-white.mb-3(style='background-color: #bd081c')
101-
.card-body
102-
img(src='https://i.imgur.com/JNNRQSm.png', height=40, style='padding: 0px 10px 0px 0px')
103-
| Pinterest
10498
.col-md-4
10599
a(href='/api/google-maps', style='color: #000')
106100
.card.mb-3(style='background-color: #0f9d58')

0 commit comments

Comments
 (0)