full
This commit is contained in:
57
scripts/e2eeVerifyCheck.js
Normal file
57
scripts/e2eeVerifyCheck.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const root = path.join(__dirname, '..')
|
||||
const { isE2eeEnvelope, opaquePreview } = require('../utils/e2ee')
|
||||
|
||||
const checks = []
|
||||
const env = JSON.stringify({ v: 1, e2ee: true, iv: 'x', ciphertext: 'y' })
|
||||
checks.push(['envelope detect', isE2eeEnvelope(env) === true])
|
||||
checks.push(['opaque', opaquePreview(env).includes('رمزنگاری')])
|
||||
checks.push(['plain', opaquePreview('سلام دنیا').includes('سلام')])
|
||||
|
||||
const idx = fs.readFileSync(path.join(root, 'index.js'), 'utf8')
|
||||
checks.push(['socket jwt binding', idx.includes('socket.data.userId') && idx.includes('jwt.verify')])
|
||||
checks.push(['sms disabled', idx.includes('status(410)')])
|
||||
|
||||
const routes = fs.readFileSync(path.join(root, 'routes/index.js'), 'utf8')
|
||||
checks.push(['panel adminAuth', routes.includes("panel/users', [adminAuth]")])
|
||||
|
||||
const profile = fs.readFileSync(
|
||||
path.join(root, 'controllers/application/profile/profileController.js'),
|
||||
'utf8'
|
||||
)
|
||||
checks.push([
|
||||
'profile strips secrets',
|
||||
!profile.includes('password: user.password') && profile.includes('e2ee_public_key')
|
||||
])
|
||||
|
||||
const userModel = fs.readFileSync(path.join(root, 'models/UserModel.js'), 'utf8')
|
||||
checks.push(['user e2ee field', userModel.includes('e2ee_public_key')])
|
||||
|
||||
const roomModel = fs.readFileSync(path.join(root, 'models/ChatRoomModel.js'), 'utf8')
|
||||
checks.push([
|
||||
'room e2ee fields',
|
||||
roomModel.includes('e2ee_wrapped_keys') && roomModel.includes('e2ee_enabled')
|
||||
])
|
||||
|
||||
const frontRoot = path.join(root, '../modstagram-next/src/lib/e2ee')
|
||||
const frontOk = ['dm.ts', 'room.ts', 'keys.ts', 'crypto.ts', 'envelope.ts'].every((f) =>
|
||||
fs.existsSync(path.join(frontRoot, f))
|
||||
)
|
||||
checks.push(['front e2ee lib', frontOk])
|
||||
|
||||
const roomCtrl = fs.readFileSync(
|
||||
path.join(root, 'controllers/application/chatRooms/chatRoomController.js'),
|
||||
'utf8'
|
||||
)
|
||||
checks.push(['room membership gate', roomCtrl.includes('NOT_A_MEMBER')])
|
||||
checks.push([
|
||||
'room e2ee APIs',
|
||||
roomCtrl.includes('getRoomE2eeKeys') && roomCtrl.includes('putRoomE2eeKeys')
|
||||
])
|
||||
|
||||
for (const [name, ok] of checks) {
|
||||
console.log(`${ok ? 'OK' : 'FAIL'} ${name}`)
|
||||
}
|
||||
if (checks.some(([, ok]) => !ok)) process.exit(1)
|
||||
console.log('ALL CHECKS PASSED')
|
||||
@@ -1,4 +1,4 @@
|
||||
# فرانت — modstagram.com → Next.js port 3001
|
||||
# فرانت — modstagram.com → Next.js (PM2 / npm start روی پورت 3004)
|
||||
# مسیر: /etc/nginx/sites-available/modstagram.com
|
||||
|
||||
server {
|
||||
@@ -10,7 +10,7 @@ server {
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3001;
|
||||
proxy_pass http://127.0.0.1:3004;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
33
scripts/recalculateAllUserRatings.js
Normal file
33
scripts/recalculateAllUserRatings.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* One-time migration: recalculate rate (total stars) and user_score (average)
|
||||
* for all users. Run from modstagram-back:
|
||||
* node scripts/recalculateAllUserRatings.js
|
||||
*/
|
||||
require('dotenv').config()
|
||||
const mongoose = require('mongoose')
|
||||
const UserModel = require('../models/UserModel')
|
||||
const { recalculateUserRating } = require('../utils/commentRating')
|
||||
|
||||
async function main() {
|
||||
const uri = process.env.DATABASE_URL || process.env.MONGODB_URI || process.env.DB_URL
|
||||
if (!uri) {
|
||||
console.error('DATABASE_URL (or MONGODB_URI/DB_URL) required')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
await mongoose.connect(uri)
|
||||
const users = await UserModel.find({}, '_id').lean()
|
||||
console.log(`Recalculating ${users.length} users...`)
|
||||
|
||||
for (const user of users) {
|
||||
await recalculateUserRating(user._id)
|
||||
}
|
||||
|
||||
console.log('Done.')
|
||||
await mongoose.disconnect()
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
28
scripts/seedGeoData.js
Normal file
28
scripts/seedGeoData.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Manual/CI trigger for the same geo seed logic that also runs automatically
|
||||
* on every backend boot (utils/ensureGeoData.js, wired in boot/mongo.js) —
|
||||
* kept as a single shared implementation so the two paths never drift.
|
||||
*
|
||||
* Run from modstagram-back:
|
||||
* node scripts/seedGeoData.js
|
||||
*/
|
||||
require('dotenv').config()
|
||||
const mongoose = require('mongoose')
|
||||
const { ensureGeoData } = require('../utils/ensureGeoData')
|
||||
|
||||
async function main() {
|
||||
const uri = process.env.DATABASE_URL
|
||||
if (!uri) {
|
||||
console.error('DATABASE_URL is required (check .env)')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
await mongoose.connect(uri, { authSource: 'admin' })
|
||||
await ensureGeoData(true)
|
||||
await mongoose.disconnect()
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -78,7 +78,7 @@ certbot --nginx --non-interactive --agree-tos --email "$ADMIN_EMAIL" \
|
||||
-d modstagram.com -d www.modstagram.com || echo " WARN: modstagram.com SSL failed"
|
||||
|
||||
certbot --nginx --non-interactive --agree-tos --email "$ADMIN_EMAIL" \
|
||||
-d api.modstagram.com || echo " WARN: api SSL failed"
|
||||
-d api.modstagram.com -d app.modstagram.com || echo " WARN: api SSL failed"
|
||||
|
||||
certbot --nginx --non-interactive --agree-tos --email "$ADMIN_EMAIL" \
|
||||
-d panel.modstagram.com || echo " WARN: panel SSL failed"
|
||||
|
||||
87
scripts/verify-backend.js
Normal file
87
scripts/verify-backend.js
Normal file
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Run from modstagram-back root on the server:
|
||||
* node scripts/verify-backend.js
|
||||
*/
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { execSync } = require('child_process')
|
||||
|
||||
const root = path.join(__dirname, '..')
|
||||
let failed = false
|
||||
|
||||
function fail (message) {
|
||||
console.error('FAIL:', message)
|
||||
failed = true
|
||||
}
|
||||
|
||||
function ok (message) {
|
||||
console.log('OK:', message)
|
||||
}
|
||||
|
||||
function walkJs (dir, out = []) {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
if (entry.name === 'node_modules' || entry.name === 'dist') continue
|
||||
const full = path.join(dir, entry.name)
|
||||
if (entry.isDirectory()) walkJs(full, out)
|
||||
else if (entry.name.endsWith('.js')) out.push(full)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
console.log('Checking merge conflicts...')
|
||||
const conflictPattern = /^<<<<<<<|^=======|^>>>>>>>/
|
||||
for (const file of walkJs(root)) {
|
||||
const firstLines = fs.readFileSync(file, 'utf8').split('\n').slice(0, 3)
|
||||
if (firstLines.some((line) => conflictPattern.test(line.trim()))) {
|
||||
fail(`merge conflict marker in ${path.relative(root, file)}`)
|
||||
}
|
||||
}
|
||||
if (!failed) ok('no merge conflict markers')
|
||||
|
||||
console.log('Syntax check...')
|
||||
const critical = [
|
||||
'index.js',
|
||||
'routes/index.js',
|
||||
'controllers/application/users/getUserController.js',
|
||||
'controllers/application/projects/getProjectController.js',
|
||||
'controllers/application/stories/storyController.js',
|
||||
'controllers/panel/projects/projectController.js'
|
||||
]
|
||||
for (const rel of critical) {
|
||||
try {
|
||||
execSync(`node --check "${path.join(root, rel)}"`, { stdio: 'pipe' })
|
||||
ok(rel)
|
||||
} catch {
|
||||
fail(`syntax error in ${rel}`)
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Loading routes...')
|
||||
try {
|
||||
process.chdir(root)
|
||||
require('../routes/index.js')
|
||||
ok('routes/index.js loaded')
|
||||
} catch (error) {
|
||||
fail(`routes load: ${error.message}`)
|
||||
}
|
||||
|
||||
console.log('Loading getUserController...')
|
||||
try {
|
||||
const mod = require('../controllers/application/users/getUserController.js')
|
||||
if (typeof mod.getPostsWeb !== 'function') {
|
||||
fail('getPostsWeb export missing')
|
||||
} else {
|
||||
ok('getPostsWeb export')
|
||||
}
|
||||
} catch (error) {
|
||||
fail(`getUserController: ${error.message}`)
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
console.error('\nBackend verification FAILED')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('\nBackend verification PASSED')
|
||||
process.exit(0)
|
||||
Reference in New Issue
Block a user