Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,8 +2,6 @@ from flask import render_template, request, flash, redirect, url_for
|
||||
from flask_login import login_user, logout_user, login_required, current_user
|
||||
from models import db, User
|
||||
from functools import wraps
|
||||
from utils.event_logger import log_event
|
||||
from models import EventType
|
||||
|
||||
def require_password_change(f):
|
||||
@wraps(f)
|
||||
@@ -33,13 +31,6 @@ def init_routes(auth_bp):
|
||||
|
||||
login_user(user, remember=remember)
|
||||
|
||||
# Log successful login
|
||||
log_event(
|
||||
event_type=EventType.USER_LOGIN,
|
||||
user_id=user.id,
|
||||
details={'remember': remember}
|
||||
)
|
||||
|
||||
# Check if user is using default password
|
||||
if password == 'changeme':
|
||||
flash('Please change your password before continuing.', 'warning')
|
||||
@@ -78,13 +69,6 @@ def init_routes(auth_bp):
|
||||
db.session.add(new_user)
|
||||
db.session.commit()
|
||||
|
||||
# Log user creation
|
||||
log_event(
|
||||
event_type=EventType.USER_CREATE,
|
||||
user_id=new_user.id,
|
||||
details={'email': email, 'username': username}
|
||||
)
|
||||
|
||||
login_user(new_user)
|
||||
return redirect(url_for('main.dashboard'))
|
||||
|
||||
@@ -93,11 +77,6 @@ def init_routes(auth_bp):
|
||||
@auth_bp.route('/logout')
|
||||
@login_required
|
||||
def logout():
|
||||
# Log logout before actually logging out
|
||||
log_event(
|
||||
event_type=EventType.USER_LOGOUT,
|
||||
user_id=current_user.id
|
||||
)
|
||||
logout_user()
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
@@ -119,14 +98,6 @@ def init_routes(auth_bp):
|
||||
|
||||
current_user.set_password(new_password)
|
||||
db.session.commit()
|
||||
|
||||
# Log password change
|
||||
log_event(
|
||||
event_type=EventType.USER_UPDATE,
|
||||
user_id=current_user.id,
|
||||
details={'action': 'password_change'}
|
||||
)
|
||||
|
||||
flash('Password changed successfully!', 'success')
|
||||
return redirect(url_for('main.dashboard'))
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, send_file
|
||||
from flask_login import login_required, current_user
|
||||
from models import db, Conversation, User, Message, MessageAttachment, EventType
|
||||
from models import db, Conversation, User, Message, MessageAttachment
|
||||
from forms import ConversationForm
|
||||
from routes.auth import require_password_change
|
||||
from utils.event_logger import log_event
|
||||
import os
|
||||
from werkzeug.utils import secure_filename
|
||||
from datetime import datetime
|
||||
@@ -85,17 +84,6 @@ def create_conversation():
|
||||
db.session.add(conversation)
|
||||
db.session.commit()
|
||||
|
||||
# Log conversation creation
|
||||
log_event(
|
||||
event_type=EventType.CONVERSATION_CREATE,
|
||||
user_id=current_user.id,
|
||||
details={
|
||||
'conversation_id': conversation.id,
|
||||
'conversation_name': conversation.name,
|
||||
'member_count': len(conversation.members)
|
||||
}
|
||||
)
|
||||
|
||||
flash('Conversation created successfully!', 'success')
|
||||
return redirect(url_for('conversations.conversations'))
|
||||
return render_template('conversations/create_conversation.html', form=form)
|
||||
@@ -239,18 +227,6 @@ def delete_conversation(conversation_id):
|
||||
|
||||
conversation = Conversation.query.get_or_404(conversation_id)
|
||||
|
||||
# Log conversation deletion before deleting
|
||||
log_event(
|
||||
event_type=EventType.CONVERSATION_DELETE,
|
||||
user_id=current_user.id,
|
||||
details={
|
||||
'conversation_id': conversation_id,
|
||||
'conversation_name': conversation.name,
|
||||
'message_count': len(conversation.messages),
|
||||
'member_count': len(conversation.members)
|
||||
}
|
||||
)
|
||||
|
||||
# Delete all messages in the conversation
|
||||
Message.query.filter_by(conversation_id=conversation_id).delete()
|
||||
|
||||
@@ -348,18 +324,6 @@ def send_message(conversation_id):
|
||||
|
||||
db.session.commit()
|
||||
|
||||
# Log message sent
|
||||
log_event(
|
||||
event_type=EventType.MESSAGE_SENT,
|
||||
user_id=current_user.id,
|
||||
details={
|
||||
'conversation_id': conversation_id,
|
||||
'message_id': message.id,
|
||||
'has_attachments': len(attachments) > 0,
|
||||
'attachment_count': len(attachments)
|
||||
}
|
||||
)
|
||||
|
||||
# Prepare message data for response
|
||||
message_data = {
|
||||
'id': message.id,
|
||||
@@ -394,19 +358,6 @@ def download_attachment(message_id, attachment_index):
|
||||
|
||||
try:
|
||||
attachment = message.attachments[attachment_index]
|
||||
|
||||
# Log attachment download
|
||||
log_event(
|
||||
event_type=EventType.ATTACHMENT_DOWNLOAD,
|
||||
user_id=current_user.id,
|
||||
details={
|
||||
'conversation_id': conversation.id,
|
||||
'message_id': message_id,
|
||||
'attachment_name': attachment.name,
|
||||
'attachment_size': attachment.size
|
||||
}
|
||||
)
|
||||
|
||||
return send_file(
|
||||
attachment.path,
|
||||
as_attachment=True,
|
||||
|
||||
171
routes/main.py
171
routes/main.py
@@ -1,8 +1,7 @@
|
||||
from flask import render_template, Blueprint, redirect, url_for, request, flash, Response, jsonify
|
||||
from flask import render_template, Blueprint, redirect, url_for, request, flash, Response
|
||||
from flask_login import current_user, login_required
|
||||
from models import User, db, Room, RoomFile, RoomMemberPermission, SiteSettings, Event, EventType
|
||||
from models import User, db, Room, RoomFile, RoomMemberPermission, SiteSettings
|
||||
from routes.auth import require_password_change
|
||||
from utils.event_logger import log_event
|
||||
import os
|
||||
from werkzeug.utils import secure_filename
|
||||
from sqlalchemy import func, case, literal_column, text
|
||||
@@ -280,14 +279,6 @@ def init_routes(main_bp):
|
||||
os.remove(old_picture_path)
|
||||
current_user.profile_picture = None
|
||||
db.session.commit()
|
||||
|
||||
# Log profile picture removal
|
||||
log_event(
|
||||
event_type=EventType.USER_UPDATE,
|
||||
user_id=current_user.id,
|
||||
details={'action': 'remove_profile_picture'}
|
||||
)
|
||||
|
||||
flash('Profile picture removed successfully!', 'success')
|
||||
return redirect(url_for('main.profile'))
|
||||
|
||||
@@ -298,10 +289,6 @@ def init_routes(main_bp):
|
||||
if existing_user:
|
||||
flash('A user with this email already exists.', 'error')
|
||||
return render_template('profile/profile.html')
|
||||
|
||||
# Track changes for event logging
|
||||
changes = {}
|
||||
|
||||
# Handle profile picture upload
|
||||
file = request.files.get('profile_picture')
|
||||
if file and file.filename:
|
||||
@@ -309,31 +296,14 @@ def init_routes(main_bp):
|
||||
file_path = os.path.join(UPLOAD_FOLDER, filename)
|
||||
file.save(file_path)
|
||||
current_user.profile_picture = filename
|
||||
changes['profile_picture'] = True
|
||||
|
||||
# Update user information
|
||||
if current_user.username != request.form.get('first_name'):
|
||||
current_user.username = request.form.get('first_name')
|
||||
changes['username'] = True
|
||||
if current_user.last_name != request.form.get('last_name'):
|
||||
current_user.last_name = request.form.get('last_name')
|
||||
changes['last_name'] = True
|
||||
if current_user.email != new_email:
|
||||
current_user.email = new_email
|
||||
changes['email'] = True
|
||||
if current_user.phone != request.form.get('phone'):
|
||||
current_user.phone = request.form.get('phone')
|
||||
changes['phone'] = True
|
||||
if current_user.company != request.form.get('company'):
|
||||
current_user.company = request.form.get('company')
|
||||
changes['company'] = True
|
||||
if current_user.position != request.form.get('position'):
|
||||
current_user.position = request.form.get('position')
|
||||
changes['position'] = True
|
||||
if current_user.notes != request.form.get('notes'):
|
||||
current_user.notes = request.form.get('notes')
|
||||
changes['notes'] = True
|
||||
|
||||
current_user.username = request.form.get('first_name')
|
||||
current_user.last_name = request.form.get('last_name')
|
||||
current_user.email = new_email
|
||||
current_user.phone = request.form.get('phone')
|
||||
current_user.company = request.form.get('company')
|
||||
current_user.position = request.form.get('position')
|
||||
current_user.notes = request.form.get('notes')
|
||||
# Handle password change if provided
|
||||
new_password = request.form.get('new_password')
|
||||
confirm_password = request.form.get('confirm_password')
|
||||
@@ -342,20 +312,9 @@ def init_routes(main_bp):
|
||||
flash('Passwords do not match.', 'error')
|
||||
return render_template('profile/profile.html')
|
||||
current_user.set_password(new_password)
|
||||
changes['password'] = True
|
||||
flash('Password updated successfully.', 'success')
|
||||
|
||||
try:
|
||||
db.session.commit()
|
||||
|
||||
# Log profile update if any changes were made
|
||||
if changes:
|
||||
log_event(
|
||||
event_type=EventType.USER_UPDATE,
|
||||
user_id=current_user.id,
|
||||
details={'changes': changes}
|
||||
)
|
||||
|
||||
flash('Profile updated successfully!', 'success')
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
@@ -396,18 +355,11 @@ def init_routes(main_bp):
|
||||
|
||||
site_settings = SiteSettings.get_settings()
|
||||
active_tab = request.args.get('tab', 'colors')
|
||||
|
||||
# Get events for the events tab
|
||||
events = []
|
||||
if active_tab == 'events':
|
||||
events = Event.query.order_by(Event.timestamp.desc()).limit(50).all()
|
||||
|
||||
return render_template('settings/settings.html',
|
||||
primary_color=site_settings.primary_color,
|
||||
secondary_color=site_settings.secondary_color,
|
||||
active_tab=active_tab,
|
||||
site_settings=site_settings,
|
||||
events=events)
|
||||
site_settings=site_settings)
|
||||
|
||||
@main_bp.route('/settings/colors', methods=['POST'])
|
||||
@login_required
|
||||
@@ -578,105 +530,4 @@ def init_routes(main_bp):
|
||||
logger.info(f"[Dynamic Colors] Generated CSS with primary color: {primary_color}")
|
||||
logger.info(f"[Dynamic Colors] Cache version: {site_settings.updated_at.timestamp()}")
|
||||
|
||||
return Response(css, mimetype='text/css')
|
||||
|
||||
@main_bp.route('/api/events')
|
||||
@login_required
|
||||
def get_events():
|
||||
if not current_user.is_admin:
|
||||
return jsonify({'success': False, 'error': 'Unauthorized'}), 403
|
||||
|
||||
# Get filter parameters
|
||||
page = request.args.get('page', 1, type=int)
|
||||
event_type = request.args.get('eventType')
|
||||
date_range = request.args.get('dateRange', '24h')
|
||||
user_id = request.args.get('userId')
|
||||
|
||||
# Build query
|
||||
query = Event.query
|
||||
|
||||
# Apply filters
|
||||
if event_type:
|
||||
query = query.filter_by(event_type=event_type)
|
||||
if user_id:
|
||||
query = query.filter_by(user_id=user_id)
|
||||
|
||||
# Apply date range filter
|
||||
if date_range != 'all':
|
||||
now = datetime.utcnow()
|
||||
if date_range == '24h':
|
||||
start_date = now - timedelta(days=1)
|
||||
elif date_range == '7d':
|
||||
start_date = now - timedelta(days=7)
|
||||
elif date_range == '30d':
|
||||
start_date = now - timedelta(days=30)
|
||||
query = query.filter(Event.timestamp >= start_date)
|
||||
|
||||
# Get total count for pagination
|
||||
total_count = query.count()
|
||||
per_page = 50
|
||||
total_pages = (total_count + per_page - 1) // per_page
|
||||
|
||||
# Get paginated results
|
||||
events = query.order_by(Event.timestamp.desc())\
|
||||
.offset((page - 1) * per_page)\
|
||||
.limit(per_page)\
|
||||
.all()
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'events': [{
|
||||
'id': event.id,
|
||||
'event_type': event.event_type,
|
||||
'timestamp': event.timestamp.isoformat(),
|
||||
'user': {
|
||||
'id': event.user.id,
|
||||
'username': event.user.username,
|
||||
'last_name': event.user.last_name or ''
|
||||
},
|
||||
'ip_address': event.ip_address,
|
||||
'details': event.details
|
||||
} for event in events],
|
||||
'total_pages': total_pages
|
||||
})
|
||||
|
||||
@main_bp.route('/api/events/<int:event_id>')
|
||||
@login_required
|
||||
def get_event_details(event_id):
|
||||
if not current_user.is_admin:
|
||||
return jsonify({'success': False, 'error': 'Unauthorized'}), 403
|
||||
|
||||
event = Event.query.get_or_404(event_id)
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'event': {
|
||||
'id': event.id,
|
||||
'event_type': event.event_type,
|
||||
'timestamp': event.timestamp.isoformat(),
|
||||
'user': {
|
||||
'id': event.user.id,
|
||||
'username': event.user.username
|
||||
},
|
||||
'ip_address': event.ip_address,
|
||||
'user_agent': event.user_agent,
|
||||
'details': event.details
|
||||
}
|
||||
})
|
||||
|
||||
@main_bp.route('/api/users')
|
||||
@login_required
|
||||
def get_users():
|
||||
if not current_user.is_admin:
|
||||
return jsonify({'success': False, 'error': 'Unauthorized'}), 403
|
||||
|
||||
users = User.query.order_by(User.username).all()
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'users': [{
|
||||
'id': user.id,
|
||||
'username': user.username,
|
||||
'last_name': user.last_name or ''
|
||||
} for user in users]
|
||||
})
|
||||
return Response(css, mimetype='text/css')
|
||||
Reference in New Issue
Block a user