mirror of
				https://github.com/cookiecutter/cookiecutter-django.git
				synced 2025-11-04 01:47:28 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			130 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
Does the following:
 | 
						|
 | 
						|
1. Generates and saves random secret key
 | 
						|
2. Removes the taskapp if celery isn't going to be used
 | 
						|
3. Copy files from /docs/ to {{ cookiecutter.repo_name }}/docs/
 | 
						|
 | 
						|
    TODO: this might have to be moved to a pre_gen_hook
 | 
						|
 | 
						|
A portion of this code was adopted from Django's standard crypto functions and
 | 
						|
utilities, specifically:
 | 
						|
    https://github.com/django/django/blob/master/django/utils/crypto.py
 | 
						|
"""
 | 
						|
import hashlib
 | 
						|
import os
 | 
						|
import random
 | 
						|
import shutil
 | 
						|
 | 
						|
from cookiecutter.config import DEFAULT_CONFIG
 | 
						|
 | 
						|
# Get the root project directory
 | 
						|
PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)
 | 
						|
 | 
						|
# Use the system PRNG if possible
 | 
						|
try:
 | 
						|
    random = random.SystemRandom()
 | 
						|
    using_sysrandom = True
 | 
						|
except NotImplementedError:
 | 
						|
    # import warnings
 | 
						|
    # warnings.warn('A secure pseudo-random number generator is not available '
 | 
						|
    #               'on your system. Falling back to Mersenne Twister.')
 | 
						|
    using_sysrandom = False
 | 
						|
 | 
						|
def get_random_string(
 | 
						|
        length=50,
 | 
						|
        allowed_chars='abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'):
 | 
						|
    """
 | 
						|
    Returns a securely generated random string.
 | 
						|
    The default length of 12 with the a-z, A-Z, 0-9 character set returns
 | 
						|
    a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
 | 
						|
    """
 | 
						|
    if not using_sysrandom:
 | 
						|
        # This is ugly, and a hack, but it makes things better than
 | 
						|
        # the alternative of predictability. This re-seeds the PRNG
 | 
						|
        # using a value that is hard for an attacker to predict, every
 | 
						|
        # time a random string is required. This may change the
 | 
						|
        # properties of the chosen random sequence slightly, but this
 | 
						|
        # is better than absolute predictability.
 | 
						|
        random.seed(
 | 
						|
            hashlib.sha256(
 | 
						|
                ("%s%s%s" % (
 | 
						|
                    random.getstate(),
 | 
						|
                    time.time(),
 | 
						|
                    settings.SECRET_KEY)).encode('utf-8')
 | 
						|
            ).digest())
 | 
						|
    return ''.join(random.choice(allowed_chars) for i in range(length))
 | 
						|
 | 
						|
def set_secret_key(setting_file_location):
 | 
						|
    # Open locals.py
 | 
						|
    with open(setting_file_location) as f:
 | 
						|
        file_ = f.read()
 | 
						|
 | 
						|
    # Generate a SECRET_KEY that matches the Django standard
 | 
						|
    SECRET_KEY = get_random_string()
 | 
						|
 | 
						|
    # Replace "CHANGEME!!!" with SECRET_KEY
 | 
						|
    file_ = file_.replace('CHANGEME!!!', SECRET_KEY, 1)
 | 
						|
 | 
						|
    # Write the results to the locals.py module
 | 
						|
    with open(setting_file_location, 'w') as f:
 | 
						|
        f.write(file_)
 | 
						|
 | 
						|
 | 
						|
def make_secret_key(project_directory):
 | 
						|
    """Generates and saves random secret key"""
 | 
						|
    # Determine the local_setting_file_location
 | 
						|
    local_setting = os.path.join(
 | 
						|
        project_directory,
 | 
						|
        'config/settings/local.py'
 | 
						|
    )
 | 
						|
 | 
						|
    # local.py settings file
 | 
						|
    set_secret_key(local_setting)
 | 
						|
 | 
						|
    env_file = os.path.join(
 | 
						|
        project_directory,
 | 
						|
        'env.example'
 | 
						|
    )
 | 
						|
 | 
						|
    # env.example file
 | 
						|
    set_secret_key(env_file)
 | 
						|
 | 
						|
 | 
						|
def remove_task_app(project_directory):
 | 
						|
    """Removes the taskapp if celery isn't going to be used"""
 | 
						|
    # Determine the local_setting_file_location
 | 
						|
    task_app_location = os.path.join(
 | 
						|
        PROJECT_DIRECTORY,
 | 
						|
        '{{ cookiecutter.repo_name }}/taskapp'
 | 
						|
    )
 | 
						|
    shutil.rmtree(task_app_location)
 | 
						|
 | 
						|
# IN PROGRESS
 | 
						|
# def copy_doc_files(project_directory):
 | 
						|
#     cookiecutters_dir = DEFAULT_CONFIG['cookiecutters_dir']
 | 
						|
#     cookiecutter_django_dir = os.path.join(
 | 
						|
#         cookiecutters_dir,
 | 
						|
#         'cookiecutter-django',
 | 
						|
#         'docs'
 | 
						|
#     )
 | 
						|
#     target_dir = os.path.join(
 | 
						|
#         project_directory,
 | 
						|
#         'docs'
 | 
						|
#     )
 | 
						|
#     for name in os.listdir(cookiecutter_django_dir):
 | 
						|
#         if name.endswith('.rst') and not name.startswith('index'):
 | 
						|
#             src = os.path.join(cookiecutter_django_dir, name)
 | 
						|
#             dst = os.path.join(target_dir, name)
 | 
						|
#             shutil.copyfile(src, dst)
 | 
						|
 | 
						|
# 1. Generates and saves random secret key
 | 
						|
make_secret_key(PROJECT_DIRECTORY)
 | 
						|
 | 
						|
# 2. Removes the taskapp if celery isn't going to be used
 | 
						|
if '{{ cookiecutter.use_celery }}'.lower() == 'n':
 | 
						|
    remove_task_app(PROJECT_DIRECTORY)
 | 
						|
 | 
						|
# 3. Copy files from /docs/ to {{ cookiecutter.repo_name }}/docs/
 | 
						|
# copy_doc_files(PROJECT_DIRECTORY)
 |