Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e0a0b91d1 | |||
| f8fb1c3f4b | |||
| b108f6fe1c | |||
| 61299a33c4 |
@@ -17,9 +17,10 @@ REDIS_PASSWORD=dev_redis_pass
|
|||||||
ADMIN_USERNAME=admin
|
ADMIN_USERNAME=admin
|
||||||
ADMIN_EMAIL=admin@localhost
|
ADMIN_EMAIL=admin@localhost
|
||||||
|
|
||||||
# Email Configuration (Mailhog for development)
|
# Email Configuration (Disabled for development)
|
||||||
SMTP_HOST=mailhog
|
# To enable email, configure a real SMTP server
|
||||||
SMTP_PORT=1025
|
SMTP_HOST=
|
||||||
|
SMTP_PORT=
|
||||||
SMTP_SECURE=false
|
SMTP_SECURE=false
|
||||||
SMTP_USER=
|
SMTP_USER=
|
||||||
SMTP_PASS=
|
SMTP_PASS=
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "picpeak-backend",
|
"name": "picpeak-backend",
|
||||||
"version": "1.0.95",
|
"version": "1.0.97",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "picpeak-backend",
|
"name": "picpeak-backend",
|
||||||
"version": "1.0.95",
|
"version": "1.0.97",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.850.0",
|
"@aws-sdk/client-s3": "^3.850.0",
|
||||||
"@aws-sdk/lib-storage": "^3.850.0",
|
"@aws-sdk/lib-storage": "^3.850.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "picpeak-backend",
|
"name": "picpeak-backend",
|
||||||
"version": "1.0.95",
|
"version": "1.0.97",
|
||||||
"description": "Backend for PicPeak event photo sharing platform",
|
"description": "Backend for PicPeak event photo sharing platform",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show or reset admin credentials
|
||||||
|
*/
|
||||||
|
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const { db } = require('../src/database/db');
|
||||||
|
const { generateReadablePassword } = require('../src/utils/passwordGenerator');
|
||||||
|
|
||||||
|
async function showAdminCredentials(resetPassword = false) {
|
||||||
|
try {
|
||||||
|
// Get admin user
|
||||||
|
const admin = await db('admin_users')
|
||||||
|
.where('username', 'admin')
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (!admin) {
|
||||||
|
console.error('❌ No admin user found in database');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n========================================');
|
||||||
|
console.log('PicPeak Admin Credentials');
|
||||||
|
console.log('========================================');
|
||||||
|
console.log(`Username: ${admin.username}`);
|
||||||
|
console.log(`Email: ${admin.email}`);
|
||||||
|
|
||||||
|
if (resetPassword) {
|
||||||
|
// Generate new password
|
||||||
|
const newPassword = generateReadablePassword();
|
||||||
|
const passwordHash = await bcrypt.hash(newPassword, 12);
|
||||||
|
|
||||||
|
// Update password
|
||||||
|
await db('admin_users')
|
||||||
|
.where('id', admin.id)
|
||||||
|
.update({
|
||||||
|
password_hash: passwordHash,
|
||||||
|
updated_at: new Date()
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Password: ${newPassword} (NEWLY RESET)`);
|
||||||
|
console.log('\n⚠️ IMPORTANT: Please save this password securely!');
|
||||||
|
} else {
|
||||||
|
console.log('Password: [hidden - use --reset flag to generate new password]');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\nLogin URL: http://localhost:3001/admin');
|
||||||
|
console.log('========================================\n');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
} finally {
|
||||||
|
await db.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for reset flag
|
||||||
|
const resetPassword = process.argv.includes('--reset');
|
||||||
|
|
||||||
|
if (resetPassword) {
|
||||||
|
console.log('🔄 Resetting admin password...');
|
||||||
|
}
|
||||||
|
|
||||||
|
showAdminCredentials(resetPassword);
|
||||||
@@ -20,6 +20,12 @@ const ATTEMPT_WINDOW = 15 * 60 * 1000; // 15 minutes window for counting attempt
|
|||||||
*/
|
*/
|
||||||
async function trackFailedAttempt(identifier, ipAddress, userAgent) {
|
async function trackFailedAttempt(identifier, ipAddress, userAgent) {
|
||||||
try {
|
try {
|
||||||
|
// Check if table exists first
|
||||||
|
const tableExists = await db.schema.hasTable('login_attempts');
|
||||||
|
if (!tableExists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await db('login_attempts').insert({
|
await db('login_attempts').insert({
|
||||||
identifier,
|
identifier,
|
||||||
ip_address: ipAddress,
|
ip_address: ipAddress,
|
||||||
@@ -48,6 +54,12 @@ async function trackFailedAttempt(identifier, ipAddress, userAgent) {
|
|||||||
*/
|
*/
|
||||||
async function trackSuccessfulLogin(identifier, ipAddress, userAgent) {
|
async function trackSuccessfulLogin(identifier, ipAddress, userAgent) {
|
||||||
try {
|
try {
|
||||||
|
// Check if table exists first
|
||||||
|
const tableExists = await db.schema.hasTable('login_attempts');
|
||||||
|
if (!tableExists) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await db('login_attempts').insert({
|
await db('login_attempts').insert({
|
||||||
identifier,
|
identifier,
|
||||||
ip_address: ipAddress,
|
ip_address: ipAddress,
|
||||||
@@ -75,6 +87,12 @@ async function trackSuccessfulLogin(identifier, ipAddress, userAgent) {
|
|||||||
*/
|
*/
|
||||||
async function checkAccountLockout(identifier) {
|
async function checkAccountLockout(identifier) {
|
||||||
try {
|
try {
|
||||||
|
// Check if table exists first
|
||||||
|
const tableExists = await db.schema.hasTable('login_attempts');
|
||||||
|
if (!tableExists) {
|
||||||
|
return { isLocked: false };
|
||||||
|
}
|
||||||
|
|
||||||
const recentWindow = new Date(Date.now() - ATTEMPT_WINDOW);
|
const recentWindow = new Date(Date.now() - ATTEMPT_WINDOW);
|
||||||
|
|
||||||
// Get recent failed attempts
|
// Get recent failed attempts
|
||||||
@@ -114,6 +132,12 @@ async function checkAccountLockout(identifier) {
|
|||||||
*/
|
*/
|
||||||
async function checkSuspiciousActivity(identifier, ipAddress) {
|
async function checkSuspiciousActivity(identifier, ipAddress) {
|
||||||
try {
|
try {
|
||||||
|
// Check if table exists first
|
||||||
|
const tableExists = await db.schema.hasTable('login_attempts');
|
||||||
|
if (!tableExists) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for rapid attempts from different IPs
|
// Check for rapid attempts from different IPs
|
||||||
const recentWindow = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes
|
const recentWindow = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes
|
||||||
|
|
||||||
@@ -153,6 +177,13 @@ function getGenericAuthError() {
|
|||||||
*/
|
*/
|
||||||
async function cleanupOldAttempts() {
|
async function cleanupOldAttempts() {
|
||||||
try {
|
try {
|
||||||
|
// Check if table exists first
|
||||||
|
const tableExists = await db.schema.hasTable('login_attempts');
|
||||||
|
if (!tableExists) {
|
||||||
|
// Table doesn't exist, skip cleanup
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const cutoffDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); // 7 days
|
const cutoffDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); // 7 days
|
||||||
|
|
||||||
const deleted = await db('login_attempts')
|
const deleted = await db('login_attempts')
|
||||||
|
|||||||
@@ -30,11 +30,13 @@ services:
|
|||||||
- FRONTEND_URL=${FRONTEND_URL:-http://localhost:3000}
|
- FRONTEND_URL=${FRONTEND_URL:-http://localhost:3000}
|
||||||
- ADMIN_URL=${ADMIN_URL:-http://localhost:3001}
|
- ADMIN_URL=${ADMIN_URL:-http://localhost:3001}
|
||||||
- TZ=${TZ:-UTC}
|
- TZ=${TZ:-UTC}
|
||||||
|
- STORAGE_PATH=/app/storage
|
||||||
volumes:
|
volumes:
|
||||||
- ./events:/app/events
|
- ./events:/app/events
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
- ./logs:/app/logs
|
- ./logs:/app/logs
|
||||||
- ./backup:/backup
|
- ./backup:/backup
|
||||||
|
- ./storage:/app/storage
|
||||||
ports:
|
ports:
|
||||||
- "3001:3001"
|
- "3001:3001"
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -106,12 +108,11 @@ services:
|
|||||||
- ./frontend:/app
|
- ./frontend:/app
|
||||||
- /app/node_modules
|
- /app/node_modules
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3005"
|
||||||
command: npm run dev
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80"]
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3005"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Dockerfile.dev - Development configuration for frontend
|
# Dockerfile.dev - Development configuration for frontend
|
||||||
FROM node:18-alpine
|
FROM node:20-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "picpeak-frontend",
|
"name": "picpeak-frontend",
|
||||||
"version": "1.0.95",
|
"version": "1.0.97",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "picpeak-frontend",
|
"name": "picpeak-frontend",
|
||||||
"version": "1.0.95",
|
"version": "1.0.97",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/react-query": "^5.0.0",
|
"@tanstack/react-query": "^5.0.0",
|
||||||
"@tiptap/extension-character-count": "^2.26.1",
|
"@tiptap/extension-character-count": "^2.26.1",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "picpeak-frontend",
|
"name": "picpeak-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.95",
|
"version": "1.0.97",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
Reference in New Issue
Block a user