Exception handling for database commit operations
This commit is contained in:
		@@ -5,6 +5,7 @@ from ..tools.logs import write
 | 
				
			|||||||
from flask import flash
 | 
					from flask import flash
 | 
				
			||||||
from flask import current_app as app
 | 
					from flask import current_app as app
 | 
				
			||||||
from flask_login import current_user
 | 
					from flask_login import current_user
 | 
				
			||||||
 | 
					from sqlalchemy.exc import SQLAlchemyError
 | 
				
			||||||
from werkzeug.utils import secure_filename
 | 
					from werkzeug.utils import secure_filename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
@@ -45,7 +46,12 @@ class Dataset(db.Model):
 | 
				
			|||||||
        for dataset in Dataset.query.all():
 | 
					        for dataset in Dataset.query.all():
 | 
				
			||||||
            dataset.default = False
 | 
					            dataset.default = False
 | 
				
			||||||
        self.default = True
 | 
					        self.default = True
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when setting default dataset {self.id}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error {exception}.'
 | 
				
			||||||
        write('system.log', f'Dataset {self.id} set as default by {current_user.get_username()}.')
 | 
					        write('system.log', f'Dataset {self.id} set as default by {current_user.get_username()}.')
 | 
				
			||||||
        flash(message='Dataset set as default.', category='success')
 | 
					        flash(message='Dataset set as default.', category='success')
 | 
				
			||||||
        return True, f'Dataset set as default.'
 | 
					        return True, f'Dataset set as default.'
 | 
				
			||||||
@@ -63,9 +69,14 @@ class Dataset(db.Model):
 | 
				
			|||||||
        filename = secure_filename('.'.join([self.id,'json']))
 | 
					        filename = secure_filename('.'.join([self.id,'json']))
 | 
				
			||||||
        data = Path(app.config.get('DATA'))
 | 
					        data = Path(app.config.get('DATA'))
 | 
				
			||||||
        file_path = path.join(data, 'questions', filename)
 | 
					        file_path = path.join(data, 'questions', filename)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.delete(self)
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when trying to delete dataset {self.id}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        remove(file_path)
 | 
					        remove(file_path)
 | 
				
			||||||
        db.session.delete(self)
 | 
					 | 
				
			||||||
        db.session.commit()
 | 
					 | 
				
			||||||
        return True, 'Dataset deleted.'
 | 
					        return True, 'Dataset deleted.'
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def create(self, data:list, default:bool=False):
 | 
					    def create(self, data:list, default:bool=False):
 | 
				
			||||||
@@ -78,8 +89,13 @@ class Dataset(db.Model):
 | 
				
			|||||||
        self.creator = current_user
 | 
					        self.creator = current_user
 | 
				
			||||||
        if default: self.make_default()
 | 
					        if default: self.make_default()
 | 
				
			||||||
        write('system.log', f'New dataset {self.get_name()} added by {current_user.get_username()}.')
 | 
					        write('system.log', f'New dataset {self.get_name()} added by {current_user.get_username()}.')
 | 
				
			||||||
        db.session.add(self)
 | 
					        try:
 | 
				
			||||||
        db.session.commit()
 | 
					            db.session.add(self)
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when trying to crreate dataset {self.id}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        return True, 'Dataset created.'
 | 
					        return True, 'Dataset created.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def check_file(self):
 | 
					    def check_file(self):
 | 
				
			||||||
@@ -103,6 +119,11 @@ class Dataset(db.Model):
 | 
				
			|||||||
            dump(data, file, indent=2)
 | 
					            dump(data, file, indent=2)
 | 
				
			||||||
        write('system.log', f'Dataset {self.id} edited by {current_user.get_username()}.')
 | 
					        write('system.log', f'Dataset {self.id} edited by {current_user.get_username()}.')
 | 
				
			||||||
        flash(f'Dataset {self.get_name()} successfully edited.', 'success')
 | 
					        flash(f'Dataset {self.get_name()} successfully edited.', 'success')
 | 
				
			||||||
        db.session.add(self)
 | 
					        try:
 | 
				
			||||||
        db.session.commit()
 | 
					            db.session.add(self)
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when trying to update dataset {self.id}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        return True, 'Dataset successfully edited.'
 | 
					        return True, 'Dataset successfully edited.'
 | 
				
			||||||
@@ -7,6 +7,7 @@ from .test import Test
 | 
				
			|||||||
from flask_login import current_user
 | 
					from flask_login import current_user
 | 
				
			||||||
from flask_mail import Message
 | 
					from flask_mail import Message
 | 
				
			||||||
from smtplib import SMTPException
 | 
					from smtplib import SMTPException
 | 
				
			||||||
 | 
					from sqlalchemy.exc import SQLAlchemyError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from datetime import datetime, timedelta
 | 
					from datetime import datetime, timedelta
 | 
				
			||||||
from uuid import uuid4
 | 
					from uuid import uuid4
 | 
				
			||||||
@@ -70,23 +71,32 @@ class Entry(db.Model):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def ready(self):
 | 
					    def ready(self):
 | 
				
			||||||
        self.generate_id()
 | 
					        self.generate_id()
 | 
				
			||||||
        db.session.add(self)
 | 
					        try:
 | 
				
			||||||
        db.session.commit()
 | 
					            db.session.add(self)
 | 
				
			||||||
        write('tests.log', f'New test ready for {self.get_first_name()} {self.get_surname()}.')
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when preparing new entry for {self.get_surname()}, {self.get_first_name()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
 | 
					        write('tests.log', f'New test ready for {self.get_surname()}, {self.get_first_name()} with id {self.id}.')
 | 
				
			||||||
        return True, f'Test ready.'
 | 
					        return True, f'Test ready.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def start(self):
 | 
					    def start(self):
 | 
				
			||||||
        self.start_time = datetime.now()
 | 
					        self.start_time = datetime.now()
 | 
				
			||||||
        self.status = 'started'
 | 
					        self.status = 'started'
 | 
				
			||||||
        write('tests.log', f'Test started by {self.get_first_name()} {self.get_surname()}.')
 | 
					        try:
 | 
				
			||||||
        db.session.commit()
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when starting test for {self.get_surname()}, {self.get_first_name()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
 | 
					        write('tests.log', f'Test started by {self.get_surname()}, {self.get_first_name()} with id {self.id}.')
 | 
				
			||||||
        return True, f'New test started with id {self.id}.'
 | 
					        return True, f'New test started with id {self.id}.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def complete(self, answers:dict=None, result:dict=None):
 | 
					    def complete(self, answers:dict=None, result:dict=None):
 | 
				
			||||||
        self.end_time = datetime.now()
 | 
					        self.end_time = datetime.now()
 | 
				
			||||||
        self.answers = answers
 | 
					        self.answers = answers
 | 
				
			||||||
        self.result = result
 | 
					        self.result = result
 | 
				
			||||||
        write('tests.log', f'Test completed by {self.get_first_name()} {self.get_surname()}.')
 | 
					 | 
				
			||||||
        delta = timedelta(minutes=int(0 if self.test.time_limit is None else self.test.time_limit)+1)
 | 
					        delta = timedelta(minutes=int(0 if self.test.time_limit is None else self.test.time_limit)+1)
 | 
				
			||||||
        if not self.test.time_limit or self.end_time <= self.start_time + delta:
 | 
					        if not self.test.time_limit or self.end_time <= self.start_time + delta:
 | 
				
			||||||
            self.status = 'completed'
 | 
					            self.status = 'completed'
 | 
				
			||||||
@@ -94,7 +104,13 @@ class Entry(db.Model):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.status = 'late'
 | 
					            self.status = 'late'
 | 
				
			||||||
            self.valid = False
 | 
					            self.valid = False
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when submitting entry for {self.get_surname()}, {self.get_first_name()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
 | 
					        write('tests.log', f'Test completed by {self.get_surname()}, {self.get_first_name()} with id {self.id}.')
 | 
				
			||||||
        return True, f'Test entry completed for id {self.id}.'
 | 
					        return True, f'Test entry completed for id {self.id}.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def validate(self):
 | 
					    def validate(self):
 | 
				
			||||||
@@ -102,15 +118,25 @@ class Entry(db.Model):
 | 
				
			|||||||
        if self.status == 'started': return False, 'The entry is still pending.'
 | 
					        if self.status == 'started': return False, 'The entry is still pending.'
 | 
				
			||||||
        self.valid = True
 | 
					        self.valid = True
 | 
				
			||||||
        self.status = 'completed'
 | 
					        self.status = 'completed'
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when validating entry {self.id}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        write('system.log', f'The entry {self.id} has been validated by {current_user.get_username()}.')
 | 
					        write('system.log', f'The entry {self.id} has been validated by {current_user.get_username()}.')
 | 
				
			||||||
        return True, f'The entry {self.id} has been validated.'
 | 
					        return True, f'The entry {self.id} has been validated.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def delete(self):
 | 
					    def delete(self):
 | 
				
			||||||
        id = self.id
 | 
					        id = self.id
 | 
				
			||||||
        name = f'{self.get_first_name()} {self.get_surname()}'
 | 
					        name = f'{self.get_first_name()} {self.get_surname()}'
 | 
				
			||||||
        db.session.delete(self)
 | 
					        try:
 | 
				
			||||||
        db.session.commit()
 | 
					            db.session.delete(self)
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when deleting entry {id}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        write('system.log', f'The entry {id} by {name} has been deleted by {current_user.get_username()}.')
 | 
					        write('system.log', f'The entry {id} by {name} has been deleted by {current_user.get_username()}.')
 | 
				
			||||||
        return True, 'Entry deleted.'
 | 
					        return True, 'Entry deleted.'
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ from ..tools.forms import JsonEncodedDict
 | 
				
			|||||||
from ..tools.logs import write
 | 
					from ..tools.logs import write
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from flask_login import current_user
 | 
					from flask_login import current_user
 | 
				
			||||||
 | 
					from sqlalchemy.exc import SQLAlchemyError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from datetime import date, datetime
 | 
					from datetime import date, datetime
 | 
				
			||||||
import secrets
 | 
					import secrets
 | 
				
			||||||
@@ -52,15 +53,25 @@ class Test(db.Model):
 | 
				
			|||||||
            errors.append('The expiry date cannot be before the start date.')
 | 
					            errors.append('The expiry date cannot be before the start date.')
 | 
				
			||||||
        if errors:
 | 
					        if errors:
 | 
				
			||||||
            return False, errors
 | 
					            return False, errors
 | 
				
			||||||
        db.session.add(self)
 | 
					        try:
 | 
				
			||||||
        db.session.commit()
 | 
					            db.session.add(self)
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when creating test {self.get_code()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        write('system.log', f'Test with code {self.get_code()} created by {current_user.get_username()}.')
 | 
					        write('system.log', f'Test with code {self.get_code()} created by {current_user.get_username()}.')
 | 
				
			||||||
        return True, f'Test with code {self.get_code()} has been created.'
 | 
					        return True, f'Test with code {self.get_code()} has been created.'
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def delete(self):
 | 
					    def delete(self):
 | 
				
			||||||
        if self.entries: return False, f'Cannot delete a test with submitted entries.'
 | 
					        if self.entries: return False, f'Cannot delete a test with submitted entries.'
 | 
				
			||||||
        db.session.delete(self)
 | 
					        db.session.delete(self)
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when deleting test {self.get_code()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        write('system.log', f'Test with code {self.get_code()} has been deleted by {current_user.get_username()}.')
 | 
					        write('system.log', f'Test with code {self.get_code()} has been deleted by {current_user.get_username()}.')
 | 
				
			||||||
        return True, f'Test with code {self.get_code()} has been deleted.'
 | 
					        return True, f'Test with code {self.get_code()} has been deleted.'
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -68,7 +79,12 @@ class Test(db.Model):
 | 
				
			|||||||
        now = datetime.now()
 | 
					        now = datetime.now()
 | 
				
			||||||
        if self.start_date.date() > now.date():
 | 
					        if self.start_date.date() > now.date():
 | 
				
			||||||
            self.start_date = now
 | 
					            self.start_date = now
 | 
				
			||||||
            db.session.commit()
 | 
					            try:
 | 
				
			||||||
 | 
					                db.session.commit()
 | 
				
			||||||
 | 
					            except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					                db.session.rollback()
 | 
				
			||||||
 | 
					                write('system.log', f'Database error when launching test {self.get_code()}: {exception}')
 | 
				
			||||||
 | 
					                return False, f'Database error: {exception}'
 | 
				
			||||||
            write('system.log', f'Test with code {self.get_code()} has been started by {current_user.get_username()}.')
 | 
					            write('system.log', f'Test with code {self.get_code()} has been started by {current_user.get_username()}.')
 | 
				
			||||||
            return True,  f'Test with code {self.get_code()} has been started.'
 | 
					            return True,  f'Test with code {self.get_code()} has been started.'
 | 
				
			||||||
        return False, f'Test with code {self.get_code()} has already started.'
 | 
					        return False, f'Test with code {self.get_code()} has already started.'
 | 
				
			||||||
@@ -77,7 +93,12 @@ class Test(db.Model):
 | 
				
			|||||||
        now = datetime.now()
 | 
					        now = datetime.now()
 | 
				
			||||||
        if self.end_date >= now:
 | 
					        if self.end_date >= now:
 | 
				
			||||||
            self.end_date = now
 | 
					            self.end_date = now
 | 
				
			||||||
            db.session.commit()
 | 
					            try:
 | 
				
			||||||
 | 
					                db.session.commit()
 | 
				
			||||||
 | 
					            except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					                db.session.rollback()
 | 
				
			||||||
 | 
					                write('system.log', f'Database error when closing test {self.get_code()}: {exception}')
 | 
				
			||||||
 | 
					                return False, f'Database error: {exception}'
 | 
				
			||||||
            write('system.log', f'Test with code {self.get_code()} ended by {current_user.get_username()}.')
 | 
					            write('system.log', f'Test with code {self.get_code()} ended by {current_user.get_username()}.')
 | 
				
			||||||
            return True, f'Test with code {self.get_code()} has been ended.'
 | 
					            return True, f'Test with code {self.get_code()} has been ended.'
 | 
				
			||||||
        return False, f'Test with code {self.get_code()} has already ended.'
 | 
					        return False, f'Test with code {self.get_code()} has already ended.'
 | 
				
			||||||
@@ -87,7 +108,12 @@ class Test(db.Model):
 | 
				
			|||||||
        code = secrets.token_hex(3).lower()
 | 
					        code = secrets.token_hex(3).lower()
 | 
				
			||||||
        adjustments[code] = time
 | 
					        adjustments[code] = time
 | 
				
			||||||
        self.adjustments = adjustments
 | 
					        self.adjustments = adjustments
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when adding adjustment to test {self.get_code()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        write('system.log', f'Time adjustment for {time} minutes with code {code} added to test {self.get_code()} by {current_user.get_username()}.')
 | 
					        write('system.log', f'Time adjustment for {time} minutes with code {code} added to test {self.get_code()} by {current_user.get_username()}.')
 | 
				
			||||||
        return True, f'Time adjustment for {time} minutes added to test {self.get_code()}. This can be accessed using the user code {code.upper()}.'
 | 
					        return True, f'Time adjustment for {time} minutes added to test {self.get_code()}. This can be accessed using the user code {code.upper()}.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -95,7 +121,12 @@ class Test(db.Model):
 | 
				
			|||||||
        if not self.adjustments: return False, f'There are no adjustments configured for test {self.get_code()}.'
 | 
					        if not self.adjustments: return False, f'There are no adjustments configured for test {self.get_code()}.'
 | 
				
			||||||
        self.adjustments.pop(code)
 | 
					        self.adjustments.pop(code)
 | 
				
			||||||
        if not self.adjustments: self.adjustments = None
 | 
					        if not self.adjustments: self.adjustments = None
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when deleting adjustment from test {self.get_code()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        write('system.log', f'Time adjustment for with code {code} has been removed from test {self.get_code()} by {current_user.get_username()}.')
 | 
					        write('system.log', f'Time adjustment for with code {code} has been removed from test {self.get_code()} by {current_user.get_username()}.')
 | 
				
			||||||
        return True, f'Time adjustment for with code {code} has been removed from test {self.get_code()}.'
 | 
					        return True, f'Time adjustment for with code {code} has been removed from test {self.get_code()}.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -104,6 +135,11 @@ class Test(db.Model):
 | 
				
			|||||||
        if start_date: self.start_date = start_date
 | 
					        if start_date: self.start_date = start_date
 | 
				
			||||||
        if end_date: self.end_date = end_date
 | 
					        if end_date: self.end_date = end_date
 | 
				
			||||||
        if time_limit is not None: self.time_limit = time_limit
 | 
					        if time_limit is not None: self.time_limit = time_limit
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when updating test {self.get_code()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        write('system.log', f'Test with code {self.get_code()} has been updated by user {current_user.get_username()}.')
 | 
					        write('system.log', f'Test with code {self.get_code()} has been updated by user {current_user.get_username()}.')
 | 
				
			||||||
        return True, f'Test with code {self.get_code()} has been updated by.'
 | 
					        return True, f'Test with code {self.get_code()} has been updated by.'
 | 
				
			||||||
@@ -7,6 +7,7 @@ from flask.helpers import url_for
 | 
				
			|||||||
from flask_login import current_user, login_user, logout_user, UserMixin
 | 
					from flask_login import current_user, login_user, logout_user, UserMixin
 | 
				
			||||||
from flask_mail import Message
 | 
					from flask_mail import Message
 | 
				
			||||||
from smtplib import SMTPException
 | 
					from smtplib import SMTPException
 | 
				
			||||||
 | 
					from sqlalchemy.exc import SQLAlchemyError
 | 
				
			||||||
from werkzeug.security import check_password_hash, generate_password_hash
 | 
					from werkzeug.security import check_password_hash, generate_password_hash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import secrets
 | 
					import secrets
 | 
				
			||||||
@@ -61,8 +62,13 @@ class User(UserMixin, db.Model):
 | 
				
			|||||||
            if user.get_username() == self.get_username(): return False, f'Username {self.get_username()} already in use.'
 | 
					            if user.get_username() == self.get_username(): return False, f'Username {self.get_username()} already in use.'
 | 
				
			||||||
            if user.get_email() == self.get_email(): return False, f'Email address {self.get_email()} already in use.'
 | 
					            if user.get_email() == self.get_email(): return False, f'Email address {self.get_email()} already in use.'
 | 
				
			||||||
        self.set_password(password=password)
 | 
					        self.set_password(password=password)
 | 
				
			||||||
        db.session.add(self)
 | 
					        try:
 | 
				
			||||||
        db.session.commit()
 | 
					            db.session.add(self)
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when registering user {self.get_username()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        write('users.log', f'User \'{self.get_username()}\' was created with id \'{self.id}\'.')
 | 
					        write('users.log', f'User \'{self.get_username()}\' was created with id \'{self.id}\'.')
 | 
				
			||||||
        if notify:
 | 
					        if notify:
 | 
				
			||||||
            email = Message(
 | 
					            email = Message(
 | 
				
			||||||
@@ -149,19 +155,35 @@ class User(UserMixin, db.Model):
 | 
				
			|||||||
            mail.send(email)
 | 
					            mail.send(email)
 | 
				
			||||||
        except SMTPException as exception:
 | 
					        except SMTPException as exception:
 | 
				
			||||||
            write('system.log', f'SMTP Error while trying to reset password for {self.get_username()} with error: {exception}')
 | 
					            write('system.log', f'SMTP Error while trying to reset password for {self.get_username()} with error: {exception}')
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
            return jsonify({'error': f'SMTP Error: {exception}'}), 500
 | 
					            return jsonify({'error': f'SMTP Error: {exception}'}), 500
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when resetting password for user {self.get_username()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        return jsonify({'success': 'Your password reset link has been generated.'}), 200
 | 
					        return jsonify({'success': 'Your password reset link has been generated.'}), 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def clear_reset_tokens(self):
 | 
					    def clear_reset_tokens(self):
 | 
				
			||||||
        self.reset_token = self.verification_token = None
 | 
					        self.reset_token = self.verification_token = None
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when resetting clearing reset tokens for user {self.get_username()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    def delete(self, notify:bool=False):
 | 
					    def delete(self, notify:bool=False):
 | 
				
			||||||
        username = self.get_username()
 | 
					        username = self.get_username()
 | 
				
			||||||
        email_address = self.get_email()
 | 
					        email_address = self.get_email()
 | 
				
			||||||
        db.session.delete(self)
 | 
					        try:
 | 
				
			||||||
        db.session.commit()
 | 
					            db.session.delete(self)
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when deleting user {self.get_username()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        message = f'User \'{username}\' was deleted by \'{current_user.get_username()}\'.'
 | 
					        message = f'User \'{username}\' was deleted by \'{current_user.get_username()}\'.'
 | 
				
			||||||
        write('users.log', message)
 | 
					        write('users.log', message)
 | 
				
			||||||
        if notify:
 | 
					        if notify:
 | 
				
			||||||
@@ -200,7 +222,12 @@ class User(UserMixin, db.Model):
 | 
				
			|||||||
            for entry in User.query.all():
 | 
					            for entry in User.query.all():
 | 
				
			||||||
                if entry.get_email() == email and not entry == self: return False, f'The email address {email} is already in use.'
 | 
					                if entry.get_email() == email and not entry == self: return False, f'The email address {email} is already in use.'
 | 
				
			||||||
            self.set_email(email)
 | 
					            self.set_email(email)
 | 
				
			||||||
        db.session.commit()
 | 
					        try:
 | 
				
			||||||
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					        except SQLAlchemyError as exception:
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            write('system.log', f'Database error when updating user {self.get_username()}: {exception}')
 | 
				
			||||||
 | 
					            return False, f'Database error: {exception}'
 | 
				
			||||||
        _current_user = current_user.get_username() if current_user.is_authenticated else 'anonymous'
 | 
					        _current_user = current_user.get_username() if current_user.is_authenticated else 'anonymous'
 | 
				
			||||||
        write('system.log', f'Information for user {self.get_username()} has been updated by {_current_user}.')
 | 
					        write('system.log', f'Information for user {self.get_username()} has been updated by {_current_user}.')
 | 
				
			||||||
        if notify:
 | 
					        if notify:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user