Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Created by https://www.gitignore.io
site.retry
*.bak

.vagrant
.idea
Expand Down Expand Up @@ -66,5 +67,3 @@ target/

env/
*.deb


1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ install:
before_script:
- ./pylint-check.py
script:
- mkdir -p ../logs
- py.test -v --cov postmaster --cov-report term-missing tests/
after_success:
- coveralls
Expand Down
1 change: 1 addition & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class BaseConfiguration(object):
SQLALCHEMY_DATABASE_URI = 'mysql://root:vagrant@localhost:3306/servermail'
basedir = path.abspath(path.dirname(__file__))
SQLALCHEMY_MIGRATE_REPO = path.join(basedir, 'db/migrations')
LOG_LOCATION = '/opt/postmaster/logs/postmaster.log'


class TestConfiguration(BaseConfiguration):
Expand Down
4 changes: 4 additions & 0 deletions docs/ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
### Unreleased

BACKWARDS INCOMPATIBILITIES / NOTES:

* 'Log File' config option is now baked into the application config and cannot be set in the api / webui / database. Use `python manage.py setlogfile <path>` or edit config.py to change the log file location. See [GH-128].

Features:

* Added the ability to install PostMaster via a deb package [GH-111]
Expand Down
6 changes: 4 additions & 2 deletions docs/Configuration/CommandLineConfiguration.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
### Before You Start
1. Logged into the server hosting PostMaster as root or as an administrator, enter the Python virtual environment (if necessary, replace the path with your install location):

Linux:
source /opt/postmaster/env/bin/activate
Windows:
C:\PostMaster\env\Scripts\activate.ps1

2. Once you've entered the Python virtual environment, navigate to the location of manage.py (replace /opt/postmaster/git with your install location):

cd /opt/postmaster/git
Expand All @@ -22,6 +22,8 @@ Use the following commands to restore the proper permissions on the PostMaster f

### Command Line Commands

**setlogfile** sets the location of the logfile. The default is `/opt/postmaster/logs/postmaster.log`.

**setdburi** sets the MySQL database URI that PostMaster uses to connect to the MySQL server used by your mail server.

**createdb** runs a database migration, and configures the default configuration settings if they are missing on the database specified using the "setdburi" command.
Expand Down
6 changes: 1 addition & 5 deletions docs/Configuration/ConfigurationsPage.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
**Minimum Password Length** specifies the minimum password length that all mail users and administrators must adhere to.

**Login Auditing** determines whether login and logout events are recorded in the log file. In order to enable this, the "Log File" setting must be configured.
**Login Auditing** determines whether login and logout events are recorded in the log file.

**Mail Database Auditing** determines whether changes to domains, users, aliases, administrators, and configuration settings should be recorded in the log file.
In order to enable this, the "Log File" setting must be configured.

**Log File** specifies a file path to where the log file should be. The path can be relative or absolute, but the file location must be writable by the web server.
When configuring this setting, "Mail Database Auditing" will be turned on automatically.

**Enable LDAP Authentication** determines whether Active Directory LDAP authentication is turned on or off. In order to enable LDAP authentication,
the "AD Server LDAP String", "AD Domain", and "AD PostMaster Group" must be configured.
Expand Down
14 changes: 9 additions & 5 deletions docs/Installation/WindowsServer2012R2.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,20 +160,24 @@ To start the migration, run the following command:

python manage.py generatekey

27. You may now exit the Python virtual environment:
27. By deafult, PostMaster logs to a Linux based path, run the following command to change the log to the text file created in step 11:

python manage.py setlogfile "$env:SystemDrive\PostMaster\logs\postmaster.log"

28. You may now exit the Python virtual environment:

deactivate

28. Restart IIS to make sure all the changes take effect:
29. Restart IIS to make sure all the changes take effect:

iisreset

29. At this point it is highly recommended that you implement SSL before using PostMaster in production.
30. At this point it is highly recommended that you implement SSL before using PostMaster in production.

29. PostMaster should now be running. Simply use the username "admin" and the password "PostMaster" to login.
31. PostMaster should now be running. Simply use the username "admin" and the password "PostMaster" to login.
You can change your username and password from Manage -> Administrators.

30. Please keep in mind that the C:\PostMaster\git\db\migrations folder should be backed up after installation/updates.
32. Please keep in mind that the C:\PostMaster\git\db\migrations folder should be backed up after installation/updates.
This is because PostMaster uses database migrations to safely upgrade the database schema,
and this folder contains auto-generated database migration scripts that allow you to revert back if a database migration ever failed.
If this folder is missing, PostMaster can't tell what state your database is in, and therefore, cannot revert back.
12 changes: 12 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,17 @@ def setdburi(uri):
else:
print(line.rstrip())


@manager.command
def setlogfile(filepath):
"""Replaces the BaseConfiguration LOG_LOCATION in config.py with one supplied"""
base_config_set = False
for line in fileinput.input('config.py', inplace=True, backup='.bak'):
if not base_config_set and 'LOG_LOCATION' in line:
print(sub(r'(?<=LOG_LOCATION = \')(.+)(?=\')', filepath, line.rstrip()))
base_config_set = True
else:
print(line.rstrip())

if __name__ == "__main__":
manager.run()
27 changes: 9 additions & 18 deletions postmaster/apiv1/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from mmap import mmap
from json import loads
from ..errors import ValidationError
from postmaster import db
from postmaster import app
from postmaster.models import Configs


Expand All @@ -26,24 +26,14 @@ def is_file_writeable(file):

def is_config_update_valid(setting, value, valid_value_regex):
""" A helper function for the update_config function on the /configs/<int:config_id> PUT route.
A bool is returned based on if the users input is valid.
A bool is returned based on if the user's input is valid.
"""
if match(valid_value_regex, value):

if setting == 'Log File':
if not is_file_writeable(value):
raise ValidationError('The specified log path is not writable')
else:
# Enables Mail Database Auditing when the log file is set
mail_db_auditing = Configs.query.filter_by(setting='Mail Database Auditing').first()
mail_db_auditing.value = 'True'
db.session.add(mail_db_auditing)

elif setting == 'Login Auditing' or setting == 'Mail Database Auditing':
log_file = Configs.query.filter_by(setting='Log File').first().value

if not log_file:
raise ValidationError('The log file must be set before auditing can be enabled')
if setting == 'Login Auditing' or setting == 'Mail Database Auditing':
log_path = app.config.get('LOG_LOCATION')
if not log_path or not is_file_writeable(log_path):
raise ValidationError('The log could not be written to "{0}". '
'Verify that the path exists and is writeable.'.format(os.path.abspath(log_path)))

elif setting == 'Enable LDAP Authentication':
ldap_string = Configs.query.filter_by(setting='AD Server LDAP String').first().value
Expand All @@ -66,11 +56,12 @@ def is_config_update_valid(setting, value, valid_value_regex):

raise ValidationError('An invalid setting value was supplied')


def get_logs_dict(numLines=50, reverseOrder=False):
"""
Returns the JSON formatted log file as a dict
"""
logPath = Configs.query.filter_by(setting='Log File').first().value
logPath = app.config.get('LOG_LOCATION')
if logPath and os.path.exists(logPath):
logFile = open(logPath, mode='r+')

Expand Down
19 changes: 1 addition & 18 deletions postmaster/static/js/configs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
function configEventListeners () {
var configBoolItems = $('a.configBool');
var configTextItems = $('a.configText');
var configLogFile = $('a.configLogFile');

configBoolItems.unbind();
configBoolItems.tooltip();
Expand All @@ -22,19 +21,6 @@ function configEventListeners () {
$(this).html(filterText(value));
}
});

configLogFile.unbind();
configLogFile.tooltip();
configLogFile.editable({
success: function () {
// Sets the Mail Database Auditing to True in the UI
$('td:contains("Mail Database Auditing")').next('td').children('a').text('True');
addStatusMessage('success', 'The setting was changed successfully');
},
display: function (value) {
$(this).html(filterText(value));
}
});
}


Expand All @@ -61,10 +47,7 @@ function fillInTable () {
'Enable LDAP Authentication'
];

if (item.setting == 'Log File') {
var cssClass = 'configLogFile'
}
else if($.inArray(item.setting, boolConfigItems) != -1) {
if($.inArray(item.setting, boolConfigItems) != -1) {
var cssClass = 'configBool'
}
else {
Expand Down
21 changes: 6 additions & 15 deletions postmaster/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from re import search, sub, IGNORECASE
from json import dumps
from datetime import datetime
from os import getcwd
from os import path
from wtforms.validators import StopValidation as WtfStopValidation
from postmaster import db, models, bcrypt
from postmaster import app, db, models, bcrypt
from postmaster.errors import ValidationError


Expand All @@ -32,11 +32,10 @@ def login_auditing_enabled():


def json_logger(category, admin, message):
"""
Takes a category (typically error or audit), a log message and the responsible
""" Takes a category (typically error or audit), a log message and the responsible
user. It then appends it with an ISO 8601 UTC timestamp to a JSON formatted log file
"""
log_path = models.Configs.query.filter_by(setting='Log File').first().value
log_path = app.config.get('LOG_LOCATION')
if log_path and ((category == 'error') or
(category == 'audit' and maildb_auditing_enabled()) or
(category == 'auth' and login_auditing_enabled())):
Expand All @@ -52,10 +51,8 @@ def json_logger(category, admin, message):
sort_keys=True)))
log_file.close()
except IOError:
raise ValidationError(
'The log could not be written to "{0}". \
Verify that the path exists and is writeable.'.format(
getcwd().replace('\\', '/') + '/' + log_path))
raise ValidationError('The log could not be written to "{0}". '
'Verify that the path exists and is writeable.'.format(path.abspath(log_path)))


def add_default_configuration_settings():
Expand Down Expand Up @@ -83,12 +80,6 @@ def add_default_configuration_settings():
mail_db_auditing.regex = '^(True|False)$'
db.session.add(mail_db_auditing)

if not models.Configs.query.filter_by(setting='Log File').first():
log_file = models.Configs()
log_file.setting = 'Log File'
log_file.regex = '^(.+)$'
db.session.add(log_file)

if not models.Configs.query.filter_by(setting='Enable LDAP Authentication').first():
ldap_auth = models.Configs()
ldap_auth.setting = 'Enable LDAP Authentication'
Expand Down
Loading