Browse Source

Made some significant changes to how the date is stored in the DB. Still working out the kinks.

Adam Day 2 years ago
parent
commit
6ff995bdf1
5 changed files with 216 additions and 117 deletions
  1. 163 111
      app.py
  2. 4 2
      templates/admin.html
  3. 26 1
      templates/admin_ils_users.html
  4. 16 2
      templates/settings.html
  5. 7 1
      templates/system_log.html

+ 163 - 111
app.py

@@ -15,7 +15,7 @@ import threading
 import atexit
 
 db_name = 'app.db'
-db = SqliteDatabase(db_name)
+db = SqliteDatabase(db_name, check_same_thread=False)
 
 
 class User(Model):
@@ -89,85 +89,93 @@ def reminder_cleanup():
 
 def scheduler(stop_event):
     while not stop_event.is_set():
-        db.connect()
-        # Get all scheduled intervals from the DB
-        intervals = Schedule.select().execute()
-        users = IlsUser.select().execute()
-
-        # Get settings
-        domain_name_setting = Settings.get(Settings.name == 'Domain Name')
-        domain_name = domain_name_setting.value
-
-        password_reset_interval_setting = Settings.get(Settings.name == 'Password Reset Interval')
-        password_reset_interval = password_reset_interval_setting.value
-
-        smtp_host_setting = Settings.get(Settings.name == 'SMTP Host')
-        smtp_host = smtp_host_setting.value
-
-        smtp_port_setting = Settings.get(Settings.name == 'SMTP Port')
-        smtp_port = smtp_port_setting.value
-
-        smtp_username_setting = Settings.get(Settings.name == 'SMTP Username')
-        smtp_username = smtp_username_setting.value
-
-        smtp_password_setting = Settings.get(Settings.name == 'SMTP Password')
-        smtp_password = smtp_password_setting.value
-
-        reset_link_setting = Settings.get(Settings.name == 'Password Reset URL')
-        reset_link = reset_link_setting.value
-
-        # Loop through each user and calculate the number of days until the users password
-        # expires based on the password_reset_interval value.
-        # Loop through all users
+        try:
+            #db.connect()
+            # Get all scheduled intervals from the DB
+            intervals = Schedule.select().execute()
+            users = IlsUser.select().execute()
+
+            # Get settings
+            domain_name_setting = Settings.get(Settings.name == 'Domain Name')
+            domain_name = domain_name_setting.value
+
+            password_reset_interval_setting = Settings.get(Settings.name == 'Password Reset Interval')
+            password_reset_interval = password_reset_interval_setting.value
+
+            smtp_host_setting = Settings.get(Settings.name == 'SMTP Host')
+            smtp_host = smtp_host_setting.value
+
+            smtp_port_setting = Settings.get(Settings.name == 'SMTP Port')
+            smtp_port = smtp_port_setting.value
+
+            smtp_username_setting = Settings.get(Settings.name == 'SMTP Username')
+            smtp_username = smtp_username_setting.value
+
+            smtp_password_setting = Settings.get(Settings.name == 'SMTP Password')
+            smtp_password = smtp_password_setting.value
+
+            suspend_setting = Settings.get(Settings.name == 'Suspend Scheduler')
+            suspend = suspend_setting.value
+
+            reset_link = "http://%s:%s" % (get_hostname(), http_port)
+            #reset_link_setting = Settings.get(Settings.name == 'Password Reset URL')
+            #reset_link = reset_link_setting.value
+
+            # Loop through each user and calculate the number of days until the users password
+            # expires based on the password_reset_interval value.
+            # Loop through all users
+
+            if suspend is False:
+                # Schedule emails to be sent for each user and interval
+                for user in users:
+                    # get the scheduled intervals
+                    for interval in intervals:
+                        # Calculate the date (yyyy-mm-dd) that the password will expire and subtract the interval
+                        # from that date to get the date that the email should be sent.
+                        # Example: If the password reset interval is 90 days and the current date is 2019-01-01
+                        # then the password will expire on 2019-04-01.  If the interval is 30 days then the
+                        # email should be sent on 2019-03-02.
+                        # Calculate the date that the password will expire
+                        password_expiration_date = datetime.datetime.strptime(user.reset_datetime, "%Y-%m-%d") + datetime.timedelta(days=int(password_reset_interval))
+                        # Subtract the interval from the password expiration date to get the date that the email should be sent
+                        email_date = password_expiration_date - datetime.timedelta(days=int(interval.interval))
+
+                        # check if reminder has already been saved to the DB
+                        reminder = EmailReminderLog.select().where(EmailReminderLog.date == email_date.strftime('%Y-%m-%d'), EmailReminderLog.username == user.username, EmailReminderLog.interval == interval.interval).execute()
+                        if reminder:
+                            continue
+                        else:
+                            # Store the date in the DB
+                            EmailReminderLog.create(date=email_date.strftime('%Y-%m-%d'), email=user.email, username=user.username, interval=interval.interval).save()
 
-        # Schedule emails to be sent for each user and interval
-        for user in users:
-            # get the scheduled intervals
-            for interval in intervals:
-                # Calculate the date (yyyy-mm-dd) that the password will expire and subtract the interval
-                # from that date to get the date that the email should be sent.
-                # Example: If the password reset interval is 90 days and the current date is 2019-01-01
-                # then the password will expire on 2019-04-01.  If the interval is 30 days then the
-                # email should be sent on 2019-03-02.
-                # Calculate the date that the password will expire
-                password_expiration_date = datetime.datetime.strptime(user.reset_datetime, "%Y-%m-%d") + datetime.timedelta(days=int(password_reset_interval))
-                # Subtract the interval from the password expiration date to get the date that the email should be sent
-                email_date = password_expiration_date - datetime.timedelta(days=int(interval.interval))
-
-                # check if reminder has already been saved to the DB
-                reminder = EmailReminderLog.select().where(EmailReminderLog.date == email_date.strftime('%Y-%m-%d'), EmailReminderLog.username == user.username, EmailReminderLog.interval == interval.interval).execute()
-                if reminder:
-                    continue
-                else:
-                    # Store the date in the DB
-                    EmailReminderLog.create(date=email_date.strftime('%Y-%m-%d'), email=user.email, username=user.username, interval=interval.interval).save()
-
-        # Get all email reminders from the DB
-        # if today's date matches the EmailReminderLog date then send the email and mark the reminder as sent
-        reminders = EmailReminderLog.select().where(EmailReminderLog.date == datetime.datetime.now().strftime('%Y-%m-%d'), EmailReminderLog.ignore == 0, EmailReminderLog.sent == 0).execute()
-        for reminder in reminders:
-            # Send the email
-            emailer = Emailer(smtp_host, smtp_port, smtp_username, smtp_password)
-            if reminder.interval == 1:
-                # 1 day reminder email
-                emailer.send_email(reminder.email, 'ILS Password Reset Reminder',
-                                   'The password for ILS account with the username "'
-                                   + reminder.username + '" will expire in ' + reminder.interval +
-                                   ' day.  To reset your password, please click the following link: ' + reset_link + '. If the password is not reset today the account will be locked.')
-            else:
-                # more than a day reminder email
-                emailer.send_email(reminder.email, 'ILS Password Reset Reminder',
-                                   'The password for ILS account with the username "'
-                                   + reminder.username + '" will expire in ' + reminder.interval +
-                                   ' days.  To reset your password, please click the following link: ' + reset_link)
-            # Mark the reminder as sent
-            reminder.sent = True
-            reminder.save()
-        db.close()
+                # Get all email reminders from the DB
+                # if today's date matches the EmailReminderLog date then send the email and mark the reminder as sent
+                reminders = EmailReminderLog.select().where(EmailReminderLog.date == datetime.datetime.now().strftime('%Y-%m-%d'), EmailReminderLog.ignore == 0, EmailReminderLog.sent == 0).execute()
+                for reminder in reminders:
+                    # Send the email
+                    emailer = Emailer(smtp_host, smtp_port, smtp_username, smtp_password)
+                    if reminder.interval == 1:
+                        # 1 day reminder email
+                        emailer.send_email(reminder.email, 'ILS Password Reset Reminder',
+                                           'The password for ILS account with the username "'
+                                           + reminder.username + '" will expire in ' + reminder.interval +
+                                           ' day.  To reset your password, please click the following link: ' + reset_link + '. If the password is not reset today the account will be locked.')
+                    else:
+                        # more than a day reminder email
+                        emailer.send_email(reminder.email, 'ILS Password Reset Reminder',
+                                           'The password for ILS account with the username "'
+                                           + reminder.username + '" will expire in ' + reminder.interval +
+                                           ' days.  To reset your password, please click the following link: ' + reset_link)
+                    # Mark the reminder as sent
+                    reminder.sent = True
+                    reminder.save()
+                # Remove all reminders from the DB that are older than today's date
+                reminder_cleanup()
+                #db.close()
+        except Exception as e:
+            pass
 
-        # Remove all reminders from the DB that are older than today's date
-        reminder_cleanup()
-        time.sleep(10)  # Sleep for 15 minutes
+        time.sleep(1)  # Sleep for 5 seconds
 
 
 # Encrypt the password with SHA256
@@ -176,6 +184,9 @@ def encrypt_password(password):
     return hash
 
 
+#db.connect()
+
+
 # Check for DB tables and create if they don't exist
 if db.table_exists('user') is False:
     db.create_tables([User, ])
@@ -196,6 +207,8 @@ if db.table_exists('settings') is False:
     Settings.create(name='Domain Name', value="lynx").save()
     Settings.create(name='Password Reset URL', value="https://terminal.idaho-lynx.org").save()
     Settings.create(name='Password Reset Interval', value="90").save()
+    Settings.create(name='Suspend Scheduler', value=False).save()
+
 
 if db.table_exists('log') is False:
     db.create_tables([Log, ])
@@ -209,8 +222,6 @@ if db.table_exists('schedule') is False:
 if db.table_exists('email_reminder_log') is False:
     db.create_tables([EmailReminderLog, ])
 
-db.close()
-
 settings = Settings.select().execute()
 
 debug_setting = Settings.get(Settings.name == 'Debug Mode')
@@ -236,8 +247,7 @@ if debug.lower() == 'true':
 else:
     debug = False
 
-
-# send_email('aday@twinfallspubliclibrary.org', 'TEST', 'This is a test email')
+#db.close()
 
 
 def shutdown_session(exception=None):
@@ -287,8 +297,6 @@ def admin_password_check():
        return True
 
 
-db.close()
-
 # Start the scheduler loop in another thread
 shutdown_scheduler = threading.Event()
 scheduler_thread = threading.Thread(target=scheduler, args=(shutdown_scheduler,))
@@ -368,6 +376,7 @@ app.jinja_env.filters['time_since'] = format_time_ago
 app.jinja_env.filters['time_until'] = format_time_until
 
 
+'''
 @app.before_request
 def before_request():
     db.connect()
@@ -377,7 +386,7 @@ def before_request():
 def after_request(response):
     db.close()
     return response
-
+'''
 
 @app.route('/admin/password/reset', methods=['GET', 'POST'])
 def admin_password_reset():
@@ -396,7 +405,6 @@ def admin_password_reset():
                 session['username'] = 'admin'
                 return redirect(url_for('admin'))
             except Exception as e:
-                print(e)
                 message = 'Username not found'
 
     context = {
@@ -423,10 +431,17 @@ def index():
         try:
             user = IlsUser.filter(IlsUser.username == username).first()
         except Exception as e:
-            print(e)
             user = None
 
         if user:
+            # Remove emailreinderlogs from this user
+            try:
+                reminders = EmailReminderLog.select().where(EmailReminderLog.username == user.username).execute()
+                for reminder in reminders:
+                    reminder.delete_instance()
+            except Exception as e:
+                pass
+
             # Reset login datetime
             user.reset_datetime = datetime.datetime.now().strftime("%Y-%m-%d")
             PasswordResetLog.create(username=user.username, date_created=datetime.datetime.now()).save()
@@ -460,6 +475,12 @@ def admin():
     if not requires_auth():
         return redirect(url_for('login'))
 
+    # Get settings
+    try:
+        password_reset_interval = Settings.get(Settings.name == 'Password Reset Interval')
+    except Exception as e:
+        password_reset_interval = None
+
     # Get a count of all IlsUsers
     try:
         ils_users = IlsUser.select().count()
@@ -472,15 +493,16 @@ def admin():
     except Exception as e:
         total_email_reminders = None
 
-    # Get a list of coming email reminders for the next 7 days
-    try:
-        email_reminders = PasswordResetLog.select().where(PasswordResetLog.date_created < datetime.datetime.now() + datetime.timedelta(days=7)).execute()
-    except Exception as e:
-        email_reminders = None
-
     # Get a list ils users that have passwords expiring in the next 7 days
+    ils_expiring_users = list()
     try:
-        ils_users_expiring = IlsUser.select().where(IlsUser.password_expires < datetime.datetime.now() + datetime.timedelta(days=7)).execute()
+        # Get a list of ILS users that have passwords expiring in the next 7 days
+        ils_users_expiring = IlsUser.select().where(IlsUser.reset_datetime + datetime.timedelta(days=int(password_reset_interval.value)) <= datetime.datetime.now() + datetime.timedelta(days=7)).execute()
+
+        for user in ils_users_expiring:
+            user = IlsUser.get(IlsUser.username == user.username)
+            ils_expiring_users.append(user)
+
     except Exception as e:
         ils_users_expiring = None
 
@@ -493,7 +515,7 @@ def admin():
 
     context = {
         'ils_user_count': ils_users,
-        'ils_users_expiring': ils_users_expiring,
+        'ils_users_expiring': ils_expiring_users,
         'email_reminders': email_reminders,
         'total_email_reminders': total_email_reminders,
     }
@@ -516,7 +538,6 @@ def admin_users():
         try:
             user = User.filter(User.username == username).first()
         except Exception as e:
-            print(e)
             user = None
 
         if user:
@@ -619,7 +640,6 @@ def admin_ils_users():
         try:
             user = IlsUser.filter(IlsUser.username == username).first()
         except Exception as e:
-            print(e)
             user = None
 
         # Check if date field was submitted if so convert to datetime object
@@ -660,15 +680,49 @@ def admin_ils_users_delete(id):
         email_reminders = EmailReminderLog.select().where(EmailReminderLog.username == user.username).execute()
         for reminder in email_reminders:
             reminder.delete_instance()
-        print('here')
     except Exception as e:
-        print('there', e)
+        pass
 
     user.delete_instance()
     Log.create(username=session['username'], action='Removed ILS user: %s' % username, ).save()
     return redirect(url_for('admin_ils_users'))
 
 
+@app.route('/admin/users/ils/delete/all', methods=['GET', 'POST'])
+def admin_ils_users_delete_all():
+    if not requires_auth():
+        return redirect(url_for('login'))
+
+    # Set the suspend scheduler to True
+    settings = Settings.select().execute()
+    for setting in settings:
+        if setting.name == 'Suspend Scheduler':
+            setting.value = 'True'
+            setting.save()
+
+    # Remove scheduled email reminders
+    try:
+        email_reminders = EmailReminderLog.select().execute()
+        for reminder in email_reminders:
+            reminder.delete_instance()
+    except Exception as e:
+        pass
+
+    # Remove all ILS users
+    users = IlsUser.select().execute()
+    for user in users:
+        user.delete_instance()
+
+    # Set the suspend scheduler to False
+    settings = Settings.select().execute()
+    for setting in settings:
+        if setting.name == 'Suspend Scheduler':
+            setting.value = 'True'
+            setting.save()
+
+    return redirect(url_for('admin_ils_users'))
+
+
 @app.route('/admin/users/ils/edit/<int:id>', methods=['GET', 'POST'])
 def admin_ils_users_edit(id):
     # Check to see if user is logged in
@@ -700,7 +754,7 @@ def admin_ils_users_edit(id):
                 for reminder in email_reminders:
                     reminder.delete_instance()
             except Exception as e:
-                print(e)
+                pass
 
             user.username = username
             user.email = email
@@ -759,12 +813,12 @@ def admin_ils_users_csv_import():
                     try:
                         reset_date = datetime.datetime.strptime(reset_date, '%m/%d/%Y').strftime('%Y-%m-%d')
                     except Exception as e:
-                        print(e)
+                        pass
 
                     try:
                         reset_date = datetime.datetime.strptime(reset_date, '%Y-%m-%d').strftime('%Y-%m-%d')
                     except Exception as e:
-                        print(e)
+                        pass
 
                     # ignore the header row
                     if username == 'ILS Username':
@@ -778,7 +832,6 @@ def admin_ils_users_csv_import():
                     try:
                         user = IlsUser.filter(IlsUser.username == username).first()
                     except Exception as e:
-                        print(e)
                         user = None
 
                     if user:
@@ -856,18 +909,17 @@ def settings():
                 else:
                     value = setting.value
 
-                # Remove all scheduled reminders
-                reminders = EmailReminderLog.select().execute()
-                for reminder in reminders:
-                    reminder.delete_instance()
-
             # Update the setting
             old_value = setting.value
             setting.value = value
             setting.save()
-            Log.create(username=session['username'], action='Changed %s setting from "%s" to "%s"' % (setting.name,
+
+            if setting.name == 'SMTP Password':
+                Log.create(username=session['username'], action='SMTP Password was changed.').save()
+            else:
+                Log.create(username=session['username'], action='Changed %s setting from "%s" to "%s"' % (setting.name,
                                                                                                       old_value,
-                                                                                                      value)).save()
+                                                                                                      setting.value)).save()
             message = '%s updated successfully' % setting.name
 
     # Get settings from DB
@@ -957,7 +1009,7 @@ def reset_scheduled_emails():
     reminders = EmailReminderLog.select().execute()
     for reminder in reminders:
         reminder.delete_instance()
-
+    time.sleep(3)
     return redirect(url_for('scheduled_emails'))
 
 

+ 4 - 2
templates/admin.html

@@ -26,9 +26,11 @@
             <div class="col-sm-12 col-md-4 mb-4">
                 <div class="card">
                     <div class="card-body text-center">
-                        <h4>Expiring in 7 days</h4>
+                        <h4>Expiring in the next 7 days</h4>
                         <ul class="text-start">
-
+                            {% for user in context.ils_users_expiring %}
+                                <li>{{ user.username }}</li>
+                            {% endfor %}
                         </ul>
                     </div>
                 </div>

+ 26 - 1
templates/admin_ils_users.html

@@ -9,7 +9,8 @@
 {% endif %}
 <div class="row">
     <div class="col">
-        <a href="#!" data-bs-toggle="modal" data-bs-target="#add-user" class="btn btn-primary float-end"><i class="ri-user-add-line"></i> Add ILS User</a>
+        <a href="#!" data-bs-toggle="modal" data-bs-target="#remove-all-users" class="btn btn-danger float-end"><i class="ri-delete-bin-line"></i> Remove all ILS Users</a>
+        <a href="#!" data-bs-toggle="modal" data-bs-target="#add-user" class="btn btn-primary float-end me-2"><i class="ri-user-add-line"></i> Add ILS User</a>
         <a href="{{ url_for('admin_ils_users_csv_download') }}" class="btn btn-dark float-end me-2"><i class="ri-file-download-fill"></i> CSV Export</a>
         <a href="{{ url_for('admin_ils_users_csv_import') }}" class="btn btn-dark float-end me-2"><i class="ri-file-upload-fill"></i> CSV Import</a>
         <h3><i class="ri-shield-user-fill"></i> ILS Users</h3>
@@ -79,4 +80,28 @@
     </div>
 </div>
 
+
+<div class="modal fade" id="remove-all-users" tabindex="-1">
+    <div class="modal-dialog modal-dialog-centered">
+        <div class="modal-content">
+            <div class="modal-header bg-light">
+                <h1 class="modal-title fs-5"><i class="ri-delete-bin-line-fill"></i> Confirmation</h1>
+                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+            </div>
+            <div class="modal-body">
+                # Confirmation asking user to confirm removal of all ILS users
+                <p class="lead">
+                    Are you sure you want to remove all ILS users?
+                </p>
+            </div>
+            <div class="modal-footer bg-light">
+                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
+                <a href="{{ url_for('admin_ils_users_delete_all') }}" class="btn btn-danger">Remove All</a>
+            </div>
+
+        </div>
+    </div>
+</div>
+
+
 {% endblock %}

+ 16 - 2
templates/settings.html

@@ -26,7 +26,17 @@
                 {% for setting in context.settings %}
                 <tr>
                     <td>{{ setting.name }}</td>
-                    <td>{{ setting.value }}</td>
+                    {% if setting.name == 'SMTP Password' %}
+                        <td>
+                            {% if setting.value == "" %}
+                                <i>Password not set</i>
+                            {% else %}
+                                <i>Password set</i>
+                            {% endif %}
+                        </td>
+                    {% else %}
+                        <td>{{ setting.value }}</td>
+                    {% endif %}
                     <td>
                         <a href="#!" data-bs-toggle="modal" data-bs-target="#setting-{{ loop.index0 }}" class="btn btn-primary">Edit</a>
                     </td>
@@ -49,7 +59,11 @@
                 <div class="modal-body">
                     <div class="mb-3">
                         <label for="value" class="form-label">{{ setting.name}}</label>
-                        <input type="text" class="form-control" id="value" name="value" value="{{ setting.value }}" required>
+                        {% if setting.name == 'SMTP Password' %}
+                            <input type="password" class="form-control" id="value" name="value" value="" required>
+                        {% else %}
+                            <input type="text" class="form-control" id="value" name="value" value="{{ setting.value }}" required>
+                        {% endif %}
                         <input type="hidden" name="id" value="{{ setting.id }}" required>
                     </div>
                 </div>

+ 7 - 1
templates/system_log.html

@@ -21,7 +21,13 @@
                 <tr>
                     <td>{{ log.username }}</td>
                     <td>{{ log.date }}</td>
-                    <td>{{ log.action }}</td>
+                    <td>
+                        {% if log.action[:21] == 'Changed SMTP Password' %}
+                            SMTP password was changed.
+                        {% else %}
+                            {{ log.action }}
+                        {% endif %}
+                    </td>
                 </tr>
                 {% endfor %}
             </tbody>