mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 19:37:06 +00:00
Compare commits
124 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ce293d1388 | |||
| f83805af4f | |||
| 97530b2203 | |||
| 170db50a1c | |||
| 1b59bb9f99 | |||
| 2ebe7777c3 | |||
| 2f9f35c396 | |||
| aecd0ff314 | |||
| e0e9a05747 | |||
| cce0543408 | |||
| a6e36b9854 | |||
| 995a4f6cb2 | |||
| d24756ca38 | |||
| f69b7aa1f0 | |||
| 50839f3240 | |||
| 74b6b3b27d | |||
| e51c2dc76b | |||
| e7b57df077 | |||
| b0fcda5901 | |||
| 92901350a0 | |||
| 253846f877 | |||
| 4b61b26661 | |||
| 66567e5a55 | |||
| b8059175c6 | |||
| a85a07ea82 | |||
| 21088a1412 | |||
| e37d5fcb61 | |||
| f6bfcceb6c | |||
| 79bb6cc415 | |||
| 99161b269e | |||
| 365c3f04c9 | |||
| 65023cf4f9 | |||
| 85bb6ae5ba | |||
| 6eeb74fdd7 | |||
| f015929a0c | |||
| c05ef1ed10 | |||
| f8593776c0 | |||
| 284132f4cc | |||
| 858933c6bb | |||
| 0a3c85bb42 | |||
| 266bdfe628 | |||
| d19554de24 | |||
| 4e4503e097 | |||
| d65ccc807f | |||
| b94c459e56 | |||
| b6a6be99da | |||
| 83765c99ad | |||
| 11a6f8d8f1 | |||
| bcb2b1bc20 | |||
| 843bdebabf | |||
| 86e18c399d | |||
| 05ca7433f1 | |||
| 3beeeab4ae | |||
| ccea25133c | |||
| ced86f308b | |||
| 6d1e5effda | |||
| 809894a04c | |||
| 9967c081c9 | |||
| 555aae5d1c | |||
| 905613d8e9 | |||
| e3ea56ce32 | |||
| d66e0ea21a | |||
| 50f5363b69 | |||
| de11df1999 | |||
| 35d8d9423a | |||
| 347e189a96 | |||
| e15de01cfa | |||
| 0d03678674 | |||
| 08c004d42d | |||
| 5fca39f32c | |||
| 8782b879a1 | |||
| d5eef1a296 | |||
| dcf08830f4 | |||
| 361ab675d3 | |||
| e1ba0df894 | |||
| f0dee9794f | |||
| 19698270e5 | |||
| f0f03c1175 | |||
| 8427b78ba6 | |||
| 62a28c6c66 | |||
| bb7568885d | |||
| 31a2367514 | |||
| b0e51bcfd6 | |||
| a8f119a1df | |||
| 2ad21765c0 | |||
| 7289774dc7 | |||
| 107e0f317b | |||
| 2d5f3e3b2e | |||
| ba44a34946 | |||
| 0c90b72c7f | |||
| 38d6e7e9cc | |||
| a57aee1ea7 | |||
| 04f9f81408 | |||
| e75631f8a5 | |||
| c0871a7b51 | |||
| 822b6e95aa | |||
| 7e9bbd2792 | |||
| b00a4dcb8e | |||
| 7555d4bd2b | |||
| bf896d07b0 | |||
| 539fb8daa3 | |||
| 35240b25ba | |||
| 4d38b2f8f0 | |||
| df0d9aa902 | |||
| 011a01d176 | |||
| 2a08ddba45 | |||
| bcba36a421 | |||
| d6bd47b4ea | |||
| 2c1ebbc399 | |||
| 330ec1afe1 | |||
| 2096534085 | |||
| 8608a350f3 | |||
| 4e82d363bc | |||
| cbd2158307 | |||
| 0355392675 | |||
| c5dca62b0b | |||
| 050a69d5ea | |||
| 07c15281c0 | |||
| 15bbf2f7d1 | |||
| 7e2491be76 | |||
| 770b4f1114 | |||
| 4b37c202f4 | |||
| de111bea55 | |||
| 6e2267a4b6 |
@@ -15,4 +15,7 @@ mail.log/
|
||||
/static/
|
||||
*.sqlite3*
|
||||
*.log*
|
||||
deployment*
|
||||
deployment*
|
||||
|
||||
/docs/
|
||||
.readthedocs.yaml
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -25,3 +25,6 @@ deployment-key*
|
||||
/custom
|
||||
staging.yml
|
||||
production.yml
|
||||
|
||||
# Docs local builds
|
||||
/docs/build
|
||||
25
.readthedocs.yaml
Normal file
25
.readthedocs.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/source/conf.py
|
||||
|
||||
# If using Sphinx, optionally build your docs in additional formats such as PDF
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
# Optionally declare the Python requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/source/requirements.txt
|
||||
5
Caddyfile
Normal file → Executable file
5
Caddyfile
Normal file → Executable file
@@ -4,12 +4,13 @@
|
||||
|
||||
@proxy_paths {
|
||||
not path /static/*
|
||||
not path /media/*
|
||||
}
|
||||
|
||||
reverse_proxy @proxy_paths http://web:8000
|
||||
reverse_proxy @proxy_paths http://server:8000
|
||||
|
||||
log {
|
||||
output stderr
|
||||
format single_field common_log
|
||||
format console
|
||||
}
|
||||
}
|
||||
2
Dockerfile
Normal file → Executable file
2
Dockerfile
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
FROM python:3.8-slim
|
||||
FROM python:3.9-slim
|
||||
|
||||
RUN groupadd -r mapper && useradd --no-log-init -r -g mapper mapper
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# BRECcIA Mapper
|
||||
|
||||
[](https://docs.gcrf-breccia.com/en/latest/?badge=latest)
|
||||
|
||||
BRECcIA Mapper is a web app to collect and explore data about the relationships between researchers and their stakeholders on large-scale, multi-site research projects.
|
||||
This allows researchers to visually represent the relationships between project staff and stakeholders involved in the their project at different points in time.
|
||||
Through this it is possible to explore the extent of networks and change over time, and identify where new relationships can be developed or existing ones strengthened.
|
||||
@@ -9,11 +11,12 @@ This work was funded through the "Building REsearch Capacity for sustainable wat
|
||||
## Deployment
|
||||
|
||||
This project is written in Python using the popular [Django](https://www.djangoproject.com/) framework.
|
||||
Deployment is managed using [Ansible](https://www.ansible.com/) and Docker (https://www.docker.com/), see the `deploy/README.md` for details.
|
||||
Deployment relies on [Docker Compose](https://docs.docker.com/compose) but is possible with various methods. See [the documentation](https://docs.gcrf-breccia.com/en/latest/1-deployment.html) for details.
|
||||
|
||||
## Contributors
|
||||
|
||||
- James Graham (@jag1g13) - developer
|
||||
- Matthew Grove (@mgrove36) - developer
|
||||
- Genevieve Agaba
|
||||
- Sebastian Reichel
|
||||
- Claire Bedelian
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 4.1.4 on 2023-01-05 16:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('activities', '0006_activity_attendance_optional'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='activity',
|
||||
name='id',
|
||||
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='activitymedium',
|
||||
name='id',
|
||||
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='activityseries',
|
||||
name='id',
|
||||
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='activitytype',
|
||||
name='id',
|
||||
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
]
|
||||
@@ -79,7 +79,7 @@ class ActivityAttendanceView(permissions.UserIsLinkedPersonMixin, SingleObjectMi
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
|
||||
if request.is_ajax():
|
||||
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
|
||||
self.object.attendance_list.add(self.get_test_person())
|
||||
|
||||
return HttpResponse(status=204)
|
||||
@@ -89,7 +89,7 @@ class ActivityAttendanceView(permissions.UserIsLinkedPersonMixin, SingleObjectMi
|
||||
def delete(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
|
||||
if request.is_ajax():
|
||||
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
|
||||
self.object.attendance_list.remove(self.get_test_person())
|
||||
|
||||
return HttpResponse(status=204)
|
||||
|
||||
16
breccia_mapper/account_adapter.py
Normal file
16
breccia_mapper/account_adapter.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from allauth.account.adapter import DefaultAccountAdapter
|
||||
from constance import config
|
||||
|
||||
|
||||
class ControlSignupsAccountAdapter(DefaultAccountAdapter):
|
||||
|
||||
def is_open_for_signup(self, request):
|
||||
"""
|
||||
Checks whether or not the site is open for signups.
|
||||
|
||||
Next to simply returning True/False you can also intervene the
|
||||
regular flow by raising an ImmediateHttpResponse
|
||||
|
||||
(Comment reproduced from the overridden method.)
|
||||
"""
|
||||
return config.ALLOW_SIGNUPS
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"model": "bootstrap_customizer.sitebootstraptheme",
|
||||
"pk": 1,
|
||||
"fields": { "site": 1, "bootstrap_theme": 1, "updated": "2023-02-23T14:41:48.620Z" }
|
||||
}
|
||||
]
|
||||
1
breccia_mapper/fixtures/bootstrap_customizer_theme.json
Normal file
1
breccia_mapper/fixtures/bootstrap_customizer_theme.json
Normal file
File diff suppressed because one or more lines are too long
0
breccia_mapper/management/__init__.py
Normal file
0
breccia_mapper/management/__init__.py
Normal file
0
breccia_mapper/management/commands/__init__.py
Normal file
0
breccia_mapper/management/commands/__init__.py
Normal file
44
breccia_mapper/management/commands/selectiveloaddata.py
Normal file
44
breccia_mapper/management/commands/selectiveloaddata.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
from django.core.management.commands import loaddata
|
||||
|
||||
from bootstrap_customizer.models import BootstrapTheme
|
||||
|
||||
|
||||
def should_add_record(record):
|
||||
if record['model'] != 'bootstrap_customizer.bootstraptheme':
|
||||
return True
|
||||
|
||||
return not BootstrapTheme.objects.filter(
|
||||
pk=record['pk'],
|
||||
).exists()
|
||||
|
||||
|
||||
class Command(loaddata.Command):
|
||||
def handle(self, *args, **options):
|
||||
args = list(args)
|
||||
|
||||
# Read the original JSON file
|
||||
file_name = args[0]
|
||||
with open(file_name) as json_file:
|
||||
json_list = json.load(json_file)
|
||||
|
||||
# Filter out records that already exists
|
||||
json_list_filtered = list(filter(should_add_record, json_list))
|
||||
if not json_list_filtered:
|
||||
print("All data are already previously loaded")
|
||||
return
|
||||
|
||||
# Write the updated JSON file
|
||||
file_dir_and_name, file_ext = os.path.splitext(file_name)
|
||||
file_name_temp = f"{file_dir_and_name}_temp{file_ext}"
|
||||
with open(file_name_temp, 'w') as json_file_temp:
|
||||
json.dump(json_list_filtered, json_file_temp)
|
||||
|
||||
# Pass the request to the actual loaddata (parent functionality)
|
||||
args[0] = file_name_temp
|
||||
super().handle(*args, **options)
|
||||
|
||||
# You can choose to not delete the file so that you can see what was added to your records
|
||||
os.remove(file_name_temp)
|
||||
@@ -13,20 +13,8 @@ Before production deployment, see
|
||||
https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
|
||||
|
||||
|
||||
Many configuration settings are input from `settings.ini`.
|
||||
The most likely required settings are: SECRET_KEY, DEBUG, ALLOWED_HOSTS, DATABASE_URL, PROJECT_*_NAME, EMAIL_*
|
||||
|
||||
- PARENT_PROJECT_NAME
|
||||
default: Parent Project Name
|
||||
Displayed in templates where the name of the parent project should be used
|
||||
|
||||
- PROJECT_LONG_NAME
|
||||
default: Project Long Name
|
||||
Displayed in templates where the full name of the project should be used
|
||||
|
||||
- PROJECT_SHORT_NAME
|
||||
default: shortname
|
||||
Displayed in templates where a short identifier for the project should be used
|
||||
Many configuration settings are input from `.env`.
|
||||
The most likely required settings are: SECRET_KEY, DEBUG, ALLOWED_HOSTS, PROJECT_*_NAME, EMAIL_*
|
||||
|
||||
- SECRET_KEY (REQUIRED)
|
||||
Used to generate CSRF tokens - must never be made public
|
||||
@@ -35,14 +23,38 @@ The most likely required settings are: SECRET_KEY, DEBUG, ALLOWED_HOSTS, DATABAS
|
||||
default: False
|
||||
Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||
|
||||
- SITE_URL
|
||||
default: localhost
|
||||
The URL the site will be deployed on. Do not include http://, https://, or a trailing slash.
|
||||
|
||||
- SITE_PROTOCOL
|
||||
default: http
|
||||
The protocol the site uses. Valid options are http or https.
|
||||
|
||||
- PROJECT_LONG_NAME
|
||||
default: Project Network Mapper
|
||||
The project's full name.
|
||||
|
||||
- PROJECT_SHORT_NAME
|
||||
default: Network Mapper
|
||||
The project's short/abbreviated name. This will also be used as the app's name when installed as PWA.
|
||||
|
||||
- PROJECT_DESCRIPTION
|
||||
default: Application to map network relationships in the organisation.
|
||||
The project's description. Used when installed as a PWA.
|
||||
|
||||
- THEME_COLOR
|
||||
default: 212121
|
||||
The project's theme color, in hex format (excluding the leading #).
|
||||
|
||||
- BACKGROUND_COLOR
|
||||
default: ffffff
|
||||
The project's background color, in hex format (excluding the leading #).
|
||||
|
||||
- ALLOWED_HOSTS
|
||||
default: * if DEBUG else localhost
|
||||
Accepted values for server header in request - protects against CSRF and CSS attacks
|
||||
|
||||
- DATABASE_URL
|
||||
default: sqlite://db.sqlite3
|
||||
URL to database - uses format described at https://github.com/jacobian/dj-database-url
|
||||
|
||||
- DBBACKUP_STORAGE_LOCATION
|
||||
default: .dbbackup
|
||||
Directory where database backups should be stored
|
||||
@@ -118,16 +130,16 @@ import dj_database_url
|
||||
|
||||
SETTINGS_EXPORT = [
|
||||
'DEBUG',
|
||||
'PARENT_PROJECT_NAME',
|
||||
'SITE_URL',
|
||||
'SITE_PROTOCOL',
|
||||
'GOOGLE_MAPS_API_KEY',
|
||||
'PROJECT_LONG_NAME',
|
||||
'PROJECT_SHORT_NAME',
|
||||
'GOOGLE_MAPS_API_KEY',
|
||||
'PROJECT_DESCRIPTION',
|
||||
'THEME_COLOR',
|
||||
'BACKGROUND_COLOR',
|
||||
]
|
||||
|
||||
PARENT_PROJECT_NAME = config('PARENT_PROJECT_NAME',
|
||||
default='Parent Project Name')
|
||||
PROJECT_LONG_NAME = config('PROJECT_LONG_NAME', default='Project Long Name')
|
||||
PROJECT_SHORT_NAME = config('PROJECT_SHORT_NAME', default='shortname')
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR.joinpath(...)
|
||||
BASE_DIR = pathlib.Path(__file__).parent.parent
|
||||
@@ -143,6 +155,27 @@ ALLOWED_HOSTS = config(
|
||||
default='*' if DEBUG else '127.0.0.1,localhost,localhost.localdomain',
|
||||
cast=Csv())
|
||||
|
||||
# Site URL
|
||||
SITE_URL = config('SITE_URL', default='localhost')
|
||||
SITE_PROTOCOL = config('SITE_PROTOCOL', default='http')
|
||||
|
||||
# CORS settings
|
||||
CORS_ALLOW_CREDENTIALS = True
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
CORS_ALLOW_CREDENTIALS = True
|
||||
CSRF_TRUSTED_ORIGINS = config(
|
||||
'TRUSTED_ORIGINS',
|
||||
default='*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain',
|
||||
cast=Csv())
|
||||
CORS_REPLACE_HTTPS_REFERER = True
|
||||
CSRF_COOKIE_DOMAIN = config(
|
||||
'SITE_URL',
|
||||
default='localhost')
|
||||
CORS_ORIGIN_WHITELIST = config(
|
||||
'TRUSTED_ORIGINS',
|
||||
default='*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain',
|
||||
cast=Csv())
|
||||
|
||||
# Application definition
|
||||
|
||||
DJANGO_APPS = [
|
||||
@@ -152,6 +185,7 @@ DJANGO_APPS = [
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.sites',
|
||||
]
|
||||
|
||||
THIRD_PARTY_APPS = [
|
||||
@@ -165,10 +199,18 @@ THIRD_PARTY_APPS = [
|
||||
'post_office',
|
||||
'bootstrap_datepicker_plus',
|
||||
'hijack',
|
||||
'compat',
|
||||
'pwa',
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'allauth.socialaccount',
|
||||
'allauth.socialaccount.providers.google',
|
||||
'allauth.socialaccount.providers.microsoft',
|
||||
'django_inlinecss',
|
||||
'bootstrap_customizer',
|
||||
]
|
||||
|
||||
FIRST_PARTY_APPS = [
|
||||
'breccia_mapper',
|
||||
'people',
|
||||
'activities',
|
||||
'export',
|
||||
@@ -184,6 +226,13 @@ MIDDLEWARE = [
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'hijack.middleware.HijackUserMiddleware',
|
||||
'django.contrib.sites.middleware.CurrentSiteMiddleware',
|
||||
'bootstrap_customizer.middleware.BootstrapThemeMiddleware',
|
||||
]
|
||||
|
||||
FIXTURE_DIRS = [
|
||||
BASE_DIR.joinpath('breccia_mapper', 'fixtures'),
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'breccia_mapper.urls'
|
||||
@@ -208,14 +257,45 @@ TEMPLATES = [
|
||||
|
||||
WSGI_APPLICATION = 'breccia_mapper.wsgi.application'
|
||||
|
||||
# allauth
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
# Needed to login by username in Django admin, regardless of `allauth`
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
# `allauth` specific authentication methods, such as login by email
|
||||
'allauth.account.auth_backends.AuthenticationBackend',
|
||||
]
|
||||
SITE_ID = 1
|
||||
ACCOUNT_DEFAULT_HTTP_PROTOCOL = SITE_PROTOCOL
|
||||
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
|
||||
ACCOUNT_EMAIL_REQUIRED = True
|
||||
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
|
||||
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 5
|
||||
# 1 day
|
||||
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 86400
|
||||
# or any other page
|
||||
ACCOUNT_LOGOUT_REDIRECT_URL = '/'
|
||||
ACCOUNT_ADAPTER = 'breccia_mapper.account_adapter.ControlSignupsAccountAdapter'
|
||||
|
||||
|
||||
PROJECT_LONG_NAME = config('PROJECT_LONG_NAME', 'Project Network Mapper')
|
||||
PROJECT_SHORT_NAME = config('PROJECT_SHORT_NAME', 'Network Mapper')
|
||||
PROJECT_DESCRIPTION = config('PROJECT_DESCRIPTION', 'Application to map network relationships in the organisation.')
|
||||
THEME_COLOR = '#' + config('THEME_COLOR', '212121')
|
||||
BACKGROUND_COLOR = '#' + config('BACKGROUND_COLOR', 'ffffff')
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default':
|
||||
config('DATABASE_URL',
|
||||
default='sqlite:///' + str(BASE_DIR.joinpath('db.sqlite3')),
|
||||
cast=dj_database_url.parse)
|
||||
'default' : {
|
||||
'ENGINE': 'django.db.backends.postgresql',
|
||||
'NAME': 'breccia-mapper',
|
||||
'USER': 'breccia-mapper',
|
||||
'PASSWORD': config('DB_PASSWORD'),
|
||||
'HOST': 'db',
|
||||
'PORT': '5432',
|
||||
}
|
||||
}
|
||||
|
||||
# Django DBBackup
|
||||
@@ -271,7 +351,7 @@ AUTH_USER_MODEL = 'people.User'
|
||||
|
||||
# Login flow
|
||||
|
||||
LOGIN_URL = reverse_lazy('login')
|
||||
LOGIN_URL = reverse_lazy('account_login')
|
||||
|
||||
LOGIN_REDIRECT_URL = reverse_lazy('people:person.profile')
|
||||
|
||||
@@ -297,6 +377,10 @@ STATIC_ROOT = BASE_DIR.joinpath('static')
|
||||
|
||||
STATICFILES_DIRS = [BASE_DIR.joinpath('breccia_mapper', 'static')]
|
||||
|
||||
# Media uploads
|
||||
MEDIA_ROOT = BASE_DIR.joinpath('media')
|
||||
MEDIA_URL = "/media/"
|
||||
|
||||
# Logging - NB the logger name is empty to capture all output
|
||||
|
||||
LOGGING = {
|
||||
@@ -340,6 +424,10 @@ logger = logging.getLogger(__name__) # pylint: disable=invalid-name
|
||||
|
||||
# Admin panel variables
|
||||
|
||||
CONSTANCE_ADDITIONAL_FIELDS = {
|
||||
'image_field': ['django.forms.ImageField', {}]
|
||||
}
|
||||
|
||||
CONSTANCE_CONFIG = {
|
||||
'NOTICE_TEXT': (
|
||||
'',
|
||||
@@ -359,17 +447,103 @@ CONSTANCE_CONFIG = {
|
||||
'RELATIONSHIP_FORM_HELP': (
|
||||
'',
|
||||
'Help text to display at the top of relationship forms.'),
|
||||
'PARENT_PROJECT_NAME': (
|
||||
'',
|
||||
'Parent project name'),
|
||||
'PROJECT_LEAD': (
|
||||
'Project Lead',
|
||||
'Project lead'),
|
||||
'PROJECT_TAGLINE': (
|
||||
'Here is your project\'s tagline.',
|
||||
'Project tagline'),
|
||||
'ALLOW_SIGNUPS': (
|
||||
False,
|
||||
'Allow new users to sign up using the site\'s sign up form'),
|
||||
'ENABLE_GOOGLE_LOGIN': (
|
||||
False,
|
||||
'Allow users to sign in using their Google accounts'),
|
||||
'ENABLE_MICROSOFT_LOGIN': (
|
||||
False,
|
||||
'Allow users to sign in using their Microsoft accounts'),
|
||||
'HOMEPAGE_HEADER_IMAGE': (
|
||||
'800x500.png',
|
||||
'Homepage header image',
|
||||
'image_field'),
|
||||
'HOMEPAGE_HEADER_IMAGE_SHRINK': (
|
||||
False,
|
||||
'Shrink the homepage header image to display the whole image at all times'),
|
||||
'HOMEPAGE_CARD_1_TITLE': (
|
||||
'Step 1',
|
||||
'Homepage card #1 title'),
|
||||
'HOMEPAGE_CARD_1_DESCRIPTION': (
|
||||
'Tell us about your position within the project',
|
||||
'Homepage card #1 description'),
|
||||
'HOMEPAGE_CARD_1_ICON': (
|
||||
'building-user',
|
||||
'Homepage card #1 icon'),
|
||||
'HOMEPAGE_CARD_2_TITLE': (
|
||||
'Step 2',
|
||||
'Homepage card #2 title'),
|
||||
'HOMEPAGE_CARD_2_DESCRIPTION': (
|
||||
'Describe your relationships with other stakeholders',
|
||||
'Homepage card #2 description'),
|
||||
'HOMEPAGE_CARD_2_ICON': (
|
||||
'handshake-simple',
|
||||
'Homepage card #2 icon'),
|
||||
'HOMEPAGE_CARD_3_TITLE': (
|
||||
'Step 3',
|
||||
'Homepage card #3 title'),
|
||||
'HOMEPAGE_CARD_3_DESCRIPTION': (
|
||||
'Use the network view to analyse relationships',
|
||||
'Homepage card #3 description'),
|
||||
'HOMEPAGE_CARD_3_ICON': (
|
||||
'diagram-project',
|
||||
'Homepage card #3 icon'),
|
||||
'HOMEPAGE_ABOUT_TITLE': (
|
||||
'About Us',
|
||||
'Homepage about section title'),
|
||||
'HOMEPAGE_ABOUT_CONTENT': (
|
||||
"""Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. In massa tempor nec feugiat nisl. Eget dolor morbi non arcu risus quis varius quam quisque. Nisl pretium fusce id velit ut tortor pretium viverra suspendisse. Vitae auctor eu augue ut lectus arcu. Tellus molestie nunc non blandit massa enim nec. At consectetur lorem donec massa sapien. Placerat orci nulla pellentesque dignissim enim sit. Sit amet mauris commodo quis imperdiet. Tellus at urna condimentum mattis pellentesque.<br/>In vitae turpis massa sed. Fermentum posuere urna nec tincidunt praesent semper feugiat nibh sed. Ut consequat semper viverra nam libero justo laoreet. Velit ut tortor pretium viverra suspendisse potenti nullam ac tortor. Nunc id cursus metus aliquam eleifend mi in nulla posuere. Aliquam eleifend mi in nulla posuere sollicitudin aliquam. Est ante in nibh mauris cursus mattis molestie a iaculis. Nunc id cursus metus aliquam. Auctor urna nunc id cursus metus aliquam. Porttitor lacus luctus accumsan tortor posuere ac ut consequat semper. Volutpat consequat mauris nunc congue nisi. Leo vel fringilla est ullamcorper eget. Vitae purus faucibus ornare suspendisse sed nisi lacus sed. Massa id neque aliquam vestibulum morbi blandit. Iaculis nunc sed augue lacus viverra vitae congue. Sodales neque sodales ut etiam.""",
|
||||
'Homepage about section content'),
|
||||
'HOMEPAGE_ABOUT_IMAGE': (
|
||||
'400x400.png',
|
||||
'Homepage about section image',
|
||||
'image_field'),
|
||||
} # yapf: disable
|
||||
|
||||
CONSTANCE_CONFIG_FIELDSETS = {
|
||||
'Notice Banner': (
|
||||
'Project options': (
|
||||
'PARENT_PROJECT_NAME',
|
||||
'PROJECT_LEAD',
|
||||
'PROJECT_TAGLINE',
|
||||
'ALLOW_SIGNUPS',
|
||||
'ENABLE_GOOGLE_LOGIN',
|
||||
'ENABLE_MICROSOFT_LOGIN',
|
||||
),
|
||||
'Homepage configuration': (
|
||||
'HOMEPAGE_HEADER_IMAGE_SHRINK',
|
||||
'HOMEPAGE_HEADER_IMAGE',
|
||||
'HOMEPAGE_CARD_1_TITLE',
|
||||
'HOMEPAGE_CARD_1_DESCRIPTION',
|
||||
'HOMEPAGE_CARD_1_ICON',
|
||||
'HOMEPAGE_CARD_2_TITLE',
|
||||
'HOMEPAGE_CARD_2_DESCRIPTION',
|
||||
'HOMEPAGE_CARD_2_ICON',
|
||||
'HOMEPAGE_CARD_3_TITLE',
|
||||
'HOMEPAGE_CARD_3_DESCRIPTION',
|
||||
'HOMEPAGE_CARD_3_ICON',
|
||||
'HOMEPAGE_ABOUT_TITLE',
|
||||
'HOMEPAGE_ABOUT_CONTENT',
|
||||
'HOMEPAGE_ABOUT_IMAGE',
|
||||
),
|
||||
'Notice banner': (
|
||||
'NOTICE_TEXT',
|
||||
'NOTICE_CLASS',
|
||||
),
|
||||
'Data Collection': (
|
||||
'CONSENT_TEXT',
|
||||
),
|
||||
'Help Text': (
|
||||
'Help text': (
|
||||
'PERSON_LIST_HELP',
|
||||
'ORGANISATION_LIST_HELP',
|
||||
'RELATIONSHIP_FORM_HELP',
|
||||
@@ -396,7 +570,7 @@ BOOTSTRAP4 = {
|
||||
EMAIL_HOST = config('EMAIL_HOST', default=None)
|
||||
DEFAULT_FROM_EMAIL = config(
|
||||
'DEFAULT_FROM_EMAIL',
|
||||
default=f'{PROJECT_SHORT_NAME}@localhost.localdomain')
|
||||
default=f'{PROJECT_SHORT_NAME.replace(" ","")}@localhost.localdomain')
|
||||
SERVER_EMAIL = DEFAULT_FROM_EMAIL
|
||||
|
||||
if EMAIL_HOST is None:
|
||||
@@ -417,6 +591,53 @@ else:
|
||||
default=(EMAIL_PORT == 465),
|
||||
cast=bool)
|
||||
|
||||
# Bootstrap Datepicker Plus Settings
|
||||
BOOTSTRAP_DATEPICKER_PLUS = {
|
||||
"variant_options": {
|
||||
"date": {
|
||||
"format": "YYYY-MM-DD",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
# PWA settings
|
||||
|
||||
PWA_SERVICE_WORKER_PATH = BASE_DIR.joinpath('static/js', 'serviceworker.js')
|
||||
|
||||
PWA_APP_NAME = PROJECT_SHORT_NAME
|
||||
PWA_APP_DESCRIPTION = PROJECT_DESCRIPTION
|
||||
PWA_APP_THEME_COLOR = THEME_COLOR
|
||||
PWA_APP_BACKGROUND_COLOR = BACKGROUND_COLOR
|
||||
PWA_APP_DISPLAY = 'standalone'
|
||||
PWA_APP_SCOPE = '/'
|
||||
PWA_APP_ORIENTATION = 'any'
|
||||
PWA_APP_START_URL = '/'
|
||||
PWA_APP_STATUS_BAR_COLOR = 'default'
|
||||
PWA_APP_ICONS = [
|
||||
{
|
||||
'src': '/media/icon-192x192.png',
|
||||
'sizes': '192x192'
|
||||
}
|
||||
]
|
||||
PWA_APP_ICONS_APPLE = [
|
||||
{
|
||||
'src': '/media/icon-192x192.png',
|
||||
'sizes': '192x192'
|
||||
}
|
||||
]
|
||||
PWA_APP_SPLASH_SCREEN = [
|
||||
{
|
||||
'src': '/media/icon-192x192.png',
|
||||
'media': '(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)'
|
||||
}
|
||||
]
|
||||
PWA_APP_DIR = 'ltr'
|
||||
PWA_APP_LANG = 'en-GB'
|
||||
PWA_APP_DEBUG_MODE = DEBUG
|
||||
|
||||
# Database default automatic primary key
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
# Upstream API keys
|
||||
|
||||
GOOGLE_MAPS_API_KEY = config('GOOGLE_MAPS_API_KEY', default=None)
|
||||
|
||||
303
breccia_mapper/static/css/emails.css
Normal file
303
breccia_mapper/static/css/emails.css
Normal file
@@ -0,0 +1,303 @@
|
||||
/* -------------------------------------
|
||||
GLOBAL
|
||||
A very basic CSS reset
|
||||
------------------------------------- */
|
||||
* {
|
||||
margin: 0;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
box-sizing: border-box;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-text-size-adjust: none;
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
line-height: 1.6em;
|
||||
/* 1.6em * 14px = 22.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||
/*line-height: 22px;*/
|
||||
}
|
||||
|
||||
/* Let's make sure all tables have defaults */
|
||||
table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
BODY & CONTAINER
|
||||
------------------------------------- */
|
||||
body {
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
.body-wrap {
|
||||
background-color: #f6f6f6;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: block !important;
|
||||
max-width: 600px !important;
|
||||
margin: 0 auto !important;
|
||||
/* makes it centered */
|
||||
clear: both !important;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
HEADER, FOOTER, MAIN
|
||||
------------------------------------- */
|
||||
.main {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e9e9e9;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.content-block {
|
||||
padding: 0 0 20px;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
clear: both;
|
||||
color: #999;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.footer p,
|
||||
.footer a,
|
||||
.footer td {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
TYPOGRAPHY
|
||||
------------------------------------- */
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
color: #000;
|
||||
margin: 40px 0 0;
|
||||
line-height: 1.2em;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 32px;
|
||||
font-weight: 500;
|
||||
/* 1.2em * 32px = 38.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||
/*line-height: 38px;*/
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
/* 1.2em * 24px = 28.8px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||
/*line-height: 29px;*/
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
/* 1.2em * 18px = 21.6px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||
/*line-height: 22px;*/
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol {
|
||||
margin-bottom: 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
p li,
|
||||
ul li,
|
||||
ol li {
|
||||
margin-left: 5px;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
LINKS & BUTTONS
|
||||
------------------------------------- */
|
||||
a {
|
||||
color: #348eda;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
text-decoration: none;
|
||||
color: #FFF;
|
||||
background-color: #348eda;
|
||||
border: solid #348eda;
|
||||
border-width: 10px 20px;
|
||||
line-height: 2em;
|
||||
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
|
||||
/*line-height: 28px;*/
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
border-radius: 5px;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
OTHER STYLES THAT MIGHT BE USEFUL
|
||||
------------------------------------- */
|
||||
.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.aligncenter {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.alignright {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.alignleft {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
ALERTS
|
||||
Change the class depending on warning email, good email or bad email
|
||||
------------------------------------- */
|
||||
.alert {
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.alert a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.alert.alert-warning {
|
||||
background-color: #FF9F00;
|
||||
}
|
||||
|
||||
.alert.alert-bad {
|
||||
background-color: #D0021B;
|
||||
}
|
||||
|
||||
.alert.alert-good {
|
||||
background-color: #68B90F;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
INVOICE
|
||||
Styles for the billing table
|
||||
------------------------------------- */
|
||||
.invoice {
|
||||
margin: 40px auto;
|
||||
text-align: left;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.invoice td {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.invoice .invoice-items {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.invoice .invoice-items td {
|
||||
border-top: #eee 1px solid;
|
||||
}
|
||||
|
||||
.invoice .invoice-items .total td {
|
||||
border-top: 2px solid #333;
|
||||
border-bottom: 2px solid #333;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||
------------------------------------- */
|
||||
@media only screen and (max-width: 640px) {
|
||||
body {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
font-weight: 800 !important;
|
||||
margin: 20px 0 5px !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 22px !important;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
.invoice {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=styles.css.map */
|
||||
@@ -12,10 +12,31 @@ body {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
main {
|
||||
padding-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.social_providers_list > form {
|
||||
display: inline-block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
|
||||
.footer {
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.footer .container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
/* end of sticky footer styles */
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
header.masthead {
|
||||
position: relative;
|
||||
background: #343a40 no-repeat center;
|
||||
-webkit-background-size: contain;
|
||||
-moz-background-size: contain;
|
||||
-o-background-size: contain;
|
||||
background-size: contain;
|
||||
-webkit-background-size: cover;
|
||||
-moz-background-size: cover;
|
||||
-o-background-size: cover;
|
||||
background-size: cover;
|
||||
padding-top: 8rem;
|
||||
padding-bottom: 8rem;
|
||||
min-height: 400px;
|
||||
@@ -12,6 +12,13 @@ header.masthead {
|
||||
z-index: -2;
|
||||
}
|
||||
|
||||
header.masthead.masthead-shrink {
|
||||
-webkit-background-size: contain;
|
||||
-moz-background-size: contain;
|
||||
-o-background-size: contain;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
header.masthead .overlay {
|
||||
position: absolute;
|
||||
background-color: #212529;
|
||||
@@ -27,6 +34,11 @@ header.masthead .textbox-container {
|
||||
background-color: rgba(30, 30, 30, 0.2);
|
||||
}
|
||||
|
||||
header.masthead > .row {
|
||||
max-width: 1140px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
header.masthead {
|
||||
padding-top: 1rem;
|
||||
|
||||
48
breccia_mapper/static/js/serviceworker.js
Normal file
48
breccia_mapper/static/js/serviceworker.js
Normal file
@@ -0,0 +1,48 @@
|
||||
var staticCacheName = "django-pwa-v" + new Date().getTime();
|
||||
var filesToCache = [
|
||||
"/offline/",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/fontawesome.min.css",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/solid.min.css",
|
||||
"/static/css/global.css",
|
||||
"/static/js/serviceworker.js",
|
||||
"/static/hijack/hijack.min.css",
|
||||
"/media/icon-192x192.png",
|
||||
];
|
||||
|
||||
// Cache on install
|
||||
self.addEventListener("install", event => {
|
||||
this.skipWaiting();
|
||||
event.waitUntil(
|
||||
caches.open(staticCacheName)
|
||||
.then(cache => {
|
||||
return cache.addAll(filesToCache);
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
// Clear cache on activate
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
caches.keys().then(cacheNames => {
|
||||
return Promise.all(
|
||||
cacheNames
|
||||
.filter(cacheName => (cacheName.startsWith("django-pwa-")))
|
||||
.filter(cacheName => (cacheName !== staticCacheName))
|
||||
.map(cacheName => caches.delete(cacheName))
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// Serve from Cache
|
||||
self.addEventListener("fetch", event => {
|
||||
event.respondWith(
|
||||
caches.match(event.request)
|
||||
.then(response => {
|
||||
return response || fetch(event.request);
|
||||
})
|
||||
.catch(() => {
|
||||
return caches.match('/offline/');
|
||||
})
|
||||
)
|
||||
});
|
||||
7
breccia_mapper/templates/404.html
Normal file
7
breccia_mapper/templates/404.html
Normal file
@@ -0,0 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Error 404: Page not Found</h2>
|
||||
|
||||
<p>Sorry, we can't find that page. Click <a href="{% url 'index' %}">here</a> to go home.</p>
|
||||
{% endblock content %}
|
||||
0
breccia_mapper/templates/account/Profile.html
Executable file
0
breccia_mapper/templates/account/Profile.html
Executable file
11
breccia_mapper/templates/account/account_inactive.html
Executable file
11
breccia_mapper/templates/account/account_inactive.html
Executable file
@@ -0,0 +1,11 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Account Inactive" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% trans "Account Inactive" %}</h1>
|
||||
|
||||
<p>{% trans "This account is inactive." %}</p>
|
||||
{% endblock %}
|
||||
1
breccia_mapper/templates/account/base.html
Executable file
1
breccia_mapper/templates/account/base.html
Executable file
@@ -0,0 +1 @@
|
||||
{% extends "base.html" %}
|
||||
93
breccia_mapper/templates/account/email.html
Executable file
93
breccia_mapper/templates/account/email.html
Executable file
@@ -0,0 +1,93 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Account Details" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1 class="h1" id="head_banner">Account Details</h1>
|
||||
|
||||
<h2 class="h2" id="head_banner">{% trans "Email Addresses" %}</h2>
|
||||
|
||||
{% if user.emailaddress_set.all %}
|
||||
|
||||
<p class="email_settings_info">{% trans 'The following email addresses are associated with your account:' %}</p>
|
||||
|
||||
<form action="{% url 'account_email' %}" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{% for emailaddress in user.emailaddress_set.all %}
|
||||
<div class="ctrlHolder">
|
||||
|
||||
<label for="email_radio_{{forloop.counter}}" class="{% if emailaddress.primary %}primary_email{%endif%}">
|
||||
|
||||
{{ emailaddress.email }}
|
||||
|
||||
{% if emailaddress.primary %}
|
||||
<span class="primary">(primary email)</span>
|
||||
{% endif %}
|
||||
|
||||
{% if not emailaddress.verified %}
|
||||
<span class="unverified">(not verified)</span>
|
||||
{% endif %}
|
||||
|
||||
<input id="email_radio_{{forloop.counter}}" type="radio" name="email" {% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{%endif %} value="{{emailaddress.email}}"/>
|
||||
|
||||
</label>
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div>
|
||||
<button class="btn btn-primary" type="submit" name="action_primary" >{% trans 'Make Primary' %}</button>
|
||||
<button class="btn btn-info" type="submit" name="action_send" >{% trans 'Re-send Verification' %}</button>
|
||||
<button class="btn btn-danger" type="submit" name="action_remove" >{% trans 'Remove' %}</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
|
||||
<p class="email_settings_info"><strong>{% trans 'Warning:'%}</strong> {% trans "You do not have any email addresses set up. Please add an email address to receive notifications, reset your password, and perform other account-related actions." %}</p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans "Add Email Address" %}</h3>
|
||||
|
||||
<form method="post" id="email_form" action="{% url 'account_email' %}">
|
||||
{% csrf_token %}
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form %}
|
||||
<button class="btn btn-primary" name="action_add" type="submit">{% trans "Add Email" %}</button>
|
||||
</form>
|
||||
|
||||
<h2 class="h2" id="head_banner">{% trans "Change Password" %}</h2>
|
||||
|
||||
<a class="btn btn-primary mb-4" href="{% url 'account_change_password' %}">{% trans "Change password" %}</a>
|
||||
|
||||
<h2 class="h2" id="head_banner">{% trans "Federated Login" %}</h2>
|
||||
|
||||
<p>You can connect third-party accounts to log into this site with them.</p>
|
||||
|
||||
<a class="btn btn-primary" href="{% url 'socialaccount_connections' %}">{% trans "Manage" %}</a>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_body %}
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var message = "{% trans 'Are you sure you want to remove the selected email address?' %}";
|
||||
var actions = document.getElementsByName('action_remove');
|
||||
if (actions.length) {
|
||||
actions[0].addEventListener("click", function(e) {
|
||||
if (! confirm(message)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,76 @@
|
||||
{% load account %}
|
||||
{% user_display user as user_display %}
|
||||
{% load i18n %}
|
||||
{% load inlinecss %}
|
||||
{% inlinecss "css/emails.css" %}
|
||||
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Your New {{ settings.PROJECT_LONG_NAME }} Account</title>
|
||||
</head>
|
||||
|
||||
<body itemscope itemtype="http://schema.org/EmailMessage">
|
||||
|
||||
<table class="body-wrap">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="container" width="600">
|
||||
<div class="content">
|
||||
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope
|
||||
itemtype="http://schema.org/ConfirmAction">
|
||||
<tr>
|
||||
<td class="content-wrap">
|
||||
<meta itemprop="name" content="Confirm Email" />
|
||||
<table width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td class="content-block">
|
||||
You have a new account on {{ settings.PROJECT_LONG_NAME }}. You can log in with the button below.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
Your username is <i>{{ user.username }}</i>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block" itemprop="handler" itemscope
|
||||
itemtype="http://schema.org/HttpActionHandler">
|
||||
<a href="{{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/accounts/login/" class="btn-primary" itemprop="url">Log in</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
The {{ settings.PROJECT_SHORT_NAME }} team
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="footer">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
{% endinlinecss %}
|
||||
@@ -0,0 +1,10 @@
|
||||
Dear user,
|
||||
|
||||
You have a new account on {{ settings.PROJECT_LONG_NAME }}. You can log in at the link below.
|
||||
|
||||
Your username is {{ user.username }}.
|
||||
|
||||
Log in: {{ settings.SITE_PROTOCOL }}://{{ settings.SITE_URL }}/accounts/login/
|
||||
|
||||
Thanks,
|
||||
The {{ settings.PROJECT_SHORT_NAME }} team
|
||||
71
breccia_mapper/templates/account/email/email_confirmation_message.html
Executable file
71
breccia_mapper/templates/account/email/email_confirmation_message.html
Executable file
@@ -0,0 +1,71 @@
|
||||
{% load account %}
|
||||
{% user_display user as user_display %}
|
||||
{% load i18n %}
|
||||
{% load inlinecss %}
|
||||
{% inlinecss "css/emails.css" %}
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Registration confirmation email</title>
|
||||
</head>
|
||||
|
||||
<body itemscope itemtype="http://schema.org/EmailMessage">
|
||||
|
||||
<table class="body-wrap">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="container" width="600">
|
||||
<div class="content">
|
||||
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
|
||||
<tr>
|
||||
<td class="content-wrap">
|
||||
<meta itemprop="name" content="Confirm Email"/>
|
||||
<table width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
Please confirm your email address by clicking the link below.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
We may need to send you critical information about our service, so it is important that we have your correct email address.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
|
||||
<a href="{{ activate_url }}" class="btn-primary" itemprop="url">Confirm email address</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
The {{ settings.PROJECT_SHORT_NAME }} team
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="footer">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
{% endinlinecss %}
|
||||
@@ -0,0 +1 @@
|
||||
{% include "account/email/email_confirmation_message.html" %}
|
||||
@@ -0,0 +1,4 @@
|
||||
{% load i18n %}
|
||||
{% autoescape off %}
|
||||
{% blocktrans %}Confirm Your Registration - {{ settings.PROJECT_SHORT_NAME }}{% endblocktrans %}
|
||||
{% endautoescape %}
|
||||
1
breccia_mapper/templates/account/email/email_confirmation_subject.html
Executable file
1
breccia_mapper/templates/account/email/email_confirmation_subject.html
Executable file
@@ -0,0 +1 @@
|
||||
Confirm Your Email
|
||||
69
breccia_mapper/templates/account/email/password_reset_key_message.html
Executable file
69
breccia_mapper/templates/account/email/password_reset_key_message.html
Executable file
@@ -0,0 +1,69 @@
|
||||
{% load i18n %}
|
||||
{% load inlinecss %}
|
||||
{% inlinecss "css/emails.css" %}
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Reset your Password</title>
|
||||
</head>
|
||||
|
||||
<body itemscope itemtype="http://schema.org/EmailMessage">
|
||||
|
||||
<table class="body-wrap">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="container" width="600">
|
||||
<div class="content">
|
||||
<table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
|
||||
<tr>
|
||||
<td class="content-wrap">
|
||||
<meta itemprop="name" content="Confirm Email"/>
|
||||
<table width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
<h2>{{ settings.PROJECT_LONG_NAME }}</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
Please reset your password by clicking the link below.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
We may need to send you critical information about our service, so it is important that we have your correct email address.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
|
||||
<a href="{{ password_reset_url }}" class="btn-primary" itemprop="url">Reset your password</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="content-block">
|
||||
The {{ settings.PROJECT_SHORT_NAME }} team
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="footer">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
</div></div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
{% endinlinecss %}
|
||||
4
breccia_mapper/templates/account/email/password_reset_key_subject.html
Executable file
4
breccia_mapper/templates/account/email/password_reset_key_subject.html
Executable file
@@ -0,0 +1,4 @@
|
||||
{% load i18n %}
|
||||
{% autoescape off %}
|
||||
{% blocktrans %}Reset Password - {{ settings.PROJECT_SHORT_NAME }}{% endblocktrans %}
|
||||
{% endautoescape %}
|
||||
32
breccia_mapper/templates/account/email_confirm.html
Executable file
32
breccia_mapper/templates/account/email_confirm.html
Executable file
@@ -0,0 +1,32 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
{% block head_title %}{% trans "Confirm Email Address" %}{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans "Confirm Email Address" %}</h3>
|
||||
|
||||
{% if confirmation %}
|
||||
|
||||
<p class="verification_sent_info" >{% blocktrans with confirmation.email_address.email as email %} Please confirm ownership of <a href="mailto:{{ email }}">{{ email }}</a>.{% endblocktrans %}</p>
|
||||
|
||||
<form method="post"action="{% url 'account_confirm_email' confirmation.key %}">
|
||||
{% csrf_token %}
|
||||
<button class="btn btn-success" type="submit">{% trans 'Confirm' %}</button>
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
|
||||
{% url 'account_email' as email_url %}
|
||||
|
||||
<p class="verification_sent_info" >{% blocktrans %}This email confirmation link expired or is invalid. Please <a href="{{ email_url }}">request a new email confirmation</a>. You will be redirected to the login page in 5 seconds.{% endblocktrans %}</p>
|
||||
<script>
|
||||
setTimeout("location.href = '{% url 'account_login' %}';",5000);
|
||||
</script>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
62
breccia_mapper/templates/account/login.html
Executable file
62
breccia_mapper/templates/account/login.html
Executable file
@@ -0,0 +1,62 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_links %}
|
||||
|
||||
<title>Sign In</title>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block head_title %}{% trans "Sign In" %} {% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans "Sign In" %}</h3>
|
||||
|
||||
<form id="login_form" method="POST" action="{% url 'account_login' %}">
|
||||
{% csrf_token %}
|
||||
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form %}
|
||||
|
||||
{% if redirect_field_value %}
|
||||
|
||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
||||
|
||||
{% endif %}
|
||||
|
||||
<button class="btn btn-primary " type="submit">{% trans "Log in" %}</button>
|
||||
{% if config.ALLOW_SIGNUPS %}
|
||||
<a class="btn btn-secondary" href="{% url 'account_signup' %}">Sign up</a>
|
||||
{% endif %}
|
||||
<a class="btn btn-outline-dark" href="{% url 'account_reset_password' %}">{% trans "Forgot password?" %}</a>
|
||||
|
||||
</form>
|
||||
|
||||
{% if config.ENABLE_GOOGLE_LOGIN or config.ENABLE_MICROSOFT_LOGIN %}
|
||||
|
||||
{% load account socialaccount %}
|
||||
|
||||
{% get_providers as socialaccount_providers %}
|
||||
<h5>Federated Login</h5>
|
||||
<div class="social_providers_list">
|
||||
|
||||
{% for provider in socialaccount_providers %}
|
||||
{% if provider.name == "Google" and config.ENABLE_GOOGLE_LOGIN or provider.name == "Microsoft Graph" and config.ENABLE_MICROSOFT_LOGIN %}
|
||||
<form action="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}" method="post">
|
||||
{% csrf_token %}
|
||||
<button class="btn btn-outline-dark" type="submit">
|
||||
{% if provider.name == "Microsoft Graph" %}
|
||||
Microsoft
|
||||
{% else %}
|
||||
{{provider.name}}
|
||||
{% endif %}
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
26
breccia_mapper/templates/account/logout.html
Executable file
26
breccia_mapper/templates/account/logout.html
Executable file
@@ -0,0 +1,26 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Sign Out" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans "Sign Out" %}</h3>
|
||||
|
||||
<p class="confirm_logout_info">{% trans 'Are you sure you want to sign out?' %}</p>
|
||||
|
||||
<form id="logout_form" method="post" action="{% url 'account_logout' %}">
|
||||
{% csrf_token %}
|
||||
|
||||
{% if redirect_field_value %}
|
||||
|
||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<button class="btn btn-success" type="submit">{% trans 'Sign Out' %}</button>
|
||||
<a class="btn btn-danger" id="custom_logout_no" href="/accounts/profile/">{% trans 'No' %}</a>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}You cannot remove your primary email address ({{email}}).{% endblocktrans %}
|
||||
2
breccia_mapper/templates/account/messages/email_confirmation_sent.txt
Executable file
2
breccia_mapper/templates/account/messages/email_confirmation_sent.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Confirmation email sent to {{email}}.{% endblocktrans %}
|
||||
2
breccia_mapper/templates/account/messages/email_confirmed.txt
Executable file
2
breccia_mapper/templates/account/messages/email_confirmed.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}You have confirmed {{email}}.{% endblocktrans %}
|
||||
2
breccia_mapper/templates/account/messages/email_deleted.txt
Executable file
2
breccia_mapper/templates/account/messages/email_deleted.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Removed email address {{email}}.{% endblocktrans %}
|
||||
4
breccia_mapper/templates/account/messages/logged_in.txt
Executable file
4
breccia_mapper/templates/account/messages/logged_in.txt
Executable file
@@ -0,0 +1,4 @@
|
||||
{% load account %}
|
||||
{% load i18n %}
|
||||
{% user_display user as name %}
|
||||
{% blocktrans %}Successfully logged in as {{name}}.{% endblocktrans %}
|
||||
2
breccia_mapper/templates/account/messages/logged_out.txt
Executable file
2
breccia_mapper/templates/account/messages/logged_out.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}You have signed out.{% endblocktrans %}
|
||||
2
breccia_mapper/templates/account/messages/password_changed.txt
Executable file
2
breccia_mapper/templates/account/messages/password_changed.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Password successfully changed.{% endblocktrans %}
|
||||
2
breccia_mapper/templates/account/messages/password_set.txt
Executable file
2
breccia_mapper/templates/account/messages/password_set.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Password successfully set.{% endblocktrans %}
|
||||
2
breccia_mapper/templates/account/messages/primary_email_set.txt
Executable file
2
breccia_mapper/templates/account/messages/primary_email_set.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Primary email address set.{% endblocktrans %}
|
||||
2
breccia_mapper/templates/account/messages/unverified_primary_email.txt
Executable file
2
breccia_mapper/templates/account/messages/unverified_primary_email.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Your primary email address must be verified.{% endblocktrans %}
|
||||
18
breccia_mapper/templates/account/password_change.html
Executable file
18
breccia_mapper/templates/account/password_change.html
Executable file
@@ -0,0 +1,18 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Change Password" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans "Change Password" %}</h3>
|
||||
|
||||
<form method="POST" action="{% url 'account_change_password' %}" id="change_password_form">
|
||||
{% csrf_token %}
|
||||
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form %}
|
||||
<button class="btn btn-info" type="submit" name="action">{% trans "Change Password" %}</button>
|
||||
</form>
|
||||
{% endblock %}
|
||||
26
breccia_mapper/templates/account/password_reset.html
Executable file
26
breccia_mapper/templates/account/password_reset.html
Executable file
@@ -0,0 +1,26 @@
|
||||
{% extends "account/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
|
||||
{% block head_title %}{% trans "Password Reset" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
{% include "account/snippets/already_logged_in.html" %}
|
||||
{% endif %}
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans "Password Reset" %}</h3>
|
||||
<p class="forgot_password_info" >{% trans "Forgotten your password? Enter your email address below to reset it." %}</p>
|
||||
|
||||
<form method="POST" id="forgot_password_form" action="{% url 'account_reset_password' %}">
|
||||
{% csrf_token %}
|
||||
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form %}
|
||||
<input class="btn btn-outline-primary " type="submit" value="{% trans 'Reset Password' %}" />
|
||||
</form>
|
||||
|
||||
<p class="forgot_password_info">{% blocktrans %}Please contact us if you are unable to reset your password.{% endblocktrans %}</p>
|
||||
|
||||
{% endblock %}
|
||||
20
breccia_mapper/templates/account/password_reset_done.html
Executable file
20
breccia_mapper/templates/account/password_reset_done.html
Executable file
@@ -0,0 +1,20 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
|
||||
{% block head_title %}{% trans "Password Reset" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3 class="h3" id="head_banner">{% trans "Password Reset Email Sent." %}</h3>
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
{% include "account/snippets/already_logged_in.html" %}
|
||||
{% block content_extra %} {% endblock %}
|
||||
{% else %}
|
||||
<p class="forgot_password_info">A password reset link has been sent to your email address. Please contact us if you do not receive it within a few minutes. <br> You will be redirected to <a href="{% url 'account_login' %}">sign in</a> in 5 seconds.</p>
|
||||
<script>
|
||||
setTimeout("location.href = '{% url 'account_login' %}';",5000);
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
24
breccia_mapper/templates/account/password_reset_from_key.html
Executable file
24
breccia_mapper/templates/account/password_reset_from_key.html
Executable file
@@ -0,0 +1,24 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% block head_title %}{% trans "Change Password" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}</h1>
|
||||
|
||||
{% if token_fail %}
|
||||
{% url 'account_reset_password' as passwd_reset_url %}
|
||||
<p>{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktrans %}</p>
|
||||
{% else %}
|
||||
{% if form %}
|
||||
<form method="POST" action="{{ action_url }}">
|
||||
{% csrf_token %}
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form %}
|
||||
<input type="submit" name="action" value="{% trans 'change password' %}"/>
|
||||
</form>
|
||||
{% else %}
|
||||
<p>{% trans 'Your password has been changed.' %}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
9
breccia_mapper/templates/account/password_reset_from_key_done.html
Executable file
9
breccia_mapper/templates/account/password_reset_from_key_done.html
Executable file
@@ -0,0 +1,9 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% block head_title %}{% trans "Change Password" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% trans "Change Password" %}</h1>
|
||||
<p>{% trans 'Your password has been changed.' %}</p>
|
||||
{% endblock %}
|
||||
18
breccia_mapper/templates/account/password_set.html
Executable file
18
breccia_mapper/templates/account/password_set.html
Executable file
@@ -0,0 +1,18 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Set Password" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans "Set Password" %}</h3>
|
||||
|
||||
<form method="POST" action="{% url 'account_set_password' %}" class="password_set">
|
||||
{% csrf_token %}
|
||||
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form %}
|
||||
<input class="btn btn-outline-primary btn-lg" type="submit" name="action" value="{% trans 'Set Password' %}"/>
|
||||
</form>
|
||||
{% endblock %}
|
||||
33
breccia_mapper/templates/account/signup.html
Executable file
33
breccia_mapper/templates/account/signup.html
Executable file
@@ -0,0 +1,33 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Sign Up" %}{% endblock %}
|
||||
{% block head_links %}
|
||||
|
||||
<title>Signup</title>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans "Sign Up" %}</h3>
|
||||
|
||||
<p class="exist_account_info">{% blocktrans %}Already have an account? Please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>
|
||||
|
||||
<form id="signup_form" method="post" action="{% url 'account_signup' %}">
|
||||
{% csrf_token %}
|
||||
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form %}
|
||||
|
||||
{% if redirect_field_value %}
|
||||
|
||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
||||
|
||||
{% endif %}
|
||||
|
||||
<button class="btn btn-primary" type="submit">{% trans "Sign Up" %}</button>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
11
breccia_mapper/templates/account/signup_closed.html
Executable file
11
breccia_mapper/templates/account/signup_closed.html
Executable file
@@ -0,0 +1,11 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Sign Up Closed" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% trans "Sign Up Closed" %}</h1>
|
||||
|
||||
<p>{% blocktrans with project_long_name=settings.PROJECT_LONG_NAME %}Signing up to {{ project_long_name }} is currently not permitted.{% endblocktrans %}</p>
|
||||
{% endblock %}
|
||||
11
breccia_mapper/templates/account/snippets/already_logged_in.html
Executable file
11
breccia_mapper/templates/account/snippets/already_logged_in.html
Executable file
@@ -0,0 +1,11 @@
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
|
||||
{% block content %}
|
||||
{% user_display user as user_display %}
|
||||
|
||||
<h3 class="h3" id="head_banner">Already Logged In</h3>
|
||||
<p class="forgot_password_info" >You are already logged in as {{ user_display }}.</p>
|
||||
<a class="btn btn-primary mb-4" id="custom_logout_no" href="{% url 'account_email' %}">Account Details</a>
|
||||
|
||||
{% endblock %}
|
||||
12
breccia_mapper/templates/account/verification_sent.html
Executable file
12
breccia_mapper/templates/account/verification_sent.html
Executable file
@@ -0,0 +1,12 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Verify Your Email Address" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3 class="h3" id="head_banner">{% trans "Verify Your Email Address" %}</h3>
|
||||
|
||||
<p id="verification_sent_info">{% blocktrans %}A verification email has been sent to your email address. Follow the link provided to activate your account. Contact us if you do not receive it within a few minutes.{% endblocktrans %}</p>
|
||||
|
||||
{% endblock %}
|
||||
22
breccia_mapper/templates/account/verified_email_required.html
Executable file
22
breccia_mapper/templates/account/verified_email_required.html
Executable file
@@ -0,0 +1,22 @@
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Verify Your Email Address" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% trans "Verify Your Email Address" %}</h1>
|
||||
|
||||
{% url 'account_email' as email_url %}
|
||||
|
||||
<p>{% blocktrans %}This part of the site requires us to verify that
|
||||
you are who you claim to be. We therefore require you to
|
||||
verify ownership of your email address. {% endblocktrans %}</p>
|
||||
|
||||
<p>{% blocktrans %}A verification email has been sent to your email address. Follow the link provided to activate your account. Contact us
|
||||
if you do not receive it within a few minutes.{% endblocktrans %}</p>
|
||||
|
||||
<p>{% blocktrans %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your email address</a>.{% endblocktrans %}</p>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
111
breccia_mapper/templates/base.html
Normal file → Executable file
111
breccia_mapper/templates/base.html
Normal file → Executable file
@@ -4,8 +4,14 @@
|
||||
{% load i18n %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
{% endif %}
|
||||
{% load bootstrap_customizer %}
|
||||
<html lang="{{ LANGUAGE_CODE|default:'en_us' }}">
|
||||
|
||||
{% load pwa %}
|
||||
{% load socialaccount %}
|
||||
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
@@ -14,23 +20,28 @@
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
{% bootstrap_css %}
|
||||
<style lang="css">
|
||||
{% bootstrap_theme_css_above_the_fold %}
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/fontawesome.min.css"
|
||||
integrity="sha256-/sdxenK1NDowSNuphgwjv8wSosSNZB0t5koXqd7XqOI="
|
||||
crossorigin="anonymous" />
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/fontawesome.min.css"
|
||||
integrity="sha512-giQeaPns4lQTBMRpOOHsYnGw1tGVzbAIHUyHRgn7+6FmiEgGGjaG0T2LZJmAPMzRCl+Cug0ItQ2xDZpTmEc+CQ=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer" />
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/solid.min.css"
|
||||
integrity="sha256-8DcgqUGhWHHsTLj1qcGr0OuPbKkN1RwDjIbZ6DKh/RA="
|
||||
crossorigin="anonymous" />
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/solid.min.css"
|
||||
integrity="sha512-6mc0R607di/biCutMUtU9K7NtNewiGQzrvWX4bWTeqmljZdJrwYvKJtnhgR+Ryvj+NRJ8+NnnCM/biGqMe/iRA=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer" />
|
||||
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
<link rel="stylesheet" href="{% static 'css/global.css' %}">
|
||||
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="{% static 'hijack/hijack-styles.css' %}" />
|
||||
href="{% static 'hijack/hijack.min.css' %}" />
|
||||
|
||||
{% if 'javascript_in_head'|bootstrap_setting %}
|
||||
{% if 'include_jquery'|bootstrap_setting %}
|
||||
@@ -46,11 +57,15 @@
|
||||
{{ form.media.css }}
|
||||
{% endif %}
|
||||
|
||||
<!-- PWA metadata -->
|
||||
{% progressive_web_app_meta %}
|
||||
|
||||
{% block extra_head %}{% endblock %}
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<link rel="stylesheet" type="text/css" href="{% bootstrap_theme_css_below_the_fold_url %}" />
|
||||
<div class="content" style="display: flex; flex-direction: column">
|
||||
{% block navbar %}
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
@@ -67,6 +82,12 @@
|
||||
|
||||
<div class="navbar-collapse collapse" id="navbarCollapse">
|
||||
<ul class="navbar-nav mt-2 mt-lg-0">
|
||||
<li class="nav-item">
|
||||
<a href="{% if request.user.person %}{% url 'people:person.profile' %}{% else %}{% url 'people:person.create' %}{% endif %}" class="nav-link">
|
||||
Profile
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'people:person.list' %}" class="nav-link">People</a>
|
||||
</li>
|
||||
@@ -83,15 +104,15 @@
|
||||
<a href="{% url 'activities:activity.list' %}" class="nav-link">Activities</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'people:map' %}" class="nav-link">Map</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'people:network' %}" class="nav-link">Network</a>
|
||||
</li>
|
||||
|
||||
{% if request.user.is_superuser %}
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'people:map' %}" class="nav-link">Map</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'people:network' %}" class="nav-link">Network</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'export:index' %}" class="nav-link">Export</a>
|
||||
</li>
|
||||
@@ -105,32 +126,27 @@
|
||||
<ul class="navbar-nav mt-2 mt-lg-0 ml-auto">
|
||||
{% if request.user.is_authenticated %}
|
||||
<li class="nav-item">
|
||||
{% if request.user.person %}
|
||||
<a href="{% url 'people:person.profile' %}" class="nav-link">
|
||||
<i class="fas fa-user-circle"></i>
|
||||
{{ request.user }}
|
||||
</a>
|
||||
|
||||
{% else %}
|
||||
<a href="{% url 'people:person.create' %}?user" class="nav-link">
|
||||
<i class="fas fa-user-circle"></i>
|
||||
{{ request.user }}
|
||||
</a>
|
||||
|
||||
{% endif %}
|
||||
<a href="{% url 'account_email' %}" class="nav-link">
|
||||
<i class="fa-solid fa-circle-user"></i>
|
||||
{% if request.user.first_name != "" %}
|
||||
{{ request.user.first_name }}
|
||||
{% else %}
|
||||
{{ request.user }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'logout' %}" class="nav-link">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
<a href="{% url 'account_logout' %}" class="nav-link">
|
||||
<i class="fa-solid fa-right-from-bracket"></i>
|
||||
Log Out
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a href="{% url 'login' %}" class="nav-link">
|
||||
<i class="fas fa-sign-in-alt"></i>
|
||||
<a href="{% url 'account_login' %}" class="nav-link">
|
||||
<i class="fa-solid fa-right-to-bracket"></i>
|
||||
Log In
|
||||
</a>
|
||||
</li>
|
||||
@@ -149,8 +165,30 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% load hijack_tags %}
|
||||
{% hijack_notification %}
|
||||
{% load hijack %}
|
||||
|
||||
{# Hijack notification if user is hijacked #}
|
||||
{% if person.user == request.user and request.user.is_hijacked %}
|
||||
<div class="djhj" id="djhj">
|
||||
<div class="djhj-notification">
|
||||
<div class="djhj-message">
|
||||
{% blocktrans trimmed with user=request.user %}
|
||||
You are currently working on behalf of <em>{{ user }}</em>.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
<form action="{% url 'hijack:release' %}" method="POST" class="djhj-actions">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="next" value="{{ request.path }}">
|
||||
<button class="djhj-button" onclick="document.getElementById('djhj').style.display = 'none';" type="button">
|
||||
{% trans 'hide' %}
|
||||
</button>
|
||||
<button class="djhj-button" type="submit">
|
||||
{% trans 'release' %}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if request.user.is_authenticated and not request.user.has_person %}
|
||||
<div class="alert alert-info rounded-0" role="alert">
|
||||
@@ -159,7 +197,7 @@
|
||||
Please fill in your details so you can be part of the network.
|
||||
|
||||
<a class="btn btn-success"
|
||||
href="{% url 'people:person.create' %}?user">Profile</a>
|
||||
href="{% url 'people:person.create' %}">Profile</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -190,6 +228,7 @@
|
||||
<footer class="footer bg-light">
|
||||
<div class="container">
|
||||
<span class="text-muted">{{ settings.PROJECT_LONG_NAME }}</span>
|
||||
<span class="text-muted">Developed by the <a href="https://gcrf-breccia.com">BRECcIA</a> team</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
@@ -1,62 +1,89 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block extra_head %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
<link rel="stylesheet"
|
||||
href="{% static 'css/masthead.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block before_content %}
|
||||
<header class="container-fluid masthead text-white text-left"
|
||||
style="background-image: url('https://via.placeholder.com/800x500')">
|
||||
|
||||
{% get_media_prefix as MEDIA_URL %}
|
||||
<header class="container-fluid masthead text-white text-left {% if config.HOMEPAGE_HEADER_IMAGE_SHRINK %}masthead-shrink{% endif %} py-2"
|
||||
style="background-image: url('{{ MEDIA_URL }}{{ config.HOMEPAGE_HEADER_IMAGE }}')">
|
||||
<div class="overlay"></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="ml-5 px-4 mt-3 pt-3 textbox-container">
|
||||
<h1 class="display-1">{{ settings.PROJECT_LONG_NAME }}</h1>
|
||||
<p class="lead">Snappy leader here...</p>
|
||||
<div class="px-4 my-3 pt-3 pb-2 textbox-container">
|
||||
<h1>{{ settings.PROJECT_LONG_NAME }}</h1>
|
||||
<p class="lead">{{ config.PROJECT_LEAD }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="bg-secondary py-3">
|
||||
<div class="container text-white">
|
||||
<h2>Snappy tagline here...</h2>
|
||||
<h2>{{ config.PROJECT_TAGLINE }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-light py-2 mb-4">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{% if config.HOMEPAGE_CARD_1_TITLE %}
|
||||
<div class="col-md-4 mx-auto">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Do Feature 1</h2>
|
||||
<h2 class="card-title">{{ config.HOMEPAGE_CARD_1_TITLE }}</h2>
|
||||
|
||||
<span class="fas fa-5x fa-atlas"></span>
|
||||
{% if config.HOMEPAGE_CARD_1_DESCRIPTION %}
|
||||
<p>{{ config.HOMEPAGE_CARD_1_DESCRIPTION|safe }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if config.HOMEPAGE_CARD_1_ICON %}
|
||||
<span class="fa-solid fa-5x fa-{{ config.HOMEPAGE_CARD_1_ICON }}"></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col-md-4">
|
||||
{% if config.HOMEPAGE_CARD_2_TITLE %}
|
||||
<div class="col-md-4 mx-auto">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Do Feature 2</h2>
|
||||
<h2 class="card-title">{{ config.HOMEPAGE_CARD_2_TITLE }}</h2>
|
||||
|
||||
<span class="fas fa-5x fa-atlas"></span>
|
||||
{% if config.HOMEPAGE_CARD_2_DESCRIPTION %}
|
||||
<p>{{ config.HOMEPAGE_CARD_2_DESCRIPTION|safe }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if config.HOMEPAGE_CARD_2_ICON %}
|
||||
<span class="fa-solid fa-5x fa-{{ config.HOMEPAGE_CARD_2_ICON }}"></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col-md-4">
|
||||
{% if config.HOMEPAGE_CARD_3_TITLE %}
|
||||
<div class="col-md-4 mx-auto">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Do Feature 3</h2>
|
||||
<h2 class="card-title">{{ config.HOMEPAGE_CARD_3_TITLE }}</h2>
|
||||
|
||||
<span class="fas fa-5x fa-atlas"></span>
|
||||
{% if config.HOMEPAGE_CARD_3_DESCRIPTION %}
|
||||
<p>{{ config.HOMEPAGE_CARD_3_DESCRIPTION|safe }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if config.HOMEPAGE_CARD_3_ICON %}
|
||||
<span class="fa-solid fa-5x fa-{{ config.HOMEPAGE_CARD_3_ICON }}"></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -65,15 +92,16 @@
|
||||
{% block content %}
|
||||
<div class="row align-items-center" style="min-height: 400px;">
|
||||
<div class="col-sm-8">
|
||||
<h2 class="pb-2">About {{ settings.PROJECT_LONG_NAME }}</h2>
|
||||
<h2 class="pb-2">{{ config.HOMEPAGE_ABOUT_TITLE }}</h2>
|
||||
|
||||
<p>
|
||||
{{ settings.PROJECT_LONG_NAME }} is...
|
||||
{{ config.HOMEPAGE_ABOUT_CONTENT|safe }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<img class="img-fluid py-3" src="https://via.placeholder.com/400x400">
|
||||
{% get_media_prefix as MEDIA_URL %}
|
||||
<img class="img-fluid py-3" src="{{ MEDIA_URL }}{{ config.HOMEPAGE_ABOUT_IMAGE }}">
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
8
breccia_mapper/templates/offline.html
Normal file
8
breccia_mapper/templates/offline.html
Normal file
@@ -0,0 +1,8 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Offline</h2>
|
||||
|
||||
<p>You are currently offline. Please connect to a network to use this platform.</p>
|
||||
|
||||
{% endblock %}
|
||||
@@ -9,7 +9,8 @@
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<input type="hidden" name="next" value="{{ next }}">
|
||||
<input type="submit" class="btn btn-info" value="Login">
|
||||
<input type="submit" class="btn btn-primary" value="Login">
|
||||
{% endbuttons %}
|
||||
<p>Forgot your password? Reset it <a href="{% url 'account_reset_password' %}">here</a>.</p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load bootstrap4 %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Password Reset Complete</h1>
|
||||
|
||||
<p>Your password has been successfully reset. You can now <a href="{% url 'account_login' %}">log in using it</a>.</p> If you haven't yet completed your profile, please do this now.
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,24 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load bootstrap4 %}
|
||||
|
||||
{% block content %}
|
||||
{% if validlink %}
|
||||
|
||||
<h1>Choose a New Password</h1>
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<input type="hidden" name="next" value="{{ next }}">
|
||||
<input type="submit" class="btn btn-info" value="Change password">
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
|
||||
<p>That link isn't valid - has it already been used? You can request a new link <a href="{% url 'account_reset_password' %}">here</a>.</p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load bootstrap4 %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Check Your Inbox</h1>
|
||||
|
||||
<p>We've emailed you instructions for how to reset your password.</p>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,15 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load bootstrap4 %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Password Reset</h1>
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<input type="hidden" name="next" value="{{ next }}">
|
||||
<input type="submit" class="btn btn-info" value="Send reset link">
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
11
breccia_mapper/templates/socialaccount/authentication_error.html
Executable file
11
breccia_mapper/templates/socialaccount/authentication_error.html
Executable file
@@ -0,0 +1,11 @@
|
||||
{% extends "socialaccount/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Federated Login Failure" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% trans "Federated Login Failure" %}</h1>
|
||||
|
||||
<p>{% trans "An error occurred while attempting to log in via your third party account." %}</p>
|
||||
{% endblock %}
|
||||
1
breccia_mapper/templates/socialaccount/base.html
Executable file
1
breccia_mapper/templates/socialaccount/base.html
Executable file
@@ -0,0 +1 @@
|
||||
{% extends "account/base.html" %}
|
||||
70
breccia_mapper/templates/socialaccount/connections.html
Executable file
70
breccia_mapper/templates/socialaccount/connections.html
Executable file
@@ -0,0 +1,70 @@
|
||||
{% extends "socialaccount/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Account Connections" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
<a class="btn btn-primary mb-4" href="{% url 'account_email' %}">{% trans "Account Details" %}</a>
|
||||
|
||||
<h2 class="h2" id="head_banner">{% trans "Account Connections" %}</h2>
|
||||
|
||||
{% if form.accounts %}
|
||||
<p>{% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
|
||||
<form method="post" action="{% url 'socialaccount_connections' %}">
|
||||
{% csrf_token %}
|
||||
|
||||
<fieldset>
|
||||
{% if form.non_field_errors %}
|
||||
<div id="errorMsg">{{ form.non_field_errors }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% for base_account in form.accounts %}
|
||||
{% with base_account.get_provider_account as account %}
|
||||
<div>
|
||||
<label for="id_account_{{ base_account.id }}">
|
||||
<input id="id_account_{{ base_account.id }}" type="radio" name="account"
|
||||
value="{{ base_account.id }}" />
|
||||
<span class="socialaccount_provider {{ base_account.provider }} {{ account.get_brand.id }}">
|
||||
{% if account.get_brand.name == "Microsoft Graph" %}
|
||||
Microsoft
|
||||
{% else %}
|
||||
{{ account.get_brand.name }}
|
||||
{% endif %}
|
||||
-
|
||||
</span>
|
||||
{{ account }}
|
||||
</label>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
|
||||
<div>
|
||||
<button class="btn btn-danger" type="submit">{% trans 'Remove' %}</button>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
<p>{% trans 'You currently have no third party accounts connected to this account.' %}</p>
|
||||
{% endif %}
|
||||
|
||||
<h3 class="h3" id="head_banner">{% trans 'Add Federated Login Account' %}</h3>
|
||||
|
||||
<p>Adding a third party account allows you to log in to this site with it.</p>
|
||||
|
||||
<div class="social_providers_list">
|
||||
{% include "socialaccount/snippets/provider_list.html" with process="connect" %}
|
||||
</div>
|
||||
|
||||
{% include "socialaccount/snippets/login_extra.html" %}
|
||||
|
||||
{% endblock %}
|
||||
15
breccia_mapper/templates/socialaccount/login_cancelled.html
Executable file
15
breccia_mapper/templates/socialaccount/login_cancelled.html
Executable file
@@ -0,0 +1,15 @@
|
||||
{% extends "socialaccount/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Login Cancelled" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{% trans "Login Cancelled" %}</h1>
|
||||
|
||||
{% url 'account_login' as login_url %}
|
||||
|
||||
<p>{% blocktrans %}Login was cancelled. If this was a mistake, please proceed to <a href="{{login_url}}">sign in</a>.{% endblocktrans %}</p>
|
||||
|
||||
{% endblock %}
|
||||
2
breccia_mapper/templates/socialaccount/messages/account_connected.txt
Executable file
2
breccia_mapper/templates/socialaccount/messages/account_connected.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Your third party account has been connected.{% endblocktrans %}
|
||||
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Your third party account is already connected to a different account on this site.{% endblocktrans %}
|
||||
2
breccia_mapper/templates/socialaccount/messages/account_disconnected.txt
Executable file
2
breccia_mapper/templates/socialaccount/messages/account_disconnected.txt
Executable file
@@ -0,0 +1,2 @@
|
||||
{% load i18n %}
|
||||
{% blocktrans %}Your third party account has been disconnected.{% endblocktrans %}
|
||||
24
breccia_mapper/templates/socialaccount/signup.html
Executable file
24
breccia_mapper/templates/socialaccount/signup.html
Executable file
@@ -0,0 +1,24 @@
|
||||
{% extends "socialaccount/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}{% trans "Signup" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{% trans "Sign Up" %}</h1>
|
||||
|
||||
<p>{% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are about to use your {% if provider_name == 'Microsoft Graph' %}Microsoft{% else %}{{provider_name}}{% endif %} account to sign up to
|
||||
{{site_name}}.{% endblocktrans %}</p>
|
||||
|
||||
<form class="signup" id="signup_form" method="post" action="{% url 'socialaccount_signup' %}">
|
||||
{% csrf_token %}
|
||||
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form %}
|
||||
{% if redirect_field_value %}
|
||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
||||
{% endif %}
|
||||
<button type="submit">{% trans "Sign Up" %} »</button>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
3
breccia_mapper/templates/socialaccount/snippets/login_extra.html
Executable file
3
breccia_mapper/templates/socialaccount/snippets/login_extra.html
Executable file
@@ -0,0 +1,3 @@
|
||||
{% load socialaccount %}
|
||||
|
||||
{% providers_media_js %}
|
||||
22
breccia_mapper/templates/socialaccount/snippets/provider_list.html
Executable file
22
breccia_mapper/templates/socialaccount/snippets/provider_list.html
Executable file
@@ -0,0 +1,22 @@
|
||||
{% load socialaccount %}
|
||||
|
||||
{% get_providers as socialaccount_providers %}
|
||||
|
||||
{% for provider in socialaccount_providers %}
|
||||
{% if provider.id == "openid" %}
|
||||
{% for brand in provider.get_brands %}
|
||||
<form action="{% provider_login_url provider.id openid=brand.openid_url process=process %}" method="post">
|
||||
{% csrf_token %}
|
||||
<button class="btn btn-outline-dark" type="submit">
|
||||
{{ brand.name }}
|
||||
</button>
|
||||
</form>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<form action="{% provider_login_url provider.id process=process scope=scope auth_params=auth_params %}" method="post">
|
||||
{% csrf_token %}
|
||||
<button class="btn btn-outline-dark" type="submit">
|
||||
{% if provider.name == 'Microsoft Graph' %}Microsoft{% else %}{{provider.name}}{% endif %}
|
||||
</button>
|
||||
</form>
|
||||
{% endfor %}
|
||||
@@ -14,10 +14,16 @@ Including another URLconf
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.conf import settings
|
||||
from django.urls import include, path
|
||||
from django.conf.urls.static import static
|
||||
from bootstrap_customizer import urls as bootstrap_customizer_urls
|
||||
|
||||
from . import views
|
||||
|
||||
admin.site.site_header = settings.PROJECT_LONG_NAME + " Admin"
|
||||
admin.site.site_title = settings.PROJECT_SHORT_NAME + " Admin"
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/',
|
||||
admin.site.urls),
|
||||
@@ -28,9 +34,6 @@ urlpatterns = [
|
||||
path('hijack/',
|
||||
include('hijack.urls', namespace='hijack')),
|
||||
|
||||
path('',
|
||||
include('django.contrib.auth.urls')),
|
||||
|
||||
path('',
|
||||
views.IndexView.as_view(),
|
||||
name='index'),
|
||||
@@ -47,4 +50,13 @@ urlpatterns = [
|
||||
|
||||
path('',
|
||||
include('activities.urls')),
|
||||
|
||||
path('',
|
||||
include('pwa.urls')),
|
||||
|
||||
path('accounts/',
|
||||
include('allauth.urls')),
|
||||
|
||||
path('bootstrap_customizer',
|
||||
include(bootstrap_customizer_urls)),
|
||||
] # yapf: disable
|
||||
|
||||
@@ -9,6 +9,8 @@ from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.urls import reverse
|
||||
from django.views.generic import TemplateView
|
||||
from django.views.generic.edit import UpdateView
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||
import typing
|
||||
|
||||
from . import forms
|
||||
|
||||
@@ -19,6 +21,10 @@ class IndexView(TemplateView):
|
||||
# Template set in Django settings file - may be customised by a customisation app
|
||||
template_name = settings.TEMPLATE_NAME_INDEX
|
||||
|
||||
class UserIsStaffMixin(UserPassesTestMixin):
|
||||
def test_func(self) -> typing.Optional[bool]:
|
||||
return self.request.user.is_staff
|
||||
|
||||
|
||||
class ConsentTextView(LoginRequiredMixin, UpdateView):
|
||||
"""View with consent text and form for users to indicate consent."""
|
||||
|
||||
4
deploy/Vagrantfile
vendored
4
deploy/Vagrantfile
vendored
@@ -21,9 +21,7 @@ Vagrant.configure("2") do |config|
|
||||
ansible.playbook = "playbook.yml"
|
||||
ansible.host_vars = {
|
||||
"default" => {
|
||||
"deploy_environment" => "vagrant",
|
||||
"django_debug" => 1,
|
||||
"django_secret_key" => "debug_only_g62WlORMbo8iAcV7vKCKBQ=="
|
||||
"deploy_environment" => "vagrant"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
134
deploy/deploy-ansible/example.env
Normal file
134
deploy/deploy-ansible/example.env
Normal file
@@ -0,0 +1,134 @@
|
||||
# REQUIRED=Secret key
|
||||
# Used to generate CSRF tokens - must never be made public
|
||||
SECRET_KEY=changeme
|
||||
|
||||
# REQUIRED=Database password
|
||||
# The password for the breccia-mapper user in the postgres database
|
||||
DB_PASSWORD=changeme
|
||||
|
||||
# REQUIRED=Google Maps API key
|
||||
# Google Maps API key to display maps of people's locations - required to enable map functionality
|
||||
# Default: None
|
||||
# GOOGLE_MAPS_API_KEY=None
|
||||
|
||||
# Debug
|
||||
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||
# Default: False
|
||||
DEBUG=False
|
||||
|
||||
# Project long name
|
||||
# The project's full name.
|
||||
# Default: Project Network Mapper
|
||||
# PROJECT_LONG_NAME=Project Network Mapper
|
||||
|
||||
# Project short name
|
||||
# The project's short/abbreviated name. This will also be used as the app's name when installed as PWA.
|
||||
# Default: Network Mapper
|
||||
# PROJECT_SHORT_NAME=Network Mapper
|
||||
|
||||
# Project description
|
||||
# The project's description. Used when installed as a PWA.
|
||||
# Default: Application to map network relationships in the organisation.
|
||||
# PROJECT_DESCRIPTION=Application to map network relationships in the organisation.
|
||||
|
||||
# Theme color
|
||||
# The project's theme color, in hex format (excluding the leading #).
|
||||
# Default: 212121
|
||||
# THEME_COLOR=212121
|
||||
|
||||
# Background color
|
||||
# The project's background color, in hex format (excluding the leading #).
|
||||
# Default: ffffff
|
||||
# BACKGROUND_COLOR=ffffff
|
||||
|
||||
# Allowed hosts
|
||||
# Accepted values for server header in request - protects against CSRF and CSS attacks
|
||||
# Default: * if DEBUG else localhost
|
||||
# ALLOWED_HOSTS=127.0.0.1,localhost,localhost.localdomain
|
||||
|
||||
# Site URL
|
||||
# The URL the site will be deployed on. Do not include http://, https://, or a trailing slash.
|
||||
# Default: localhost
|
||||
# SITE_URL=localhost
|
||||
|
||||
# Site protocol
|
||||
# The protocol the site uses. Valid options are http or https.
|
||||
# Default: http
|
||||
# SITE_PROTOCOL=http
|
||||
|
||||
# Trusted origins
|
||||
# The trusted origin domains of requests - protects against CSRF and CSS attacks
|
||||
# Default: '*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain'
|
||||
# TRUSTED_ORIGINS=http://127.0.0.1,http://localhost,http://localhost.localdomain
|
||||
|
||||
# Database backup storage location
|
||||
# Directory where database backups should be stored
|
||||
# Default: .dbbackup
|
||||
# DBBACKUP_STORAGE_LOCATION=.dbbackup
|
||||
|
||||
# Default language
|
||||
# Default language - used for translation - has not been enabled
|
||||
# Default: en-gb
|
||||
# LANGUAGE_CODE=en-gb
|
||||
|
||||
# Timezone
|
||||
# Default timezone
|
||||
# Default: UTC
|
||||
# TIME_ZONE=UTC
|
||||
|
||||
# Logging level
|
||||
# Level of messages written to log file
|
||||
# Default: INFO
|
||||
# LOG_LEVEL=INFO
|
||||
|
||||
# Logging filename
|
||||
# Path to logfile
|
||||
# Default: debug.log
|
||||
# LOG_FILENAME=debug.log
|
||||
|
||||
# Logging duration
|
||||
# Number of days of logs to keep - logfile is rotated out at the end of each day
|
||||
# Default: 14
|
||||
# LOG_DAYS=14
|
||||
|
||||
# STMP host
|
||||
# Hostname of SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST=None
|
||||
|
||||
# Default from email address
|
||||
# Email address from which messages are sent
|
||||
# Default: None
|
||||
# DEFAULT_FROM_EMAIL=None
|
||||
|
||||
# [DEBUG ONLY] Email file path
|
||||
# Directory where emails will be stored if not using an SMTP server
|
||||
# Default: mail.log
|
||||
# EMAIL_FILE_PATH=mail.log
|
||||
|
||||
# SMTP username
|
||||
# Username to authenticate with SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST_USER=None
|
||||
|
||||
# SMTP password
|
||||
# Password to authenticate with SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST_PASSWORD=None
|
||||
|
||||
# SMTP port
|
||||
# Port to access on SMTP server
|
||||
# Default: 25
|
||||
# EMAIL_PORT=25
|
||||
|
||||
# SMTP use TLS
|
||||
# Use TLS to communicate with SMTP server? Usually on port 587
|
||||
# Cannot be enabled at the same time as EMAIL_USE_SSL
|
||||
# Default: True if EMAIL_PORT == 587 else False
|
||||
# EMAIL_USE_TLS=True if EMAIL_PORT == 587 else False
|
||||
|
||||
# SMTP use SSL
|
||||
# Use SSL to communicate with SMTP server? Usually on port 465
|
||||
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
||||
# Default: True if EMAIL_PORT == 465 else False
|
||||
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
||||
4
deploy/deploy-ansible/inventory.example.yml
Normal file
4
deploy/deploy-ansible/inventory.example.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
all:
|
||||
hosts:
|
||||
example.com:
|
||||
|
||||
104
deploy/deploy-ansible/playbook.yml
Normal file
104
deploy/deploy-ansible/playbook.yml
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
- hosts: all
|
||||
become_user: root
|
||||
become_method: sudo
|
||||
become: yes
|
||||
|
||||
pre_tasks:
|
||||
- name: Check if running under Vagrant
|
||||
stat:
|
||||
path: /vagrant
|
||||
register: vagrant_dir
|
||||
|
||||
vars:
|
||||
project_name: network-mapper
|
||||
project_dir: /srv/{{ project_name }}
|
||||
project_src_dir: "{{ project_dir }}/src"
|
||||
provision_superuser: false
|
||||
superuser_username: admin
|
||||
superuser_password: admin
|
||||
superuser_email: email@example.com
|
||||
|
||||
tasks:
|
||||
- name: Vagrant specific tasks
|
||||
block:
|
||||
- name: Add Docker repository
|
||||
get_url:
|
||||
url: https://download.docker.com/linux/centos/docker-ce.repo
|
||||
dest: '/etc/yum.repos.d/docker-ce.repo'
|
||||
when: deploy_environment is defined and deploy_environment == "vagrant"
|
||||
|
||||
- name: Install system dependencies
|
||||
ansible.builtin.yum:
|
||||
name:
|
||||
- git
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-compose-plugin
|
||||
state: present
|
||||
|
||||
# - name: Update system packages
|
||||
# ansible.builtin.yum:
|
||||
# name: '*'
|
||||
# state: latest
|
||||
|
||||
- name: Clone / update from source repos
|
||||
ansible.builtin.git:
|
||||
repo: 'https://github.com/Southampton-RSG/breccia-mapper.git'
|
||||
dest: '{{ project_src_dir }}'
|
||||
version: dev # master
|
||||
accept_hostkey: yes
|
||||
|
||||
- name: Copy template files
|
||||
ansible.builtin.template:
|
||||
src: '{{ item }}.j2'
|
||||
dest: '{{ project_dir }}/{{ item }}'
|
||||
mode: 0600
|
||||
loop:
|
||||
- Caddyfile
|
||||
- docker-compose.yml
|
||||
|
||||
- name: Copy settings file
|
||||
ansible.builtin.copy:
|
||||
src: '.env'
|
||||
dest: '{{ project_dir }}/.env'
|
||||
mode: 0600
|
||||
|
||||
- name: Copy site icon
|
||||
ansible.builtin.copy:
|
||||
src: 'icon-192x192.png'
|
||||
dest: '{{ project_dir }}/icon-192x192.png'
|
||||
mode: 0600
|
||||
|
||||
- name: Start Docker
|
||||
ansible.builtin.systemd:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Pull latest docker images
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: docker compose pull {{ item }}
|
||||
loop:
|
||||
- caddy
|
||||
- server
|
||||
- db
|
||||
|
||||
- name: Start containers
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: docker compose up -d
|
||||
|
||||
- name: Provision superuser
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: sudo docker compose exec -it server /bin/bash -c "DJANGO_SUPERUSER_USERNAME='{{ superuser_username }}' DJANGO_SUPERUSER_PASSWORD='{{ superuser_password }}' DJANGO_SUPERUSER_EMAIL='{{ superuser_email }}' /app/manage.py createsuperuser --no-input"
|
||||
when: provision_superuser
|
||||
|
||||
- name: Display warning about new superuser
|
||||
debug:
|
||||
msg:
|
||||
- "[WARNING] A superuser has been provisioned with the username \"{{ superuser_username }}\" and the password that was provided. This user has unlimited access to the network mapper."
|
||||
when: provision_superuser
|
||||
16
deploy/deploy-ansible/templates/Caddyfile.j2
Executable file
16
deploy/deploy-ansible/templates/Caddyfile.j2
Executable file
@@ -0,0 +1,16 @@
|
||||
:80 :443 {
|
||||
root * /srv
|
||||
file_server
|
||||
|
||||
@proxy_paths {
|
||||
not path /static/*
|
||||
not path /media/*
|
||||
}
|
||||
|
||||
reverse_proxy @proxy_paths http://server:8000
|
||||
|
||||
log {
|
||||
output stderr
|
||||
format console
|
||||
}
|
||||
}
|
||||
57
deploy/deploy-ansible/templates/docker-compose.yml.j2
Executable file
57
deploy/deploy-ansible/templates/docker-compose.yml.j2
Executable file
@@ -0,0 +1,57 @@
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
server:
|
||||
image: mgrove36/breccia-mapper:latest
|
||||
build: {{ project_src_dir }}
|
||||
ports:
|
||||
- 8000:8000
|
||||
environment:
|
||||
DJANGO_DEBUG: ${DEBUG}
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- static_files:/app/static
|
||||
- media_files:/app/media
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
caddy:
|
||||
image: caddy:2
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||
# Caddy serves static files collected by Django
|
||||
- static_files:/srv/static:ro
|
||||
- media_files:/srv/media
|
||||
- {{ project_dir }}/icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
depends_on:
|
||||
- server
|
||||
|
||||
db:
|
||||
image: postgres:15.2-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: 'breccia-mapper'
|
||||
POSTGRES_USER: 'breccia-mapper'
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data/
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
static_files:
|
||||
media_files:
|
||||
postgres_data:
|
||||
16
deploy/deploy-docker/Caddyfile
Normal file
16
deploy/deploy-docker/Caddyfile
Normal file
@@ -0,0 +1,16 @@
|
||||
:80 :443 {
|
||||
root * /srv
|
||||
file_server
|
||||
|
||||
@proxy_paths {
|
||||
not path /static/*
|
||||
not path /media/*
|
||||
}
|
||||
|
||||
reverse_proxy @proxy_paths http://server:8000
|
||||
|
||||
log {
|
||||
output stderr
|
||||
format console
|
||||
}
|
||||
}
|
||||
55
deploy/deploy-docker/docker-compose.yml
Normal file
55
deploy/deploy-docker/docker-compose.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
server:
|
||||
image: mgrove36/breccia-mapper:latest
|
||||
build: .
|
||||
environment:
|
||||
DJANGO_DEBUG: ${DEBUG}
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- static_files:/app/static
|
||||
- media_files:/app/media
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
caddy:
|
||||
image: caddy:2
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||
# Caddy serves static files collected by Django
|
||||
- static_files:/srv/static:ro
|
||||
- media_files:/srv/media
|
||||
- ./icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
depends_on:
|
||||
- server
|
||||
|
||||
db:
|
||||
image: postgres:15.2-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: 'breccia-mapper'
|
||||
POSTGRES_USER: 'breccia-mapper'
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data/
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
static_files:
|
||||
media_files:
|
||||
postgres_data:
|
||||
134
deploy/deploy-docker/example.env
Normal file
134
deploy/deploy-docker/example.env
Normal file
@@ -0,0 +1,134 @@
|
||||
# REQUIRED=Secret key
|
||||
# Used to generate CSRF tokens - must never be made public
|
||||
SECRET_KEY=changeme
|
||||
|
||||
# REQUIRED=Database password
|
||||
# The password for the breccia-mapper user in the postgres database
|
||||
DB_PASSWORD=changeme
|
||||
|
||||
# REQUIRED=Google Maps API key
|
||||
# Google Maps API key to display maps of people's locations - required to enable map functionality
|
||||
# Default: None
|
||||
# GOOGLE_MAPS_API_KEY=None
|
||||
|
||||
# Debug
|
||||
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||
# Default: False
|
||||
DEBUG=False
|
||||
|
||||
# Project long name
|
||||
# The project's full name.
|
||||
# Default: Project Network Mapper
|
||||
# PROJECT_LONG_NAME=Project Network Mapper
|
||||
|
||||
# Project short name
|
||||
# The project's short/abbreviated name. This will also be used as the app's name when installed as PWA.
|
||||
# Default: Network Mapper
|
||||
# PROJECT_SHORT_NAME=Network Mapper
|
||||
|
||||
# Project description
|
||||
# The project's description. Used when installed as a PWA.
|
||||
# Default: Application to map network relationships in the organisation.
|
||||
# PROJECT_DESCRIPTION=Application to map network relationships in the organisation.
|
||||
|
||||
# Theme color
|
||||
# The project's theme color, in hex format (excluding the leading #).
|
||||
# Default: 212121
|
||||
# THEME_COLOR=212121
|
||||
|
||||
# Background color
|
||||
# The project's background color, in hex format (excluding the leading #).
|
||||
# Default: ffffff
|
||||
# BACKGROUND_COLOR=ffffff
|
||||
|
||||
# Allowed hosts
|
||||
# Accepted values for server header in request - protects against CSRF and CSS attacks
|
||||
# Default: * if DEBUG else localhost
|
||||
# ALLOWED_HOSTS=127.0.0.1,localhost,localhost.localdomain
|
||||
|
||||
# Site URL
|
||||
# The URL the site will be deployed on. Do not include http://, https://, or a trailing slash.
|
||||
# Default: localhost
|
||||
# SITE_URL=localhost
|
||||
|
||||
# Site protocol
|
||||
# The protocol the site uses. Valid options are http or https.
|
||||
# Default: http
|
||||
# SITE_PROTOCOL=http
|
||||
|
||||
# Trusted origins
|
||||
# The trusted origin domains of requests - protects against CSRF and CSS attacks
|
||||
# Default: '*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain'
|
||||
# TRUSTED_ORIGINS=http://127.0.0.1,http://localhost,http://localhost.localdomain
|
||||
|
||||
# Database backup storage location
|
||||
# Directory where database backups should be stored
|
||||
# Default: .dbbackup
|
||||
# DBBACKUP_STORAGE_LOCATION=.dbbackup
|
||||
|
||||
# Default language
|
||||
# Default language - used for translation - has not been enabled
|
||||
# Default: en-gb
|
||||
# LANGUAGE_CODE=en-gb
|
||||
|
||||
# Timezone
|
||||
# Default timezone
|
||||
# Default: UTC
|
||||
# TIME_ZONE=UTC
|
||||
|
||||
# Logging level
|
||||
# Level of messages written to log file
|
||||
# Default: INFO
|
||||
# LOG_LEVEL=INFO
|
||||
|
||||
# Logging filename
|
||||
# Path to logfile
|
||||
# Default: debug.log
|
||||
# LOG_FILENAME=debug.log
|
||||
|
||||
# Logging duration
|
||||
# Number of days of logs to keep - logfile is rotated out at the end of each day
|
||||
# Default: 14
|
||||
# LOG_DAYS=14
|
||||
|
||||
# STMP host
|
||||
# Hostname of SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST=None
|
||||
|
||||
# Default from email address
|
||||
# Email address from which messages are sent
|
||||
# Default: None
|
||||
# DEFAULT_FROM_EMAIL=None
|
||||
|
||||
# [DEBUG ONLY] Email file path
|
||||
# Directory where emails will be stored if not using an SMTP server
|
||||
# Default: mail.log
|
||||
# EMAIL_FILE_PATH=mail.log
|
||||
|
||||
# SMTP username
|
||||
# Username to authenticate with SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST_USER=None
|
||||
|
||||
# SMTP password
|
||||
# Password to authenticate with SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST_PASSWORD=None
|
||||
|
||||
# SMTP port
|
||||
# Port to access on SMTP server
|
||||
# Default: 25
|
||||
# EMAIL_PORT=25
|
||||
|
||||
# SMTP use TLS
|
||||
# Use TLS to communicate with SMTP server? Usually on port 587
|
||||
# Cannot be enabled at the same time as EMAIL_USE_SSL
|
||||
# Default: True if EMAIL_PORT == 587 else False
|
||||
# EMAIL_USE_TLS=True if EMAIL_PORT == 587 else False
|
||||
|
||||
# SMTP use SSL
|
||||
# Use SSL to communicate with SMTP server? Usually on port 465
|
||||
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
||||
# Default: True if EMAIL_PORT == 465 else False
|
||||
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
||||
28
deploy/deploy-vagrant/Vagrantfile
vendored
Normal file
28
deploy/deploy-vagrant/Vagrantfile
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# All Vagrant configuration is done below. The "2" in Vagrant.configure
|
||||
# configures the configuration version (we support older styles for
|
||||
# backwards compatibility). Please don't change it unless you know what
|
||||
# you're doing.
|
||||
Vagrant.configure("2") do |config|
|
||||
# Every Vagrant development environment requires a box. You can search for
|
||||
# boxes at https://vagrantcloud.com/search.
|
||||
config.vm.box = "generic/rocky8"
|
||||
|
||||
# Create a forwarded port mapping which allows access to a specific port
|
||||
# within the machine from a port on the host machine and only allow access
|
||||
# via 127.0.0.1 to disable public access
|
||||
config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
|
||||
|
||||
# Provision VM using Ansible playbook
|
||||
config.vm.provision "ansible" do |ansible|
|
||||
ansible.verbose = "v"
|
||||
ansible.playbook = "playbook.yml"
|
||||
ansible.host_vars = {
|
||||
"default" => {
|
||||
"deploy_environment" => "vagrant"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
134
deploy/deploy-vagrant/example.env
Normal file
134
deploy/deploy-vagrant/example.env
Normal file
@@ -0,0 +1,134 @@
|
||||
# REQUIRED=Secret key
|
||||
# Used to generate CSRF tokens - must never be made public
|
||||
SECRET_KEY=changeme
|
||||
|
||||
# REQUIRED=Database password
|
||||
# The password for the breccia-mapper user in the postgres database
|
||||
DB_PASSWORD=changeme
|
||||
|
||||
# REQUIRED=Google Maps API key
|
||||
# Google Maps API key to display maps of people's locations - required to enable map functionality
|
||||
# Default: None
|
||||
# GOOGLE_MAPS_API_KEY=None
|
||||
|
||||
# Debug
|
||||
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||
# Default: False
|
||||
DEBUG=False
|
||||
|
||||
# Project long name
|
||||
# The project's full name.
|
||||
# Default: Project Network Mapper
|
||||
# PROJECT_LONG_NAME=Project Network Mapper
|
||||
|
||||
# Project short name
|
||||
# The project's short/abbreviated name. This will also be used as the app's name when installed as PWA.
|
||||
# Default: Network Mapper
|
||||
# PROJECT_SHORT_NAME=Network Mapper
|
||||
|
||||
# Project description
|
||||
# The project's description. Used when installed as a PWA.
|
||||
# Default: Application to map network relationships in the organisation.
|
||||
# PROJECT_DESCRIPTION=Application to map network relationships in the organisation.
|
||||
|
||||
# Theme color
|
||||
# The project's theme color, in hex format (excluding the leading #).
|
||||
# Default: 212121
|
||||
# THEME_COLOR=212121
|
||||
|
||||
# Background color
|
||||
# The project's background color, in hex format (excluding the leading #).
|
||||
# Default: ffffff
|
||||
# BACKGROUND_COLOR=ffffff
|
||||
|
||||
# Allowed hosts
|
||||
# Accepted values for server header in request - protects against CSRF and CSS attacks
|
||||
# Default: * if DEBUG else localhost
|
||||
# ALLOWED_HOSTS=127.0.0.1,localhost,localhost.localdomain
|
||||
|
||||
# Site URL
|
||||
# The URL the site will be deployed on. Do not include http://, https://, or a trailing slash.
|
||||
# Default: localhost
|
||||
# SITE_URL=localhost
|
||||
|
||||
# Site protocol
|
||||
# The protocol the site uses. Valid options are http or https.
|
||||
# Default: http
|
||||
# SITE_PROTOCOL=http
|
||||
|
||||
# Trusted origins
|
||||
# The trusted origin domains of requests - protects against CSRF and CSS attacks
|
||||
# Default: '*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain'
|
||||
# TRUSTED_ORIGINS=http://127.0.0.1,http://localhost,http://localhost.localdomain
|
||||
|
||||
# Database backup storage location
|
||||
# Directory where database backups should be stored
|
||||
# Default: .dbbackup
|
||||
# DBBACKUP_STORAGE_LOCATION=.dbbackup
|
||||
|
||||
# Default language
|
||||
# Default language - used for translation - has not been enabled
|
||||
# Default: en-gb
|
||||
# LANGUAGE_CODE=en-gb
|
||||
|
||||
# Timezone
|
||||
# Default timezone
|
||||
# Default: UTC
|
||||
# TIME_ZONE=UTC
|
||||
|
||||
# Logging level
|
||||
# Level of messages written to log file
|
||||
# Default: INFO
|
||||
# LOG_LEVEL=INFO
|
||||
|
||||
# Logging filename
|
||||
# Path to logfile
|
||||
# Default: debug.log
|
||||
# LOG_FILENAME=debug.log
|
||||
|
||||
# Logging duration
|
||||
# Number of days of logs to keep - logfile is rotated out at the end of each day
|
||||
# Default: 14
|
||||
# LOG_DAYS=14
|
||||
|
||||
# STMP host
|
||||
# Hostname of SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST=None
|
||||
|
||||
# Default from email address
|
||||
# Email address from which messages are sent
|
||||
# Default: None
|
||||
# DEFAULT_FROM_EMAIL=None
|
||||
|
||||
# [DEBUG ONLY] Email file path
|
||||
# Directory where emails will be stored if not using an SMTP server
|
||||
# Default: mail.log
|
||||
# EMAIL_FILE_PATH=mail.log
|
||||
|
||||
# SMTP username
|
||||
# Username to authenticate with SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST_USER=None
|
||||
|
||||
# SMTP password
|
||||
# Password to authenticate with SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST_PASSWORD=None
|
||||
|
||||
# SMTP port
|
||||
# Port to access on SMTP server
|
||||
# Default: 25
|
||||
# EMAIL_PORT=25
|
||||
|
||||
# SMTP use TLS
|
||||
# Use TLS to communicate with SMTP server? Usually on port 587
|
||||
# Cannot be enabled at the same time as EMAIL_USE_SSL
|
||||
# Default: True if EMAIL_PORT == 587 else False
|
||||
# EMAIL_USE_TLS=True if EMAIL_PORT == 587 else False
|
||||
|
||||
# SMTP use SSL
|
||||
# Use SSL to communicate with SMTP server? Usually on port 465
|
||||
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
||||
# Default: True if EMAIL_PORT == 465 else False
|
||||
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
||||
104
deploy/deploy-vagrant/playbook.yml
Normal file
104
deploy/deploy-vagrant/playbook.yml
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
- hosts: all
|
||||
become_user: root
|
||||
become_method: sudo
|
||||
become: yes
|
||||
|
||||
pre_tasks:
|
||||
- name: Check if running under Vagrant
|
||||
stat:
|
||||
path: /vagrant
|
||||
register: vagrant_dir
|
||||
|
||||
vars:
|
||||
project_name: network-mapper
|
||||
project_dir: /srv/{{ project_name }}
|
||||
project_src_dir: "{{ project_dir }}/src"
|
||||
provision_superuser: false
|
||||
superuser_username: admin
|
||||
superuser_password: admin
|
||||
superuser_email: email@example.com
|
||||
|
||||
tasks:
|
||||
- name: Vagrant specific tasks
|
||||
block:
|
||||
- name: Add Docker repository
|
||||
get_url:
|
||||
url: https://download.docker.com/linux/centos/docker-ce.repo
|
||||
dest: '/etc/yum.repos.d/docker-ce.repo'
|
||||
when: deploy_environment is defined and deploy_environment == "vagrant"
|
||||
|
||||
- name: Install system dependencies
|
||||
ansible.builtin.yum:
|
||||
name:
|
||||
- git
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-compose-plugin
|
||||
state: present
|
||||
|
||||
# - name: Update system packages
|
||||
# ansible.builtin.yum:
|
||||
# name: '*'
|
||||
# state: latest
|
||||
|
||||
- name: Clone / update from source repos
|
||||
ansible.builtin.git:
|
||||
repo: 'https://github.com/Southampton-RSG/breccia-mapper.git'
|
||||
dest: '{{ project_src_dir }}'
|
||||
version: dev # master
|
||||
accept_hostkey: yes
|
||||
|
||||
- name: Copy template files
|
||||
ansible.builtin.template:
|
||||
src: '{{ item }}.j2'
|
||||
dest: '{{ project_dir }}/{{ item }}'
|
||||
mode: 0600
|
||||
loop:
|
||||
- Caddyfile
|
||||
- docker-compose.yml
|
||||
|
||||
- name: Copy settings file
|
||||
ansible.builtin.copy:
|
||||
src: '.env'
|
||||
dest: '{{ project_dir }}/.env'
|
||||
mode: 0600
|
||||
|
||||
- name: Copy site icon
|
||||
ansible.builtin.copy:
|
||||
src: 'icon-192x192.png'
|
||||
dest: '{{ project_dir }}/icon-192x192.png'
|
||||
mode: 0600
|
||||
|
||||
- name: Start Docker
|
||||
ansible.builtin.systemd:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Pull latest docker images
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: docker compose pull {{ item }}
|
||||
loop:
|
||||
- caddy
|
||||
- server
|
||||
- db
|
||||
|
||||
- name: Start containers
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: docker compose up -d
|
||||
|
||||
- name: Provision superuser
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: sudo docker compose exec -it server /bin/bash -c "DJANGO_SUPERUSER_USERNAME='{{ superuser_username }}' DJANGO_SUPERUSER_PASSWORD='{{ superuser_password }}' DJANGO_SUPERUSER_EMAIL='{{ superuser_email }}' /app/manage.py createsuperuser --no-input"
|
||||
when: provision_superuser
|
||||
|
||||
- name: Display warning about new superuser
|
||||
debug:
|
||||
msg:
|
||||
- "[WARNING] A superuser has been provisioned with the username \"{{ superuser_username }}\" and the password that was provided. This user has unlimited access to the network mapper."
|
||||
when: provision_superuser
|
||||
16
deploy/deploy-vagrant/templates/Caddyfile.j2
Executable file
16
deploy/deploy-vagrant/templates/Caddyfile.j2
Executable file
@@ -0,0 +1,16 @@
|
||||
:80 :443 {
|
||||
root * /srv
|
||||
file_server
|
||||
|
||||
@proxy_paths {
|
||||
not path /static/*
|
||||
not path /media/*
|
||||
}
|
||||
|
||||
reverse_proxy @proxy_paths http://server:8000
|
||||
|
||||
log {
|
||||
output stderr
|
||||
format console
|
||||
}
|
||||
}
|
||||
57
deploy/deploy-vagrant/templates/docker-compose.yml.j2
Executable file
57
deploy/deploy-vagrant/templates/docker-compose.yml.j2
Executable file
@@ -0,0 +1,57 @@
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
server:
|
||||
image: mgrove36/breccia-mapper:latest
|
||||
build: {{ project_src_dir }}
|
||||
ports:
|
||||
- 8000:8000
|
||||
environment:
|
||||
DJANGO_DEBUG: ${DEBUG}
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- static_files:/app/static
|
||||
- media_files:/app/media
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
caddy:
|
||||
image: caddy:2
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||
# Caddy serves static files collected by Django
|
||||
- static_files:/srv/static:ro
|
||||
- media_files:/srv/media
|
||||
- {{ project_dir }}/icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
depends_on:
|
||||
- server
|
||||
|
||||
db:
|
||||
image: postgres:15.2-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: 'breccia-mapper'
|
||||
POSTGRES_USER: 'breccia-mapper'
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data/
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
static_files:
|
||||
media_files:
|
||||
postgres_data:
|
||||
134
deploy/example.env
Normal file
134
deploy/example.env
Normal file
@@ -0,0 +1,134 @@
|
||||
# REQUIRED=Secret key
|
||||
# Used to generate CSRF tokens - must never be made public
|
||||
SECRET_KEY=changeme
|
||||
|
||||
# REQUIRED=Database password
|
||||
# The password for the breccia-mapper user in the postgres database
|
||||
DB_PASSWORD=changeme
|
||||
|
||||
# REQUIRED=Google Maps API key
|
||||
# Google Maps API key to display maps of people's locations - required to enable map functionality
|
||||
# Default: None
|
||||
# GOOGLE_MAPS_API_KEY=None
|
||||
|
||||
# Debug
|
||||
# Should the server run in debug mode? Provides information to users which is unsafe in production
|
||||
# Default: False
|
||||
DEBUG=False
|
||||
|
||||
# Project long name
|
||||
# The project's full name.
|
||||
# Default: Project Network Mapper
|
||||
# PROJECT_LONG_NAME=Project Network Mapper
|
||||
|
||||
# Project short name
|
||||
# The project's short/abbreviated name. This will also be used as the app's name when installed as PWA.
|
||||
# Default: Network Mapper
|
||||
# PROJECT_SHORT_NAME=Network Mapper
|
||||
|
||||
# Project description
|
||||
# The project's description. Used when installed as a PWA.
|
||||
# Default: Application to map network relationships in the organisation.
|
||||
# PROJECT_DESCRIPTION=Application to map network relationships in the organisation.
|
||||
|
||||
# Theme color
|
||||
# The project's theme color, in hex format (excluding the leading #).
|
||||
# Default: 212121
|
||||
# THEME_COLOR=212121
|
||||
|
||||
# Background color
|
||||
# The project's background color, in hex format (excluding the leading #).
|
||||
# Default: ffffff
|
||||
# BACKGROUND_COLOR=ffffff
|
||||
|
||||
# Allowed hosts
|
||||
# Accepted values for server header in request - protects against CSRF and CSS attacks
|
||||
# Default: * if DEBUG else localhost
|
||||
# ALLOWED_HOSTS=127.0.0.1,localhost,localhost.localdomain
|
||||
|
||||
# Site URL
|
||||
# The URL the site will be deployed on. Do not include http://, https://, or a trailing slash.
|
||||
# Default: localhost
|
||||
# SITE_URL=localhost
|
||||
|
||||
# Site protocol
|
||||
# The protocol the site uses. Valid options are http or https.
|
||||
# Default: http
|
||||
# SITE_PROTOCOL=http
|
||||
|
||||
# Trusted origins
|
||||
# The trusted origin domains of requests - protects against CSRF and CSS attacks
|
||||
# Default: '*' if DEBUG else 'http://127.0.0.1,http://localhost,http://localhost.localdomain'
|
||||
# TRUSTED_ORIGINS=http://127.0.0.1,http://localhost,http://localhost.localdomain
|
||||
|
||||
# Database backup storage location
|
||||
# Directory where database backups should be stored
|
||||
# Default: .dbbackup
|
||||
# DBBACKUP_STORAGE_LOCATION=.dbbackup
|
||||
|
||||
# Default language
|
||||
# Default language - used for translation - has not been enabled
|
||||
# Default: en-gb
|
||||
# LANGUAGE_CODE=en-gb
|
||||
|
||||
# Timezone
|
||||
# Default timezone
|
||||
# Default: UTC
|
||||
# TIME_ZONE=UTC
|
||||
|
||||
# Logging level
|
||||
# Level of messages written to log file
|
||||
# Default: INFO
|
||||
# LOG_LEVEL=INFO
|
||||
|
||||
# Logging filename
|
||||
# Path to logfile
|
||||
# Default: debug.log
|
||||
# LOG_FILENAME=debug.log
|
||||
|
||||
# Logging duration
|
||||
# Number of days of logs to keep - logfile is rotated out at the end of each day
|
||||
# Default: 14
|
||||
# LOG_DAYS=14
|
||||
|
||||
# STMP host
|
||||
# Hostname of SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST=None
|
||||
|
||||
# Default from email address
|
||||
# Email address from which messages are sent
|
||||
# Default: None
|
||||
# DEFAULT_FROM_EMAIL=None
|
||||
|
||||
# [DEBUG ONLY] Email file path
|
||||
# Directory where emails will be stored if not using an SMTP server
|
||||
# Default: mail.log
|
||||
# EMAIL_FILE_PATH=mail.log
|
||||
|
||||
# SMTP username
|
||||
# Username to authenticate with SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST_USER=None
|
||||
|
||||
# SMTP password
|
||||
# Password to authenticate with SMTP server
|
||||
# Default: None
|
||||
# EMAIL_HOST_PASSWORD=None
|
||||
|
||||
# SMTP port
|
||||
# Port to access on SMTP server
|
||||
# Default: 25
|
||||
# EMAIL_PORT=25
|
||||
|
||||
# SMTP use TLS
|
||||
# Use TLS to communicate with SMTP server? Usually on port 587
|
||||
# Cannot be enabled at the same time as EMAIL_USE_SSL
|
||||
# Default: True if EMAIL_PORT == 587 else False
|
||||
# EMAIL_USE_TLS=True if EMAIL_PORT == 587 else False
|
||||
|
||||
# SMTP use SSL
|
||||
# Use SSL to communicate with SMTP server? Usually on port 465
|
||||
# Cannot be enabled at the same time as EMAIL_USE_TLS
|
||||
# Default: True if EMAIL_PORT == 465 else False
|
||||
# EMAIL_USE_SSL=True if EMAIL_PORT == 465 else False
|
||||
@@ -1,5 +1,4 @@
|
||||
all:
|
||||
hosts:
|
||||
example.com:
|
||||
django_debug: 1
|
||||
django_secret_key: debug_only_g62WlORMbo8iAcV7vKCKBQ==
|
||||
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
register: vagrant_dir
|
||||
|
||||
vars:
|
||||
project_name: mapper
|
||||
project_name: network-mapper
|
||||
project_dir: /srv/{{ project_name }}
|
||||
project_src_dir: "{{ project_dir }}/src"
|
||||
provision_superuser: false
|
||||
superuser_username: admin
|
||||
superuser_password: admin
|
||||
superuser_email: email@example.com
|
||||
|
||||
tasks:
|
||||
- name: Vagrant specific tasks
|
||||
@@ -43,7 +47,7 @@
|
||||
ansible.builtin.git:
|
||||
repo: 'https://github.com/Southampton-RSG/breccia-mapper.git'
|
||||
dest: '{{ project_src_dir }}'
|
||||
version: docker
|
||||
version: dev # master
|
||||
accept_hostkey: yes
|
||||
|
||||
- name: Copy template files
|
||||
@@ -55,10 +59,17 @@
|
||||
- Caddyfile
|
||||
- docker-compose.yml
|
||||
|
||||
- name: Create database file
|
||||
ansible.builtin.file:
|
||||
path: "{{ project_dir }}/db.sqlite3"
|
||||
state: touch
|
||||
- name: Copy settings file
|
||||
ansible.builtin.copy:
|
||||
src: '.env'
|
||||
dest: '{{ project_dir }}/.env'
|
||||
mode: 0600
|
||||
|
||||
- name: Copy site icon
|
||||
ansible.builtin.copy:
|
||||
src: 'icon-192x192.png'
|
||||
dest: '{{ project_dir }}/icon-192x192.png'
|
||||
mode: 0600
|
||||
|
||||
- name: Start Docker
|
||||
ansible.builtin.systemd:
|
||||
@@ -72,15 +83,22 @@
|
||||
cmd: docker compose pull {{ item }}
|
||||
loop:
|
||||
- caddy
|
||||
|
||||
- name: Build custom images
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: docker compose build {{ item }}
|
||||
loop:
|
||||
- web
|
||||
- server
|
||||
- db
|
||||
|
||||
- name: Start containers
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: docker compose up -d
|
||||
|
||||
- name: Provision superuser
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ project_dir }}"
|
||||
cmd: sudo docker compose exec -it server /bin/bash -c "DJANGO_SUPERUSER_USERNAME='{{ superuser_username }}' DJANGO_SUPERUSER_PASSWORD='{{ superuser_password }}' DJANGO_SUPERUSER_EMAIL='{{ superuser_email }}' /app/manage.py createsuperuser --no-input"
|
||||
when: provision_superuser
|
||||
|
||||
- name: Display warning about new superuser
|
||||
debug:
|
||||
msg:
|
||||
- "[WARNING] A superuser has been provisioned with the username \"{{ superuser_username }}\" and the password that was provided. This user has unlimited access to the network mapper."
|
||||
when: provision_superuser
|
||||
7
deploy/templates/Caddyfile.j2
Normal file → Executable file
7
deploy/templates/Caddyfile.j2
Normal file → Executable file
@@ -1,15 +1,16 @@
|
||||
http://* {
|
||||
:80 :443 {
|
||||
root * /srv
|
||||
file_server
|
||||
|
||||
@proxy_paths {
|
||||
not path /static/*
|
||||
not path /media/*
|
||||
}
|
||||
|
||||
reverse_proxy @proxy_paths http://web:8000
|
||||
reverse_proxy @proxy_paths http://server:8000
|
||||
|
||||
log {
|
||||
output stderr
|
||||
format single_field common_log
|
||||
format console
|
||||
}
|
||||
}
|
||||
38
deploy/templates/docker-compose.yml.j2
Normal file → Executable file
38
deploy/templates/docker-compose.yml.j2
Normal file → Executable file
@@ -1,18 +1,19 @@
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
web:
|
||||
image: breccia-mapper
|
||||
server:
|
||||
image: mgrove36/breccia-mapper:latest
|
||||
build: {{ project_src_dir }}
|
||||
ports:
|
||||
- 8000:8000
|
||||
environment:
|
||||
DEBUG: {{ django_debug }}
|
||||
DATABASE_URL: sqlite:////app/db.sqlite3
|
||||
SECRET_KEY: {{ django_secret_key }}
|
||||
DJANGO_DEBUG: ${DEBUG}
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- {{ project_dir }}/db.sqlite3:/app/db.sqlite3:z
|
||||
- static_files:/app/static
|
||||
- media_files:/app/media
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
caddy:
|
||||
image: caddy:2
|
||||
@@ -24,12 +25,31 @@ services:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||
# Caddy serves static files collected by Django
|
||||
- static_files:/srv/static:ro
|
||||
- media_files:/srv/media
|
||||
- {{ project_dir }}/icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
depends_on:
|
||||
- web
|
||||
- server
|
||||
|
||||
db:
|
||||
image: postgres:15.2-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: 'breccia-mapper'
|
||||
POSTGRES_USER: 'breccia-mapper'
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data/
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
static_files:
|
||||
media_files:
|
||||
postgres_data:
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
version: '3.1'
|
||||
|
||||
services:
|
||||
web:
|
||||
image: breccia-mapper
|
||||
server:
|
||||
image: mgrove36/breccia-mapper:latest
|
||||
build: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
environment:
|
||||
DEBUG: ${DJANGO_DEBUG}
|
||||
DATABASE_URL: sqlite:////app/db.sqlite3
|
||||
SECRET_KEY: ${DJANGO_SECRET_KEY}
|
||||
DJANGO_DEBUG: ${DEBUG}
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- ./db.sqlite3:/app/db.sqlite3:z
|
||||
- static_files:/app/static
|
||||
- media_files:/app/media
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
caddy:
|
||||
image: caddy:2
|
||||
@@ -24,12 +25,31 @@ services:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||
# Caddy serves static files collected by Django
|
||||
- static_files:/srv/static:ro
|
||||
- media_files:/srv/media
|
||||
- ./icon-192x192.png:/srv/media/icon-192x192.png:ro
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
depends_on:
|
||||
- web
|
||||
- server
|
||||
|
||||
db:
|
||||
image: postgres:15.2-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: 'breccia-mapper'
|
||||
POSTGRES_USER: 'breccia-mapper'
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data/
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U breccia-mapper"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
static_files:
|
||||
media_files:
|
||||
postgres_data:
|
||||
|
||||
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.https://www.sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
199
docs/source/1-deployment.md
Normal file
199
docs/source/1-deployment.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# Deployment
|
||||
|
||||
The [BRECcIA Network Mapper](https://github.com/Southampton-RSG/breccia-mapper) can be deployed in a variety of ways, most of which utilise Docker.
|
||||
Ansible deployment has been tested on RHEL7 and RHEL8.
|
||||
|
||||
## Choosing How to Deploy
|
||||
|
||||
If you are an organisation deploying the app on a server, [Ansible](#ansible) is recommended. If Ansible is not used on your server, [Docker Compose](#docker-compose) or [Vagrant](#vagrant) are recommended.
|
||||
|
||||
If you are an individual deploying the app on your local machine, [Docker (for individuals)](#docker-for-individuals) is recommended. However, if you are planning on making the app accessible to other people (outside your computer), we advise deploying the app on a server.
|
||||
|
||||
## Ansible
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- [Ansible](https://www.ansible.com/)
|
||||
|
||||
:::{note}
|
||||
Deployment with Ansible has been tested on RHEL7 and RHEL8, but is compatible with other Linux distributions with minor changes to the playbook (`playbook.yml`)
|
||||
:::
|
||||
|
||||
To deploy the BRECcIA Network Mapper with Ansible:
|
||||
|
||||
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
||||
|
||||
```bash
|
||||
curl https://github.com/Southampton-RSG/breccia-mapper/releases/latest/download/deploy-ansible.tar.gz | tar xzv && cd network-mapper
|
||||
```
|
||||
|
||||
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in the `network-mapper` folder.
|
||||
|
||||
3. Copy `example.env` to `.env`:
|
||||
|
||||
```bash
|
||||
cp example.env .env
|
||||
```
|
||||
|
||||
4. Edit this file as desired. Note that some variables are required, and that `True` and `False` values must have correct capitalisation.
|
||||
5. Copy `inventory.example.yml` to `inventory.yml`:
|
||||
|
||||
```bash
|
||||
cp inventory.example.yml inventory.yml
|
||||
```
|
||||
|
||||
6. Edit this file to reflect your Ansible setup:
|
||||
- Use your server's hostname instead of `example.com`
|
||||
7. If you would like a new superuser to be provisioned (e.g. during initial install), edit the `provision_superuser` variable in `playbook.yml` to `true`.
|
||||
- Then change the `superuser_*` options below it as desired.
|
||||
8. Run the Ansible playbook `playbook.yml` with this inventory file using:
|
||||
|
||||
```bash
|
||||
ansible-playbook playbook.yml -i inventory.yml -K -k -u <SSH username>
|
||||
```
|
||||
|
||||
This will ask for your SSH and sudo passwords for the server before deploying.
|
||||
To redeploy updates, the same command can be run again - it's safe to redeploy on top of an existing deployment.
|
||||
|
||||
:::{warning}
|
||||
If you changed the `provision_superuser` variable in `playbook.yml` to `true`, remember to change it back to `false`.
|
||||
:::
|
||||
|
||||
|
||||
## Docker Compose
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- [Docker Compose](https://docs.docker.com/compose) (installed by default with most [Docker](https://docker.com/) installs)
|
||||
|
||||
:::{note}
|
||||
Deployment with Docker has been tested on RHEL7, RHEL8, and Ubuntu 22.04 LTS
|
||||
:::
|
||||
|
||||
To deploy the BRECcIA Network Mapper with Docker:
|
||||
|
||||
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
||||
|
||||
```bash
|
||||
curl https://github.com/Southampton-RSG/releases/latest/download/deploy-docker.tar.gz | tar xzv && cd network-mapper
|
||||
```
|
||||
|
||||
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in the `network-mapper` folder.
|
||||
3. Copy `example.env` to `.env`:
|
||||
|
||||
```bash
|
||||
cp example.env .env
|
||||
```
|
||||
|
||||
4. Edit this file as desired. Note that some variables are required, and that `True` and `False` values must have correct capitalisation.
|
||||
5. Start the containers with the following command (you may need to use `sudo`):
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
6. If desired (e.g. on initial deployment), create a superuser by running the following, and enter their details when prompted:
|
||||
|
||||
```bash
|
||||
docker compose exec -it server /bin/bash -c "/app/manage.py createsuperuser"
|
||||
```
|
||||
|
||||
:::{important}
|
||||
If you don't create a superuser when you first deploy the app, you will be unable to log in.
|
||||
:::
|
||||
|
||||
## Vagrant
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- [Vagrant](https://www.vagrantup.com/)
|
||||
- [Ansible](https://www.ansible.com/)
|
||||
|
||||
To deploy the BRECcIA Network Mapper with Vagrant:
|
||||
|
||||
1. Download and extract the deployment files from [the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest):
|
||||
|
||||
```bash
|
||||
curl https://github.com/Southampton-RSG/releases/latest/download/deploy-vagrant.tar.gz | tar xzv && cd network-mapper
|
||||
```
|
||||
|
||||
2. Copy your logo (192x192 pixels) to `icon-192x192.png` in the `network-mapper` folder.
|
||||
3. Copy `example.env` to `.env`:
|
||||
|
||||
```bash
|
||||
cp example.env .env
|
||||
```
|
||||
|
||||
4. Edit this file as desired. Note that some variables are required, and that `True` and `False` values must have correct capitalisation.
|
||||
5. If you would like a new superuser to be provisioned (e.g. during initial install), edit the `provision_superuser` variable in `playbook.yml` to `true`.
|
||||
- Then change the `superuser_*` options below it as desired.
|
||||
6. To change where the app is accessible from, edit the `config.vm.network` line in `Vagrantfile`.
|
||||
- By default, the app is accessible only from `http://localhost:8080`.
|
||||
- To make it available from any IP address, replace `host: 8080, host_ip: "127.0.0.1"` with `host: 8080`.
|
||||
- To change the port the app is available on, edit `host: 8080`.
|
||||
- More details are available in the [Vagrant docs](https://developer.hashicorp.com/vagrant/docs/networking).
|
||||
6. Start the virtual machine:
|
||||
|
||||
```bash
|
||||
vagrant up
|
||||
```
|
||||
|
||||
7. Deploy the Network Mapper on the virtual machine:
|
||||
|
||||
```bash
|
||||
vagrant provision
|
||||
```
|
||||
|
||||
|
||||
:::{note}
|
||||
To stop the virtual machine, run `vagrant halt` in this directory. More commands are explained in the [Vagrant docs](https://developer.hashicorp.com/vagrant/docs/cli).
|
||||
:::
|
||||
|
||||
## Docker (for individuals)
|
||||
|
||||
This is the recommended deployment method for individuals who are not planning on making the network mapper accessible to other users.
|
||||
|
||||
:::{warning}
|
||||
The network mapper will not run with Docker on Arm-based devices. This includes devices with Apple silicon - e.g. M1 and M2 Macs.
|
||||
|
||||
To run it on these devices you will need to build it yourself, which requires additional knowledge of Docker.
|
||||
:::
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- [Docker Compose](https://docs.docker.com/compose) is installed and running. If you are not familiar with Docker, we recommend using [Docker Desktop](https://docs.docker.com/desktop/). Simply install and run it.
|
||||
|
||||
To deploy the BRECcIA Network Mapper with Docker:
|
||||
|
||||
1. Download `deploy-docker.zip` [from the latest release](https://github.com/Southampton-RSG/breccia-mapper/releases/latest).
|
||||
2. Extract the zip file into an appropriate folder.
|
||||
3. Copy your logo (192x192 pixels) to `icon-192x192.png` in the `network-mapper` folder.
|
||||
4. Copy `example.env` to `.env` in this folder.
|
||||
5. Edit this file as desired. Note that some variables are required, and that `True` and `False` values must have correct capitalisation.
|
||||
|
||||
- Variables are set with the following syntax, in this case setting the `DEBUG` variable to `False`:
|
||||
|
||||
```Dotenv
|
||||
DEBUG=False
|
||||
```
|
||||
|
||||
6. Open a terminal window in this folder. On Windows, do this by holding `Shift` and right clicking inside the folder; then selecting either `Open in Terminal` or `Open PowerShell window here`.
|
||||
6. Start the network mapper with the following command:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
7. If desired (e.g. on initial deployment), create a superuser by running the following, and enter their details when prompted:
|
||||
|
||||
```bash
|
||||
docker compose exec -it server /bin/bash -c "/app/manage.py createsuperuser"
|
||||
```
|
||||
|
||||
Once the network mapper has been started for the first time with the above steps, it will appear in Docker Desktop (if installed). It can then be stopped/started again from here.
|
||||
|
||||
To stop it from the terminal, run
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
193
docs/source/2-configuration.md
Normal file
193
docs/source/2-configuration.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Configuration
|
||||
|
||||
After installing the [BRECcIA Network Mapper](https://github.com/Southampton-RSG/breccia-mapper), some configuration must be done in the web interface. You will need to log in with an admin account.
|
||||
|
||||
:::{note}
|
||||
Admin dashboard: this is the admin section of the site, accessed by clicking `Admin` in the navigation bar at the top of the screen.
|
||||
:::
|
||||
|
||||
## Setup
|
||||
|
||||
### Activity Mediums
|
||||
|
||||
Each activity medium is a property of an activity - intended for storing, for example, whether the activity was face-to-face or virtual. Add an activity medium for each medium you wish to be available.
|
||||
|
||||
- In the admin dashboard, click `Add` next to `Activity mediums` and provide the name of the medium.
|
||||
|
||||
### Activity Types
|
||||
|
||||
Activities are categorised into types. Add an activity type for each type you wish to be available. For example: meetings, seminars, and training courses.
|
||||
|
||||
- In the admin dashboard, click `Add` next to `Activity types` and provide the name of the activity type.
|
||||
|
||||
### Activity Series
|
||||
|
||||
Activities in a series (e.g. a set of connected meetings or courses) can be linked together with an activity series. Activity series are created in the admin dashboard, and activities are linked to series when creating or updating the activities.
|
||||
|
||||
When new activity series next to be created, create them in the admin dashboard.
|
||||
|
||||
- In the admin dashboard, click `Add` next to `Activity series` and provide the name of the series, along with the type and medium of the activities in this series.
|
||||
|
||||
### Site Theme
|
||||
|
||||
If desired, you can adjust the site's theming through the admin dashboard. All of the below steps are optional.
|
||||
|
||||
- In the admin dashboard, click `Bootstrap themes` under `BOOTSTRAP_CUSTOMIZER`, then select `Default Theme`.
|
||||
- Toggle rounded corners (e.g. for buttons), shadows, and gradients with the checkboxes.
|
||||
- Click each colour to change it - a pop-up will appear allowing you to choose the new colour.
|
||||
- Change the site's fonts by replacing the content of the `Font family base` field.
|
||||
- Change the font size with the `Font size base` field.
|
||||
- Change the line height with the `Line height base` field.
|
||||
- Change the main background and text colours with the `Body background` and `Body color` fields respectively.
|
||||
|
||||
- Change the heading font by expanding the `Headings` section and replacing the content of the `Headings font family` field.
|
||||
- Change the heading font weight (i.e. thickness) by expanding the `Headings` section and replacing the content of the `Headings font weight` field.
|
||||
- Change the heading line height by expanding the `Headings` section and replacing the content of the `Headings line height` field.
|
||||
|
||||
Then click `Save`.
|
||||
|
||||
### Main Configuration Options
|
||||
|
||||
There are several general settings which must be configured. Open the admin dashboard and click `Config` under `CONSTANCE`, then configure the available settings, as explained below.
|
||||
|
||||
- `CONSENT_TEXT`: The text shown to users when requesting consent to use their data. This text accompanies a checkbox captioned `I have read and understood this information and consent to my data being used in this way`.
|
||||
- `PERSON_LIST_HELP`: Help text to display at the top of the people list.
|
||||
- `ORGANISATION_LIST_HELP`: Help text to display at the top of the organisaton list.
|
||||
- `RELATIONSHIP_FORM_HELP`: Help text to display at the top of relationship forms.
|
||||
- `HOMEPAGE_HEADER_IMAGE_SHRINK`: Whether the homepage header image should be shrunk to display the whole image at all times.
|
||||
- `HOMEPAGE_HEADER_IMAGE`: The header image for the homepage.
|
||||
- `HOMEPAGE_CARD_1_TITLE`: The title for the first card displayed on the homepage.
|
||||
- `HOMEPAGE_CARD_1_DESCRIPTION`: The description for the first card displayed on the homepage.
|
||||
- `HOMEPAGE_CARD_1_ICON`: The icon for the first card displayed on the homepage. Icons are FontAwesome 6 icons, which are listed [here](https://fontawesome.com/v6/search?m=free).
|
||||
- `HOMEPAGE_CARD_2_TITLE`: The title for the second card displayed on the homepage.
|
||||
- `HOMEPAGE_CARD_2_DESCRIPTION`: The description for the second card displayed on the homepage.
|
||||
- `HOMEPAGE_CARD_2_ICON`: The icon for the second card displayed on the homepage. Icons are FontAwesome 6 icons, which are listed [here](https://fontawesome.com/v6/search?m=free).
|
||||
- `HOMEPAGE_CARD_3_TITLE`: The title for the third card displayed on the homepage.
|
||||
- `HOMEPAGE_CARD_3_DESCRIPTION`: The description for the third card displayed on the homepage.
|
||||
- `HOMEPAGE_CARD_3_ICON`: The icon for the third card displayed on the homepage. Icons are FontAwesome 6 icons, which are listed [here](https://fontawesome.com/v6/search?m=free).
|
||||
- `HOMEPAGE_ABOUT_TITLE`: The title for the about section on the homepage.
|
||||
- `HOMEPAGE_ABOUT_CONTENT`: The content for the about section on the homepage. HTML is accepted.
|
||||
- `HOMEPAGE_ABOUT_IMAGE`: The image for the about section on the homepage.
|
||||
- `NOTICE_TEXT`: Text to be displayed in a notice banner at the top of every page.
|
||||
- `NOTICE_CLASS`: CSS class to use for the background of the notice banner.
|
||||
- `PARENT_PROJECT_NAME`: The name of the project's parent project, if one exists.
|
||||
- `PROJECT_LEAD`: The project's lead person, organisation, or similar.
|
||||
- `PROJECT_TAGLINE`: The project's tagline.
|
||||
- `ALLOW_SIGNUPS`: Whether new users should be able to sign themselves up through the site. This is useful for minimising the number of users that must be manually created, and it is recommended that this feature is disabled once all users have created their accounts.
|
||||
- `ENABLE_GOOGLE_LOGIN`: Whether login through Google should be enabled. Only enable this if Google login has been configured. See [Google login](#google).
|
||||
- `ENABLE_MICROSOFT_LOGIN`: Whether login through Microsoft should be enabled. Only enable this if Microsoft login has been configured. See [Microsoft login](#microsoft).
|
||||
|
||||
Then click `Save`.
|
||||
|
||||
### Questions
|
||||
|
||||
There are several types of questions, but they all have the same set of information stored in them:
|
||||
|
||||
- `Version`: The version of the question - this should be incremented when the question is altered.
|
||||
- `Text`: The main text of the question.
|
||||
- `Filter text`: Each question appears as a filter on the `Network` page. This is alternative text to replace the full question as the filter title. If left blank, the main text of the question will be used.
|
||||
- `Help text`: Help text shown below the question when people enter their answer.
|
||||
- `Answer is public`: Whether answers to this question should be considered public.
|
||||
- `Is multiple choice`: Whether users should only be allowed to select multiple options, instead of just one.
|
||||
- `Hardcoded field`: The name of the hardcoded field that the question relates to. This is not applicable for non-preset questions (i.e. ones that you create).
|
||||
- `Allow free text`: Whether users should be allowed to enter their own text in addition to choosing an available option. When a user enters free text, a new option will be created with their input.
|
||||
- `Order`: The priority order for the question to be displayed in. Lower priority questions will be displayed earlier in the list of questions.
|
||||
- Question choices
|
||||
- `Text`: The main text of the option.
|
||||
- `Order`: The priority order for the option to be displayed in. Lower priority options will be displayed earlier in the list of options.
|
||||
- `Is negative response`: Only applicable for relationship questions. Whether the option indicates the relationship is of the lowest level of closeness. This allows automatic population of questions if the relationship being reported is not at all close. All options marked as negative responses will be selected when this button is pressed.
|
||||
- `Delete?`: Whether the option should be deleted when the question is saved.
|
||||
|
||||
There are various types of questions, which can be added by clicking `Add` next to the appropriate section in the admin dashboard:
|
||||
|
||||
- Organisation questions: Questions that are shown when creating an organisation or updating its details.
|
||||
- Organisation relationship questions: Questions that are shown when reporting a relationship with an organisation.
|
||||
- Person questions: Questions that are shown when creating a person or updating their details.
|
||||
- Relationship questions: Questions that are shown when reporting a relationship with a person.
|
||||
|
||||
### Existing Questions
|
||||
|
||||
Some "person questions" (i.e. questions about people) are preset, but require answers to be provided.
|
||||
|
||||
1. In the admin dashboard, click `Person questions` under `PEOPLE`, then select each of the following questions in turn:
|
||||
|
||||
- Disciplines
|
||||
- Research theme affiliation
|
||||
- Role
|
||||
|
||||
2. For each question, provide a set of possible answers as per the instructions [above](#questions).
|
||||
|
||||
:::{note}
|
||||
At least one organisation must also exist for people to be able to create their profiles (unless the organisation question is removed). To create an organisation follow the instructions [below](#organisations).
|
||||
:::
|
||||
|
||||
### Organisations
|
||||
|
||||
Organisations are created through the main site (not the admin dashboard).
|
||||
|
||||
1. Click `Organisations` in the navigation bar at the top of the screen.
|
||||
2. Click `New Organisation` at the top of the page.
|
||||
2. Answer the questions shown.
|
||||
4. Finally click `Submit`.
|
||||
|
||||
### People
|
||||
|
||||
:::{note}
|
||||
When a `Person` is created for a user who does not have an account, an anonymous account is created for them - with login disabled and a random username (starting `autogen_`). This allows administrators to edit their details on their behalf. You should not delete these users unless you wish to delete all data relating to that person.
|
||||
:::
|
||||
|
||||
People are created through the main site (not the admin dashboard). People should only be created when it is known that the person will not have a login of their own to the site - e.g. for researchers logging data for multiple individuals.
|
||||
|
||||
1. Click `People` in the navigation bar at the top of the screen.
|
||||
2. Click `New Person` at the top of the page.
|
||||
2. Answer the questions shown.
|
||||
4. Finally click `Submit`.
|
||||
|
||||
## Federated Login
|
||||
|
||||
Federated login is supported for Google an Microsoft accounts, and can be set up through the `SOCIAL ACCOUNTS` section of the admin dashboard.
|
||||
|
||||
### Google
|
||||
|
||||
You will first need to create an OAuth application in Google Cloud Platform. You can do this by following [Google's guide](https://support.google.com/cloud/answer/6158849). The redirect URL is `[your-site-url]/accounts/google/login/callback/`.
|
||||
|
||||
Then:
|
||||
|
||||
- In the admin dashboard, click `Add` next to `Social applications`.
|
||||
- Select `Google` as the provider.
|
||||
- Enter `Google` as the name.
|
||||
- Enter the client ID from Google in the `Client id` field.
|
||||
- Enter the client secret from Google in the `Secret key` field.
|
||||
- Leave the `Key` field blank.
|
||||
- Click `Choose all` under the `Available sites` box, to enable Google login on this site.
|
||||
- Click `Save`.
|
||||
|
||||
Then enable Google login with the `ENABLE_GOOGLE_LOGIN` option in the `Config` section of the admin dashboard, as per [these instructions](#main-configuration-options).
|
||||
|
||||
### Microsoft
|
||||
|
||||
You will first need to create an OAuth application in Azure Active Directory. You can do this by following [Microsoft's guide](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app). The redirect URL is `[your-site-url]/accounts/microsoft/login/callback/`. You will also need to add a client secret.
|
||||
|
||||
Then:
|
||||
|
||||
- In the admin dashboard, click `Add` next to `Social applications`.
|
||||
- Select `Microsoft Graph` as the provider.
|
||||
- Enter `Microsoft` as the name.
|
||||
- Enter the `Application (client) ID` from Azure in the `Client id` field. This is obtained from the `Overview` page and is different to the `Secret ID`.
|
||||
- Enter the client secret value from Google in the `Secret key` field.
|
||||
- Leave the `Key` field blank.
|
||||
- Click `Choose all` under the `Available sites` box, to enable Google login on this site.
|
||||
- Click `Save`.
|
||||
|
||||
Then enable Microsoft login with the `ENABLE_MICROSOFT_LOGIN` option in the `Config` section of the admin dashboard, as per [these instructions](#main-configuration-options).
|
||||
|
||||
(inviting_users)=
|
||||
## Inviting Users
|
||||
|
||||
In the admin dashboard, click `Add` next to `Users`. Choose a username for them, enter their email address, and enter a temporary password. It does not matter what this password is, and you do not need to remember or store it, as the new user is automatically sent an email welcoming them to the platform and providing instructions for how to reset their password.
|
||||
|
||||
If the user you wish to invite has already had a `Person` created for them, they will already have an account with login disabled and a random username (starting `autogen_`). To find this account, go to `People` (in the `PEOPLE` section) in the admin dashboard and select the appropriate person. Then click the blue eye icon next to the `User` field.
|
||||
|
||||

|
||||
|
||||
This will take you to the user, and you can then change their username and add a first name, last name, and email address. Note that a welcome email will not be sent to the user in this case, so you will have to let them know that their account is active and what their username is. They can use the *forgot password* option when logging in to set their password.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user