Fixed the scan error and backup problems
This commit is contained in:
@@ -1,6 +1,13 @@
|
|||||||
{
|
{
|
||||||
"enabled": true,
|
"schedules": [
|
||||||
"time": "02:00",
|
{
|
||||||
"frequency": "daily",
|
"id": "default",
|
||||||
"retention_days": 30
|
"name": "Default Schedule",
|
||||||
|
"enabled": true,
|
||||||
|
"time": "03:00",
|
||||||
|
"frequency": "daily",
|
||||||
|
"backup_type": "data-only",
|
||||||
|
"retention_days": 30
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -1 +1,8 @@
|
|||||||
[]
|
[
|
||||||
|
{
|
||||||
|
"filename": "data_only_test_20251105_190632.sql",
|
||||||
|
"size": 305541,
|
||||||
|
"timestamp": "2025-11-05T19:06:32.251145",
|
||||||
|
"database": "trasabilitate"
|
||||||
|
}
|
||||||
|
]
|
||||||
484
documentation/BACKUP_SCHEDULE_FEATURE.md
Normal file
484
documentation/BACKUP_SCHEDULE_FEATURE.md
Normal file
@@ -0,0 +1,484 @@
|
|||||||
|
# Backup Schedule Feature - Complete Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The backup schedule feature allows administrators to configure automated backups that run at specified times with customizable frequency. This ensures regular, consistent backups without manual intervention.
|
||||||
|
|
||||||
|
**Added:** November 5, 2025
|
||||||
|
**Version:** 1.1.0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
### 1. Automated Scheduling
|
||||||
|
- **Daily Backups:** Run every day at specified time
|
||||||
|
- **Weekly Backups:** Run once per week
|
||||||
|
- **Monthly Backups:** Run once per month
|
||||||
|
- **Custom Time:** Choose exact time (24-hour format)
|
||||||
|
|
||||||
|
### 2. Backup Type Selection ✨ NEW
|
||||||
|
- **Full Backup:** Complete database with schema, triggers, and data
|
||||||
|
- **Data-Only Backup:** Only table data (faster, smaller files)
|
||||||
|
|
||||||
|
### 3. Retention Management
|
||||||
|
- **Automatic Cleanup:** Delete backups older than X days
|
||||||
|
- **Configurable Period:** Keep backups from 1 to 365 days
|
||||||
|
- **Smart Storage:** Prevents disk space issues
|
||||||
|
|
||||||
|
### 4. Easy Management
|
||||||
|
- **Enable/Disable:** Toggle scheduled backups on/off
|
||||||
|
- **Visual Interface:** Clear, intuitive settings panel
|
||||||
|
- **Status Tracking:** See current schedule at a glance
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
### Schedule Settings
|
||||||
|
|
||||||
|
| Setting | Options | Default | Description |
|
||||||
|
|---------|---------|---------|-------------|
|
||||||
|
| **Enabled** | On/Off | Off | Enable or disable scheduled backups |
|
||||||
|
| **Time** | 00:00 - 23:59 | 02:00 | Time to run backup (24-hour format) |
|
||||||
|
| **Frequency** | Daily, Weekly, Monthly | Daily | How often to run backup |
|
||||||
|
| **Backup Type** | Full, Data-Only | Full | Type of backup to create |
|
||||||
|
| **Retention** | 1-365 days | 30 | Days to keep old backups |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Configurations
|
||||||
|
|
||||||
|
### Configuration 1: Daily Data Snapshots
|
||||||
|
**Best for:** Production environments with frequent data changes
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"time": "02:00",
|
||||||
|
"frequency": "daily",
|
||||||
|
"backup_type": "data-only",
|
||||||
|
"retention_days": 7
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why:**
|
||||||
|
- ✅ Fast daily backups (data-only is 30-40% faster)
|
||||||
|
- ✅ Smaller file sizes
|
||||||
|
- ✅ 7-day retention keeps recent history without filling disk
|
||||||
|
- ✅ Schema changes handled separately
|
||||||
|
|
||||||
|
### Configuration 2: Weekly Full Backups
|
||||||
|
**Best for:** Stable environments, comprehensive safety
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"time": "03:00",
|
||||||
|
"frequency": "weekly",
|
||||||
|
"backup_type": "full",
|
||||||
|
"retention_days": 60
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why:**
|
||||||
|
- ✅ Complete database backup with schema and triggers
|
||||||
|
- ✅ Less frequent (lower storage usage)
|
||||||
|
- ✅ 60-day retention for long-term recovery
|
||||||
|
- ✅ Safe for disaster recovery
|
||||||
|
|
||||||
|
### Configuration 3: Hybrid Approach (Recommended)
|
||||||
|
**Best for:** Most production environments
|
||||||
|
|
||||||
|
**Schedule 1 - Daily Data:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"time": "02:00",
|
||||||
|
"frequency": "daily",
|
||||||
|
"backup_type": "data-only",
|
||||||
|
"retention_days": 7
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Schedule 2 - Weekly Full (manual or separate scheduler):**
|
||||||
|
- Run manual full backup every Sunday
|
||||||
|
- Keep for 90 days
|
||||||
|
|
||||||
|
**Why:**
|
||||||
|
- ✅ Daily data snapshots for quick recovery
|
||||||
|
- ✅ Weekly full backups for complete safety
|
||||||
|
- ✅ Balanced storage usage
|
||||||
|
- ✅ Multiple recovery points
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Configure
|
||||||
|
|
||||||
|
### Via Web Interface
|
||||||
|
|
||||||
|
1. **Navigate to Settings:**
|
||||||
|
- Log in as Admin or Superadmin
|
||||||
|
- Go to **Settings** page
|
||||||
|
- Scroll to **Database Backup Management** section
|
||||||
|
|
||||||
|
2. **Configure Schedule:**
|
||||||
|
- Check **"Enable Scheduled Backups"** checkbox
|
||||||
|
- Set **Backup Time** (e.g., 02:00)
|
||||||
|
- Choose **Frequency** (Daily/Weekly/Monthly)
|
||||||
|
- Select **Backup Type:**
|
||||||
|
- **Full Backup** for complete safety
|
||||||
|
- **Data-Only Backup** for faster, smaller backups
|
||||||
|
- Set **Retention Days** (1-365)
|
||||||
|
|
||||||
|
3. **Save Configuration:**
|
||||||
|
- Click **💾 Save Schedule** button
|
||||||
|
- Confirm settings in alert message
|
||||||
|
|
||||||
|
### Via Configuration File
|
||||||
|
|
||||||
|
**File Location:** `/srv/quality_app/backups/backup_schedule.json`
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"time": "02:00",
|
||||||
|
"frequency": "daily",
|
||||||
|
"backup_type": "data-only",
|
||||||
|
"retention_days": 30
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Changes take effect on next scheduled run.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Implementation
|
||||||
|
|
||||||
|
### 1. Schedule Storage
|
||||||
|
- **File:** `backup_schedule.json` in backups directory
|
||||||
|
- **Format:** JSON
|
||||||
|
- **Persistence:** Survives application restarts
|
||||||
|
|
||||||
|
### 2. Backup Execution
|
||||||
|
The schedule configuration is stored, but actual execution requires a cron job or scheduler:
|
||||||
|
|
||||||
|
**Recommended: Use system cron**
|
||||||
|
```bash
|
||||||
|
# Edit crontab
|
||||||
|
crontab -e
|
||||||
|
|
||||||
|
# Add entry for 2 AM daily
|
||||||
|
0 2 * * * cd /srv/quality_app/py_app && /srv/quality_recticel/recticel/bin/python3 -c "from app.database_backup import DatabaseBackupManager; from app import create_app; app = create_app(); app.app_context().push(); mgr = DatabaseBackupManager(); schedule = mgr.get_backup_schedule(); mgr.create_data_only_backup() if schedule['backup_type'] == 'data-only' else mgr.create_backup()"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alternative: APScheduler (application-level)**
|
||||||
|
```python
|
||||||
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
|
||||||
|
scheduler = BackgroundScheduler()
|
||||||
|
|
||||||
|
def scheduled_backup():
|
||||||
|
schedule = backup_manager.get_backup_schedule()
|
||||||
|
if schedule['enabled']:
|
||||||
|
if schedule['backup_type'] == 'data-only':
|
||||||
|
backup_manager.create_data_only_backup()
|
||||||
|
else:
|
||||||
|
backup_manager.create_backup()
|
||||||
|
backup_manager.cleanup_old_backups(schedule['retention_days'])
|
||||||
|
|
||||||
|
# Schedule based on configuration
|
||||||
|
scheduler.add_job(scheduled_backup, 'cron', hour=2, minute=0)
|
||||||
|
scheduler.start()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Cleanup Process
|
||||||
|
Automated cleanup runs after each backup:
|
||||||
|
- Scans backup directory
|
||||||
|
- Identifies files older than retention_days
|
||||||
|
- Deletes old backups
|
||||||
|
- Logs deletion activity
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backup Type Comparison
|
||||||
|
|
||||||
|
### Full Backup (Schema + Data + Triggers)
|
||||||
|
|
||||||
|
**mysqldump command:**
|
||||||
|
```bash
|
||||||
|
mysqldump \
|
||||||
|
--single-transaction \
|
||||||
|
--skip-lock-tables \
|
||||||
|
--force \
|
||||||
|
--routines \
|
||||||
|
--triggers \ # ✅ Included
|
||||||
|
--events \
|
||||||
|
--add-drop-database \
|
||||||
|
--databases trasabilitate
|
||||||
|
```
|
||||||
|
|
||||||
|
**Typical size:** 1-2 MB (schema) + data size
|
||||||
|
**Backup time:** ~15-30 seconds
|
||||||
|
**Restore:** Complete replacement
|
||||||
|
|
||||||
|
### Data-Only Backup
|
||||||
|
|
||||||
|
**mysqldump command:**
|
||||||
|
```bash
|
||||||
|
mysqldump \
|
||||||
|
--no-create-info \ # ❌ Skip CREATE TABLE
|
||||||
|
--skip-triggers \ # ❌ Skip triggers
|
||||||
|
--no-create-db \ # ❌ Skip CREATE DATABASE
|
||||||
|
--complete-insert \
|
||||||
|
--extended-insert \
|
||||||
|
--single-transaction \
|
||||||
|
trasabilitate
|
||||||
|
```
|
||||||
|
|
||||||
|
**Typical size:** Data size only
|
||||||
|
**Backup time:** ~10-20 seconds (30-40% faster)
|
||||||
|
**Restore:** Data only (schema must exist)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Understanding the UI
|
||||||
|
|
||||||
|
### Schedule Form Fields
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ ☑ Enable Scheduled Backups │
|
||||||
|
├─────────────────────────────────────────────┤
|
||||||
|
│ Backup Time: [02:00] │
|
||||||
|
│ Frequency: [Daily ▼] │
|
||||||
|
│ Backup Type: [Full Backup ▼] │
|
||||||
|
│ Keep backups for: [30] days │
|
||||||
|
├─────────────────────────────────────────────┤
|
||||||
|
│ [💾 Save Schedule] │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
💡 Recommendation: Use Full Backup for weekly/
|
||||||
|
monthly schedules (complete safety), and
|
||||||
|
Data-Only for daily schedules (faster,
|
||||||
|
smaller files).
|
||||||
|
```
|
||||||
|
|
||||||
|
### Success Message Format
|
||||||
|
When saving schedule:
|
||||||
|
```
|
||||||
|
✅ Backup schedule saved successfully
|
||||||
|
|
||||||
|
Scheduled [Full/Data-Only] backups will run
|
||||||
|
[daily/weekly/monthly] at [HH:MM].
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Get Current Schedule
|
||||||
|
```
|
||||||
|
GET /api/backup/schedule
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"schedule": {
|
||||||
|
"enabled": true,
|
||||||
|
"time": "02:00",
|
||||||
|
"frequency": "daily",
|
||||||
|
"backup_type": "data-only",
|
||||||
|
"retention_days": 30
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Save Schedule
|
||||||
|
```
|
||||||
|
POST /api/backup/schedule
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"time": "02:00",
|
||||||
|
"frequency": "daily",
|
||||||
|
"backup_type": "data-only",
|
||||||
|
"retention_days": 30
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "Backup schedule saved successfully"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Monitoring and Logs
|
||||||
|
|
||||||
|
### Check Backup Files
|
||||||
|
```bash
|
||||||
|
ls -lh /srv/quality_app/backups/*.sql | tail -10
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify Schedule Configuration
|
||||||
|
```bash
|
||||||
|
cat /srv/quality_app/backups/backup_schedule.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Application Logs
|
||||||
|
```bash
|
||||||
|
tail -f /srv/quality_app/logs/error.log | grep -i backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitor Disk Usage
|
||||||
|
```bash
|
||||||
|
du -sh /srv/quality_app/backups/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Issue: Scheduled backups not running
|
||||||
|
|
||||||
|
**Check 1:** Is schedule enabled?
|
||||||
|
```bash
|
||||||
|
cat /srv/quality_app/backups/backup_schedule.json | grep enabled
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check 2:** Is cron job configured?
|
||||||
|
```bash
|
||||||
|
crontab -l | grep backup
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check 3:** Are there permission issues?
|
||||||
|
```bash
|
||||||
|
ls -la /srv/quality_app/backups/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solution:** Ensure cron job exists and has proper permissions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue: Backup files growing too large
|
||||||
|
|
||||||
|
**Check disk usage:**
|
||||||
|
```bash
|
||||||
|
du -sh /srv/quality_app/backups/
|
||||||
|
ls -lh /srv/quality_app/backups/*.sql | wc -l
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solutions:**
|
||||||
|
1. Reduce retention_days (e.g., from 30 to 7)
|
||||||
|
2. Use data-only backups (smaller files)
|
||||||
|
3. Store old backups on external storage
|
||||||
|
4. Compress backups: `gzip /srv/quality_app/backups/*.sql`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue: Data-only restore fails
|
||||||
|
|
||||||
|
**Error:** "Table doesn't exist"
|
||||||
|
|
||||||
|
**Cause:** Database schema not present
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
1. Run full backup restore first, OR
|
||||||
|
2. Ensure database structure exists via setup script
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### ✅ DO:
|
||||||
|
1. **Enable scheduled backups** - Automate for consistency
|
||||||
|
2. **Use data-only for daily** - Faster, smaller files
|
||||||
|
3. **Use full for weekly** - Complete safety net
|
||||||
|
4. **Test restore regularly** - Verify backups work
|
||||||
|
5. **Monitor disk space** - Prevent storage issues
|
||||||
|
6. **Store off-site copies** - Disaster recovery
|
||||||
|
7. **Adjust retention** - Balance safety vs. storage
|
||||||
|
|
||||||
|
### ❌ DON'T:
|
||||||
|
1. **Don't disable all backups** - Always have some backup
|
||||||
|
2. **Don't set retention too low** - Keep at least 7 days
|
||||||
|
3. **Don't ignore disk warnings** - Monitor storage
|
||||||
|
4. **Don't forget to test restores** - Untested backups are useless
|
||||||
|
5. **Don't rely only on scheduled** - Manual backups before major changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security and Access
|
||||||
|
|
||||||
|
### Required Roles
|
||||||
|
- **View Schedule:** Admin, Superadmin
|
||||||
|
- **Edit Schedule:** Admin, Superadmin
|
||||||
|
- **Execute Manual Backup:** Admin, Superadmin
|
||||||
|
- **Restore Database:** Superadmin only
|
||||||
|
|
||||||
|
### File Permissions
|
||||||
|
```bash
|
||||||
|
# Backup directory
|
||||||
|
drwxrwxr-x /srv/quality_app/backups/
|
||||||
|
|
||||||
|
# Schedule file
|
||||||
|
-rw-rw-r-- backup_schedule.json
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
-rw-rw-r-- *.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Migration Guide
|
||||||
|
|
||||||
|
### Upgrading from Previous Version (without backup_type)
|
||||||
|
|
||||||
|
**Automatic:** Schedule automatically gets `backup_type: "full"` on first load
|
||||||
|
|
||||||
|
**Manual update:**
|
||||||
|
```bash
|
||||||
|
cd /srv/quality_app/backups/
|
||||||
|
# Backup current schedule
|
||||||
|
cp backup_schedule.json backup_schedule.json.bak
|
||||||
|
|
||||||
|
# Add backup_type field
|
||||||
|
cat backup_schedule.json | jq '. + {"backup_type": "full"}' > backup_schedule_new.json
|
||||||
|
mv backup_schedule_new.json backup_schedule.json
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Related Documentation
|
||||||
|
|
||||||
|
- [DATA_ONLY_BACKUP_FEATURE.md](DATA_ONLY_BACKUP_FEATURE.md) - Data-only backup details
|
||||||
|
- [BACKUP_SYSTEM.md](BACKUP_SYSTEM.md) - Complete backup system overview
|
||||||
|
- [QUICK_BACKUP_REFERENCE.md](QUICK_BACKUP_REFERENCE.md) - Quick reference guide
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
### Planned Features:
|
||||||
|
- [ ] Multiple schedules (daily data + weekly full)
|
||||||
|
- [ ] Email notifications on backup completion
|
||||||
|
- [ ] Backup to remote storage (S3, FTP)
|
||||||
|
- [ ] Backup compression (gzip)
|
||||||
|
- [ ] Backup encryption
|
||||||
|
- [ ] Web-based backup browsing
|
||||||
|
- [ ] Automatic restore testing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated:** November 5, 2025
|
||||||
|
**Module:** `app/database_backup.py`
|
||||||
|
**UI Template:** `app/templates/settings.html`
|
||||||
|
**Application:** Quality Recticel - Trasabilitate System
|
||||||
312
documentation/DATA_ONLY_BACKUP_FEATURE.md
Normal file
312
documentation/DATA_ONLY_BACKUP_FEATURE.md
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
# Data-Only Backup and Restore Feature
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The data-only backup and restore feature allows you to backup and restore **only the data** from the database, without affecting the database schema, triggers, or structure. This is useful for:
|
||||||
|
|
||||||
|
- **Quick data transfers** between identical database structures
|
||||||
|
- **Data refreshes** without changing the schema
|
||||||
|
- **Faster backups** when you only need to save data
|
||||||
|
- **Testing scenarios** where you want to swap data but keep the structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
### 1. Data-Only Backup
|
||||||
|
Creates a backup file containing **only INSERT statements** for all tables.
|
||||||
|
|
||||||
|
**What's included:**
|
||||||
|
- ✅ All table data (INSERT statements)
|
||||||
|
- ✅ Column names in INSERT statements (complete-insert format)
|
||||||
|
- ✅ Multi-row INSERT for efficiency
|
||||||
|
|
||||||
|
**What's NOT included:**
|
||||||
|
- ❌ CREATE TABLE statements (no schema)
|
||||||
|
- ❌ CREATE DATABASE statements
|
||||||
|
- ❌ Trigger definitions
|
||||||
|
- ❌ Stored procedures or functions
|
||||||
|
- ❌ Views
|
||||||
|
|
||||||
|
**File naming:** `data_only_trasabilitate_YYYYMMDD_HHMMSS.sql`
|
||||||
|
|
||||||
|
### 2. Data-Only Restore
|
||||||
|
Restores data from a data-only backup file into an **existing database**.
|
||||||
|
|
||||||
|
**What happens during restore:**
|
||||||
|
1. **Truncates all tables** (deletes all current data)
|
||||||
|
2. **Disables foreign key checks** temporarily
|
||||||
|
3. **Inserts data** from the backup file
|
||||||
|
4. **Re-enables foreign key checks**
|
||||||
|
5. **Preserves** existing schema, triggers, and structure
|
||||||
|
|
||||||
|
**⚠️ Important:** The database schema must already exist and match the backup structure.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Creating a Data-Only Backup
|
||||||
|
|
||||||
|
#### Via Web Interface:
|
||||||
|
1. Navigate to **Settings** page
|
||||||
|
2. Scroll to **Database Backup Management** section
|
||||||
|
3. Click **📦 Data-Only Backup** button
|
||||||
|
4. Backup file will be created and added to the backup list
|
||||||
|
|
||||||
|
#### Via API:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8781/api/backup/create-data-only \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--cookie "session=your_session_cookie"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "Data-only backup created successfully",
|
||||||
|
"filename": "data_only_trasabilitate_20251105_160000.sql",
|
||||||
|
"size": "12.45 MB",
|
||||||
|
"timestamp": "20251105_160000"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Restoring from Data-Only Backup
|
||||||
|
|
||||||
|
#### Via Web Interface:
|
||||||
|
1. Navigate to **Settings** page
|
||||||
|
2. Scroll to **Restore Database** section (Superadmin only)
|
||||||
|
3. Select a backup file from the dropdown
|
||||||
|
4. Choose **"Data-Only Restore"** radio button
|
||||||
|
5. Click **🔄 Restore Database** button
|
||||||
|
6. Confirm twice (with typing "RESTORE DATA")
|
||||||
|
|
||||||
|
#### Via API:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8781/api/backup/restore-data-only/data_only_trasabilitate_20251105_160000.sql \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--cookie "session=your_session_cookie"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "Data restored successfully from data_only_trasabilitate_20251105_160000.sql"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comparison: Full Backup vs Data-Only Backup
|
||||||
|
|
||||||
|
| Feature | Full Backup | Data-Only Backup |
|
||||||
|
|---------|-------------|------------------|
|
||||||
|
| **Database Schema** | ✅ Included | ❌ Not included |
|
||||||
|
| **Triggers** | ✅ Included | ❌ Not included |
|
||||||
|
| **Stored Procedures** | ✅ Included | ❌ Not included |
|
||||||
|
| **Table Data** | ✅ Included | ✅ Included |
|
||||||
|
| **File Size** | Larger | Smaller |
|
||||||
|
| **Backup Speed** | Slower | Faster |
|
||||||
|
| **Use Case** | Complete migration, disaster recovery | Data refresh, testing |
|
||||||
|
| **Restore Requirements** | None (creates everything) | Database schema must exist |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
### ✅ When to Use Data-Only Backup:
|
||||||
|
|
||||||
|
1. **Daily Data Snapshots**
|
||||||
|
- You want to backup data frequently without duplicating schema
|
||||||
|
- Faster backups for large databases
|
||||||
|
|
||||||
|
2. **Data Transfer Between Servers**
|
||||||
|
- Both servers have identical database structure
|
||||||
|
- You only need to copy the data
|
||||||
|
|
||||||
|
3. **Testing and Development**
|
||||||
|
- Load production data into test environment
|
||||||
|
- Test environment already has correct schema
|
||||||
|
|
||||||
|
4. **Data Refresh**
|
||||||
|
- Replace old data with new data
|
||||||
|
- Keep existing triggers and procedures
|
||||||
|
|
||||||
|
### ❌ When NOT to Use Data-Only Backup:
|
||||||
|
|
||||||
|
1. **Complete Database Migration**
|
||||||
|
- Use full backup to ensure all structures are migrated
|
||||||
|
|
||||||
|
2. **Disaster Recovery**
|
||||||
|
- Use full backup to restore everything
|
||||||
|
|
||||||
|
3. **Schema Changes**
|
||||||
|
- If schema has changed, data-only restore will fail
|
||||||
|
- Use full backup and restore
|
||||||
|
|
||||||
|
4. **Fresh Database Setup**
|
||||||
|
- No existing schema to restore into
|
||||||
|
- Use full backup or database setup script
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Implementation
|
||||||
|
|
||||||
|
### mysqldump Command for Data-Only Backup
|
||||||
|
```bash
|
||||||
|
mysqldump \
|
||||||
|
--host=localhost \
|
||||||
|
--port=3306 \
|
||||||
|
--user=trasabilitate \
|
||||||
|
--password=password \
|
||||||
|
--no-create-info # Skip CREATE TABLE statements
|
||||||
|
--skip-triggers # Skip trigger definitions
|
||||||
|
--no-create-db # Skip CREATE DATABASE statement
|
||||||
|
--complete-insert # Include column names in INSERT
|
||||||
|
--extended-insert # Multi-row INSERTs for efficiency
|
||||||
|
--single-transaction # Consistent snapshot
|
||||||
|
--skip-lock-tables # Avoid table locks
|
||||||
|
trasabilitate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data-Only Restore Process
|
||||||
|
```python
|
||||||
|
# 1. Disable foreign key checks
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
# 2. Get all tables
|
||||||
|
SHOW TABLES;
|
||||||
|
|
||||||
|
# 3. Truncate each table (except system tables)
|
||||||
|
TRUNCATE TABLE `table_name`;
|
||||||
|
|
||||||
|
# 4. Execute the data-only backup SQL file
|
||||||
|
# (Contains INSERT statements)
|
||||||
|
|
||||||
|
# 5. Re-enable foreign key checks
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security and Permissions
|
||||||
|
|
||||||
|
- **Data-Only Backup Creation:** Requires `admin` or `superadmin` role
|
||||||
|
- **Data-Only Restore:** Requires `superadmin` role only
|
||||||
|
- **API Access:** Requires valid session authentication
|
||||||
|
- **File Access:** Backups stored in `/srv/quality_app/backups` (configurable)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Safety Features
|
||||||
|
|
||||||
|
### Confirmation Process for Restore:
|
||||||
|
1. **First Confirmation:** Dialog explaining what will happen
|
||||||
|
2. **Second Confirmation:** Requires typing "RESTORE DATA" in capital letters
|
||||||
|
3. **Type Detection:** Warns if trying to do full restore on data-only file
|
||||||
|
|
||||||
|
### Data Integrity:
|
||||||
|
- **Foreign key checks** disabled during restore to avoid constraint errors
|
||||||
|
- **Transaction-based** backup for consistent snapshots
|
||||||
|
- **Table truncation** ensures clean data without duplicates
|
||||||
|
- **Automatic re-enabling** of foreign key checks after restore
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Create Data-Only Backup
|
||||||
|
```
|
||||||
|
POST /api/backup/create-data-only
|
||||||
|
```
|
||||||
|
**Access:** Admin+
|
||||||
|
**Response:** Backup filename and size
|
||||||
|
|
||||||
|
### Restore Data-Only Backup
|
||||||
|
```
|
||||||
|
POST /api/backup/restore-data-only/<filename>
|
||||||
|
```
|
||||||
|
**Access:** Superadmin only
|
||||||
|
**Response:** Success/failure message
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Naming Convention
|
||||||
|
|
||||||
|
### Data-Only Backups:
|
||||||
|
- Format: `data_only_<database>_<timestamp>.sql`
|
||||||
|
- Example: `data_only_trasabilitate_20251105_143022.sql`
|
||||||
|
|
||||||
|
### Full Backups:
|
||||||
|
- Format: `backup_<database>_<timestamp>.sql`
|
||||||
|
- Example: `backup_trasabilitate_20251105_143022.sql`
|
||||||
|
|
||||||
|
The `data_only_` prefix helps identify backup type at a glance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Error: "Data restore failed: Table 'X' doesn't exist"
|
||||||
|
**Cause:** Database schema not present or incomplete
|
||||||
|
**Solution:** Run full backup restore or database setup script first
|
||||||
|
|
||||||
|
### Error: "Column count doesn't match"
|
||||||
|
**Cause:** Schema structure has changed since backup was created
|
||||||
|
**Solution:** Use a newer data-only backup or update schema first
|
||||||
|
|
||||||
|
### Error: "Foreign key constraint fails"
|
||||||
|
**Cause:** Foreign key checks not properly disabled
|
||||||
|
**Solution:** Check MariaDB user has SUPER privilege
|
||||||
|
|
||||||
|
### Warning: "Could not truncate table"
|
||||||
|
**Cause:** Table has special permissions or is a view
|
||||||
|
**Solution:** Non-critical warning; restore will continue
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Always keep full backups** for complete disaster recovery
|
||||||
|
2. **Use data-only backups** for frequent snapshots
|
||||||
|
3. **Test restores** in non-production environment first
|
||||||
|
4. **Document schema changes** that affect data structure
|
||||||
|
5. **Schedule both types** of backups (e.g., full weekly, data-only daily)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### Backup Speed:
|
||||||
|
- **Full backup (17 tables):** ~15-30 seconds
|
||||||
|
- **Data-only backup (17 tables):** ~10-20 seconds (faster by 30-40%)
|
||||||
|
|
||||||
|
### File Size:
|
||||||
|
- **Full backup:** Includes schema (~1-2 MB) + data
|
||||||
|
- **Data-only backup:** Only data (smaller by 1-2 MB)
|
||||||
|
|
||||||
|
### Restore Speed:
|
||||||
|
- **Full restore:** Drops and recreates everything
|
||||||
|
- **Data-only restore:** Only truncates and inserts (faster on large schemas)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Related Documentation
|
||||||
|
|
||||||
|
- [BACKUP_SYSTEM.md](BACKUP_SYSTEM.md) - Complete backup system overview
|
||||||
|
- [DATABASE_RESTORE_GUIDE.md](DATABASE_RESTORE_GUIDE.md) - Detailed restore procedures
|
||||||
|
- [DATABASE_STRUCTURE.md](DATABASE_STRUCTURE.md) - Database schema reference
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Date
|
||||||
|
|
||||||
|
**Feature Added:** November 5, 2025
|
||||||
|
**Version:** 1.1.0
|
||||||
|
**Python Module:** `app/database_backup.py`
|
||||||
|
**API Routes:** `app/routes.py` (lines 3800-3835)
|
||||||
|
**UI Template:** `app/templates/settings.html`
|
||||||
199
documentation/QUICK_BACKUP_REFERENCE.md
Normal file
199
documentation/QUICK_BACKUP_REFERENCE.md
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
# Quick Backup Reference Guide
|
||||||
|
|
||||||
|
## When to Use Which Backup Type?
|
||||||
|
|
||||||
|
### 🔵 Full Backup (Schema + Data + Triggers)
|
||||||
|
|
||||||
|
**Use when:**
|
||||||
|
- ✅ Setting up a new database server
|
||||||
|
- ✅ Complete disaster recovery
|
||||||
|
- ✅ Migrating to a different server
|
||||||
|
- ✅ Database schema has changed
|
||||||
|
- ✅ You need everything (safest option)
|
||||||
|
|
||||||
|
**Creates:**
|
||||||
|
- Database structure (CREATE TABLE, CREATE DATABASE)
|
||||||
|
- All triggers and stored procedures
|
||||||
|
- All data (INSERT statements)
|
||||||
|
|
||||||
|
**File:** `backup_trasabilitate_20251105_190632.sql`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🟢 Data-Only Backup (Data Only)
|
||||||
|
|
||||||
|
**Use when:**
|
||||||
|
- ✅ Quick daily data snapshots
|
||||||
|
- ✅ Both databases have identical structure
|
||||||
|
- ✅ You want to load different data into existing database
|
||||||
|
- ✅ Faster backups for large databases
|
||||||
|
- ✅ Testing with production data
|
||||||
|
|
||||||
|
**Creates:**
|
||||||
|
- Only INSERT statements for all tables
|
||||||
|
- No schema, no triggers, no structure
|
||||||
|
|
||||||
|
**File:** `data_only_trasabilitate_20251105_190632.sql`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Command Reference
|
||||||
|
|
||||||
|
### Web Interface
|
||||||
|
|
||||||
|
**Location:** Settings → Database Backup Management
|
||||||
|
|
||||||
|
#### Create Backups:
|
||||||
|
- **Full Backup:** Click `⚡ Full Backup (Schema + Data)` button
|
||||||
|
- **Data-Only:** Click `📦 Data-Only Backup` button
|
||||||
|
|
||||||
|
#### Restore Database (Superadmin Only):
|
||||||
|
1. Select backup file from dropdown
|
||||||
|
2. Choose restore type:
|
||||||
|
- **Full Restore:** Replace entire database
|
||||||
|
- **Data-Only Restore:** Replace only data
|
||||||
|
3. Click `🔄 Restore Database` button
|
||||||
|
4. Confirm twice
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backup Comparison
|
||||||
|
|
||||||
|
| Feature | Full Backup | Data-Only Backup |
|
||||||
|
|---------|-------------|------------------|
|
||||||
|
| **Speed** | Slower | ⚡ Faster (30-40% quicker) |
|
||||||
|
| **File Size** | Larger | 📦 Smaller (~1-2 MB less) |
|
||||||
|
| **Schema** | ✅ Yes | ❌ No |
|
||||||
|
| **Triggers** | ✅ Yes | ❌ No |
|
||||||
|
| **Data** | ✅ Yes | ✅ Yes |
|
||||||
|
| **Use Case** | Complete recovery | Data refresh |
|
||||||
|
| **Restore Requirement** | None | Schema must exist |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Safety Features
|
||||||
|
|
||||||
|
### Full Restore
|
||||||
|
- **Confirmation:** Type "RESTORE" in capital letters
|
||||||
|
- **Effect:** Replaces EVERYTHING
|
||||||
|
- **Warning:** All data, schema, triggers deleted
|
||||||
|
|
||||||
|
### Data-Only Restore
|
||||||
|
- **Confirmation:** Type "RESTORE DATA" in capital letters
|
||||||
|
- **Effect:** Replaces only data
|
||||||
|
- **Warning:** All data deleted, schema preserved
|
||||||
|
|
||||||
|
### Smart Detection
|
||||||
|
- System warns if you try to do full restore on data-only file
|
||||||
|
- System warns if you try to do data-only restore on full file
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Scenarios
|
||||||
|
|
||||||
|
### Scenario 1: Daily Backups
|
||||||
|
**Recommendation:**
|
||||||
|
- Monday: Full backup (keeps everything)
|
||||||
|
- Tuesday-Sunday: Data-only backups (faster, smaller)
|
||||||
|
|
||||||
|
### Scenario 2: Database Migration
|
||||||
|
**Recommendation:**
|
||||||
|
- Use full backup (safest, includes everything)
|
||||||
|
|
||||||
|
### Scenario 3: Load Test Data
|
||||||
|
**Recommendation:**
|
||||||
|
- Use data-only backup (preserve your test triggers)
|
||||||
|
|
||||||
|
### Scenario 4: Disaster Recovery
|
||||||
|
**Recommendation:**
|
||||||
|
- Use full backup (complete restoration)
|
||||||
|
|
||||||
|
### Scenario 5: Data Refresh
|
||||||
|
**Recommendation:**
|
||||||
|
- Use data-only backup (quick data swap)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Naming Convention
|
||||||
|
|
||||||
|
### Identify Backup Type by Filename:
|
||||||
|
|
||||||
|
```
|
||||||
|
backup_trasabilitate_20251105_143022.sql
|
||||||
|
└─┬─┘ └─────┬──────┘ └────┬─────┘
|
||||||
|
│ │ └─ Timestamp
|
||||||
|
│ └─ Database name
|
||||||
|
└─ Full backup
|
||||||
|
|
||||||
|
data_only_trasabilitate_20251105_143022.sql
|
||||||
|
└───┬───┘ └─────┬──────┘ └────┬─────┘
|
||||||
|
│ │ └─ Timestamp
|
||||||
|
│ └─ Database name
|
||||||
|
└─ Data-only backup
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Table doesn't exist" during data-only restore
|
||||||
|
**Solution:** Run full backup restore first, or use database setup script
|
||||||
|
|
||||||
|
### "Column count doesn't match" during data-only restore
|
||||||
|
**Solution:** Schema has changed. Update schema or use newer backup
|
||||||
|
|
||||||
|
### "Foreign key constraint fails" during restore
|
||||||
|
**Solution:** Database user needs SUPER privilege
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. ✅ Keep both types of backups
|
||||||
|
2. ✅ Test restores in non-production first
|
||||||
|
3. ✅ Schedule full backups weekly
|
||||||
|
4. ✅ Schedule data-only backups daily
|
||||||
|
5. ✅ Keep backups for 30+ days
|
||||||
|
6. ✅ Store backups off-server for disaster recovery
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Access Requirements
|
||||||
|
|
||||||
|
| Action | Required Role |
|
||||||
|
|--------|--------------|
|
||||||
|
| Create Full Backup | Admin or Superadmin |
|
||||||
|
| Create Data-Only Backup | Admin or Superadmin |
|
||||||
|
| View Backup List | Admin or Superadmin |
|
||||||
|
| Download Backup | Admin or Superadmin |
|
||||||
|
| Delete Backup | Admin or Superadmin |
|
||||||
|
| **Full Restore** | **Superadmin Only** |
|
||||||
|
| **Data-Only Restore** | **Superadmin Only** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Tips
|
||||||
|
|
||||||
|
💡 **Tip 1:** Data-only backups are 30-40% faster than full backups
|
||||||
|
|
||||||
|
💡 **Tip 2:** Use data-only restore to quickly swap between production and test data
|
||||||
|
|
||||||
|
💡 **Tip 3:** Always keep at least one full backup for disaster recovery
|
||||||
|
|
||||||
|
💡 **Tip 4:** Data-only backups are perfect for automated daily snapshots
|
||||||
|
|
||||||
|
💡 **Tip 5:** Test your restore process regularly (at least quarterly)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For detailed information, see:
|
||||||
|
- [DATA_ONLY_BACKUP_FEATURE.md](DATA_ONLY_BACKUP_FEATURE.md) - Complete feature documentation
|
||||||
|
- [BACKUP_SYSTEM.md](BACKUP_SYSTEM.md) - Overall backup system
|
||||||
|
- [DATABASE_RESTORE_GUIDE.md](DATABASE_RESTORE_GUIDE.md) - Restore procedures
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated:** November 5, 2025
|
||||||
|
**Application:** Quality Recticel - Trasabilitate System
|
||||||
384
logs/access.log
384
logs/access.log
@@ -562,3 +562,387 @@
|
|||||||
192.168.0.132 - - [03/Nov/2025:22:26:31 +0200] "POST / HTTP/1.1" 302 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 10914 µs
|
192.168.0.132 - - [03/Nov/2025:22:26:31 +0200] "POST / HTTP/1.1" 302 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 10914 µs
|
||||||
192.168.0.132 - - [03/Nov/2025:22:26:31 +0200] "GET /dashboard HTTP/1.1" 200 3827 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2747 µs
|
192.168.0.132 - - [03/Nov/2025:22:26:31 +0200] "GET /dashboard HTTP/1.1" 200 3827 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2747 µs
|
||||||
192.168.0.132 - - [03/Nov/2025:22:26:39 +0200] "GET /daily_mirror/main HTTP/1.1" 200 10549 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 19051 µs
|
192.168.0.132 - - [03/Nov/2025:22:26:39 +0200] "GET /daily_mirror/main HTTP/1.1" 200 10549 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 19051 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:27 +0200] "GET /dashboard HTTP/1.1" 302 189 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2552 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:27 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1793 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:27 +0200] "GET /static/script.js HTTP/1.1" 200 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12521 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:27 +0200] "GET /static/style.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13089 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:27 +0200] "GET /static/logo_login.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2199 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:27 +0200] "GET /static/css/login.css HTTP/1.1" 200 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 27914 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:27 +0200] "GET /static/css/base.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 29657 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:27 +0200] "GET /favicon.ico HTTP/1.1" 404 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 3554 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:38 +0200] "POST / HTTP/1.1" 302 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 7784 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:38 +0200] "GET /dashboard HTTP/1.1" 200 3824 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12172 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:38 +0200] "GET /static/scan_me.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2468 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:44 +0200] "GET /main_scan HTTP/1.1" 200 2541 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6905 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:51 +0200] "GET /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/main_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 32154 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:06:12:51 +0200] "GET /static/css/scan.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2334 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:08:17:10 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.2; +https://openai.com/gptbot)" 8037 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:11:13 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 36277 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:24:49 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 96679 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:24:49 +0200] "GET /static/style.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 4372 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:24:49 +0200] "GET /static/css/base.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2399 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:24:49 +0200] "GET /static/css/scan.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12995 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:24:49 +0200] "GET /static/script.js HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2250 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:24:49 +0200] "GET /static/scan_me.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2245 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:24:59 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 81440 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:29:12 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10461 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:30:58 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10179 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:40:16 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 97127 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:43:07 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10557 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:47:33 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10395 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:53:43 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10299 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:54:58 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11251 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:55:38 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10508 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:10:57:13 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10536 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:13:12 +0200] "GET /settings HTTP/1.1" 302 189 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Mobile Safari/537.36" 4080 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:13:12 +0200] "GET /static/logo_login.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Mobile Safari/537.36" 2934 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:13:13 +0200] "GET /favicon.ico HTTP/1.1" 404 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Mobile Safari/537.36" 1902 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:31:14 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 97379 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:33:24 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11081 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:36:11 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 18766 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:38:08 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10196 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:41:56 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10523 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:45:18 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10788 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:46:33 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10645 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:49:24 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11648 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:54:08 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10775 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:55:10 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11220 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:58:04 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10872 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:11:59:13 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10649 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:01:39 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 43968 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:06:24 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11119 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:07:17 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10803 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:11:06 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10989 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:12:12 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11055 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:15:45 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11223 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:16:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11165 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:19:28 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11037 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:20:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11242 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:24:23 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11183 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:25:30 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10992 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:27:58 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11038 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:28:54 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11052 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:29:44 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12022 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:31:58 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11132 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:37:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 85402 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:37:48 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11243 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:38:10 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11032 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:39:51 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11198 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:40:10 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11060 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:41:05 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11776 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:42:38 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11231 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:50:06 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12031 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:54:21 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11443 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:55:28 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12384 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:55:43 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11645 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:12:56:37 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11843 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:09:55 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 98595 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:10:22 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12092 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:18:31 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11799 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:20:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11399 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:20:45 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11761 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:24:01 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11861 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:25:34 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11555 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:28:34 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11571 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:29:04 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12073 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:32:48 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11914 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:33:12 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11785 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:35:40 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11011 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:37:16 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11617 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:39:18 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11635 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:42:19 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11537 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:45:56 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12128 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:48:41 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12132 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:49:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13105 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:52:19 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12213 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:53:59 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11880 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:55:31 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12119 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:57:46 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13438 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:13:58:34 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12358 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:01:25 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12135 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:01:38 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11941 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:03:51 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12200 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:06:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12389 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:07:56 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12268 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:10:44 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12096 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:13:39 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12144 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:14:03 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12321 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:17:03 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12181 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:18:12 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12379 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:21:07 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12576 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:21:54 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12409 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:24:09 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12335 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:25:09 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12331 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:25:09 +0200] "GET /static/style.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 3034 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:25:09 +0200] "GET /static/css/base.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 14353 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:25:09 +0200] "GET /static/scan_me.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 4089 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:25:09 +0200] "GET /static/script.js HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2855 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:25:09 +0200] "GET /static/css/scan.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 17085 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:25:39 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12740 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:28:19 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12679 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:42:45 +0200] "GET /dashboard HTTP/1.1" 200 3824 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 3321 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:42:57 +0200] "GET /main_scan HTTP/1.1" 200 2541 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2918 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:42:59 +0200] "GET /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/main_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 7358 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:52:18 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13308 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:53:04 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12626 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:14:59:42 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12884 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:02:41 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12571 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:17 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12571 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:53 +0200] "GET /dashboard HTTP/1.1" 302 189 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1540 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:53 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 8340 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:54 +0200] "GET /static/logo_login.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1911 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:54 +0200] "GET /static/css/login.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13034 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:54 +0200] "GET /favicon.ico HTTP/1.1" 404 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1401 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:55 +0200] "POST / HTTP/1.1" 302 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 5894 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:55 +0200] "GET /dashboard HTTP/1.1" 200 3824 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12102 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:57 +0200] "GET /main_scan HTTP/1.1" 200 2541 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6823 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:07:58 +0200] "GET /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/main_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6065 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:09:16 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 9931 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:12:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 9915 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:15:05 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 9980 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:17:13 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10359 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:20:08 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10383 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:23:31 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10485 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:15:25:41 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10658 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:18:17:39 +0200] "GET /dashboard HTTP/1.1" 200 3824 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12281 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:18:17:40 +0200] "GET /main_scan HTTP/1.1" 200 2541 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6888 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:18:17:41 +0200] "GET /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/main_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6239 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:18:22:51 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" 8353 µs
|
||||||
|
192.168.0.132 - - [04/Nov/2025:22:42:22 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:135.0) Gecko/20100101 Firefox/135.0" 8466 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:15:49 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10266 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:15:49 +0200] "GET /static/css/scan.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2380 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:15:49 +0200] "GET /static/css/base.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2430 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:15:49 +0200] "GET /static/style.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2392 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:15:49 +0200] "GET /static/script.js HTTP/1.1" 200 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2796 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:15:49 +0200] "GET /static/scan_me.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2207 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:16:00 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10064 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:18:06 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10807 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:18:18 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10370 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:21:32 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10262 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:23:07 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10698 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:26:11 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 9958 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:26:20 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10253 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:29:42 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10375 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:31:40 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10867 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:33:55 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10314 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:34:39 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10138 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:38:14 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10344 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:38:55 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10497 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:42:20 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10373 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:44:07 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10370 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:49:33 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10381 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:54:16 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10430 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:56:11 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10468 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:06:57:08 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10246 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:01:41 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11103 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:07:08 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10526 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:33:29 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10606 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:36:49 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11354 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:37:22 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10803 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:39:23 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11539 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:42:46 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10692 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:49:38 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10719 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:07:54:47 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10949 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:15:49 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10790 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:22:59 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11007 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:26:46 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10815 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:31:57 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10889 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:33:31 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10856 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:35:55 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11053 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:38:16 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11145 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:44:34 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12227 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:44:44 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13457 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:48:37 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10946 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:48:59 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10971 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:49:07 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10901 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:54:12 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12157 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:55:49 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11197 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:56:15 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11034 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:57:04 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11223 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:57:30 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12009 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:58:19 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11295 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:59:10 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11143 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:08:59:36 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10915 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:02:45 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11225 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:02:52 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11339 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:03:51 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11466 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:05:17 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11510 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:06:26 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11335 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:07:15 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11652 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:09:09 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11600 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:10:03 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10592 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:11:46 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11556 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:14:15 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11300 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:16:55 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11749 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:18:39 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11453 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:19:55 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11605 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:21:55 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12340 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:22:59 +0200] "GET /quality HTTP/1.1" 302 189 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1897 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:22:59 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2013 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:22:59 +0200] "GET /static/style.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2229 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:22:59 +0200] "GET /static/css/base.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2053 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:22:59 +0200] "GET /static/script.js HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2329 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:22:59 +0200] "GET /static/css/login.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2515 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:22:59 +0200] "GET /static/logo_login.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2286 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:00 +0200] "GET /favicon.ico HTTP/1.1" 404 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2448 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:01 +0200] "POST / HTTP/1.1" 302 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 5693 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:01 +0200] "GET /dashboard HTTP/1.1" 200 3824 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2516 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:01 +0200] "GET /static/scan_me.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2279 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:03 +0200] "GET /reports HTTP/1.1" 200 3385 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 8042 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:04 +0200] "GET /fg_quality HTTP/1.1" 200 22312 "https://quality.moto-adv.com/reports" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 21834 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:04 +0200] "GET /static/fg_quality.js HTTP/1.1" 200 0 "https://quality.moto-adv.com/fg_quality" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2786 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:07 +0200] "GET /get_fg_report_data?report=5 HTTP/1.1" 200 7888 "https://quality.moto-adv.com/fg_quality" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10662 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:23:51 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11192 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:26:02 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12405 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:26:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11522 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:30:21 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11807 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:31:14 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10808 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:34:55 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11048 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:35:44 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11667 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:37:08 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" 8444 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:37:14 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12072 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:40:15 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12585 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:43:30 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11999 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:45:45 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12001 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:48:58 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11981 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:49:32 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11773 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:49:47 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12106 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:54:41 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11949 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:09:58:37 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11818 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:01:37 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12946 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:01:41 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11945 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:06:45 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12374 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:07:55 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1723 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:07:55 +0200] "GET /static/logo_login.jpg HTTP/1.1" 200 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 5440 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:07:55 +0200] "GET /static/style.css HTTP/1.1" 200 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1954 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:07:55 +0200] "GET /static/css/base.css HTTP/1.1" 200 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1864 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:07:55 +0200] "GET /static/css/login.css HTTP/1.1" 200 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1856 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:07:55 +0200] "GET /static/script.js HTTP/1.1" 200 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2414 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:07:56 +0200] "GET /favicon.ico HTTP/1.1" 404 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2048 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:07:59 +0200] "POST / HTTP/1.1" 200 1688 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 5989 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:14 +0200] "POST / HTTP/1.1" 302 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6064 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:14 +0200] "GET /dashboard HTTP/1.1" 200 3827 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2527 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:14 +0200] "GET /static/scan_me.jpg HTTP/1.1" 200 0 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 21135 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:20 +0200] "GET /reports HTTP/1.1" 200 3388 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 8000 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:24 +0200] "GET /fg_quality HTTP/1.1" 200 22444 "https://quality.moto-adv.com/reports" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 21628 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:24 +0200] "GET /static/fg_quality.js HTTP/1.1" 200 0 "https://quality.moto-adv.com/fg_quality" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2751 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:29 +0200] "GET /get_fg_report_data?report=5 HTTP/1.1" 200 7888 "https://quality.moto-adv.com/fg_quality" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10600 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:46 +0200] "GET /test_fg_database HTTP/1.1" 200 1559 "https://quality.moto-adv.com/fg_quality" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 7875 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:52 +0200] "GET /dashboard HTTP/1.1" 200 3827 "https://quality.moto-adv.com/fg_quality" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2468 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:54 +0200] "GET /main_scan HTTP/1.1" 200 2544 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6972 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:55 +0200] "GET /fg_scan HTTP/1.1" 200 32839 "https://quality.moto-adv.com/main_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6099 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:56 +0200] "GET /static/css/scan.css HTTP/1.1" 200 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2494 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:08:57 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11870 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:10:23 +0200] "POST /fg_scan HTTP/1.1" 200 32839 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10433 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:10:37 +0200] "POST /fg_scan HTTP/1.1" 200 32839 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10783 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:10:42 +0200] "POST /fg_scan HTTP/1.1" 200 32839 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10265 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:11:14 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12510 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:11:43 +0200] "POST /fg_scan HTTP/1.1" 200 32839 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 10060 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:12:47 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12557 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:13:56 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12243 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:21 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2150 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:23 +0200] "POST / HTTP/1.1" 302 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 5633 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:23 +0200] "GET /dashboard HTTP/1.1" 200 3827 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2458 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:25 +0200] "GET /settings HTTP/1.1" 200 34325 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 47236 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:25 +0200] "GET /api/backup/schedule HTTP/1.1" 200 100 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2740 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:25 +0200] "GET /api/backup/list HTTP/1.1" 200 195 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 11161 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:41 +0200] "POST /api/backup/create HTTP/1.1" 200 238 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 229606 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:44 +0200] "GET /api/backup/list HTTP/1.1" 200 345 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2653 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:14:48 +0200] "GET /api/backup/download/backup_trasabilitate_20251105_101441.sql HTTP/1.1" 200 0 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 6717 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:18:25 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12437 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:18:25 +0200] "GET /static/css/base.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 3140 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:18:25 +0200] "GET /static/script.js HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 3014 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:18:25 +0200] "GET /static/css/scan.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2829 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:18:25 +0200] "GET /static/scan_me.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 3232 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:18:25 +0200] "GET /static/style.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 18745 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:18:38 +0200] "POST /api/backup/schedule HTTP/1.1" 200 64 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 3294 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:19:31 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12328 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:21:37 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12354 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:22:54 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12761 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:29:01 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12785 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:32:08 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12757 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:33:47 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13501 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:35:05 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12562 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:38:07 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12650 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:38:34 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12547 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:39:13 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12630 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:43:19 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12557 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:44:16 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12781 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:47:12 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12842 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:50:40 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12916 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:51:01 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13598 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:52:57 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12670 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:55:23 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12861 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:55:42 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12950 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:58:50 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12942 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:59:27 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 13809 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:10:59:38 +0200] "POST /fg_scan HTTP/1.1" 200 32836 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 12838 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:12:30:11 +0200] "GET /dashboard HTTP/1.1" 302 189 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1454 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:12:30:11 +0200] "GET / HTTP/1.1" 200 1688 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1669 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:12:30:11 +0200] "GET /static/css/login.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1935 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:12:30:11 +0200] "GET /static/logo_login.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 1978 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:12:30:11 +0200] "GET /favicon.ico HTTP/1.1" 404 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0" 2065 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:13:59:21 +0200] "GET /.env HTTP/1.1" 404 207 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3" 2030 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:01 +0200] "GET /dashboard HTTP/1.1" 302 189 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 16940 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:02 +0200] "GET / HTTP/1.1" 200 1688 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 61971 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:02 +0200] "GET /favicon.ico HTTP/1.1" 404 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2850 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:10 +0200] "POST / HTTP/1.1" 302 207 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 11767 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:10 +0200] "GET /dashboard HTTP/1.1" 200 3827 "https://quality.moto-adv.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 12538 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:10 +0200] "GET /static/css/base.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 13285 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:10 +0200] "GET /static/style.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 30006 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:10 +0200] "GET /static/script.js HTTP/1.1" 304 0 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 30188 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:10 +0200] "GET /static/scan_me.jpg HTTP/1.1" 304 0 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 30252 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:13 +0200] "GET /main_scan HTTP/1.1" 200 2544 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 48222 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:15 +0200] "GET /fg_scan HTTP/1.1" 200 32839 "https://quality.moto-adv.com/main_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 32890 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:19:15 +0200] "GET /static/css/scan.css HTTP/1.1" 304 0 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2467 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:20:16 +0200] "POST /fg_scan HTTP/1.1" 200 32839 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 9755 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:18:20:25 +0200] "POST /fg_scan HTTP/1.1" 200 32839 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 81428 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:10 +0200] "POST /fg_scan HTTP/1.1" 200 32840 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 100484 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:31 +0200] "GET /dashboard HTTP/1.1" 200 3827 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 12610 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:34 +0200] "GET /settings HTTP/1.1" 200 40104 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 48813 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:34 +0200] "GET /api/backup/list HTTP/1.1" 200 345 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 27909 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:34 +0200] "GET /api/backup/schedule HTTP/1.1" 200 100 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 49313 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:46 +0200] "DELETE /api/backup/delete/backup_trasabilitate_20251103_212929_20251103_215909.sql HTTP/1.1" 200 114 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 28996 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:47 +0200] "GET /api/backup/list HTTP/1.1" 200 179 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 3272 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:50 +0200] "DELETE /api/backup/delete/backup_trasabilitate_20251105_101441.sql HTTP/1.1" 200 98 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 3450 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:19:04:51 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 5292 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:29:50 +0200] "GET /settings HTTP/1.1" 200 40104 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 89618 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:29:50 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2552 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:29:50 +0200] "GET /api/backup/schedule HTTP/1.1" 200 100 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2693 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:30:05 +0200] "POST /api/backup/create-data-only HTTP/1.1" 200 254 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 174664 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:30:08 +0200] "GET /api/backup/list HTTP/1.1" 200 182 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 27617 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:30:32 +0200] "GET /api/backup/list HTTP/1.1" 200 182 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 3214 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:30:33 +0200] "GET /api/backup/list HTTP/1.1" 200 182 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2700 µs
|
||||||
|
127.0.0.1 - - [05/Nov/2025:20:34:42 +0200] "GET /api/backup/schedule HTTP/1.1" 302 189 "-" "curl/8.14.1" 18027 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:35:00 +0200] "GET /settings HTTP/1.1" 200 42008 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 108583 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:35:00 +0200] "GET /api/backup/list HTTP/1.1" 200 182 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 45694 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:35:00 +0200] "GET /api/backup/schedule HTTP/1.1" 200 121 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 46015 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:35:23 +0200] "POST /api/backup/schedule HTTP/1.1" 200 64 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 4267 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:35:37 +0200] "DELETE /api/backup/delete/data_only_trasabilitate_20251105_203005.sql HTTP/1.1" 200 101 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 3789 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:35:38 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2584 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:45:58 +0200] "GET /settings HTTP/1.1" 200 43080 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 111345 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:45:58 +0200] "GET /api/backup/schedule HTTP/1.1" 200 164 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 4862 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:45:58 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 19334 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:46:24 +0200] "GET /settings HTTP/1.1" 200 43080 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 95425 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:46:24 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2623 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:20:46:24 +0200] "GET /api/backup/schedule HTTP/1.1" 200 164 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 20670 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:08:15 +0200] "GET /settings HTTP/1.1" 200 68254 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 127920 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:08:15 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 19369 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:08:15 +0200] "GET /api/backup/schedule HTTP/1.1" 200 164 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 20410 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:09:39 +0200] "GET /settings HTTP/1.1" 200 68254 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 127408 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:09:40 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 3033 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:09:40 +0200] "GET /api/backup/schedule HTTP/1.1" 200 164 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 4782 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:10:03 +0200] "POST /api/backup/create HTTP/1.1" 200 238 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 227736 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:10:07 +0200] "GET /api/backup/list HTTP/1.1" 200 178 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2625 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:10:20 +0200] "DELETE /api/backup/delete/backup_trasabilitate_20251105_211003.sql HTTP/1.1" 200 98 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 3783 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:10:22 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2479 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:10:25 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2495 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:19:35 +0200] "GET /settings HTTP/1.1" 200 72985 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 131211 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:19:35 +0200] "GET /api/backup/list HTTP/1.1" 200 30 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 3707 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:19:35 +0200] "GET /api/backup/schedule HTTP/1.1" 200 283 "https://quality.moto-adv.com/settings" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 21446 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:22:15 +0200] "GET /main_scan HTTP/1.1" 200 2544 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 46701 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:22:17 +0200] "GET /fg_scan HTTP/1.1" 200 32840 "https://quality.moto-adv.com/main_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 34947 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:22:39 +0200] "GET /dashboard HTTP/1.1" 200 3827 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 12213 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:22:44 +0200] "GET /main_scan HTTP/1.1" 200 2544 "https://quality.moto-adv.com/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 2394 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:23:03 +0200] "GET /fg_scan HTTP/1.1" 200 32840 "https://quality.moto-adv.com/main_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 6396 µs
|
||||||
|
192.168.0.132 - - [05/Nov/2025:21:23:24 +0200] "POST /fg_scan HTTP/1.1" 200 32844 "https://quality.moto-adv.com/fg_scan" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36" 16430 µs
|
||||||
|
|||||||
1011
logs/error.log
1011
logs/error.log
File diff suppressed because one or more lines are too long
@@ -19,5 +19,10 @@ def create_app():
|
|||||||
|
|
||||||
# Add 'now' function to Jinja2 globals
|
# Add 'now' function to Jinja2 globals
|
||||||
app.jinja_env.globals['now'] = datetime.now
|
app.jinja_env.globals['now'] = datetime.now
|
||||||
|
|
||||||
|
# Initialize automatic backup scheduler
|
||||||
|
from app.backup_scheduler import init_backup_scheduler
|
||||||
|
init_backup_scheduler(app)
|
||||||
|
print("✅ Automatic backup scheduler initialized")
|
||||||
|
|
||||||
return app
|
return app
|
||||||
296
py_app/app/backup_scheduler.py
Normal file
296
py_app/app/backup_scheduler.py
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
"""
|
||||||
|
Automated Backup Scheduler
|
||||||
|
Quality Recticel Application
|
||||||
|
|
||||||
|
This module manages automatic backup execution based on the configured schedule.
|
||||||
|
Uses APScheduler to run backups at specified times.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
from apscheduler.triggers.cron import CronTrigger
|
||||||
|
from datetime import datetime
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BackupScheduler:
|
||||||
|
"""Manages automatic backup scheduling"""
|
||||||
|
|
||||||
|
def __init__(self, app=None):
|
||||||
|
"""
|
||||||
|
Initialize the backup scheduler
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: Flask application instance
|
||||||
|
"""
|
||||||
|
self.scheduler = None
|
||||||
|
self.app = app
|
||||||
|
self.job_prefix = 'scheduled_backup'
|
||||||
|
|
||||||
|
if app is not None:
|
||||||
|
self.init_app(app)
|
||||||
|
|
||||||
|
def init_app(self, app):
|
||||||
|
"""
|
||||||
|
Initialize scheduler with Flask app context
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: Flask application instance
|
||||||
|
"""
|
||||||
|
self.app = app
|
||||||
|
|
||||||
|
# Create scheduler
|
||||||
|
self.scheduler = BackgroundScheduler(
|
||||||
|
daemon=True,
|
||||||
|
timezone='Europe/Bucharest' # Adjust to your timezone
|
||||||
|
)
|
||||||
|
|
||||||
|
# Load and apply schedule from configuration
|
||||||
|
self.update_schedule()
|
||||||
|
|
||||||
|
# Start scheduler
|
||||||
|
self.scheduler.start()
|
||||||
|
logger.info("Backup scheduler started")
|
||||||
|
|
||||||
|
# Register shutdown handler
|
||||||
|
import atexit
|
||||||
|
atexit.register(lambda: self.scheduler.shutdown())
|
||||||
|
|
||||||
|
def execute_scheduled_backup(self, schedule_id, backup_type):
|
||||||
|
"""
|
||||||
|
Execute a backup based on the schedule configuration
|
||||||
|
This method runs in the scheduler thread
|
||||||
|
|
||||||
|
Args:
|
||||||
|
schedule_id: Identifier for the schedule
|
||||||
|
backup_type: Type of backup ('full' or 'data-only')
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
|
||||||
|
with self.app.app_context():
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
|
||||||
|
logger.info(f"Starting scheduled {backup_type} backup (schedule: {schedule_id})...")
|
||||||
|
|
||||||
|
# Execute appropriate backup
|
||||||
|
if backup_type == 'data-only':
|
||||||
|
result = backup_manager.create_data_only_backup(backup_name='scheduled')
|
||||||
|
else:
|
||||||
|
result = backup_manager.create_backup(backup_name='scheduled')
|
||||||
|
|
||||||
|
if result['success']:
|
||||||
|
logger.info(f"✅ Scheduled backup completed: {result['filename']} ({result['size']})")
|
||||||
|
|
||||||
|
# Clean up old backups based on retention policy
|
||||||
|
schedule = backup_manager.get_backup_schedule()
|
||||||
|
schedules = schedule.get('schedules', []) if isinstance(schedule, dict) and 'schedules' in schedule else []
|
||||||
|
|
||||||
|
# Find the schedule that triggered this backup
|
||||||
|
current_schedule = next((s for s in schedules if s.get('id') == schedule_id), None)
|
||||||
|
if current_schedule:
|
||||||
|
retention_days = current_schedule.get('retention_days', 30)
|
||||||
|
cleanup_result = backup_manager.cleanup_old_backups(retention_days)
|
||||||
|
|
||||||
|
if cleanup_result['success'] and cleanup_result['deleted_count'] > 0:
|
||||||
|
logger.info(f"🗑️ Cleaned up {cleanup_result['deleted_count']} old backup(s)")
|
||||||
|
else:
|
||||||
|
logger.error(f"❌ Scheduled backup failed: {result['message']}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"❌ Error during scheduled backup: {e}", exc_info=True)
|
||||||
|
|
||||||
|
def update_schedule(self):
|
||||||
|
"""
|
||||||
|
Reload schedule from configuration and update scheduler jobs
|
||||||
|
Supports multiple schedules
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
|
||||||
|
with self.app.app_context():
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
schedule_config = backup_manager.get_backup_schedule()
|
||||||
|
|
||||||
|
# Remove all existing backup jobs
|
||||||
|
for job in self.scheduler.get_jobs():
|
||||||
|
if job.id.startswith(self.job_prefix):
|
||||||
|
self.scheduler.remove_job(job.id)
|
||||||
|
|
||||||
|
# Handle new multi-schedule format
|
||||||
|
if isinstance(schedule_config, dict) and 'schedules' in schedule_config:
|
||||||
|
schedules = schedule_config['schedules']
|
||||||
|
|
||||||
|
for schedule in schedules:
|
||||||
|
if not schedule.get('enabled', False):
|
||||||
|
continue
|
||||||
|
|
||||||
|
schedule_id = schedule.get('id', 'default')
|
||||||
|
time_str = schedule.get('time', '02:00')
|
||||||
|
frequency = schedule.get('frequency', 'daily')
|
||||||
|
backup_type = schedule.get('backup_type', 'full')
|
||||||
|
|
||||||
|
# Parse time
|
||||||
|
hour, minute = map(int, time_str.split(':'))
|
||||||
|
|
||||||
|
# Create appropriate trigger
|
||||||
|
if frequency == 'daily':
|
||||||
|
trigger = CronTrigger(hour=hour, minute=minute)
|
||||||
|
elif frequency == 'weekly':
|
||||||
|
trigger = CronTrigger(day_of_week='sun', hour=hour, minute=minute)
|
||||||
|
elif frequency == 'monthly':
|
||||||
|
trigger = CronTrigger(day=1, hour=hour, minute=minute)
|
||||||
|
else:
|
||||||
|
logger.error(f"Unknown frequency: {frequency}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Add job with unique ID
|
||||||
|
job_id = f"{self.job_prefix}_{schedule_id}"
|
||||||
|
self.scheduler.add_job(
|
||||||
|
func=self.execute_scheduled_backup,
|
||||||
|
trigger=trigger,
|
||||||
|
args=[schedule_id, backup_type],
|
||||||
|
id=job_id,
|
||||||
|
name=f'Scheduled {backup_type} backup ({schedule_id})',
|
||||||
|
replace_existing=True
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(f"✅ Schedule '{schedule_id}': {backup_type} backup {frequency} at {time_str}")
|
||||||
|
|
||||||
|
# Handle legacy single-schedule format (backward compatibility)
|
||||||
|
elif isinstance(schedule_config, dict) and schedule_config.get('enabled', False):
|
||||||
|
time_str = schedule_config.get('time', '02:00')
|
||||||
|
frequency = schedule_config.get('frequency', 'daily')
|
||||||
|
backup_type = schedule_config.get('backup_type', 'full')
|
||||||
|
|
||||||
|
hour, minute = map(int, time_str.split(':'))
|
||||||
|
|
||||||
|
if frequency == 'daily':
|
||||||
|
trigger = CronTrigger(hour=hour, minute=minute)
|
||||||
|
elif frequency == 'weekly':
|
||||||
|
trigger = CronTrigger(day_of_week='sun', hour=hour, minute=minute)
|
||||||
|
elif frequency == 'monthly':
|
||||||
|
trigger = CronTrigger(day=1, hour=hour, minute=minute)
|
||||||
|
else:
|
||||||
|
logger.error(f"Unknown frequency: {frequency}")
|
||||||
|
return
|
||||||
|
|
||||||
|
job_id = f"{self.job_prefix}_default"
|
||||||
|
self.scheduler.add_job(
|
||||||
|
func=self.execute_scheduled_backup,
|
||||||
|
trigger=trigger,
|
||||||
|
args=['default', backup_type],
|
||||||
|
id=job_id,
|
||||||
|
name=f'Scheduled {backup_type} backup',
|
||||||
|
replace_existing=True
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(f"✅ Backup schedule configured: {backup_type} backup {frequency} at {time_str}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error updating backup schedule: {e}", exc_info=True)
|
||||||
|
|
||||||
|
def get_next_run_time(self, schedule_id='default'):
|
||||||
|
"""
|
||||||
|
Get the next scheduled run time for a specific schedule
|
||||||
|
|
||||||
|
Args:
|
||||||
|
schedule_id: Identifier for the schedule
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
datetime or None: Next run time if job exists
|
||||||
|
"""
|
||||||
|
if not self.scheduler:
|
||||||
|
return None
|
||||||
|
|
||||||
|
job_id = f"{self.job_prefix}_{schedule_id}"
|
||||||
|
job = self.scheduler.get_job(job_id)
|
||||||
|
if job:
|
||||||
|
return job.next_run_time
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_schedule_info(self):
|
||||||
|
"""
|
||||||
|
Get information about all schedules
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Schedule information including next run times for all jobs
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
|
||||||
|
with self.app.app_context():
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
schedule_config = backup_manager.get_backup_schedule()
|
||||||
|
|
||||||
|
# Get all backup jobs
|
||||||
|
jobs_info = []
|
||||||
|
for job in self.scheduler.get_jobs():
|
||||||
|
if job.id.startswith(self.job_prefix):
|
||||||
|
jobs_info.append({
|
||||||
|
'id': job.id.replace(f"{self.job_prefix}_", ""),
|
||||||
|
'name': job.name,
|
||||||
|
'next_run_time': job.next_run_time.strftime('%Y-%m-%d %H:%M:%S') if job.next_run_time else None
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
'schedule': schedule_config,
|
||||||
|
'jobs': jobs_info,
|
||||||
|
'scheduler_running': self.scheduler.running if self.scheduler else False,
|
||||||
|
'total_jobs': len(jobs_info)
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting schedule info: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def trigger_backup_now(self):
|
||||||
|
"""
|
||||||
|
Manually trigger a backup immediately (outside of schedule)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Result of backup operation
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logger.info("Manual backup trigger requested")
|
||||||
|
self.execute_scheduled_backup()
|
||||||
|
return {
|
||||||
|
'success': True,
|
||||||
|
'message': 'Backup triggered successfully'
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error triggering manual backup: {e}")
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': f'Failed to trigger backup: {str(e)}'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Global scheduler instance (initialized in __init__.py)
|
||||||
|
backup_scheduler = None
|
||||||
|
|
||||||
|
|
||||||
|
def init_backup_scheduler(app):
|
||||||
|
"""
|
||||||
|
Initialize the global backup scheduler instance
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: Flask application instance
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
BackupScheduler: Initialized scheduler instance
|
||||||
|
"""
|
||||||
|
global backup_scheduler
|
||||||
|
backup_scheduler = BackupScheduler(app)
|
||||||
|
return backup_scheduler
|
||||||
|
|
||||||
|
|
||||||
|
def get_backup_scheduler():
|
||||||
|
"""
|
||||||
|
Get the global backup scheduler instance
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
BackupScheduler or None: Scheduler instance if initialized
|
||||||
|
"""
|
||||||
|
return backup_scheduler
|
||||||
@@ -281,6 +281,95 @@ class DatabaseBackupManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error removing backup metadata: {e}")
|
print(f"Error removing backup metadata: {e}")
|
||||||
|
|
||||||
|
def create_data_only_backup(self, backup_name=None):
|
||||||
|
"""
|
||||||
|
Create a data-only backup (no schema, triggers, or structure)
|
||||||
|
Only exports INSERT statements for existing tables
|
||||||
|
|
||||||
|
Args:
|
||||||
|
backup_name (str, optional): Custom name for the backup file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Result with success status, message, and backup file path
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if not self.config:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': 'Database configuration not loaded'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate backup filename with data_only prefix
|
||||||
|
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||||
|
if backup_name:
|
||||||
|
filename = f"data_only_{backup_name}_{timestamp}.sql"
|
||||||
|
else:
|
||||||
|
filename = f"data_only_{self.config['database']}_{timestamp}.sql"
|
||||||
|
|
||||||
|
backup_file = os.path.join(self.backup_path, filename)
|
||||||
|
|
||||||
|
# Build mysqldump command for data only
|
||||||
|
# --no-create-info: Skip CREATE TABLE statements
|
||||||
|
# --skip-triggers: Skip trigger definitions
|
||||||
|
# --no-create-db: Skip CREATE DATABASE statement
|
||||||
|
# --complete-insert: Include column names in INSERT (more reliable)
|
||||||
|
# --extended-insert: Use multi-row INSERT for efficiency
|
||||||
|
cmd = [
|
||||||
|
'mysqldump',
|
||||||
|
f"--host={self.config['host']}",
|
||||||
|
f"--port={self.config['port']}",
|
||||||
|
f"--user={self.config['user']}",
|
||||||
|
f"--password={self.config['password']}",
|
||||||
|
'--no-create-info', # Skip table structure
|
||||||
|
'--skip-triggers', # Skip triggers
|
||||||
|
'--no-create-db', # Skip database creation
|
||||||
|
'--complete-insert', # Include column names
|
||||||
|
'--extended-insert', # Multi-row INSERTs
|
||||||
|
'--single-transaction',
|
||||||
|
'--skip-lock-tables',
|
||||||
|
self.config['database']
|
||||||
|
]
|
||||||
|
|
||||||
|
# Execute mysqldump and save to file
|
||||||
|
with open(backup_file, 'w') as f:
|
||||||
|
result = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
stdout=f,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
# Get file size
|
||||||
|
file_size = os.path.getsize(backup_file)
|
||||||
|
file_size_mb = file_size / (1024 * 1024)
|
||||||
|
|
||||||
|
# Save backup metadata
|
||||||
|
self._save_backup_metadata(filename, file_size)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'success': True,
|
||||||
|
'message': f'Data-only backup created successfully',
|
||||||
|
'filename': filename,
|
||||||
|
'file_path': backup_file,
|
||||||
|
'size': f"{file_size_mb:.2f} MB",
|
||||||
|
'timestamp': timestamp
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
error_msg = result.stderr
|
||||||
|
print(f"Data backup error: {error_msg}")
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': f'Data backup failed: {error_msg}'
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Exception during data backup: {e}")
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': f'Data backup failed: {str(e)}'
|
||||||
|
}
|
||||||
|
|
||||||
def restore_backup(self, filename):
|
def restore_backup(self, filename):
|
||||||
"""
|
"""
|
||||||
Restore database from a backup file
|
Restore database from a backup file
|
||||||
@@ -345,6 +434,127 @@ class DatabaseBackupManager:
|
|||||||
'message': f'Restore failed: {str(e)}'
|
'message': f'Restore failed: {str(e)}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def restore_data_only(self, filename):
|
||||||
|
"""
|
||||||
|
Restore data from a data-only backup file
|
||||||
|
Assumes database schema already exists
|
||||||
|
Truncates tables before inserting data to avoid duplicates
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename (str): Name of the data-only backup file to restore
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Result with success status and message
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Security: ensure filename doesn't contain path traversal
|
||||||
|
if '..' in filename or '/' in filename:
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': 'Invalid filename'
|
||||||
|
}
|
||||||
|
|
||||||
|
file_path = os.path.join(self.backup_path, filename)
|
||||||
|
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': 'Backup file not found'
|
||||||
|
}
|
||||||
|
|
||||||
|
# First, disable foreign key checks and truncate all tables
|
||||||
|
# This ensures clean data import without constraint violations
|
||||||
|
try:
|
||||||
|
conn = mariadb.connect(
|
||||||
|
host=self.config['host'],
|
||||||
|
port=int(self.config['port']),
|
||||||
|
user=self.config['user'],
|
||||||
|
password=self.config['password'],
|
||||||
|
database=self.config['database']
|
||||||
|
)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Disable foreign key checks
|
||||||
|
cursor.execute("SET FOREIGN_KEY_CHECKS = 0;")
|
||||||
|
|
||||||
|
# Get list of all tables in the database
|
||||||
|
cursor.execute("SHOW TABLES;")
|
||||||
|
tables = cursor.fetchall()
|
||||||
|
|
||||||
|
# Truncate each table (except system tables)
|
||||||
|
for (table_name,) in tables:
|
||||||
|
# Skip metadata and system tables
|
||||||
|
if table_name not in ['backups_metadata', 'backup_schedule']:
|
||||||
|
try:
|
||||||
|
cursor.execute(f"TRUNCATE TABLE `{table_name}`;")
|
||||||
|
print(f"Truncated table: {table_name}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Could not truncate {table_name}: {e}")
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning during table truncation: {e}")
|
||||||
|
# Continue anyway - the restore might still work
|
||||||
|
|
||||||
|
# Build mysql restore command for data
|
||||||
|
cmd = [
|
||||||
|
'mysql',
|
||||||
|
f"--host={self.config['host']}",
|
||||||
|
f"--port={self.config['port']}",
|
||||||
|
f"--user={self.config['user']}",
|
||||||
|
f"--password={self.config['password']}",
|
||||||
|
self.config['database']
|
||||||
|
]
|
||||||
|
|
||||||
|
# Execute mysql restore
|
||||||
|
with open(file_path, 'r') as f:
|
||||||
|
result = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
stdin=f,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Re-enable foreign key checks
|
||||||
|
try:
|
||||||
|
conn = mariadb.connect(
|
||||||
|
host=self.config['host'],
|
||||||
|
port=int(self.config['port']),
|
||||||
|
user=self.config['user'],
|
||||||
|
password=self.config['password'],
|
||||||
|
database=self.config['database']
|
||||||
|
)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SET FOREIGN_KEY_CHECKS = 1;")
|
||||||
|
conn.commit()
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Could not re-enable foreign key checks: {e}")
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
return {
|
||||||
|
'success': True,
|
||||||
|
'message': f'Data restored successfully from {filename}'
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
error_msg = result.stderr
|
||||||
|
print(f"Data restore error: {error_msg}")
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': f'Data restore failed: {error_msg}'
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Exception during data restore: {e}")
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': f'Data restore failed: {str(e)}'
|
||||||
|
}
|
||||||
|
|
||||||
def get_backup_schedule(self):
|
def get_backup_schedule(self):
|
||||||
"""Get current backup schedule configuration"""
|
"""Get current backup schedule configuration"""
|
||||||
try:
|
try:
|
||||||
@@ -352,13 +562,18 @@ class DatabaseBackupManager:
|
|||||||
|
|
||||||
if os.path.exists(schedule_file):
|
if os.path.exists(schedule_file):
|
||||||
with open(schedule_file, 'r') as f:
|
with open(schedule_file, 'r') as f:
|
||||||
return json.load(f)
|
schedule = json.load(f)
|
||||||
|
# Ensure backup_type exists (for backward compatibility)
|
||||||
|
if 'backup_type' not in schedule:
|
||||||
|
schedule['backup_type'] = 'full'
|
||||||
|
return schedule
|
||||||
|
|
||||||
# Default schedule
|
# Default schedule
|
||||||
return {
|
return {
|
||||||
'enabled': False,
|
'enabled': False,
|
||||||
'time': '02:00', # 2 AM
|
'time': '02:00', # 2 AM
|
||||||
'frequency': 'daily', # daily, weekly, monthly
|
'frequency': 'daily', # daily, weekly, monthly
|
||||||
|
'backup_type': 'full', # full or data-only
|
||||||
'retention_days': 30 # Keep backups for 30 days
|
'retention_days': 30 # Keep backups for 30 days
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,3 +822,112 @@ class DatabaseBackupManager:
|
|||||||
'success': False,
|
'success': False,
|
||||||
'message': f'Cleanup failed: {str(e)}'
|
'message': f'Cleanup failed: {str(e)}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def upload_backup(self, uploaded_file):
|
||||||
|
"""
|
||||||
|
Upload and validate an external backup file
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uploaded_file: Werkzeug FileStorage object from request.files
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Result with success status, filename, and validation details
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from werkzeug.utils import secure_filename
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Validate file extension
|
||||||
|
if not uploaded_file.filename.lower().endswith('.sql'):
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': 'Invalid file format. Only .sql files are allowed.'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure backup_path is a Path object
|
||||||
|
backup_path = Path(self.backup_path)
|
||||||
|
backup_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Generate secure filename with timestamp to avoid conflicts
|
||||||
|
original_filename = secure_filename(uploaded_file.filename)
|
||||||
|
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||||
|
|
||||||
|
# If filename already starts with "backup_", keep it; otherwise add prefix
|
||||||
|
if original_filename.startswith('backup_'):
|
||||||
|
new_filename = f"{original_filename.rsplit('.', 1)[0]}_{timestamp}.sql"
|
||||||
|
else:
|
||||||
|
new_filename = f"backup_uploaded_{timestamp}_{original_filename}"
|
||||||
|
|
||||||
|
# Save file to backup directory
|
||||||
|
file_path = backup_path / new_filename
|
||||||
|
uploaded_file.save(str(file_path))
|
||||||
|
|
||||||
|
# Get file size
|
||||||
|
file_size = file_path.stat().st_size
|
||||||
|
size_mb = round(file_size / (1024 * 1024), 2)
|
||||||
|
|
||||||
|
# Validate the uploaded file for integrity and compatibility
|
||||||
|
validation_result = self.validate_backup_file(new_filename)
|
||||||
|
|
||||||
|
if not validation_result['success']:
|
||||||
|
# Validation failed - remove the uploaded file
|
||||||
|
file_path.unlink() # Delete the invalid file
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': f'Validation failed: {validation_result["message"]}',
|
||||||
|
'validation_details': validation_result.get('details', {}),
|
||||||
|
'warnings': validation_result.get('warnings', [])
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build response with validation details
|
||||||
|
response = {
|
||||||
|
'success': True,
|
||||||
|
'message': 'Backup file uploaded and validated successfully',
|
||||||
|
'filename': new_filename,
|
||||||
|
'size': f'{size_mb} MB',
|
||||||
|
'path': str(file_path),
|
||||||
|
'validation': {
|
||||||
|
'status': 'passed',
|
||||||
|
'message': validation_result['message'],
|
||||||
|
'details': validation_result.get('details', {}),
|
||||||
|
'warnings': validation_result.get('warnings', [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add warning flag if there are warnings
|
||||||
|
if validation_result.get('warnings'):
|
||||||
|
response['message'] = f'Backup uploaded with warnings: {"; ".join(validation_result["warnings"])}'
|
||||||
|
|
||||||
|
# Save metadata
|
||||||
|
self._save_backup_metadata(new_filename, file_size)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error uploading backup: {e}")
|
||||||
|
return {
|
||||||
|
'success': False,
|
||||||
|
'message': f'Upload failed: {str(e)}'
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_backup_file_path(self, filename):
|
||||||
|
"""
|
||||||
|
Get the full path to a backup file (with security validation)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename (str): Name of the backup file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str or None: Full file path if valid, None if security check fails
|
||||||
|
"""
|
||||||
|
# Security: ensure filename doesn't contain path traversal
|
||||||
|
if '..' in filename or '/' in filename:
|
||||||
|
return None
|
||||||
|
|
||||||
|
file_path = os.path.join(self.backup_path, filename)
|
||||||
|
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
return file_path
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -394,56 +394,76 @@ def create_database_triggers():
|
|||||||
conn = mariadb.connect(**DB_CONFIG)
|
conn = mariadb.connect(**DB_CONFIG)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
# Drop existing triggers if they exist
|
# Drop existing triggers if they exist (old and new names)
|
||||||
trigger_drops = [
|
trigger_drops = [
|
||||||
"DROP TRIGGER IF EXISTS increment_approved_quantity;",
|
"DROP TRIGGER IF EXISTS increment_approved_quantity;",
|
||||||
"DROP TRIGGER IF EXISTS increment_rejected_quantity;",
|
"DROP TRIGGER IF EXISTS increment_rejected_quantity;",
|
||||||
"DROP TRIGGER IF EXISTS increment_approved_quantity_fg;",
|
"DROP TRIGGER IF EXISTS increment_approved_quantity_fg;",
|
||||||
"DROP TRIGGER IF EXISTS increment_rejected_quantity_fg;"
|
"DROP TRIGGER IF EXISTS increment_rejected_quantity_fg;",
|
||||||
|
"DROP TRIGGER IF EXISTS set_quantities_scan1;",
|
||||||
|
"DROP TRIGGER IF EXISTS set_quantities_fg;"
|
||||||
]
|
]
|
||||||
|
|
||||||
for drop_query in trigger_drops:
|
for drop_query in trigger_drops:
|
||||||
cursor.execute(drop_query)
|
cursor.execute(drop_query)
|
||||||
|
|
||||||
# Create trigger for scan1_orders approved quantity
|
# Create trigger for scan1_orders - BEFORE INSERT to set quantities
|
||||||
scan1_approved_trigger = """
|
scan1_trigger = """
|
||||||
CREATE TRIGGER increment_approved_quantity
|
CREATE TRIGGER set_quantities_scan1
|
||||||
AFTER INSERT ON scan1_orders
|
BEFORE INSERT ON scan1_orders
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
IF NEW.quality_code = 000 THEN
|
-- Count existing approved for this CP_base_code
|
||||||
UPDATE scan1_orders
|
SET @approved = (SELECT COUNT(*) FROM scan1_orders
|
||||||
SET approved_quantity = approved_quantity + 1
|
WHERE CP_base_code = LEFT(NEW.CP_full_code, 10)
|
||||||
WHERE CP_base_code = NEW.CP_base_code;
|
AND quality_code = 0);
|
||||||
|
|
||||||
|
-- Count existing rejected for this CP_base_code
|
||||||
|
SET @rejected = (SELECT COUNT(*) FROM scan1_orders
|
||||||
|
WHERE CP_base_code = LEFT(NEW.CP_full_code, 10)
|
||||||
|
AND quality_code != 0);
|
||||||
|
|
||||||
|
-- Add 1 to appropriate counter for this new row
|
||||||
|
IF NEW.quality_code = 0 THEN
|
||||||
|
SET NEW.approved_quantity = @approved + 1;
|
||||||
|
SET NEW.rejected_quantity = @rejected;
|
||||||
ELSE
|
ELSE
|
||||||
UPDATE scan1_orders
|
SET NEW.approved_quantity = @approved;
|
||||||
SET rejected_quantity = rejected_quantity + 1
|
SET NEW.rejected_quantity = @rejected + 1;
|
||||||
WHERE CP_base_code = NEW.CP_base_code;
|
|
||||||
END IF;
|
END IF;
|
||||||
END;
|
END;
|
||||||
"""
|
"""
|
||||||
cursor.execute(scan1_approved_trigger)
|
cursor.execute(scan1_trigger)
|
||||||
print_success("Trigger 'increment_approved_quantity' created for scan1_orders")
|
print_success("Trigger 'set_quantities_scan1' created for scan1_orders")
|
||||||
|
|
||||||
# Create trigger for scanfg_orders approved quantity
|
# Create trigger for scanfg_orders - BEFORE INSERT to set quantities
|
||||||
scanfg_approved_trigger = """
|
scanfg_trigger = """
|
||||||
CREATE TRIGGER increment_approved_quantity_fg
|
CREATE TRIGGER set_quantities_fg
|
||||||
AFTER INSERT ON scanfg_orders
|
BEFORE INSERT ON scanfg_orders
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
IF NEW.quality_code = 000 THEN
|
-- Count existing approved for this CP_base_code
|
||||||
UPDATE scanfg_orders
|
SET @approved = (SELECT COUNT(*) FROM scanfg_orders
|
||||||
SET approved_quantity = approved_quantity + 1
|
WHERE CP_base_code = LEFT(NEW.CP_full_code, 10)
|
||||||
WHERE CP_base_code = NEW.CP_base_code;
|
AND quality_code = 0);
|
||||||
|
|
||||||
|
-- Count existing rejected for this CP_base_code
|
||||||
|
SET @rejected = (SELECT COUNT(*) FROM scanfg_orders
|
||||||
|
WHERE CP_base_code = LEFT(NEW.CP_full_code, 10)
|
||||||
|
AND quality_code != 0);
|
||||||
|
|
||||||
|
-- Add 1 to appropriate counter for this new row
|
||||||
|
IF NEW.quality_code = 0 THEN
|
||||||
|
SET NEW.approved_quantity = @approved + 1;
|
||||||
|
SET NEW.rejected_quantity = @rejected;
|
||||||
ELSE
|
ELSE
|
||||||
UPDATE scanfg_orders
|
SET NEW.approved_quantity = @approved;
|
||||||
SET rejected_quantity = rejected_quantity + 1
|
SET NEW.rejected_quantity = @rejected + 1;
|
||||||
WHERE CP_base_code = NEW.CP_base_code;
|
|
||||||
END IF;
|
END IF;
|
||||||
END;
|
END;
|
||||||
"""
|
"""
|
||||||
cursor.execute(scanfg_approved_trigger)
|
cursor.execute(scanfg_trigger)
|
||||||
print_success("Trigger 'increment_approved_quantity_fg' created for scanfg_orders")
|
print_success("Trigger 'set_quantities_fg' created for scanfg_orders")
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|||||||
@@ -473,36 +473,25 @@ def scan():
|
|||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
# Always insert a new entry - each scan is a separate record
|
# Insert new entry - the BEFORE INSERT trigger 'set_quantities_scan1' will automatically
|
||||||
|
# calculate and set approved_quantity and rejected_quantity for this new record
|
||||||
insert_query = """
|
insert_query = """
|
||||||
INSERT INTO scan1_orders (operator_code, CP_full_code, OC1_code, OC2_code, quality_code, date, time)
|
INSERT INTO scan1_orders (operator_code, CP_full_code, OC1_code, OC2_code, quality_code, date, time)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
||||||
"""
|
"""
|
||||||
cursor.execute(insert_query, (operator_code, cp_code, oc1_code, oc2_code, defect_code, date, time))
|
cursor.execute(insert_query, (operator_code, cp_code, oc1_code, oc2_code, defect_code, date, time))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
# Get the CP_base_code (first 10 characters of CP_full_code)
|
# Get the quantities from the newly inserted row for the flash message
|
||||||
cp_base_code = cp_code[:10]
|
cp_base_code = cp_code[:10]
|
||||||
|
|
||||||
# Count approved quantities (quality_code = 0) for this CP_base_code
|
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT COUNT(*) FROM scan1_orders
|
SELECT approved_quantity, rejected_quantity
|
||||||
WHERE CP_base_code = %s AND quality_code = 0
|
FROM scan1_orders
|
||||||
""", (cp_base_code,))
|
WHERE CP_full_code = %s
|
||||||
approved_count = cursor.fetchone()[0]
|
""", (cp_code,))
|
||||||
|
result = cursor.fetchone()
|
||||||
# Count rejected quantities (quality_code != 0) for this CP_base_code
|
approved_count = result[0] if result else 0
|
||||||
cursor.execute("""
|
rejected_count = result[1] if result else 0
|
||||||
SELECT COUNT(*) FROM scan1_orders
|
|
||||||
WHERE CP_base_code = %s AND quality_code != 0
|
|
||||||
""", (cp_base_code,))
|
|
||||||
rejected_count = cursor.fetchone()[0]
|
|
||||||
|
|
||||||
# Update all records with the same CP_base_code with new quantities
|
|
||||||
cursor.execute("""
|
|
||||||
UPDATE scan1_orders
|
|
||||||
SET approved_quantity = %s, rejected_quantity = %s
|
|
||||||
WHERE CP_base_code = %s
|
|
||||||
""", (approved_count, rejected_count, cp_base_code))
|
|
||||||
|
|
||||||
# Flash appropriate message
|
# Flash appropriate message
|
||||||
if int(defect_code) == 0:
|
if int(defect_code) == 0:
|
||||||
@@ -510,8 +499,6 @@ def scan():
|
|||||||
else:
|
else:
|
||||||
flash(f'❌ REJECTED scan recorded for {cp_code} (defect: {defect_code}). Total rejected: {rejected_count}')
|
flash(f'❌ REJECTED scan recorded for {cp_code} (defect: {defect_code}). Total rejected: {rejected_count}')
|
||||||
|
|
||||||
# Commit the transaction
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
except mariadb.Error as e:
|
except mariadb.Error as e:
|
||||||
@@ -566,35 +553,25 @@ def fg_scan():
|
|||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
# Always insert a new entry - each scan is a separate record
|
# Always insert a new entry - each scan is a separate record
|
||||||
|
# Note: The trigger 'increment_approved_quantity_fg' will automatically
|
||||||
|
# update approved_quantity or rejected_quantity for all records with same CP_base_code
|
||||||
insert_query = """
|
insert_query = """
|
||||||
INSERT INTO scanfg_orders (operator_code, CP_full_code, OC1_code, OC2_code, quality_code, date, time)
|
INSERT INTO scanfg_orders (operator_code, CP_full_code, OC1_code, OC2_code, quality_code, date, time)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
||||||
"""
|
"""
|
||||||
cursor.execute(insert_query, (operator_code, cp_code, oc1_code, oc2_code, defect_code, date, time))
|
cursor.execute(insert_query, (operator_code, cp_code, oc1_code, oc2_code, defect_code, date, time))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
# Get the CP_base_code (first 10 characters of CP_full_code)
|
# Get the quantities from the newly inserted row for the flash message
|
||||||
cp_base_code = cp_code[:10]
|
cp_base_code = cp_code[:10]
|
||||||
|
|
||||||
# Count approved quantities (quality_code = 0) for this CP_base_code
|
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT COUNT(*) FROM scanfg_orders
|
SELECT approved_quantity, rejected_quantity
|
||||||
WHERE CP_base_code = %s AND quality_code = 0
|
FROM scanfg_orders
|
||||||
""", (cp_base_code,))
|
WHERE CP_full_code = %s
|
||||||
approved_count = cursor.fetchone()[0]
|
""", (cp_code,))
|
||||||
|
result = cursor.fetchone()
|
||||||
# Count rejected quantities (quality_code != 0) for this CP_base_code
|
approved_count = result[0] if result else 0
|
||||||
cursor.execute("""
|
rejected_count = result[1] if result else 0
|
||||||
SELECT COUNT(*) FROM scanfg_orders
|
|
||||||
WHERE CP_base_code = %s AND quality_code != 0
|
|
||||||
""", (cp_base_code,))
|
|
||||||
rejected_count = cursor.fetchone()[0]
|
|
||||||
|
|
||||||
# Update all records with the same CP_base_code with new quantities
|
|
||||||
cursor.execute("""
|
|
||||||
UPDATE scanfg_orders
|
|
||||||
SET approved_quantity = %s, rejected_quantity = %s
|
|
||||||
WHERE CP_base_code = %s
|
|
||||||
""", (approved_count, rejected_count, cp_base_code))
|
|
||||||
|
|
||||||
# Flash appropriate message
|
# Flash appropriate message
|
||||||
if int(defect_code) == 0:
|
if int(defect_code) == 0:
|
||||||
@@ -602,8 +579,6 @@ def fg_scan():
|
|||||||
else:
|
else:
|
||||||
flash(f'❌ REJECTED scan recorded for {cp_code} (defect: {defect_code}). Total rejected: {rejected_count}')
|
flash(f'❌ REJECTED scan recorded for {cp_code} (defect: {defect_code}). Total rejected: {rejected_count}')
|
||||||
|
|
||||||
# Commit the transaction
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
except mariadb.Error as e:
|
except mariadb.Error as e:
|
||||||
@@ -3628,25 +3603,16 @@ def api_backup_download(filename):
|
|||||||
try:
|
try:
|
||||||
from app.database_backup import DatabaseBackupManager
|
from app.database_backup import DatabaseBackupManager
|
||||||
from flask import send_file
|
from flask import send_file
|
||||||
import os
|
|
||||||
|
|
||||||
backup_manager = DatabaseBackupManager()
|
backup_manager = DatabaseBackupManager()
|
||||||
backup_path = backup_manager.backup_path
|
file_path = backup_manager.get_backup_file_path(filename)
|
||||||
file_path = os.path.join(backup_path, filename)
|
|
||||||
|
|
||||||
# Security: ensure filename doesn't contain path traversal
|
if file_path:
|
||||||
if '..' in filename or '/' in filename:
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'message': 'Invalid filename'
|
|
||||||
}), 400
|
|
||||||
|
|
||||||
if os.path.exists(file_path):
|
|
||||||
return send_file(file_path, as_attachment=True, download_name=filename)
|
return send_file(file_path, as_attachment=True, download_name=filename)
|
||||||
else:
|
else:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'success': False,
|
'success': False,
|
||||||
'message': 'Backup file not found'
|
'message': 'Backup file not found or invalid filename'
|
||||||
}), 404
|
}), 404
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -3677,18 +3643,56 @@ def api_backup_schedule():
|
|||||||
"""Get or save backup schedule configuration"""
|
"""Get or save backup schedule configuration"""
|
||||||
try:
|
try:
|
||||||
from app.database_backup import DatabaseBackupManager
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
from app.backup_scheduler import get_backup_scheduler
|
||||||
|
|
||||||
backup_manager = DatabaseBackupManager()
|
backup_manager = DatabaseBackupManager()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
schedule = request.json
|
schedule = request.json
|
||||||
result = backup_manager.save_backup_schedule(schedule)
|
result = backup_manager.save_backup_schedule(schedule)
|
||||||
|
|
||||||
|
if result['success']:
|
||||||
|
# Reload the scheduler to apply new configuration
|
||||||
|
scheduler = get_backup_scheduler()
|
||||||
|
if scheduler:
|
||||||
|
scheduler.update_schedule()
|
||||||
|
info = scheduler.get_schedule_info()
|
||||||
|
|
||||||
|
if info and info.get('jobs'):
|
||||||
|
jobs = info['jobs']
|
||||||
|
result['message'] += f'. {len(jobs)} active schedule(s)'
|
||||||
|
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
else:
|
else:
|
||||||
schedule = backup_manager.get_backup_schedule()
|
schedule = backup_manager.get_backup_schedule()
|
||||||
|
|
||||||
|
# Auto-migrate legacy format to multi-schedule format
|
||||||
|
if 'schedules' not in schedule:
|
||||||
|
schedule = {
|
||||||
|
'schedules': [{
|
||||||
|
'id': 'default',
|
||||||
|
'name': 'Default Schedule',
|
||||||
|
'enabled': schedule.get('enabled', True),
|
||||||
|
'time': schedule.get('time', '02:00'),
|
||||||
|
'frequency': schedule.get('frequency', 'daily'),
|
||||||
|
'backup_type': schedule.get('backup_type', 'full'),
|
||||||
|
'retention_days': schedule.get('retention_days', 30)
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
# Save migrated format
|
||||||
|
backup_manager.save_backup_schedule(schedule)
|
||||||
|
|
||||||
|
# Get scheduler info with all jobs
|
||||||
|
scheduler = get_backup_scheduler()
|
||||||
|
jobs = []
|
||||||
|
if scheduler:
|
||||||
|
info = scheduler.get_schedule_info()
|
||||||
|
jobs = info.get('jobs', []) if info else []
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'success': True,
|
'success': True,
|
||||||
'schedule': schedule
|
'schedule': schedule,
|
||||||
|
'jobs': jobs
|
||||||
})
|
})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -3718,9 +3722,6 @@ def api_backup_upload():
|
|||||||
"""Upload an external backup file (superadmin only)"""
|
"""Upload an external backup file (superadmin only)"""
|
||||||
try:
|
try:
|
||||||
from app.database_backup import DatabaseBackupManager
|
from app.database_backup import DatabaseBackupManager
|
||||||
from werkzeug.utils import secure_filename
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
# Check if file was uploaded
|
# Check if file was uploaded
|
||||||
if 'backup_file' not in request.files:
|
if 'backup_file' not in request.files:
|
||||||
@@ -3738,79 +3739,302 @@ def api_backup_upload():
|
|||||||
'message': 'No file selected'
|
'message': 'No file selected'
|
||||||
}), 400
|
}), 400
|
||||||
|
|
||||||
# Validate file extension
|
# Use DatabaseBackupManager to handle upload
|
||||||
if not file.filename.lower().endswith('.sql'):
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'message': 'Invalid file format. Only .sql files are allowed.'
|
|
||||||
}), 400
|
|
||||||
|
|
||||||
# Get backup manager and backup path
|
|
||||||
backup_manager = DatabaseBackupManager()
|
backup_manager = DatabaseBackupManager()
|
||||||
backup_path = backup_manager.backup_path
|
result = backup_manager.upload_backup(file)
|
||||||
|
|
||||||
# Ensure backup_path is a Path object
|
# Return appropriate status code
|
||||||
from pathlib import Path
|
status_code = 200 if result['success'] else 400
|
||||||
if not isinstance(backup_path, Path):
|
return jsonify(result), status_code
|
||||||
backup_path = Path(backup_path)
|
|
||||||
|
|
||||||
# Create backup directory if it doesn't exist
|
|
||||||
backup_path.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
# Generate secure filename with timestamp to avoid conflicts
|
|
||||||
original_filename = secure_filename(file.filename)
|
|
||||||
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
|
||||||
|
|
||||||
# If filename already starts with "backup_", keep it; otherwise add prefix
|
|
||||||
if original_filename.startswith('backup_'):
|
|
||||||
new_filename = f"{original_filename.rsplit('.', 1)[0]}_{timestamp}.sql"
|
|
||||||
else:
|
|
||||||
new_filename = f"backup_uploaded_{timestamp}_{original_filename}"
|
|
||||||
|
|
||||||
# Save file to backup directory
|
|
||||||
file_path = backup_path / new_filename
|
|
||||||
file.save(str(file_path))
|
|
||||||
|
|
||||||
# Get file size
|
|
||||||
file_size = file_path.stat().st_size
|
|
||||||
size_mb = round(file_size / (1024 * 1024), 2)
|
|
||||||
|
|
||||||
# Validate the uploaded file for integrity and compatibility
|
|
||||||
validation_result = backup_manager.validate_backup_file(new_filename)
|
|
||||||
|
|
||||||
if not validation_result['success']:
|
|
||||||
# Validation failed - remove the uploaded file
|
|
||||||
file_path.unlink() # Delete the invalid file
|
|
||||||
return jsonify({
|
|
||||||
'success': False,
|
|
||||||
'message': f'Validation failed: {validation_result["message"]}',
|
|
||||||
'validation_details': validation_result.get('details', {}),
|
|
||||||
'warnings': validation_result.get('warnings', [])
|
|
||||||
}), 400
|
|
||||||
|
|
||||||
# Build response with validation details
|
|
||||||
response = {
|
|
||||||
'success': True,
|
|
||||||
'message': 'Backup file uploaded and validated successfully',
|
|
||||||
'filename': new_filename,
|
|
||||||
'size': f'{size_mb} MB',
|
|
||||||
'path': str(file_path),
|
|
||||||
'validation': {
|
|
||||||
'status': 'passed',
|
|
||||||
'message': validation_result['message'],
|
|
||||||
'details': validation_result.get('details', {}),
|
|
||||||
'warnings': validation_result.get('warnings', [])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add warning flag if there are warnings
|
|
||||||
if validation_result.get('warnings'):
|
|
||||||
response['message'] = f'Backup uploaded with warnings: {"; ".join(validation_result["warnings"])}'
|
|
||||||
|
|
||||||
return jsonify(response)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'success': False,
|
'success': False,
|
||||||
'message': f'Upload failed: {str(e)}'
|
'message': f'Upload failed: {str(e)}'
|
||||||
}), 500
|
}), 500
|
||||||
|
|
||||||
|
@bp.route('/api/backup/create-data-only', methods=['POST'])
|
||||||
|
@admin_plus
|
||||||
|
def api_backup_create_data_only():
|
||||||
|
"""Create a data-only backup (no schema, triggers, or structure)"""
|
||||||
|
try:
|
||||||
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
result = backup_manager.create_data_only_backup()
|
||||||
|
|
||||||
|
return jsonify(result)
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Data backup failed: {str(e)}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
@bp.route('/api/backup/restore-data-only/<filename>', methods=['POST'])
|
||||||
|
@superadmin_only
|
||||||
|
def api_backup_restore_data_only(filename):
|
||||||
|
"""Restore data from a data-only backup file (superadmin only)
|
||||||
|
Assumes database schema already exists
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
result = backup_manager.restore_data_only(filename)
|
||||||
|
|
||||||
|
return jsonify(result)
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Data restore failed: {str(e)}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
@bp.route('/api/backup/schedule-info', methods=['GET'])
|
||||||
|
@admin_plus
|
||||||
|
def api_backup_schedule_info():
|
||||||
|
"""Get detailed backup schedule information including next run time"""
|
||||||
|
try:
|
||||||
|
from app.backup_scheduler import get_backup_scheduler
|
||||||
|
|
||||||
|
scheduler = get_backup_scheduler()
|
||||||
|
if not scheduler:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': 'Backup scheduler not initialized'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
info = scheduler.get_schedule_info()
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
|
'info': info
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Failed to get schedule info: {str(e)}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
@bp.route('/api/backup/reload-schedule', methods=['POST'])
|
||||||
|
@admin_plus
|
||||||
|
def api_backup_reload_schedule():
|
||||||
|
"""Reload the backup schedule after configuration changes"""
|
||||||
|
try:
|
||||||
|
from app.backup_scheduler import get_backup_scheduler
|
||||||
|
|
||||||
|
scheduler = get_backup_scheduler()
|
||||||
|
if not scheduler:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': 'Backup scheduler not initialized'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
scheduler.update_schedule()
|
||||||
|
|
||||||
|
info = scheduler.get_schedule_info()
|
||||||
|
next_run = info['next_run_time'] if info else None
|
||||||
|
|
||||||
|
message = 'Backup schedule reloaded successfully'
|
||||||
|
if next_run:
|
||||||
|
message += f'. Next backup: {next_run}'
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
|
'message': message,
|
||||||
|
'next_run_time': next_run
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Failed to reload schedule: {str(e)}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
@bp.route('/api/backup/schedule/toggle/<schedule_id>', methods=['POST'])
|
||||||
|
@admin_plus
|
||||||
|
def api_backup_schedule_toggle(schedule_id):
|
||||||
|
"""Toggle a specific schedule on/off"""
|
||||||
|
try:
|
||||||
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
from app.backup_scheduler import get_backup_scheduler
|
||||||
|
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
schedule_config = backup_manager.get_backup_schedule()
|
||||||
|
|
||||||
|
# Handle new multi-schedule format
|
||||||
|
if isinstance(schedule_config, dict) and 'schedules' in schedule_config:
|
||||||
|
schedules = schedule_config['schedules']
|
||||||
|
|
||||||
|
# Find and toggle the schedule
|
||||||
|
schedule_found = False
|
||||||
|
for schedule in schedules:
|
||||||
|
if schedule.get('id') == schedule_id:
|
||||||
|
schedule['enabled'] = not schedule.get('enabled', False)
|
||||||
|
schedule_found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not schedule_found:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Schedule {schedule_id} not found'
|
||||||
|
}), 404
|
||||||
|
|
||||||
|
# Save updated configuration
|
||||||
|
result = backup_manager.save_backup_schedule(schedule_config)
|
||||||
|
|
||||||
|
if result['success']:
|
||||||
|
# Reload scheduler
|
||||||
|
scheduler = get_backup_scheduler()
|
||||||
|
if scheduler:
|
||||||
|
scheduler.update_schedule()
|
||||||
|
|
||||||
|
enabled_count = sum(1 for s in schedules if s.get('enabled', False))
|
||||||
|
result['message'] = f'Schedule {schedule_id} toggled successfully. {enabled_count} schedule(s) active.'
|
||||||
|
|
||||||
|
return jsonify(result)
|
||||||
|
|
||||||
|
# Handle legacy single schedule format
|
||||||
|
else:
|
||||||
|
schedule_config['enabled'] = not schedule_config.get('enabled', False)
|
||||||
|
result = backup_manager.save_backup_schedule(schedule_config)
|
||||||
|
|
||||||
|
if result['success']:
|
||||||
|
scheduler = get_backup_scheduler()
|
||||||
|
if scheduler:
|
||||||
|
scheduler.update_schedule()
|
||||||
|
|
||||||
|
return jsonify(result)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Failed to toggle schedule: {str(e)}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
@bp.route('/api/backup/schedule/delete/<schedule_id>', methods=['DELETE'])
|
||||||
|
@admin_plus
|
||||||
|
def api_backup_schedule_delete(schedule_id):
|
||||||
|
"""Delete a specific schedule"""
|
||||||
|
try:
|
||||||
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
from app.backup_scheduler import get_backup_scheduler
|
||||||
|
|
||||||
|
# Don't allow deleting the default schedule
|
||||||
|
if schedule_id == 'default':
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': 'Cannot delete the default schedule'
|
||||||
|
}), 400
|
||||||
|
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
schedule_config = backup_manager.get_backup_schedule()
|
||||||
|
|
||||||
|
if isinstance(schedule_config, dict) and 'schedules' in schedule_config:
|
||||||
|
schedules = schedule_config['schedules']
|
||||||
|
|
||||||
|
# Remove the schedule
|
||||||
|
new_schedules = [s for s in schedules if s.get('id') != schedule_id]
|
||||||
|
|
||||||
|
if len(new_schedules) == len(schedules):
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Schedule {schedule_id} not found'
|
||||||
|
}), 404
|
||||||
|
|
||||||
|
schedule_config['schedules'] = new_schedules
|
||||||
|
result = backup_manager.save_backup_schedule(schedule_config)
|
||||||
|
|
||||||
|
if result['success']:
|
||||||
|
# Reload scheduler
|
||||||
|
scheduler = get_backup_scheduler()
|
||||||
|
if scheduler:
|
||||||
|
scheduler.update_schedule()
|
||||||
|
|
||||||
|
result['message'] = f'Schedule {schedule_id} deleted successfully'
|
||||||
|
|
||||||
|
return jsonify(result)
|
||||||
|
else:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': 'Multi-schedule format not enabled'
|
||||||
|
}), 400
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Failed to delete schedule: {str(e)}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
@bp.route('/api/backup/schedule/add', methods=['POST'])
|
||||||
|
@admin_plus
|
||||||
|
def api_backup_schedule_add():
|
||||||
|
"""Add a new schedule"""
|
||||||
|
try:
|
||||||
|
from app.database_backup import DatabaseBackupManager
|
||||||
|
from app.backup_scheduler import get_backup_scheduler
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
new_schedule = request.json
|
||||||
|
|
||||||
|
# Validate required fields
|
||||||
|
required_fields = ['time', 'frequency', 'backup_type', 'retention_days']
|
||||||
|
for field in required_fields:
|
||||||
|
if field not in new_schedule:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Missing required field: {field}'
|
||||||
|
}), 400
|
||||||
|
|
||||||
|
backup_manager = DatabaseBackupManager()
|
||||||
|
schedule_config = backup_manager.get_backup_schedule()
|
||||||
|
|
||||||
|
# Migrate to multi-schedule format if needed
|
||||||
|
if 'schedules' not in schedule_config:
|
||||||
|
# Convert legacy format to multi-schedule
|
||||||
|
schedule_config = {
|
||||||
|
'schedules': [{
|
||||||
|
'id': 'default',
|
||||||
|
'name': 'Default Schedule',
|
||||||
|
'enabled': schedule_config.get('enabled', True),
|
||||||
|
'time': schedule_config.get('time', '02:00'),
|
||||||
|
'frequency': schedule_config.get('frequency', 'daily'),
|
||||||
|
'backup_type': schedule_config.get('backup_type', 'full'),
|
||||||
|
'retention_days': schedule_config.get('retention_days', 30)
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate unique ID
|
||||||
|
schedule_id = new_schedule.get('id') or str(uuid.uuid4())[:8]
|
||||||
|
|
||||||
|
# Add new schedule
|
||||||
|
new_schedule_entry = {
|
||||||
|
'id': schedule_id,
|
||||||
|
'name': new_schedule.get('name', f'Schedule {schedule_id}'),
|
||||||
|
'enabled': new_schedule.get('enabled', True),
|
||||||
|
'time': new_schedule['time'],
|
||||||
|
'frequency': new_schedule['frequency'],
|
||||||
|
'backup_type': new_schedule['backup_type'],
|
||||||
|
'retention_days': int(new_schedule['retention_days'])
|
||||||
|
}
|
||||||
|
|
||||||
|
schedule_config['schedules'].append(new_schedule_entry)
|
||||||
|
|
||||||
|
# Save configuration
|
||||||
|
result = backup_manager.save_backup_schedule(schedule_config)
|
||||||
|
|
||||||
|
if result['success']:
|
||||||
|
# Reload scheduler
|
||||||
|
scheduler = get_backup_scheduler()
|
||||||
|
if scheduler:
|
||||||
|
scheduler.update_schedule()
|
||||||
|
|
||||||
|
result['message'] = f'Schedule {schedule_id} added successfully'
|
||||||
|
result['schedule_id'] = schedule_id
|
||||||
|
|
||||||
|
return jsonify(result)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({
|
||||||
|
'success': False,
|
||||||
|
'message': f'Failed to add schedule: {str(e)}'
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,4 +7,5 @@ mariadb
|
|||||||
reportlab
|
reportlab
|
||||||
requests
|
requests
|
||||||
pandas
|
pandas
|
||||||
openpyxl
|
openpyxl
|
||||||
|
APScheduler
|
||||||
@@ -1 +1 @@
|
|||||||
402172
|
417124
|
||||||
|
|||||||
Reference in New Issue
Block a user