Skip to content

feat: Implement python-decouple for environment variables management #187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
29 changes: 29 additions & 0 deletions contrib/env-sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
SECRET_KEY='insert_key_here'
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1
#DATABASE_URL=
EMAIL_HOST=smtp.example.com
EMAIL_HOST_PASSWORD=your_email_password
[email protected]
EMAIL_PORT=587
SERVER_EMAIL=
DEFAULT_FROM_EMAIL=
[email protected]
ADMIN_NAME=Admin1
LANGUAGE_CODE=pt-br
CRM_IP=127.0.0.1
CRM_REPLY_TO="'Do not reply' <[email protected]>"
CLIENT_ID=
CLIENT_SECRET=
GOOGLE_RECAPTCHA_SITE_KEY=
GOOGLE_RECAPTCHA_SECRET_KEY=
REDIRECT_URI=
LOAD_RATE_BACKEND=

SECRET_CRM_PREFIX='123/'
SECRET_ADMIN_PREFIX='456-admin/'
SECRET_LOGIN_PREFIX= '789-login/'

SITE_TITLE = 'CRM'
ADMIN_HEADER = "ADMIN"
ADMIN_TITLE = "CRM Admin"
34 changes: 25 additions & 9 deletions docs/installation_and_configuration_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,26 @@ Their full list is [here](https://docs.djangoproject.com/en/dev/ref/settings/).
The settings missing in this list are CRM specific settings. Explanations can be found in the comments to them.
Most of the settings can be left at their default values.

### Environment Variables and `python-decouple`

This project utilizes `python-decouple` to manage environment variables. This approach offers enhanced security and flexibility by keeping sensitive information out of the codebase and allowing for environment-specific configurations.

#### Why Use Environment Variables?

* **Security:** Sensitive data like API keys, database credentials, and secret keys are stored outside of the code repository, reducing the risk of accidental exposure.
* **Flexibility:** You can easily switch between different environments (development, testing, production) by simply changing the environment variables, without modifying the code.
* **Organization:** All configuration settings are centralized in a `.env` file, making them easier to manage and update.

#### How to Configure Environment Variables

1. Copy contrib/env-sample to .env in the root project.

Ensure `python-decouple` is installed in your virtual environment. If you followed the "Install the requirements" step, it should already be installed. If not, run:

```pip install python-decouple```
2. Replace de default values to your values in .env.


The default settings are for running the project on a development server.
Change them for the production server.

Expand All @@ -182,16 +202,12 @@ But in the following, you will need to specify at least the `EMAIL_HOST` and `AD

### DATABASES settings

Provide data to connect to the database:
To work between development and production environments, we suggest using dj-database-url, this way, the connection will be configured as a url, in .env, and we set a default value, so if it does not exist, use sqlite3.

- `ENGINE` and `PORT` are specified by default for MySQL database. Change them for PostgreSQL
- Specify `PASSWORD`
Ensure `dj-database-url` is installed in your virtual environment. If you followed the "Install the requirements" step, it should already be installed. If not, run:

Detailed instructions [here](https://docs.djangoproject.com/en/dev/ref/settings/#std-setting-DATABASES).
```pip install dj-database-url```

In the database, configure the `USER` (by default 'crm_user') specified in the `DATABASES` setting
to have the right to create and drop databases (running tests will create
and then destroy a separate [test database](https://docs.djangoproject.com/en/dev/topics/testing/overview/#the-test-database)).

#### For MySQL database, it is recommended to

Expand All @@ -211,15 +227,15 @@ You can configure them directly in postgresql.conf `(/etc/postgresql/<version>/m

### EMAIL_HOST settings

Specify details for connecting to an email account through which CRM will be able to send notifications to users and administrators.
Specify details at .env for connecting to an email account through which CRM will be able to send notifications to users and administrators.

- `EMAIL_HOST` (smtp server)
- `EMAIL_HOST_PASSWORD`
- `EMAIL_HOST_USER` (login)

### ADMINS settings

Add the addresses of CRM administrators to the list, so they can receive error logs.
Add the addresses at .env of CRM administrators to the list, so they can receive error logs.
`ADMINS = [("<Admin1 name>", "<[email protected]>"), (...)]`

## CRM and database testing
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
certifi==2025.1.31
charset-normalizer==3.4.1
Django==5.1.8
dj-database-url==2.3.0
et-xmlfile==2.0.0
frozenlist==1.5.0
geoip2==5.0.1
Expand All @@ -17,6 +18,7 @@
pandas==2.2.3
polib==1.2.0
python-dateutil==2.9.0.post0
python-decouple==3.8
pytz==2025.2
requests==2.32.3
six==1.17.0
Expand Down
69 changes: 31 additions & 38 deletions webcrm/settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import os
import sys
from pathlib import Path
from datetime import datetime as dt
from django.utils.translation import gettext_lazy as _
from decouple import config, Csv
from dj_database_url import parse as dburl

from crm.settings import * # NOQA
from massmail.settings import * # NOQA
Expand All @@ -19,47 +22,36 @@
# To get new value of key use code:
# from django.core.management.utils import get_random_secret_key
# print(get_random_secret_key())
SECRET_KEY = 'j1c=6$s-dh#$ywt@(q4cm=j&0c*!0x!e-qm6k1%yoliec(15tn'
SECRET_KEY = config('SECRET_KEY')

# Add your hosts to the list.
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[], cast=Csv())

# Database
default_dburl = 'sqlite:///' + os.path.join(BASE_DIR, 'db.sqlite3') # Use sqlite if database is not setted in .env

DATABASES = {
'default': {
# for MySQl
'ENGINE': 'django.db.backends.mysql',
'PORT': '3306',

# for PostgreSQL
# "ENGINE": "django.db.backends.postgresql",
# 'PORT': '5432', # for PostgreSQL

'NAME': 'crm_db',
'USER': 'crm_user',
'PASSWORD': 'crmpass',
'HOST': 'localhost',
}
'default': config('DATABASE_URL', default=default_dburl, cast=dburl) ## Configure .env with DATABASE_URL=<user>:<pass>@<host>:<port>/<dbname>
}

EMAIL_HOST = '<specify host>' # 'smtp.example.com'
EMAIL_HOST_PASSWORD = '<specify password>'
EMAIL_HOST_USER = '[email protected]'
EMAIL_PORT = 587
EMAIL_HOST = config('EMAIL_HOST')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')
EMAIL_HOST_USER = config('EMAIL_HOST_USER')
EMAIL_PORT = config('EMAIL_PORT')
EMAIL_SUBJECT_PREFIX = 'CRM: '
EMAIL_USE_TLS = True
SERVER_EMAIL = '[email protected]'
DEFAULT_FROM_EMAIL = '[email protected]'
SERVER_EMAIL = config('SERVER_EMAIL')
DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL')

ADMINS = [("<Admin1>", "<[email protected]>")] # specify admin
ADMINS = [(config('ADMIN_NAME'), config('ADMIN_EMAIL'))] # specify admin

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
DEBUG = config('DEBUG', default=False, cast=bool)

FORMS_URLFIELD_ASSUME_HTTPS = True

# Internationalization
LANGUAGE_CODE = 'en'
LANGUAGE_CODE = config('LANGUAGE_CODE')
LANGUAGES = [
('ar', 'Arabic'),
('cs', 'Czech'),
Expand Down Expand Up @@ -191,14 +183,15 @@

# For more security, replace the url prefixes
# with your own unique value.
SECRET_CRM_PREFIX = '123/'
SECRET_ADMIN_PREFIX = '456-admin/'
SECRET_LOGIN_PREFIX = '789-login/'
SECRET_CRM_PREFIX = config('SECRET_CRM_PREFIX')
SECRET_ADMIN_PREFIX = config('SECRET_ADMIN_PREFIX')
SECRET_LOGIN_PREFIX = config('SECRET_LOGIN_PREFIX')

# Specify ip of host to avoid importing emails sent by CRM
CRM_IP = "127.0.0.1"
CRM_IP = config('CRM_IP')

CRM_REPLY_TO = ["'Do not reply' <[email protected]>"]
#CRM_REPLY_TO = ["'Do not reply' <[email protected]>"]
CRM_REPLY_TO = config('CRM_REPLY_TO', default=[], cast=Csv())

# List of addresses to which users are not allowed to send mail.
NOT_ALLOWED_EMAILS = []
Expand Down Expand Up @@ -245,8 +238,8 @@

# 2-Step Verification Credentials for Google Accounts.
# OAuth 2.0
CLIENT_ID = ''
CLIENT_SECRET = ''
CLIENT_ID = config('CLIENT_ID')
CLIENT_SECRET = config('CLIENT_SECRET')
OAUTH2_DATA = {
'smtp.gmail.com': {
'scope': "https://mail.google.com/",
Expand All @@ -256,11 +249,11 @@
}
}
# Hardcoded dummy redirect URI for non-web apps.
REDIRECT_URI = ''
REDIRECT_URI = config('REDIRECT_URI')

# Credentials for Google reCAPTCHA.
GOOGLE_RECAPTCHA_SITE_KEY = ''
GOOGLE_RECAPTCHA_SECRET_KEY = ''
GOOGLE_RECAPTCHA_SITE_KEY = config('GOOGLE_RECAPTCHA_SITE_KEY')
GOOGLE_RECAPTCHA_SECRET_KEY = config('GOOGLE_RECAPTCHA_SECRET_KEY')

GEOIP = False
GEOIP_PATH = MEDIA_ROOT / 'geodb'
Expand All @@ -280,9 +273,9 @@


# Site headers
SITE_TITLE = 'CRM'
ADMIN_HEADER = "ADMIN"
ADMIN_TITLE = "CRM Admin"
SITE_TITLE = config('SITE_TITLE')
ADMIN_HEADER = config('ADMIN_HEADER')
ADMIN_TITLE = config('ADMIN_TITLE')
INDEX_TITLE = _('Main Menu')


Expand Down