Move from instagram to facebook oauth
This commit is contained in:
parent
08cda89609
commit
e9860202a8
6
env.dist
6
env.dist
@ -5,9 +5,9 @@ SESSION_SECRET=your-super-secret-session-key-change-this-in-production
|
||||
GOOGLE_CLIENT_ID=your-google-client-id
|
||||
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||
|
||||
# Instagram OAuth credentials
|
||||
INSTAGRAM_CLIENT_ID=your-instagram-client-id
|
||||
INSTAGRAM_CLIENT_SECRET=your-instagram-client-secret
|
||||
# Facebook OAuth credentials
|
||||
FACEBOOK_CLIENT_ID=your-facebook-app-id
|
||||
FACEBOOK_CLIENT_SECRET=your-facebook-app-secret
|
||||
|
||||
# Database configuration
|
||||
DATABASE_URL=./water_stations.db
|
||||
|
174
migrate-instagram-to-facebook.js
Normal file
174
migrate-instagram-to-facebook.js
Normal file
@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
const path = require('path');
|
||||
|
||||
console.log('🔄 Starting Instagram to Facebook schema migration...');
|
||||
|
||||
// Open database
|
||||
const dbPath = path.join(__dirname, 'water_stations.db');
|
||||
const db = new sqlite3.Database(dbPath);
|
||||
|
||||
db.serialize(() => {
|
||||
console.log('📋 Checking current database schema...');
|
||||
|
||||
// Check if instagram_id column exists
|
||||
db.all("PRAGMA table_info(users)", (err, columns) => {
|
||||
if (err) {
|
||||
console.error('❌ Error checking table schema:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const hasInstagramId = columns.some(col => col.name === 'instagram_id');
|
||||
const hasFacebookId = columns.some(col => col.name === 'facebook_id');
|
||||
|
||||
console.log(`📊 Current schema status:`);
|
||||
console.log(` - instagram_id column exists: ${hasInstagramId}`);
|
||||
console.log(` - facebook_id column exists: ${hasFacebookId}`);
|
||||
|
||||
if (!hasInstagramId && hasFacebookId) {
|
||||
console.log('✅ Migration already completed! Database is up to date.');
|
||||
db.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasInstagramId) {
|
||||
// Count Instagram users before migration
|
||||
db.get('SELECT COUNT(*) as count FROM users WHERE instagram_id IS NOT NULL', (err, row) => {
|
||||
if (err) {
|
||||
console.error('❌ Error counting Instagram users:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const instagramUserCount = row.count;
|
||||
console.log(`📊 Found ${instagramUserCount} Instagram users in database`);
|
||||
|
||||
if (instagramUserCount > 0) {
|
||||
console.log('⚠️ WARNING: Instagram OAuth is no longer supported.');
|
||||
console.log(' These users will need to register again using Facebook or Google OAuth,');
|
||||
console.log(' or create a username/password account.');
|
||||
}
|
||||
|
||||
performMigration(hasFacebookId, instagramUserCount);
|
||||
});
|
||||
} else {
|
||||
console.log('📄 No instagram_id column found, performing clean schema update...');
|
||||
performMigration(hasFacebookId, 0);
|
||||
}
|
||||
});
|
||||
|
||||
function performMigration(hasFacebookId, instagramUserCount) {
|
||||
console.log('\n🔧 Performing database migration...');
|
||||
|
||||
// Add facebook_id column if it doesn't exist
|
||||
if (!hasFacebookId) {
|
||||
console.log('➕ Adding facebook_id column...');
|
||||
db.run('ALTER TABLE users ADD COLUMN facebook_id TEXT', (err) => {
|
||||
if (err) {
|
||||
console.error('❌ Error adding facebook_id column:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('✅ facebook_id column added successfully');
|
||||
dropInstagramColumn(instagramUserCount);
|
||||
});
|
||||
} else {
|
||||
dropInstagramColumn(instagramUserCount);
|
||||
}
|
||||
}
|
||||
|
||||
function dropInstagramColumn(instagramUserCount) {
|
||||
// Check if instagram_id column exists before trying to drop it
|
||||
db.all("PRAGMA table_info(users)", (err, columns) => {
|
||||
if (err) {
|
||||
console.error('❌ Error checking table schema:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const hasInstagramId = columns.some(col => col.name === 'instagram_id');
|
||||
|
||||
if (hasInstagramId) {
|
||||
console.log('🗑️ Removing deprecated instagram_id column...');
|
||||
|
||||
// SQLite doesn't support DROP COLUMN directly, so we need to recreate the table
|
||||
const createNewTableSQL = `
|
||||
CREATE TABLE users_new (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT UNIQUE,
|
||||
email TEXT UNIQUE,
|
||||
password_hash TEXT,
|
||||
google_id TEXT,
|
||||
facebook_id TEXT,
|
||||
display_name TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`;
|
||||
|
||||
db.run(createNewTableSQL, (err) => {
|
||||
if (err) {
|
||||
console.error('❌ Error creating new users table:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Copy data from old table to new table (excluding instagram_id)
|
||||
const copyDataSQL = `
|
||||
INSERT INTO users_new (id, username, email, password_hash, google_id, facebook_id, display_name, created_at)
|
||||
SELECT id, username, email, password_hash, google_id, NULL, display_name, created_at
|
||||
FROM users
|
||||
`;
|
||||
|
||||
db.run(copyDataSQL, (err) => {
|
||||
if (err) {
|
||||
console.error('❌ Error copying data to new table:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Drop old table and rename new table
|
||||
db.run('DROP TABLE users', (err) => {
|
||||
if (err) {
|
||||
console.error('❌ Error dropping old users table:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
db.run('ALTER TABLE users_new RENAME TO users', (err) => {
|
||||
if (err) {
|
||||
console.error('❌ Error renaming new users table:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
completeMigration(instagramUserCount);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
completeMigration(instagramUserCount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function completeMigration(instagramUserCount) {
|
||||
console.log('\n✅ Database migration completed successfully!');
|
||||
console.log('\n📊 Migration Summary:');
|
||||
console.log(' ✅ facebook_id column added');
|
||||
console.log(' ✅ instagram_id column removed (deprecated)');
|
||||
|
||||
if (instagramUserCount > 0) {
|
||||
console.log(` ⚠️ ${instagramUserCount} Instagram users will need to re-register`);
|
||||
console.log('\n📝 Next Steps:');
|
||||
console.log(' 1. Set up Facebook OAuth credentials in your .env file');
|
||||
console.log(' 2. Notify existing Instagram users to register with Facebook/Google OAuth');
|
||||
console.log(' 3. Consider adding a migration notice in your app UI');
|
||||
}
|
||||
|
||||
console.log('\n🎉 Your database is now ready for Facebook OAuth!');
|
||||
|
||||
db.close((err) => {
|
||||
if (err) {
|
||||
console.error('❌ Error closing database:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
});
|
19
package-lock.json
generated
19
package-lock.json
generated
@ -16,8 +16,8 @@
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"passport": "^0.6.0",
|
||||
"passport-facebook": "^3.0.0",
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-instagram": "^1.0.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"sqlite3": "^5.1.6"
|
||||
},
|
||||
@ -1769,10 +1769,11 @@
|
||||
"url": "https://github.com/sponsors/jaredhanson"
|
||||
}
|
||||
},
|
||||
"node_modules/passport-google-oauth20": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz",
|
||||
"integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==",
|
||||
"node_modules/passport-facebook": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz",
|
||||
"integrity": "sha512-K/qNzuFsFISYAyC1Nma4qgY/12V3RSLFdFVsPKXiKZt434wOvthFW1p7zKa1iQihQMRhaWorVE1o3Vi1o+ZgeQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"passport-oauth2": "1.x.x"
|
||||
},
|
||||
@ -1780,10 +1781,10 @@
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/passport-instagram": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-instagram/-/passport-instagram-1.0.0.tgz",
|
||||
"integrity": "sha512-irnGcLgCa+vYF5k/7+gU/uiLfzs6VJds8cMOFiuwq2mRAiRrEPyM5rIzXurDGCQl7s5uhEcolpBOGqChUGPtAg==",
|
||||
"node_modules/passport-google-oauth20": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz",
|
||||
"integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==",
|
||||
"dependencies": {
|
||||
"passport-oauth2": "1.x.x"
|
||||
},
|
||||
|
@ -5,7 +5,8 @@
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"dev": "nodemon server.js"
|
||||
"dev": "nodemon server.js",
|
||||
"migrate": "node migrate-instagram-to-facebook.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"bcryptjs": "^2.4.3",
|
||||
@ -16,8 +17,8 @@
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"passport": "^0.6.0",
|
||||
"passport-facebook": "^3.0.0",
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-instagram": "^1.0.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"sqlite3": "^5.1.6"
|
||||
},
|
||||
|
@ -107,14 +107,14 @@
|
||||
background: #c23321;
|
||||
}
|
||||
|
||||
.btn-instagram {
|
||||
background: #e4405f;
|
||||
.btn-facebook {
|
||||
background: #1877f2;
|
||||
color: white;
|
||||
width: 49%;
|
||||
}
|
||||
|
||||
.btn-instagram:hover {
|
||||
background: #d62d46;
|
||||
.btn-facebook:hover {
|
||||
background: #166fe5;
|
||||
}
|
||||
|
||||
.divider {
|
||||
@ -212,7 +212,7 @@
|
||||
</div>
|
||||
|
||||
<a href="/auth/google" class="btn btn-google" id="googleBtn">Google</a>
|
||||
<a href="/auth/instagram" class="btn btn-instagram" id="instagramBtn">Instagram</a>
|
||||
<a href="/auth/facebook" class="btn btn-facebook" id="facebookBtn">Facebook</a>
|
||||
|
||||
<div class="toggle-form">
|
||||
<a href="#" onclick="toggleForm()">Don't have an account? Register</a>
|
||||
@ -241,7 +241,7 @@
|
||||
</div>
|
||||
|
||||
<a href="/auth/google" class="btn btn-google" id="googleRegBtn">Sign up with Google</a>
|
||||
<a href="/auth/instagram" class="btn btn-instagram" id="instagramRegBtn">Sign up with Instagram</a>
|
||||
<a href="/auth/facebook" class="btn btn-facebook" id="facebookRegBtn">Sign up with Facebook</a>
|
||||
|
||||
<div class="toggle-form">
|
||||
<a href="#" onclick="toggleForm()">Already have an account? Login</a>
|
||||
@ -361,9 +361,9 @@
|
||||
if (redirectUrl) {
|
||||
const encodedRedirect = encodeURIComponent(redirectUrl);
|
||||
document.getElementById('googleBtn').href = `/auth/google?redirect=${encodedRedirect}`;
|
||||
document.getElementById('instagramBtn').href = `/auth/instagram?redirect=${encodedRedirect}`;
|
||||
document.getElementById('facebookBtn').href = `/auth/facebook?redirect=${encodedRedirect}`;
|
||||
document.getElementById('googleRegBtn').href = `/auth/google?redirect=${encodedRedirect}`;
|
||||
document.getElementById('instagramRegBtn').href = `/auth/instagram?redirect=${encodedRedirect}`;
|
||||
document.getElementById('facebookRegBtn').href = `/auth/facebook?redirect=${encodedRedirect}`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
32
server.js
32
server.js
@ -4,7 +4,7 @@ const session = require('express-session');
|
||||
const SQLiteStore = require('connect-sqlite3')(session);
|
||||
const passport = require('passport');
|
||||
const GoogleStrategy = require('passport-google-oauth20').Strategy;
|
||||
const InstagramStrategy = require('passport-instagram').Strategy;
|
||||
const FacebookStrategy = require('passport-facebook').Strategy;
|
||||
const LocalStrategy = require('passport-local').Strategy;
|
||||
const bcrypt = require('bcryptjs');
|
||||
const bodyParser = require('body-parser');
|
||||
@ -28,7 +28,7 @@ db.serialize(() => {
|
||||
email TEXT UNIQUE,
|
||||
password_hash TEXT,
|
||||
google_id TEXT,
|
||||
instagram_id TEXT,
|
||||
facebook_id TEXT,
|
||||
display_name TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)`);
|
||||
@ -162,7 +162,7 @@ passport.use(new LocalStrategy(
|
||||
function initializeOAuthStrategies(baseUrl = '') {
|
||||
// Clear existing strategies
|
||||
passport.unuse('google');
|
||||
passport.unuse('instagram');
|
||||
passport.unuse('facebook');
|
||||
|
||||
// Google OAuth Strategy
|
||||
passport.use(new GoogleStrategy({
|
||||
@ -190,20 +190,22 @@ function initializeOAuthStrategies(baseUrl = '') {
|
||||
});
|
||||
}));
|
||||
|
||||
// Instagram OAuth Strategy
|
||||
passport.use(new InstagramStrategy({
|
||||
clientID: process.env.INSTAGRAM_CLIENT_ID,
|
||||
clientSecret: process.env.INSTAGRAM_CLIENT_SECRET,
|
||||
callbackURL: `${baseUrl}/auth/instagram/callback`
|
||||
// Facebook OAuth Strategy
|
||||
passport.use(new FacebookStrategy({
|
||||
clientID: process.env.FACEBOOK_CLIENT_ID,
|
||||
clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
|
||||
callbackURL: `${baseUrl}/auth/facebook/callback`,
|
||||
profileFields: ['id', 'displayName', 'emails']
|
||||
}, (accessToken, refreshToken, profile, done) => {
|
||||
db.get('SELECT * FROM users WHERE instagram_id = ?', [profile.id], (err, user) => {
|
||||
db.get('SELECT * FROM users WHERE facebook_id = ?', [profile.id], (err, user) => {
|
||||
if (err) return done(err);
|
||||
|
||||
if (user) {
|
||||
return done(null, user);
|
||||
} else {
|
||||
db.run('INSERT INTO users (instagram_id, display_name) VALUES (?, ?)',
|
||||
[profile.id, profile.displayName],
|
||||
const email = profile.emails && profile.emails[0] ? profile.emails[0].value : null;
|
||||
db.run('INSERT INTO users (facebook_id, display_name, email) VALUES (?, ?, ?)',
|
||||
[profile.id, profile.displayName, email],
|
||||
function(err) {
|
||||
if (err) return done(err);
|
||||
|
||||
@ -261,7 +263,7 @@ app.get('/auth/google/callback',
|
||||
}
|
||||
);
|
||||
|
||||
app.get('/auth/instagram', (req, res, next) => {
|
||||
app.get('/auth/facebook', (req, res, next) => {
|
||||
if (req.query.redirect) {
|
||||
req.session.redirectUrl = req.query.redirect;
|
||||
}
|
||||
@ -270,11 +272,11 @@ app.get('/auth/instagram', (req, res, next) => {
|
||||
const baseUrl = getBaseUrl(req);
|
||||
initializeOAuthStrategies(baseUrl);
|
||||
|
||||
passport.authenticate('instagram')(req, res, next);
|
||||
passport.authenticate('facebook', { scope: ['email'] })(req, res, next);
|
||||
});
|
||||
|
||||
app.get('/auth/instagram/callback',
|
||||
passport.authenticate('instagram', { failureRedirect: '/login' }),
|
||||
app.get('/auth/facebook/callback',
|
||||
passport.authenticate('facebook', { failureRedirect: '/login' }),
|
||||
(req, res) => {
|
||||
const redirectUrl = req.session.redirectUrl || '/city/salem/dashboard';
|
||||
delete req.session.redirectUrl;
|
||||
|
Loading…
x
Reference in New Issue
Block a user