diff --git a/.gitignore b/.gitignore index 8cf83e1908..3866c30c95 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,9 @@ docs/_build InvenTree/media InvenTree/static +# Local config file +config.yaml + # Key file secret_key.txt diff --git a/.travis.yml b/.travis.yml index 58bdad303f..5df4432cef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ addons: before_install: - make requirements - - make secret + - make setup - make migrate script: diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index cd55fc1b25..66f22be9e4 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -11,11 +11,18 @@ database setup in this file. """ +import sys import os import logging import tempfile import yaml + +def eprint(*args, **kwargs): + """ Print a warning message to stderr """ + print(*args, file=sys.stderr, **kwargs) + + # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -23,7 +30,7 @@ cfg_filename = os.path.join(BASE_DIR, 'config.yaml') if not os.path.exists(cfg_filename): CONFIG = {} - print("Warning: config.yaml not found - using default settings") + eprint("Warning: config.yaml not found - using default settings") else: with open(cfg_filename, 'r') as cfg: CONFIG = yaml.safe_load(cfg) @@ -52,7 +59,7 @@ if cors_opt: CORS_ORIGIN_ALLOW_ALL = cors_opt.get('allow_all', False) if CORS_ORIGIN_ALLOW_ALL: - print("Warning: CORS requests are allowed for any domain!") + eprint("Warning: CORS requests are allowed for any domain!") else: CORS_ORIGIN_WHITELIST = cors_opt.get('whitelist', []) @@ -156,7 +163,7 @@ DATABASES = {} if 'database' in CONFIG: DATABASES['default'] = CONFIG['database'] else: - print("Warning: Database backend not specified - using default (sqlite)") + eprint("Warning: Database backend not specified - using default (sqlite)") DATABASES['default'] = { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'inventree_db.sqlite3'), diff --git a/InvenTree/config.yaml b/InvenTree/config_template.yaml similarity index 84% rename from InvenTree/config.yaml rename to InvenTree/config_template.yaml index 510951842a..b08efdb8be 100644 --- a/InvenTree/config.yaml +++ b/InvenTree/config_template.yaml @@ -3,15 +3,20 @@ # Ref: https://docs.djangoproject.com/en/2.2/ref/settings/#std:setting-DATABASES # Specify database parameters below as they appear in the Django docs database: + # Example configuration - sqlite (default) ENGINE: django.db.backends.sqlite3 - NAME: inventree_db.sqlite3 + NAME: inventree_db.sqlite3 # For more complex database installations, further parameters are required # Refer to the django documentation for full list of options - # USER: db_username - # PASSWORD: db_password - # HOST: db_hostname - # PORT: db_port + + # Example Configuration - MySQL + #ENGINE: django.db.backends.mysql + #NAME: inventree + #USER: inventree + #PASSWORD: password + #HOST: '' + #PORT: '' # Set debug to False to run in production mode debug: True @@ -36,7 +41,7 @@ cors: # MEDIA_ROOT is the local filesystem location for storing uploaded files # By default, it is stored in a directory named 'media' local to the InvenTree directory # This should be changed for a production installation -media_root: './media' +media_root: 'media' # STATIC_ROOT is the local filesystem location for storing static files # By default it is stored in a directory named 'static' local to the InvenTree directory @@ -47,4 +52,4 @@ log_queries: False # Backup options # Set the backup_dir parameter to store backup files in a specific location -# backup_dir = "/home/me/inventree-backup/" \ No newline at end of file +backup_dir: '/mnt/c/Users/Oliver/inventree-backup/' \ No newline at end of file diff --git a/InvenTree/keygen.py b/InvenTree/keygen.py deleted file mode 100644 index c96df22794..0000000000 --- a/InvenTree/keygen.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Generates a Django SECRET_KEY file to be used by manage.py -""" - -import random -import string -import os -import sys -import argparse - -KEY_FN = 'secret_key.txt' -KEY_DIR = os.path.dirname(os.path.realpath(__file__)) - - -def generate_key(length=50): - """ Generate a random string - - Args: - length: Number of characters in returned string (default = 50) - - Returns: - Randomized secret key string - """ - - options = string.digits + string.ascii_letters + string.punctuation - key = ''.join([random.choice(options) for i in range(length)]) - return key - - -if __name__ == '__main__': - - parser = argparse.ArgumentParser(description='Generate Django SECRET_KEY file') - parser.add_argument('--output', help='Specify key file path', default=None) - parser.add_argument('--force', '-f', help='Override key file (if it exists)', action='store_true') - parser.add_argument('--dummy', '-d', help='Dummy run (display key only', action='store_true') - - args = parser.parse_args() - - if args.output: - key_filename = args.output - else: - key_filename = os.path.join(KEY_DIR, KEY_FN) - - key_data = generate_key() - - if args.dummy: - print('SECRET_KEY: {k}'.format(k=key_data)) - sys.exit(0) - - if not args.force and os.path.exists(key_filename): - print("Key file already exists - '{f}'".format(f=key_filename)) - sys.exit(0) - - with open(key_filename, 'w') as key_file: - print("Generating SECRET_KEY file - '{f}'".format(f=key_filename)) - key_file.write(key_data) diff --git a/InvenTree/setup.py b/InvenTree/setup.py new file mode 100644 index 0000000000..b74cfe7358 --- /dev/null +++ b/InvenTree/setup.py @@ -0,0 +1,68 @@ +""" +Performs initial setup functions. + +- Generates a Django SECRET_KEY file to be used by manage.py +- Copies config template file (if a config file does not already exist) +""" + +import random +import string +import os +import sys +import argparse +from shutil import copyfile + +OUTPUT_DIR = os.path.dirname(os.path.realpath(__file__)) + +KEY_FN = 'secret_key.txt' +CONFIG_FN = 'config.yaml' +CONFIG_TEMPLATE_FN = 'config_template.yaml' + + +def generate_key(length=50): + """ Generate a random string + + Args: + length: Number of characters in returned string (default = 50) + + Returns: + Randomized secret key string + """ + + options = string.digits + string.ascii_letters + string.punctuation + key = ''.join([random.choice(options) for i in range(length)]) + return key + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser(description='Generate Django SECRET_KEY file') + parser.add_argument('--force', '-f', help='Override existing files', action='store_true') + parser.add_argument('--dummy', '-d', help='Dummy run (do not create any files)', action='store_true') + + args = parser.parse_args() + + # Places to store files + key_filename = os.path.join(OUTPUT_DIR, KEY_FN) + conf_template = os.path.join(OUTPUT_DIR, CONFIG_TEMPLATE_FN) + conf_filename = os.path.join(OUTPUT_DIR, CONFIG_FN) + + # Generate secret key data + key_data = generate_key() + + if args.dummy: + print('SECRET_KEY: {k}'.format(k=key_data)) + sys.exit(0) + + if not args.force and os.path.exists(key_filename): + print("Key file already exists - '{f}'".format(f=key_filename)) + else: + with open(key_filename, 'w') as key_file: + print("Generating SECRET_KEY file - '{f}'".format(f=key_filename)) + key_file.write(key_data) + + if not args.force and os.path.exists(conf_filename): + print("Config file already exists (skipping)") + else: + print("Copying config template to 'config.yaml'") + copyfile(conf_template, conf_filename) diff --git a/Makefile b/Makefile index dda44c9a03..900a67c7b2 100644 --- a/Makefile +++ b/Makefile @@ -19,13 +19,18 @@ migrate: requirements: pip3 install -U -r requirements.txt -secret: - python3 InvenTree/keygen.py +setup: + python3 InvenTree/setup.py superuser: python3 InvenTree/manage.py createsuperuser -install: requirements secret migrate superuser +install: requirements setup migrate superuser + +mysql: + apt-get install mysql-server + apt-get install libmysqlclient-dev + pip3 install mysqlclient style: flake8 InvenTree @@ -47,4 +52,4 @@ backup: python3 InvenTree/manage.py dbbackup python3 InvenTree/manage.py mediabackup -.PHONY: clean migrate requirements secret superuser install style test coverage documentation backup \ No newline at end of file +.PHONY: clean migrate requirements setup superuser install mysql style test coverage documentation backup \ No newline at end of file diff --git a/docs/config.rst b/docs/config.rst index fc768b8e87..e737caa46c 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -15,7 +15,7 @@ To support install specific settings, a simple configuration file ``config.yaml` The default configuration file launches a *DEBUG* configuration with a simple SQLITE database backend. This default configuration file is shown below: -.. literalinclude :: ../InvenTree/config.yaml +.. literalinclude :: ../InvenTree/config_template.yaml :language: yaml :linenos: @@ -30,7 +30,17 @@ Database options are specified under the *database* heading in the configuration By default, InvenTree uses an sqlite database file : ``inventree_db.sqlite3``. This provides a simple, portable database file that is easy to use for debug and testing purposes. -**MYSQL:** MySQL database backend is supported with the native Django implemetation. +**MYSQL:** MySQL database backend is supported with the native Django implemetation. To run InvenTree with the MySQL backend, a number of extra packages need to be installed: + +* mysql-server - *MySQL backend server* +* libmysqlclient-dev - *Required for connecting to the MySQL database in Python* +* (pip) mysqlclient - *Python package for communication with MySQL database* + +These requirements can be installed from the base directory with the command ``make mysql``. + +It is up to the database adminstrator to create a new database to store inventree data, in addition to a username/password to access the data. + +The database options then need to be adjusted to communicate the MySQL backend. Refer to the `Django docs `_ for further information. **POSTGRESQL:** PostgreSQL database backend is supported with the native Django implementation. Note that to use this backend, the ``psycopg2`` Python library must first be installed. diff --git a/docs/start.rst b/docs/start.rst index 9fe52868aa..6150c22bb0 100644 --- a/docs/start.rst +++ b/docs/start.rst @@ -52,7 +52,7 @@ Development and Testing Other shorthand functions are provided for the development and testing process: * ``make requirements`` - Install all required underlying packages using PIP -* ``make secret`` - Generate the SECRET_KEY file for session validation +* ``make setup`` - Perform one-time setup functions * ``make superuser`` - Create a superuser account * ``make backup`` - Backup database tables and media files * ``make test`` - Run all unit tests