mirror of
https://github.com/HaitiData/haitidata.git
synced 2026-10-26 17:35:17 +00:00
Bump to 2.10.4
This commit is contained in:
1 parent
aedadb16f7
commit
f67a4980ef
436 files changed
+24645
-32623
No files matched your search
@@ -0,0 +1,166 @@
|
||||
COMPOSE_PROJECT_NAME=haitidata
|
||||
BACKUPS_VOLUME_DRIVER=local
|
||||
|
||||
DOCKER_HOST_IP=
|
||||
DOCKER_ENV=production
|
||||
# See https://github.com/geosolutions-it/geonode-generic/issues/28
|
||||
# to see why we force API version to 1.24
|
||||
DOCKER_API_VERSION="1.24"
|
||||
|
||||
C_FORCE_ROOT=1
|
||||
IS_CELERY=false
|
||||
IS_FIRST_START=true
|
||||
FORCE_REINIT=false
|
||||
|
||||
SITEURL=http://localhost/
|
||||
ALLOWED_HOSTS=['django',]
|
||||
|
||||
GEONODE_INSTANCE_NAME=geonode
|
||||
DJANGO_SETTINGS_MODULE=haitidata.settings
|
||||
UWSGI_CMD=uwsgi --ini /usr/src/haitidata/uwsgi.ini
|
||||
|
||||
# #################
|
||||
# backend
|
||||
# #################
|
||||
GEONODE_DATABASE=geonode
|
||||
GEONODE_DATABASE_PASSWORD=geonode
|
||||
GEONODE_GEODATABASE=geonode_data
|
||||
GEONODE_GEODATABASE_PASSWORD=geonode_data
|
||||
|
||||
DATABASE_URL=postgres://geonode:geonode@db:5432/geonode
|
||||
GEODATABASE_URL=postgis://geonode:geonode@db:5432/geonode_data
|
||||
DEFAULT_BACKEND_DATASTORE=datastore
|
||||
BROKER_URL=amqp://guest:guest@rabbitmq:5672/
|
||||
|
||||
# #################
|
||||
# geoserver
|
||||
# #################
|
||||
GEOSERVER_WEB_UI_LOCATION=http://localhost/geoserver/
|
||||
GEOSERVER_PUBLIC_LOCATION=http://localhost/geoserver/
|
||||
GEOSERVER_LOCATION=http://geoserver:8080/geoserver/
|
||||
GEOSERVER_ADMIN_PASSWORD=geoserver
|
||||
|
||||
OGC_REQUEST_TIMEOUT=30
|
||||
OGC_REQUEST_MAX_RETRIES=1
|
||||
OGC_REQUEST_BACKOFF_FACTOR=0.3
|
||||
OGC_REQUEST_POOL_MAXSIZE=10
|
||||
OGC_REQUEST_POOL_CONNECTIONS=10
|
||||
|
||||
# Java Options & Memory
|
||||
GEOSERVER_JAVA_OPTS=-Djava.awt.headless=true -Xms2G -Xmx4G -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Duser.timezone=GMT -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=true -DGEOSERVER_CSRF_DISABLED=true
|
||||
|
||||
# Data Uploader
|
||||
DEFAULT_BACKEND_UPLOADER=geonode.importer
|
||||
TIME_ENABLED=True
|
||||
MOSAIC_ENABLED=False
|
||||
|
||||
# #################
|
||||
# nginx
|
||||
# HTTPD Server
|
||||
# #################
|
||||
# IP or domain name and port where the server can be reached on HTTP (leave HOST empty if you want to use HTTPS only)
|
||||
GEONODE_LB_HOST_IP=localhost
|
||||
HTTP_HOST=localhost
|
||||
# port where the server can be reached on HTTP
|
||||
GEONODE_LB_PORT=80
|
||||
HTTP_PORT=80
|
||||
|
||||
# IP or domain name and port where the server can be reached on HTTPS (leave HOST empty if you want to use HTTP only)
|
||||
# HTTPS_HOST=localhost
|
||||
# port where the server can be reached on HTTPS
|
||||
# GEONODE_LB_PORT=443
|
||||
# HTTPS_PORT=443
|
||||
|
||||
# Let's Encrypt certificates for https encryption. You must have a domain name as HTTPS_HOST (doesn't work
|
||||
# with an ip) and it must be reachable from the outside. This can be one of the following :
|
||||
# disabled : we do not get a certificate at all (a placeholder certificate will be used)
|
||||
# staging : we get staging certificates (are invalid, but allow to test the process completely and have much higher limit rates)
|
||||
# production : we get a normal certificate (default)
|
||||
LETSENCRYPT_MODE=disabled
|
||||
# LETSENCRYPT_MODE=staging
|
||||
# LETSENCRYPT_MODE=production
|
||||
|
||||
RESOLVER=127.0.0.11
|
||||
|
||||
# #################
|
||||
# Security
|
||||
# #################
|
||||
# Admin Settings
|
||||
ADMIN_PASSWORD=admin
|
||||
ADMIN_EMAIL=admin@localhost
|
||||
|
||||
# EMAIL Notifications
|
||||
EMAIL_ENABLE=False
|
||||
DJANGO_EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
|
||||
DJANGO_EMAIL_HOST=localhost
|
||||
DJANGO_EMAIL_PORT=25
|
||||
DJANGO_EMAIL_HOST_USER=
|
||||
DJANGO_EMAIL_HOST_PASSWORD=
|
||||
DJANGO_EMAIL_USE_TLS=False
|
||||
DEFAULT_FROM_EMAIL='GeoNode <no-reply@geonode.org>'
|
||||
|
||||
# Session/Access Control
|
||||
LOCKDOWN_GEONODE=False
|
||||
CORS_ORIGIN_ALLOW_ALL=True
|
||||
SESSION_EXPIRED_CONTROL_ENABLED=True
|
||||
DEFAULT_ANONYMOUS_VIEW_PERMISSION=True
|
||||
DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=True
|
||||
|
||||
# Users Registration
|
||||
ACCOUNT_OPEN_SIGNUP=True
|
||||
ACCOUNT_EMAIL_REQUIRED=True
|
||||
ACCOUNT_APPROVAL_REQUIRED=False
|
||||
ACCOUNT_CONFIRM_EMAIL_ON_GET=False
|
||||
ACCOUNT_EMAIL_VERIFICATION='optional'
|
||||
ACCOUNT_EMAIL_CONFIRMATION_EMAIL=False
|
||||
ACCOUNT_EMAIL_CONFIRMATION_REQUIRED=False
|
||||
|
||||
# OAuth2
|
||||
OAUTH2_API_KEY=
|
||||
OAUTH2_CLIENT_ID=Jrchz2oPY3akmzndmgUTYrs9gczlgoV20YPSvqaV
|
||||
OAUTH2_CLIENT_SECRET=rCnp5txobUo83EpQEblM8fVj3QT5zb5qRfxNsuPzCqZaiRyIoxM4jdgMiZKFfePBHYXCLd7B8NlkfDBY9HKeIQPcy5Cp08KQNpRHQbjpLItDHv12GvkSeXp6OxaUETv3
|
||||
|
||||
# GeoNode APIs
|
||||
API_LOCKDOWN=False
|
||||
TASTYPIE_APIKEY=
|
||||
|
||||
# #################
|
||||
# Production and
|
||||
# Monitoring
|
||||
# #################
|
||||
DEBUG=False
|
||||
|
||||
SECRET_KEY='myv-y4#7j-d*p-__@j#*3z@!y24fz8%^z2v6atuy4bo9vqr1_a'
|
||||
|
||||
STATIC_ROOT=/mnt/volumes/statics/static/
|
||||
MEDIA_ROOT=/mnt/volumes/statics/uploaded/
|
||||
GEOIP_PATH=/mnt/volumes/statics/geoip.db
|
||||
|
||||
CACHE_BUSTING_STATIC_ENABLED=False
|
||||
CACHE_BUSTING_MEDIA_ENABLED=False
|
||||
|
||||
MAX_DOCUMENT_SIZE=2
|
||||
CLIENT_RESULTS_LIMIT=5
|
||||
API_LIMIT_PER_PAGE=1000
|
||||
ALLOWED_DOCUMENT_TYPES=['doc', 'docx', 'gif', 'jpg', 'jpeg', 'ods', 'odt', 'odp', 'pdf', 'png','ppt', 'pptx', 'rar', 'sld', 'tif', 'tiff', 'txt', 'xls', 'xlsx', 'xml', 'zip', 'gz', 'qml']
|
||||
|
||||
# GIS Client
|
||||
GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY=mapstore
|
||||
MAPBOX_ACCESS_TOKEN=
|
||||
BING_API_KEY=
|
||||
GOOGLE_API_KEY=
|
||||
|
||||
# Monitoring
|
||||
MONITORING_ENABLED=True
|
||||
MONITORING_DATA_TTL=365
|
||||
USER_ANALYTICS_ENABLED=True
|
||||
USER_ANALYTICS_GZIP=False
|
||||
MONITORING_SERVICE_NAME=local-geonode
|
||||
MONITORING_HOST_NAME=geonode
|
||||
|
||||
# Other Options/Contribs
|
||||
MODIFY_TOPICCATEGORY=True
|
||||
AVATAR_GRAVATAR_SSL=True
|
||||
EXIF_ENABLED=False
|
||||
CREATE_LAYER=False
|
||||
FAVORITE_ENABLED=False
|
||||
+10
-9
@@ -1,6 +1,3 @@
|
||||
|
||||
.DS_Store
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
@@ -10,7 +7,7 @@ __pycache__/
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
# env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
@@ -46,12 +43,9 @@ nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
|
||||
# Translations
|
||||
#*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
celerybeat-schedule.*
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
@@ -61,7 +55,14 @@ target/
|
||||
|
||||
# Downstream Project
|
||||
downloaded/
|
||||
geoserver/
|
||||
uploaded/
|
||||
static_root/
|
||||
development.db
|
||||
development.db-journal
|
||||
local_settings.py
|
||||
|
||||
.idea/
|
||||
|
||||
/.vscode/settings.json
|
||||
|
||||
.DS_Store
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
FROM python:2.7.16-stretch
|
||||
MAINTAINER GeoNode development team
|
||||
|
||||
RUN mkdir -p /usr/src/haitidata
|
||||
|
||||
# This section is borrowed from the official Django image but adds GDAL and others
|
||||
RUN apt-get update && apt-get install -y \
|
||||
gcc \
|
||||
zip \
|
||||
gettext \
|
||||
postgresql-client libpq-dev \
|
||||
sqlite3 \
|
||||
python-gdal python-psycopg2 \
|
||||
python-imaging python-lxml \
|
||||
python-dev libgdal-dev \
|
||||
python-ldap \
|
||||
libmemcached-dev libsasl2-dev zlib1g-dev \
|
||||
python-pylibmc \
|
||||
uwsgi uwsgi-plugin-python \
|
||||
--no-install-recommends && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list
|
||||
RUN apt-get update && apt-get install -y geoip-bin
|
||||
|
||||
# add bower and grunt command
|
||||
COPY . /usr/src/haitidata/
|
||||
WORKDIR /usr/src/haitidata
|
||||
|
||||
RUN apt-get update && apt-get -y install cron
|
||||
COPY monitoring-cron /etc/cron.d/monitoring-cron
|
||||
RUN chmod 0644 /etc/cron.d/monitoring-cron
|
||||
RUN crontab /etc/cron.d/monitoring-cron
|
||||
RUN touch /var/log/cron.log
|
||||
RUN service cron start
|
||||
|
||||
COPY wait-for-databases.sh /usr/bin/wait-for-databases
|
||||
RUN chmod +x /usr/bin/wait-for-databases
|
||||
RUN chmod +x /usr/src/haitidata/tasks.py \
|
||||
&& chmod +x /usr/src/haitidata/entrypoint.sh
|
||||
|
||||
# Upgrade pip
|
||||
RUN pip install pip==20.1
|
||||
|
||||
# To understand the next section (the need for requirements.txt and setup.py)
|
||||
# Please read: https://packaging.python.org/requirements/
|
||||
|
||||
# fix for known bug in system-wide packages
|
||||
RUN ln -fs /usr/lib/python2.7/plat-x86_64-linux-gnu/_sysconfigdata*.py /usr/lib/python2.7/
|
||||
|
||||
# app-specific requirements
|
||||
RUN pip install --src /usr/src -r requirements.txt
|
||||
RUN pip install -e .
|
||||
|
||||
# Install pygdal (after requirements for numpy 1.16)
|
||||
RUN pip install pygdal==$(gdal-config --version).*
|
||||
|
||||
ENTRYPOINT service cron restart && /usr/src/haitidata/entrypoint.sh
|
||||
@@ -0,0 +1,29 @@
|
||||
up:
|
||||
# bring up the services
|
||||
docker-compose up -d
|
||||
|
||||
build:
|
||||
docker-compose build django
|
||||
docker-compose build celery
|
||||
|
||||
sync:
|
||||
# set up the database tablea
|
||||
docker-compose run django python manage.py makemigrations --noinput
|
||||
docker-compose exec django python manage.py migrate account --noinput
|
||||
docker-compose run django python manage.py migrate --noinput
|
||||
|
||||
wait:
|
||||
sleep 5
|
||||
|
||||
logs:
|
||||
docker-compose logs --follow
|
||||
|
||||
down:
|
||||
docker-compose down
|
||||
|
||||
test:
|
||||
docker-compose run django python manage.py test --failfast
|
||||
|
||||
reset: down up wait sync
|
||||
|
||||
hardreset: pull build reset
|
||||
@@ -0,0 +1,231 @@
|
||||
# Haitidata
|
||||
|
||||
GeoNode template project. Generates a django project with GeoNode support.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Developer Workshop](#developer-Workshop)
|
||||
- [Create a custom project](#create-a-custom-project)
|
||||
- [Start your server using Docker](#start-your-server-using-docker)
|
||||
- [Run the instance in development mode](#run-the-instance-in-development-mode)
|
||||
- [Run the instance on a public site](#run-the-instance-on-a-public-site)
|
||||
- [Stop the Docker Images](#stop-the-docker-images)
|
||||
- [Recommended: Track your changes](#recommended-track-your-changes)
|
||||
- [Hints: Configuring `requirements.txt`](#hints-configuring-requirementstxt)
|
||||
- [Hints: Using Ansible](#hints-using-ansible)
|
||||
- [Configuration](#configuration)
|
||||
|
||||
## Developer Workshop
|
||||
|
||||
Available at
|
||||
|
||||
```bash
|
||||
http://geonode.org/dev-workshop
|
||||
```
|
||||
|
||||
## Create a custom project
|
||||
|
||||
**NOTE**: *You can call your geonode project whatever you like following the naming conventions for python packages (generally lower case with underscores (``_``). In the examples below, replace ``my_geonode`` with whatever you would like to name your project.*
|
||||
|
||||
### Using a Python virtual environment
|
||||
|
||||
**NOTE**: *Skip this part if you want to run the project using Docker instead*
|
||||
|
||||
(see [Start your server using Docker](#start-your-server-using-docker))
|
||||
|
||||
To setup your project using a local python virtual environment, follow these instructions:
|
||||
|
||||
1. Prepare the Environment
|
||||
|
||||
```bash
|
||||
git clone https://github.com/GeoNode/geonode-project.git -b <your_branch>
|
||||
mkvirtualenv my_geonode
|
||||
pip install Django==1.11.29
|
||||
|
||||
django-admin startproject --template=./geonode-project -e py,sh,md,rst,json,yml,ini,env,sample -n monitoring-cron -n Dockerfile my_geonode
|
||||
|
||||
cd my_geonode
|
||||
```
|
||||
|
||||
2. Setup the Python Dependencies
|
||||
|
||||
**NOTE**: *Important: modify your `requirements.txt` file, by adding the `GeoNode` branch before continue!*
|
||||
|
||||
(see [Hints: Configuring `requirements.txt`](#hints-configuring-requirementstxt))
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
pip install -e .
|
||||
|
||||
# Install GDAL Utilities for Python
|
||||
pip install pygdal=="`gdal-config --version`.*"
|
||||
|
||||
# Using the Default Settings
|
||||
DJANGO_SETTINGS_MODULE=my_geonode.settings paver reset
|
||||
DJANGO_SETTINGS_MODULE=my_geonode.settings paver setup
|
||||
DJANGO_SETTINGS_MODULE=my_geonode.settings paver sync
|
||||
DJANGO_SETTINGS_MODULE=my_geonode.settings paver start
|
||||
|
||||
# Using the Custom Local Settings
|
||||
# - Remember that `.settings` includes `.local_settings`
|
||||
cp my_geonode/local_settings.py.sample my_geonode/local_settings.py
|
||||
|
||||
DJANGO_SETTINGS_MODULE=my_geonode.local_settings paver reset
|
||||
DJANGO_SETTINGS_MODULE=my_geonode.local_settings paver setup
|
||||
DJANGO_SETTINGS_MODULE=my_geonode.local_settings paver sync
|
||||
DJANGO_SETTINGS_MODULE=my_geonode.local_settings paver start
|
||||
```
|
||||
|
||||
3. Access GeoNode from browser
|
||||
|
||||
**NOTE**: default admin user is ``admin`` (with pw: ``admin``)
|
||||
|
||||
```bash
|
||||
http://localhost:8000/
|
||||
```
|
||||
|
||||
## Start your server using Docker
|
||||
|
||||
You need Docker 1.12 or higher, get the latest stable official release for your platform.
|
||||
|
||||
1. Prepare the Environment
|
||||
|
||||
```bash
|
||||
git clone https://github.com/GeoNode/geonode-project.git -b <your_branch>
|
||||
mkvirtualenv my_geonode
|
||||
pip install Django==1.11.29
|
||||
|
||||
django-admin startproject --template=./geonode-project -e py,sh,md,rst,json,yml,ini,env,sample -n monitoring-cron -n Dockerfile my_geonode
|
||||
|
||||
cd my_geonode
|
||||
```
|
||||
|
||||
2. Run `docker-compose` to start it up (get a cup of coffee or tea while you wait)
|
||||
|
||||
```bash
|
||||
docker-compose build --no-cache
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
```bash
|
||||
set COMPOSE_CONVERT_WINDOWS_PATHS=1
|
||||
```
|
||||
|
||||
before running `docker-compose up`
|
||||
|
||||
3. Access the site on http://localhost/
|
||||
|
||||
## Run the instance in development mode
|
||||
|
||||
### Use dedicated docker-compose files while developing
|
||||
|
||||
**NOTE**: In this example we are going to keep localhost as the target IP for GeoNode
|
||||
|
||||
```bash
|
||||
docker-compose -f docker-compose.development.yml -f docker-compose.development.override.yml up
|
||||
```
|
||||
|
||||
## Run the instance on a public site
|
||||
|
||||
### Preparation of the image (First time only)
|
||||
|
||||
**NOTE**: In this example we are going to publish to the public IP http://123.456.789.111
|
||||
|
||||
```bash
|
||||
vim .env
|
||||
--> replace localhost with 123.456.789.111 everywhere
|
||||
```
|
||||
|
||||
### Startup the image
|
||||
|
||||
```bash
|
||||
docker-compose up --build -d
|
||||
```
|
||||
|
||||
### Stop the Docker Images
|
||||
|
||||
```bash
|
||||
docker-compose stop
|
||||
```
|
||||
|
||||
### Fully Wipe-out the Docker Images
|
||||
|
||||
**WARNING**: This will wipe out all the repositories created until now.
|
||||
|
||||
**NOTE**: The images must be stopped first
|
||||
|
||||
```bash
|
||||
docker system prune -a
|
||||
```
|
||||
|
||||
## Recommended: Track your changes
|
||||
|
||||
Step 1. Install Git (for Linux, Mac or Windows).
|
||||
|
||||
Step 2. Init git locally and do the first commit:
|
||||
|
||||
```bash
|
||||
git init
|
||||
git add *
|
||||
git commit -m "Initial Commit"
|
||||
```
|
||||
|
||||
Step 3. Set up a free account on github or bitbucket and make a copy of the repo there.
|
||||
|
||||
## Hints: Configuring `requirements.txt`
|
||||
|
||||
You may want to configure your requirements.txt, if you are using additional or custom versions of python packages. For example
|
||||
|
||||
```python
|
||||
Django==1.11.29
|
||||
git+git://github.com/<your organization>/geonode.git@<your branch>
|
||||
```
|
||||
|
||||
## Hints: Using Ansible
|
||||
|
||||
You will need to use Ansible Role in order to run the playbook.
|
||||
|
||||
In order to install and setup Ansible, run the following commands
|
||||
|
||||
```bash
|
||||
sudo apt-get install software-properties-common
|
||||
sudo apt-add-repository ppa:ansible/ansible
|
||||
sudo apt-get update
|
||||
sudo apt-get install ansible
|
||||
```
|
||||
|
||||
A sample Ansible Role can be found at https://github.com/GeoNode/ansible-geonode
|
||||
|
||||
To install the default one, run
|
||||
|
||||
```bash
|
||||
sudo ansible-galaxy install GeoNode.geonode
|
||||
```
|
||||
|
||||
you will find the Ansible files into the ``~/.ansible/roles`` folder. Those must be updated in order to match the GeoNode and GeoServer versions you will need to install.
|
||||
|
||||
To run the Ansible playbook use something like this
|
||||
|
||||
```bash
|
||||
ANSIBLE_ROLES_PATH=~.ansible/roles ansible-playbook -e "gs_root_password=<new gs root password>" -e "gs_admin_password=<new gs admin password>" -e "dj_superuser_password=<new django admin password>" -i inventory --limit all playbook.yml
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
**NOTE**: *For `GeoNode` settings, make use of the `ENVIRONMENT` variables whenever is possible. Avoid overwriting them yourself, you might me missing some additional logic done on `geonode.settings`*
|
||||
|
||||
Since this application uses geonode, base source of settings is ``geonode.settings`` module. It provides defaults for many items, which are used by geonode. This application has own settings module, ``haitidata.settings``, which includes ``geonode.settings``. It customizes few elements:
|
||||
* static/media files locations - they will be collected and stored along with this application files by default. This is useful during development.
|
||||
* Adds ``haitidata`` to installed applications, updates templates, staticfiles dirs, sets urlconf to ``haitidata.urls``.
|
||||
|
||||
Whether you deploy development or production environment, you should create additional settings file. Convention is to make ``haitidata.local_settings`` module. It is recommended to use ``haitidata/local_settings.py``.. That file contains small subset of settings for edition. It should:
|
||||
* not be versioned along with application (because changes you make for your private deployment may become public),
|
||||
* have customized at least ``DATABASES``, ``SECRET_KEY`` and ``SITEURL``.
|
||||
|
||||
You can add more settings there, note however, some settings (notably ``DEBUG_STATIC``, ``EMAIL_ENABLE``, ``*_ROOT``, and few others) can be used by other settings, or as condition values, which change other settings. For example, ``EMAIL_ENABLE`` defined in ``geonode.settings`` enables whole email handling block, so if you disable it in your ``local_settings``, derived settings will be preserved. You should carefully check if additional settings you change don't trigger other settings.
|
||||
|
||||
To illustrate whole concept of chained settings:
|
||||
|
||||
|GeoNode configuration| |(optionally) Your deployment(s) | |Your application default configuration|
|
||||
|---|---|---|---|---|
|
||||
|`geonode.settings`|included by ->|`haitidata.local_settings`|included by ->|`haitidata.settings`|
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
Haitidata
|
||||
========================
|
||||
|
||||
You should write some docs, it's good for the soul.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install geonode with::
|
||||
|
||||
$ sudo add-apt-repository ppa:geonode/stable
|
||||
|
||||
$ sudo apt-get update
|
||||
|
||||
$ sudo apt-get install geonode
|
||||
|
||||
Create a new template based on the geonode example project.::
|
||||
|
||||
$ django-admin startproject my_geonode --template=https://github.com/GeoNode/geonode-project/archive/2.6.zip -epy,rst
|
||||
$ sudo pip install -e my_geonode
|
||||
|
||||
.. note:: You should NOT use the name geonode for your project as it will conflict with the default geonode package name.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Rename the local_settings.py.sample to local_settings.py and edit it's content by setting the SITEURL and SITENAME.
|
||||
|
||||
Edit the file /etc/apache2/sites-available/geonode and change the following directive from:
|
||||
|
||||
WSGIScriptAlias / /var/www/geonode/wsgi/geonode.wsgi
|
||||
|
||||
to:
|
||||
|
||||
WSGIScriptAlias / /path/to/my_geonode/my_geonode/wsgi.py
|
||||
|
||||
To avoid having to grant apache permissions (i.e. www-data user and group) to your home dir where you likely setup the geonode-project; you may want to instead copy the wsgi.py file next to geonode.wsgi and replace the file name instead of the entire path.
|
||||
|
||||
$ cp /path/to/my_geonode/my_geonode/wsgi.py /var/www/geonode/wsgi/wsgi.py
|
||||
|
||||
Add the "Directory" directive for your folder like the following example:
|
||||
|
||||
<Directory "/home/vagrant/my_geonode/my_geonode/">
|
||||
|
||||
Order allow,deny
|
||||
|
||||
Options Indexes FollowSymLinks
|
||||
|
||||
Allow from all
|
||||
|
||||
Require all granted
|
||||
|
||||
IndexOptions FancyIndexing
|
||||
|
||||
</Directory>
|
||||
|
||||
Restart apache::
|
||||
|
||||
$ sudo service apache2 restart
|
||||
|
||||
Edit the templates in my_geonode/templates, the css and images to match your needs.
|
||||
|
||||
In the my_geonode folder run::
|
||||
|
||||
$ python manage.py collectstatic
|
||||
|
||||
Github Considerations
|
||||
------------------------
|
||||
|
||||
While it is helpful to recommit your django project wrapper back to a distributed version control repository.
|
||||
* It is also important to remember that production instances will store security information in the local_settings.py
|
||||
* Admin/Devs should always remember to exclude this file in the .gitignore file in the same folder as the .git::
|
||||
|
||||
$ nano .gitignore
|
||||
|
||||
/{project}/local_settings.py
|
||||
|
||||
save, make sure the file is also removed from git cache::
|
||||
|
||||
$ git rm -f --cache //local_settings.py
|
||||
|
||||
$ git status
|
||||
|
||||
confirm the file is no longer staged for the next commit or that if it is as "removed"
|
||||
@@ -1,10 +0,0 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Chart
|
||||
|
||||
|
||||
class ChartAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'title']
|
||||
|
||||
|
||||
admin.site.register(Chart, ChartAdmin)
|
||||
@@ -1,27 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('layers', '24_to_26'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Chart',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('title', models.CharField(max_length=128, blank=True)),
|
||||
('category', models.CharField(max_length=200)),
|
||||
('quantity', models.CharField(max_length=200)),
|
||||
('type', models.SmallIntegerField(default=0, choices=[(0, b'Bar chart'), (1, b'Pie chart'), (2, b'Donut chart')])),
|
||||
('aggr_type', models.SmallIntegerField(default=3, choices=[(0, b'Sum'), (1, b'Mean'), (2, b'Category count'), (3, b'Max'), (4, b'Min')])),
|
||||
('abstract', models.TextField(blank=True)),
|
||||
('layer', models.ForeignKey(to='layers.Layer')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -1,32 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.conf import settings
|
||||
import charts_app.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('charts_app', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='chart',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='chart',
|
||||
name='layer',
|
||||
field=models.ForeignKey(to='layers.Layer', validators=[charts_app.models.validate_wfs]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='chart',
|
||||
name='type',
|
||||
field=models.SmallIntegerField(default=0, choices=[(0, b'Bar chart'), (1, b'Pie chart'), (2, b'Donut chart'), (3, b'Line chart')]),
|
||||
),
|
||||
]
|
||||
@@ -1,24 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('charts_app', '0002_auto_20170705_0742'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='chart',
|
||||
name='quantity',
|
||||
field=models.CharField(max_length=200, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='chart',
|
||||
name='title',
|
||||
field=models.CharField(max_length=128),
|
||||
),
|
||||
]
|
||||
@@ -1,80 +0,0 @@
|
||||
from django.db import models
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.conf import settings
|
||||
from django.forms import ModelForm, ValidationError as VE
|
||||
|
||||
from geonode.layers.models import Layer
|
||||
|
||||
from wfs_harvest.utils import get_featno, get_fields
|
||||
|
||||
|
||||
def validate_wfs(value):
|
||||
lyr = Layer.objects.get(pk=value)
|
||||
if lyr.service_type != 'WFS':
|
||||
raise ValidationError(_('%(lyr_title)s is not a WFS layer'),
|
||||
code='not_a_wfs',
|
||||
params={'lyr_title': lyr.title})
|
||||
|
||||
feat_no = get_featno(value)
|
||||
if feat_no > settings.MAX_CSV_RECORDS:
|
||||
raise ValidationError(_('%(lyr_title)s has too many features; '
|
||||
'chart functionality is not available '
|
||||
'for very large datasets'),
|
||||
code='too_many_records',
|
||||
params={'lyr_title': lyr.title})
|
||||
|
||||
|
||||
class Chart(models.Model):
|
||||
CHART_TYPES = (
|
||||
(0, 'Bar chart'),
|
||||
(1, 'Pie chart'),
|
||||
(2, 'Donut chart'),
|
||||
(3, 'Line chart')
|
||||
)
|
||||
|
||||
AGGREGATION_TYPES = (
|
||||
(0, 'Sum'),
|
||||
(1, 'Mean'),
|
||||
(2, 'Category count'),
|
||||
(3, 'Max'),
|
||||
(4, 'Min'),
|
||||
)
|
||||
|
||||
layer = models.ForeignKey(Layer, validators=[validate_wfs])
|
||||
title = models.CharField(max_length=128, blank=False)
|
||||
category = models.CharField(max_length=200)
|
||||
quantity = models.CharField(max_length=200, blank=True)
|
||||
type = models.SmallIntegerField(choices=CHART_TYPES, default=0)
|
||||
aggr_type = models.SmallIntegerField(choices=AGGREGATION_TYPES, default=3)
|
||||
abstract = models.TextField(blank=True)
|
||||
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null = True)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('chart_detail', kwargs={'pk': self.pk})
|
||||
|
||||
class ChartForm(ModelForm):
|
||||
def clean(self):
|
||||
cleaned_data = super(ChartForm, self).clean()
|
||||
layer = cleaned_data.get('layer')
|
||||
category = cleaned_data.get('category')
|
||||
quantity = cleaned_data.get('quantity')
|
||||
aggr_type = cleaned_data.get('aggr_type')
|
||||
categories, quantities = get_fields(layer)
|
||||
|
||||
if category not in categories:
|
||||
lyr = Layer.objects.get(pk=layer)
|
||||
raise VE(_('%(lyr_title)s does not contain the field %(category)s'),
|
||||
code='non_extant_category_field',
|
||||
params={'lyr_title': lyr.title, 'category': category})
|
||||
|
||||
if quantity not in quantities and aggr_type != 2:
|
||||
lyr = Layer.objects.get(pk=layer)
|
||||
raise VE(_('%(lyr_title)s does not contain the field %(quantity)s'),
|
||||
code='non_extant_quantity_field',
|
||||
params={'lyr_title': lyr.title, 'quantity': quantity})
|
||||
|
||||
class Meta:
|
||||
model = Chart
|
||||
fields = '__all__'
|
||||
@@ -1,68 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Donut Chart v1</title>
|
||||
<h1>Simple Donut Chart v1</h1>
|
||||
<h2>Zero values excluded</h2>
|
||||
<p>D3js version 4, use canvas</p>
|
||||
<canvas width="960" height="500"></canvas>
|
||||
<script src="//d3js.org/d3.v4.min.js"></script>
|
||||
<script>
|
||||
|
||||
var canvas = document.querySelector("canvas"),
|
||||
context = canvas.getContext("2d");
|
||||
|
||||
var width = canvas.width,
|
||||
height = canvas.height,
|
||||
radius = Math.min(width, height) / 2;
|
||||
|
||||
var colors = ["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00", "#800000", "#8E388E",
|
||||
"#7171C6", "#7D9EC0", "#388E8E", "#71C671", "#8E8E38", "#C5C1AA", "#C67171"];
|
||||
|
||||
var arc = d3.arc()
|
||||
.outerRadius(radius - 10)
|
||||
.innerRadius(radius - 70)
|
||||
.context(context);
|
||||
|
||||
var labelArc = d3.arc()
|
||||
.outerRadius(radius - 40)
|
||||
.innerRadius(radius - 40)
|
||||
.context(context);
|
||||
|
||||
var pie = d3.pie()
|
||||
.sort(null)
|
||||
.value(function(d) { return d.area; });
|
||||
|
||||
context.translate(width / 2, height / 2);
|
||||
|
||||
d3.csv("{% url "get_csv" %}", function(d) {
|
||||
d.area = +d.area;
|
||||
if (d.area !== 0) {
|
||||
return d;}
|
||||
}, function(error, data) {
|
||||
if (error) throw error;
|
||||
|
||||
var arcs = pie(data);
|
||||
|
||||
arcs.forEach(function(d, i) {
|
||||
context.beginPath();
|
||||
arc(d);
|
||||
context.fillStyle = colors[i];
|
||||
context.fill();
|
||||
});
|
||||
|
||||
context.beginPath();
|
||||
arcs.forEach(arc);
|
||||
context.strokeStyle = "#fff";
|
||||
context.stroke();
|
||||
|
||||
context.textAlign = "center";
|
||||
context.textBaseline = "middle";
|
||||
context.fillStyle = "#000";
|
||||
arcs.forEach(function(d) {
|
||||
var c = labelArc.centroid(d);
|
||||
context.fillText(d.data.name, c[0], c[1]);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
<body></body>
|
||||
@@ -1,169 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Donut Chart v2</title>
|
||||
<h1>Simple Donut Chart v2</h1>
|
||||
<h2>Zero values excluded, label with ticks</h2>
|
||||
<p>D3js version 3, use svg</p>
|
||||
<style>
|
||||
|
||||
body {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
width: 960px;
|
||||
height: 500px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
path.slice{
|
||||
stroke-width:2px;
|
||||
}
|
||||
|
||||
polyline{
|
||||
opacity: .3;
|
||||
stroke: black;
|
||||
stroke-width: 2px;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<body>
|
||||
<script src="http://d3js.org/d3.v3.min.js"></script>
|
||||
<script>
|
||||
|
||||
|
||||
var svg = d3.select("body")
|
||||
.append("svg")
|
||||
.append("g")
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "slices");
|
||||
svg.append("g")
|
||||
.attr("class", "labels");
|
||||
svg.append("g")
|
||||
.attr("class", "lines");
|
||||
|
||||
var width = 960,
|
||||
height = 500,
|
||||
radius = Math.min(width, height) / 2;
|
||||
|
||||
var pie = d3.layout.pie()
|
||||
.sort(null)
|
||||
.value(function(d) {
|
||||
return d.area;
|
||||
});
|
||||
|
||||
var arc = d3.svg.arc()
|
||||
.outerRadius(radius * 0.8)
|
||||
.innerRadius(radius * 0.4);
|
||||
|
||||
var outerArc = d3.svg.arc()
|
||||
.innerRadius(radius * 0.9)
|
||||
.outerRadius(radius * 0.9);
|
||||
|
||||
d3.csv("{% url "get_csv" %}", function(d) {
|
||||
d.area = +d.area;
|
||||
if (d.area !== 0) {
|
||||
return d;}
|
||||
}, function(error, data) {
|
||||
if (error) throw error;
|
||||
|
||||
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
|
||||
|
||||
var key = function(d){ return d.data.name};
|
||||
|
||||
var color = d3.scale.ordinal()
|
||||
.domain([key])
|
||||
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
|
||||
|
||||
|
||||
var slice = svg.select(".slices").selectAll("path.slice")
|
||||
.data(pie(data), key);
|
||||
|
||||
slice.enter()
|
||||
.insert("path")
|
||||
.style("fill", function(d) { return color(d.data.area); })
|
||||
.attr("class", "slice");
|
||||
|
||||
slice
|
||||
.transition().duration(1000)
|
||||
.attrTween("d", function(d) {
|
||||
this._current = this._current || d;
|
||||
var interpolate = d3.interpolate(this._current, d);
|
||||
this._current = interpolate(0);
|
||||
return function(t) {
|
||||
return arc(interpolate(t));
|
||||
};
|
||||
})
|
||||
|
||||
|
||||
|
||||
/* ------- TEXT LABELS -------*/
|
||||
|
||||
var text = svg.select(".labels").selectAll("text")
|
||||
.data(pie(data), key);
|
||||
|
||||
text.enter()
|
||||
.append("text")
|
||||
.attr("dy", ".35em")
|
||||
.text(function(d) {
|
||||
return d.data.name + ' - ' +d.data.area; ;
|
||||
});
|
||||
|
||||
function midAngle(d){
|
||||
return d.startAngle + (d.endAngle - d.startAngle)/2;
|
||||
}
|
||||
|
||||
text.transition().duration(1000)
|
||||
.attrTween("transform", function(d) {
|
||||
this._current = this._current || d;
|
||||
var interpolate = d3.interpolate(this._current, d);
|
||||
this._current = interpolate(0);
|
||||
return function(t) {
|
||||
var d2 = interpolate(t);
|
||||
var pos = outerArc.centroid(d2);
|
||||
pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
|
||||
return "translate("+ pos +")";
|
||||
};
|
||||
})
|
||||
.styleTween("text-anchor", function(d){
|
||||
this._current = this._current || d;
|
||||
var interpolate = d3.interpolate(this._current, d);
|
||||
this._current = interpolate(0);
|
||||
return function(t) {
|
||||
var d2 = interpolate(t);
|
||||
return midAngle(d2) < Math.PI ? "start":"end";
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
/* ------- SLICE TO TEXT POLYLINES -------*/
|
||||
|
||||
var polyline = svg.select(".lines").selectAll("polyline")
|
||||
.data(pie(data), key);
|
||||
|
||||
polyline.enter()
|
||||
.append("polyline");
|
||||
|
||||
polyline.transition().duration(1000)
|
||||
.attrTween("points", function(d){
|
||||
this._current = this._current || d;
|
||||
var interpolate = d3.interpolate(this._current, d);
|
||||
this._current = interpolate(0);
|
||||
return function(t) {
|
||||
var d2 = interpolate(t);
|
||||
var pos = outerArc.centroid(d2);
|
||||
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
|
||||
return [arc.centroid(d2), outerArc.centroid(d2), pos];
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
@@ -1,65 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Pie Chart v1</title>
|
||||
<h1>Simple Pie Chart v1</h1>
|
||||
<h2>All data</h2>
|
||||
<p>D3js version 4, use svg</p>
|
||||
<style>
|
||||
|
||||
.arc text {
|
||||
font: 10px sans-serif;
|
||||
text-anchor: middle;
|
||||
}
|
||||
|
||||
.arc path {
|
||||
stroke: #fff;
|
||||
}
|
||||
|
||||
</style>
|
||||
<svg width="960" height="500"></svg>
|
||||
<script src="https://d3js.org/d3.v4.min.js"></script>
|
||||
<script>
|
||||
|
||||
var svg = d3.select("svg"),
|
||||
width = +svg.attr("width"),
|
||||
height = +svg.attr("height"),
|
||||
radius = Math.min(width, height) / 2,
|
||||
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
|
||||
|
||||
var color = d3.scaleOrdinal(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
|
||||
|
||||
var pie = d3.pie()
|
||||
.sort(null)
|
||||
.value(function(d) { return d.area; });
|
||||
|
||||
var path = d3.arc()
|
||||
.outerRadius(radius - 10)
|
||||
.innerRadius(0);
|
||||
|
||||
var label = d3.arc()
|
||||
.outerRadius(radius - 40)
|
||||
.innerRadius(radius - 40);
|
||||
|
||||
|
||||
d3.csv("{% url "get_csv" %}", function(d) {
|
||||
d.area = +d.area;
|
||||
return d;
|
||||
}, function(error, data) {
|
||||
if (error) throw error;
|
||||
|
||||
var arc = g.selectAll(".arc")
|
||||
.data(pie(data))
|
||||
.enter().append("g")
|
||||
.attr("class", "arc");
|
||||
|
||||
arc.append("path")
|
||||
.attr("d", path)
|
||||
.attr("fill", function(d) { return color(d.data.name); });
|
||||
|
||||
arc.append("text")
|
||||
.attr("transform", function(d) { return "translate(" + label.centroid(d) + ")"; })
|
||||
.attr("dy", "0.35em")
|
||||
.text(function(d) { return d.data.name; });
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -1,67 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Pie Chart v2</title>
|
||||
<h1>Simple Pie Chart v2</h1>
|
||||
<h2>Zero values excluded</h2>
|
||||
<p>D3js version 4, use svg</p>
|
||||
<style>
|
||||
|
||||
.arc text {
|
||||
font: 10px sans-serif;
|
||||
text-anchor: middle;
|
||||
}
|
||||
|
||||
.arc path {
|
||||
stroke: #fff;
|
||||
}
|
||||
|
||||
</style>
|
||||
<svg width="960" height="500"></svg>
|
||||
<script src="https://d3js.org/d3.v4.min.js"></script>
|
||||
<script>
|
||||
|
||||
|
||||
var svg = d3.select("svg"),
|
||||
width = +svg.attr("width"),
|
||||
height = +svg.attr("height"),
|
||||
radius = Math.min(width, height) / 2,
|
||||
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
|
||||
|
||||
var color = d3.scaleOrdinal(d3.schemeCategory20);
|
||||
|
||||
var pie = d3.pie()
|
||||
.sort(null)
|
||||
.value(function(d) { return d.{{ quantity }}; });
|
||||
|
||||
var path = d3.arc()
|
||||
.outerRadius(radius - 10)
|
||||
.innerRadius(0);
|
||||
|
||||
var label = d3.arc()
|
||||
.outerRadius(radius - 40)
|
||||
.innerRadius(radius - 40);
|
||||
|
||||
|
||||
d3.csv("/table?lyrname={{ lyrname }}&category={{ category }}&quantity={{ quantity }}", function(d) {
|
||||
d.area = +d.area;
|
||||
if (d.area !== 0) {
|
||||
return d;}
|
||||
}, function(error, data) {
|
||||
if (error) throw error;
|
||||
|
||||
var arc = g.selectAll(".arc")
|
||||
.data(pie(data))
|
||||
.enter().append("g")
|
||||
.attr("class", "arc");
|
||||
|
||||
arc.append("path")
|
||||
.attr("d", path)
|
||||
.attr("fill", function(d) { return color(d.data.{{ category }}); });
|
||||
|
||||
arc.append("text")
|
||||
.attr("transform", function(d) { return "translate(" + label.centroid(d) + ")"; })
|
||||
.attr("dy", "0.35em")
|
||||
.text(function(d) { return d.data.{{ category }}; });
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -1,10 +0,0 @@
|
||||
from django.conf.urls import url
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [url(r'^(?P<pk>[0-9]+)/$', views.ChartDetail.as_view(), name='chart_detail'),
|
||||
url(r'^add/(?P<layer_id>[0-9]+)/$', views.ChartCreate.as_view(), name='chart_add'),
|
||||
url(r'^(?P<pk>[0-9]+)/update/$', views.ChartUpdate.as_view(), name='chart_update'),
|
||||
url(r'^(?P<pk>[0-9]+)/delete/$', views.ChartDelete.as_view(), name='chart_delete'),
|
||||
url(r'^$', views.ChartList.as_view(), name='chart_list')
|
||||
]
|
||||
@@ -1,105 +0,0 @@
|
||||
from django.views.generic.detail import DetailView
|
||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||
from django.views.generic.list import ListView
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
||||
|
||||
from geonode.layers.models import Layer
|
||||
|
||||
from .models import Chart, ChartForm
|
||||
from wfs_harvest.utils import get_fields
|
||||
|
||||
|
||||
class LoginRequiredMixin(object):
|
||||
@classmethod
|
||||
def as_view(cls, **initkwargs):
|
||||
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
|
||||
return login_required(view)
|
||||
|
||||
|
||||
class ChartDetail(DetailView):
|
||||
model = Chart
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
obj = super(ChartDetail, self).get_object(queryset=queryset)
|
||||
lyr_obj = Layer.objects.get(pk=obj.layer)
|
||||
if not self.request.user.has_perm('download_resourcebase', lyr_obj.get_self_resource()):
|
||||
raise PermissionDenied
|
||||
return obj
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ChartDetail, self).get_context_data(**kwargs)
|
||||
return context
|
||||
|
||||
|
||||
class ChartCreate(LoginRequiredMixin, CreateView):
|
||||
form_class = ChartForm
|
||||
template_name = 'charts_app/chart_update_form.html'
|
||||
|
||||
def get_initial(self):
|
||||
layer_id = self.kwargs['layer_id']
|
||||
initial = self.initial.copy()
|
||||
initial['layer'] = layer_id
|
||||
return initial
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
layer_id = self.kwargs['layer_id']
|
||||
layer = Layer.objects.get(pk=layer_id)
|
||||
if not self.request.user.has_perm('download_resourcebase', layer.get_self_resource()):
|
||||
raise PermissionDenied
|
||||
fieldnames, num_fieldnames = get_fields(layer_id)
|
||||
ctx = super(ChartCreate, self).get_context_data(**kwargs)
|
||||
ctx['fieldnames'] = fieldnames
|
||||
ctx['num_fieldnames'] = num_fieldnames
|
||||
ctx['layer'] = layer
|
||||
return ctx
|
||||
|
||||
def form_valid(self, form):
|
||||
if not self.request.user.has_perm('download_resourcebase', form.instance.layer.get_self_resource()):
|
||||
raise PermissionDenied
|
||||
form.instance.created_by = self.request.user
|
||||
return super(ChartCreate, self).form_valid(form)
|
||||
|
||||
|
||||
class ChartUpdate(LoginRequiredMixin, UpdateView):
|
||||
model = Chart
|
||||
fields = '__all__'
|
||||
template_name = 'charts_app/chart_update_form.html'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
obj = super(ChartUpdate, self).get_object(queryset=queryset)
|
||||
is_chart_owner = (self.request.user == obj.created_by)
|
||||
lyr_obj = Layer.objects.get(pk=obj.layer)
|
||||
is_lyr_owner = (self.request.user == lyr_obj.owner)
|
||||
if not (self.request.user.is_superuser or is_chart_owner or is_lyr_owner):
|
||||
raise PermissionDenied
|
||||
return obj
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.created_by = self.request.user
|
||||
return super(ChartUpdate, self).form_valid(form)
|
||||
|
||||
|
||||
class ChartDelete(LoginRequiredMixin, DeleteView):
|
||||
model = Chart
|
||||
success_url = '/layers/'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
obj = super(ChartDelete, self).get_object(queryset=queryset)
|
||||
is_chart_owner = (self.request.user == obj.created_by)
|
||||
lyr_obj = Layer.objects.get(pk=obj.layer)
|
||||
is_lyr_owner = (self.request.user == lyr_obj.owner)
|
||||
if not (self.request.user.is_superuser or is_chart_owner or is_lyr_owner):
|
||||
raise PermissionDenied
|
||||
return obj
|
||||
|
||||
|
||||
class ChartList(ListView):
|
||||
model = Chart
|
||||
fields = '__all__'
|
||||
template_name = 'charts_app/chart_list.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ChartList, self).get_context_data(**kwargs)
|
||||
return context
|
||||
Whitespace-only changes.
File renamed without changes.
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -0,0 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ClipAndShipConfig(AppConfig):
|
||||
name = 'clip_and_ship'
|
||||
File renamed without changes.
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
File renamed without changes.
@@ -1,3 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import tempfile
|
||||
@@ -6,20 +9,33 @@ import zipfile
|
||||
import urllib2
|
||||
|
||||
import subprocess
|
||||
|
||||
from pyproj import Proj, transform
|
||||
from django.conf import settings
|
||||
from django.http import Http404, HttpResponse, JsonResponse
|
||||
from django.shortcuts import render
|
||||
from django.views.generic.detail import View
|
||||
from geonode.layers.views import _resolve_layer, _PERMISSION_MSG_VIEW
|
||||
from geonode.layers.models import Layer
|
||||
|
||||
WCS_URL = settings.GEOSERVER_BASE_URL + \
|
||||
WCS_URL = settings.GEOSERVER_PUBLIC_LOCATION + \
|
||||
'wcs?request=getcoverage&' \
|
||||
'version=1.0.0&service=WCS&coverage={layer_name}&' \
|
||||
'format=geotiff&crs=EPSG:4326&bbox={bbox}&width={width}&' \
|
||||
'height={height}'
|
||||
|
||||
WCS_URL_2_0_1 = settings.GEOSERVER_BASE_URL + \
|
||||
WCS_URL_2_0_1 = settings.GEOSERVER_PUBLIC_LOCATION + \
|
||||
'wcs?request=getcoverage&' \
|
||||
'version=2.0.1&service=WCS&coverageid={layer_name}&' \
|
||||
'format=geotiff&crs=EPSG:4326&subset=E({x1},{x2})&subset=N({y1},{y2})'
|
||||
|
||||
WCS_URL_dev = settings.GEOSERVER_PUBLIC_LOCATION + \
|
||||
'wcs?request=getcoverage&' \
|
||||
'version=1.0.0&service=WCS&coverage={layer_name}&' \
|
||||
'format=geotiff&crs=EPSG:4326&bbox={bbox}&width={width}&' \
|
||||
'height={height}'
|
||||
|
||||
WCS_URL_2_0_1_dev = settings.GEOSERVER_PUBLIC_LOCATION + \
|
||||
'wcs?request=getcoverage&' \
|
||||
'version=2.0.1&service=WCS&coverageid={layer_name}&' \
|
||||
'format=geotiff&crs=EPSG:4326&subset=E({x1},{x2})&subset=N({y1},{y2})'
|
||||
@@ -62,12 +78,20 @@ def download_wcs(layername, bbox_string, width, height, raster_filepath):
|
||||
|
||||
:return:
|
||||
"""
|
||||
wcs_formatted_url = WCS_URL.format(
|
||||
layer_name=layername,
|
||||
bbox=bbox_string,
|
||||
width=width,
|
||||
height=height
|
||||
)
|
||||
if layername == 'geonode:ortho_images' or layername == 'geonode:lidar':
|
||||
wcs_formatted_url = WCS_URL_dev.format(
|
||||
layer_name=layername,
|
||||
bbox=bbox_string,
|
||||
width=width,
|
||||
height=height
|
||||
)
|
||||
else:
|
||||
wcs_formatted_url = WCS_URL.format(
|
||||
layer_name=layername,
|
||||
bbox=bbox_string,
|
||||
width=width,
|
||||
height=height
|
||||
)
|
||||
|
||||
response = urllib2.urlopen(wcs_formatted_url)
|
||||
fh = open(raster_filepath, "w")
|
||||
@@ -83,13 +107,22 @@ def download_wcs_v2(layername, x1, x2, y1, y2, raster_filepath):
|
||||
|
||||
:return:
|
||||
"""
|
||||
wcs_formatted_url = WCS_URL_2_0_1.format(
|
||||
layer_name=layername,
|
||||
x1=x1,
|
||||
x2=x2,
|
||||
y1=y1,
|
||||
y2=y2
|
||||
)
|
||||
if layername == 'geonode:ortho_images' or layername == 'geonode:lidar':
|
||||
wcs_formatted_url = WCS_URL_2_0_1_dev.format(
|
||||
layer_name=layername,
|
||||
x1=x1,
|
||||
x2=x2,
|
||||
y1=y1,
|
||||
y2=y2
|
||||
)
|
||||
else:
|
||||
wcs_formatted_url = WCS_URL_2_0_1.format(
|
||||
layer_name=layername,
|
||||
x1=x1,
|
||||
x2=x2,
|
||||
y1=y1,
|
||||
y2=y2
|
||||
)
|
||||
|
||||
response = urllib2.urlopen(wcs_formatted_url)
|
||||
fh = open(raster_filepath, "w")
|
||||
@@ -106,11 +139,10 @@ def clip_layer(request, layername):
|
||||
"""
|
||||
# PREPARATION
|
||||
try:
|
||||
layer = _resolve_layer(
|
||||
request,
|
||||
layername,
|
||||
'base.view_resourcebase',
|
||||
_PERMISSION_MSG_VIEW)
|
||||
layer = Layer.objects.get(
|
||||
workspace=layername.split(':')[0],
|
||||
name=layername.split(':')[1]
|
||||
)
|
||||
except Http404 as e:
|
||||
response = JsonResponse({
|
||||
'error': '%s. '
|
||||
@@ -318,11 +350,10 @@ def download_clip(request, layername, clip_filename):
|
||||
:return: The HTTPResponse with a file.
|
||||
"""
|
||||
# PREPARATION
|
||||
layer = _resolve_layer(
|
||||
request,
|
||||
layername,
|
||||
'base.view_resourcebase',
|
||||
_PERMISSION_MSG_VIEW)
|
||||
layer = Layer.objects.get(
|
||||
workspace=layername.split(':')[0],
|
||||
name=layername.split(':')[1]
|
||||
)
|
||||
|
||||
query = request.GET or request.POST
|
||||
params = {
|
||||
@@ -401,7 +432,7 @@ def download_clip(request, layername, clip_filename):
|
||||
|
||||
|
||||
class ClipView(View):
|
||||
template_name = 'clip-and-ship/clip-page.html'
|
||||
template_name = 'clip_and_ship/clip_page.html'
|
||||
|
||||
def get(self, request, geotiffname):
|
||||
context = {
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
GEOSERVER_URL: "https://build.geo-solutions.it/geonode/geoserver/latest/geoserver-2.15.4.war"
|
||||
DATA_DIR_URL: "https://build.geo-solutions.it/geonode/geoserver/latest/data-2.15.4.zip"
|
||||
JETTY_RUNNER_URL: "https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.7.v20170914/jetty-runner-9.4.7.v20170914.jar"
|
||||
WINDOWS:
|
||||
py2exe: "http://downloads.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe"
|
||||
nose: "https://s3.amazonaws.com/geonodedeps/nose-1.3.3.win32-py2.7.exe"
|
||||
pyproj: "https://pyproj.googlecode.com/files/pyproj-1.9.3.win32-py2.7.exe"
|
||||
lxml: "https://pypi.python.org/packages/2.7/l/lxml/lxml-3.6.0.win32-py2.7.exe"
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
docker-compose build --no-cache; docker-compose stop; docker-compose up -d; docker system prune -a
|
||||
@@ -0,0 +1,10 @@
|
||||
version: '2.2'
|
||||
services:
|
||||
|
||||
django:
|
||||
build: .
|
||||
# Loading the app is defined here to allow for
|
||||
# autoreload on changes it is mounted on top of the
|
||||
# old copy that docker added when creating the image
|
||||
volumes:
|
||||
- '.:/usr/src/haitidata'
|
||||
@@ -0,0 +1,113 @@
|
||||
version: '2.2'
|
||||
services:
|
||||
|
||||
db:
|
||||
image: geonode/postgis:11
|
||||
restart: unless-stopped
|
||||
container_name: db4${COMPOSE_PROJECT_NAME}
|
||||
stdin_open: true
|
||||
# tty: true
|
||||
labels:
|
||||
org.geonode.component: db
|
||||
org.geonode.instance.name: geonode
|
||||
volumes:
|
||||
- dbdata:/var/lib/postgresql/data
|
||||
- dbbackups:/pg_backups
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
geoserver:
|
||||
image: geonode/geoserver:2.15.4
|
||||
build: ./docker/geoserver/
|
||||
restart: unless-stopped
|
||||
container_name: geoserver4${COMPOSE_PROJECT_NAME}
|
||||
stdin_open: true
|
||||
# tty: true
|
||||
labels:
|
||||
org.geonode.component: geoserver
|
||||
org.geonode.instance.name: geonode
|
||||
depends_on:
|
||||
- db
|
||||
- data-dir-conf
|
||||
volumes:
|
||||
- geoserver-data-dir:/geoserver_data/data
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
django:
|
||||
restart: unless-stopped
|
||||
build: .
|
||||
container_name: django4${COMPOSE_PROJECT_NAME}
|
||||
stdin_open: true
|
||||
# tty: true
|
||||
labels:
|
||||
org.geonode.component: django
|
||||
org.geonode.instance.name: geonode
|
||||
depends_on:
|
||||
- db
|
||||
- data-dir-conf
|
||||
# command: paver start_django -b 0.0.0.0:8000
|
||||
# command: uwsgi --ini uwsgi.ini
|
||||
volumes:
|
||||
- statics:/mnt/volumes/statics
|
||||
- geoserver-data-dir:/geoserver_data/data
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
geonode:
|
||||
image: geonode/nginx:geoserver
|
||||
build: ./docker/nginx/
|
||||
restart: unless-stopped
|
||||
container_name: nginx4${COMPOSE_PROJECT_NAME}
|
||||
stdin_open: true
|
||||
# tty: true
|
||||
labels:
|
||||
org.geonode.component: nginx
|
||||
org.geonode.instance.name: geonode
|
||||
depends_on:
|
||||
- django
|
||||
- geoserver
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- nginx-confd:/etc/nginx
|
||||
- nginx-certificates:/geonode-certificates
|
||||
- statics:/mnt/volumes/statics
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
# Gets and installs letsencrypt certificates
|
||||
letsencrypt:
|
||||
image: geonode/letsencrypt:2.10.4
|
||||
build: ./docker/letsencrypt/
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- nginx-certificates:/geonode-certificates/
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
data-dir-conf:
|
||||
image: geonode/geoserver_data:2.15.4
|
||||
restart: on-failure
|
||||
container_name: gsconf4${COMPOSE_PROJECT_NAME}
|
||||
labels:
|
||||
org.geonode.component: conf
|
||||
org.geonode.instance.name: geonode
|
||||
command: /bin/true
|
||||
volumes:
|
||||
- geoserver-data-dir:/geoserver_data/data
|
||||
|
||||
volumes:
|
||||
statics:
|
||||
name: ${COMPOSE_PROJECT_NAME}-statics
|
||||
nginx-confd:
|
||||
name: ${COMPOSE_PROJECT_NAME}-nginxconfd
|
||||
nginx-certificates:
|
||||
name: ${COMPOSE_PROJECT_NAME}-nginxcerts
|
||||
geoserver-data-dir:
|
||||
name: ${COMPOSE_PROJECT_NAME}-gsdatadir
|
||||
dbdata:
|
||||
name: ${COMPOSE_PROJECT_NAME}-dbdata
|
||||
dbbackups:
|
||||
name: ${COMPOSE_PROJECT_NAME}-dbbackups
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
docker kill $(docker ps -q); docker rm $(docker ps -a -q); docker rmi $(docker images -q); docker volume ls -qf dangling=true | xargs -r docker volume rm; docker system prune -a
|
||||
@@ -0,0 +1,97 @@
|
||||
FROM tomcat:9-jre8
|
||||
MAINTAINER GeoNode Development Team
|
||||
|
||||
#
|
||||
# Set GeoServer version and data directory
|
||||
#
|
||||
ENV GEOSERVER_VERSION=2.15.4
|
||||
ENV GEOSERVER_DATA_DIR="/geoserver_data/data"
|
||||
|
||||
#
|
||||
# Download and install GeoServer
|
||||
#
|
||||
RUN cd /usr/local/tomcat/webapps \
|
||||
&& wget --no-check-certificate --progress=bar:force:noscroll https://build.geo-solutions.it/geonode/geoserver/latest/geoserver-${GEOSERVER_VERSION}.war \
|
||||
&& unzip -q geoserver-${GEOSERVER_VERSION}.war -d geoserver \
|
||||
&& rm geoserver-${GEOSERVER_VERSION}.war \
|
||||
&& mkdir -p $GEOSERVER_DATA_DIR
|
||||
|
||||
VOLUME $GEOSERVER_DATA_DIR
|
||||
|
||||
# added by simonelanucara https://github.com/simonelanucara
|
||||
# Optionally add JAI, ImageIO and Marlin Render for improved Geoserver performance
|
||||
WORKDIR /tmp
|
||||
ARG JAI_IMAGEIO=true
|
||||
RUN if [ "$JAI_IMAGEIO" = true ]; then \
|
||||
wget https://github.com/bourgesl/marlin-renderer/releases/download/v0_9_3/marlin-0.9.3-Unsafe.jar && \
|
||||
mv /tmp/marlin-0.9.3-Unsafe.jar /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/ ; \
|
||||
fi
|
||||
|
||||
###########docker host###############
|
||||
# Set DOCKERHOST variable if DOCKER_HOST exists
|
||||
ARG DOCKERHOST=${DOCKERHOST}
|
||||
# for debugging
|
||||
RUN echo -n #1===>DOCKERHOST=${DOCKERHOST}
|
||||
#
|
||||
ENV DOCKERHOST ${DOCKERHOST}
|
||||
# for debugging
|
||||
RUN echo -n #2===>DOCKERHOST=${DOCKERHOST}
|
||||
|
||||
###########docker host ip#############
|
||||
# Set GEONODE_HOST_IP address if it exists
|
||||
ARG GEONODE_HOST_IP=${GEONODE_HOST_IP}
|
||||
# for debugging
|
||||
RUN echo -n #1===>GEONODE_HOST_IP=${GEONODE_HOST_IP}
|
||||
#
|
||||
ENV GEONODE_HOST_IP ${GEONODE_HOST_IP}
|
||||
# for debugging
|
||||
RUN echo -n #2===>GEONODE_HOST_IP=${GEONODE_HOST_IP}
|
||||
# If empty set DOCKER_HOST_IP to GEONODE_HOST_IP
|
||||
ENV DOCKER_HOST_IP=${DOCKER_HOST_IP:-${GEONODE_HOST_IP}}
|
||||
# for debugging
|
||||
RUN echo -n #1===>DOCKER_HOST_IP=${DOCKER_HOST_IP}
|
||||
# Trying to set the value of DOCKER_HOST_IP from DOCKER_HOST
|
||||
RUN if ! [ -z ${DOCKER_HOST_IP} ]; \
|
||||
then echo export DOCKER_HOST_IP=${DOCKERHOST} | \
|
||||
sed 's/tcp:\/\/\([^:]*\).*/\1/' >> /root/.bashrc; \
|
||||
else echo "DOCKER_HOST_IP is already set!"; fi
|
||||
# for debugging
|
||||
RUN echo -n #2===>DOCKER_HOST_IP=${DOCKER_HOST_IP}
|
||||
|
||||
# Set WEBSERVER public port
|
||||
ARG PUBLIC_PORT=${PUBLIC_PORT}
|
||||
# for debugging
|
||||
RUN echo -n #1===>PUBLIC_PORT=${PUBLIC_PORT}
|
||||
#
|
||||
ENV PUBLIC_PORT=${PUBLIC_PORT}
|
||||
# for debugging
|
||||
RUN echo -n #2===>PUBLIC_PORT=${PUBLIC_PORT}
|
||||
|
||||
# set nginx base url for geoserver
|
||||
RUN echo export NGINX_BASE_URL=http://${NGINX_HOST}:${NGINX_PORT}/ | \
|
||||
sed 's/tcp:\/\/\([^:]*\).*/\1/' >> /root/.bashrc
|
||||
|
||||
# copy the script and perform the run of scripts from entrypoint.sh
|
||||
RUN mkdir -p /usr/local/tomcat/tmp
|
||||
WORKDIR /usr/local/tomcat/tmp
|
||||
COPY set_geoserver_auth.sh /usr/local/tomcat/tmp
|
||||
COPY setup_auth.sh /usr/local/tomcat/tmp
|
||||
COPY requirements.txt /usr/local/tomcat/tmp
|
||||
COPY get_dockerhost_ip.py /usr/local/tomcat/tmp
|
||||
COPY get_nginxhost_ip.py /usr/local/tomcat/tmp
|
||||
COPY entrypoint.sh /usr/local/tomcat/tmp
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get -y upgrade \
|
||||
&& apt-get install -y python python-pip python-dev \
|
||||
&& chmod +x /usr/local/tomcat/tmp/set_geoserver_auth.sh \
|
||||
&& chmod +x /usr/local/tomcat/tmp/setup_auth.sh \
|
||||
&& chmod +x /usr/local/tomcat/tmp/entrypoint.sh \
|
||||
&& pip install pip==9.0.3 \
|
||||
&& pip install -r requirements.txt \
|
||||
&& chmod +x /usr/local/tomcat/tmp/get_dockerhost_ip.py \
|
||||
&& chmod +x /usr/local/tomcat/tmp/get_nginxhost_ip.py
|
||||
|
||||
ENV JAVA_OPTS="-Djava.awt.headless=true -XX:MaxPermSize=512m -XX:PermSize=256m -Xms512m -Xmx2048m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Duser.timezone=GMT -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=true"
|
||||
|
||||
CMD ["/usr/local/tomcat/tmp/entrypoint.sh"]
|
||||
@@ -0,0 +1,128 @@
|
||||
# geoserver-docker
|
||||
|
||||
[GeoServer](http://geoserver.org) is an open source server for sharing geospatial data.
|
||||
This is a docker image that eases setting up a GeoServer running specifically for [GeoNode](https://github.com/GeoNode/geoserver-geonode-ext) with an additional separated data directory.
|
||||
|
||||
The image is based on the official Tomcat 9 image
|
||||
|
||||
## Installation
|
||||
|
||||
This image is available as a [trusted build on the docker hub](https://registry.hub.docker.com/r/geonode/geoserver/), and is the recommended method of installation.
|
||||
Simple pull the image from the docker hub.
|
||||
|
||||
```bash
|
||||
$ docker pull geonode/geoserver
|
||||
```
|
||||
|
||||
Alternatively you can build the image locally
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/geonode/geoserver-docker.git
|
||||
$ cd geoserver-docker
|
||||
$ docker build -t "geonode/geoserver" .
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
You can quick start the image using the command line
|
||||
|
||||
```bash
|
||||
$ docker run --name "geoserver" -v /var/run/docker.sock:/var/run/docker.sock -d -p 8080:8080 geonode/geoserver
|
||||
```
|
||||
|
||||
Point your browser to `http://localhost:8080/geoserver` and login using GeoServer's default username and password:
|
||||
|
||||
* Username: admin
|
||||
* Password: geoserver
|
||||
|
||||
## How to use different versions
|
||||
|
||||
There are mainly two different versions of this image which are useful for running **GeoNode** with different authentication system types. These versions are released as specific tags for two authentication mechanisms:
|
||||
|
||||
**Cookie based authn**:
|
||||
- [geonode/geoserver:2.9.x](https://hub.docker.com/r/geonode/geoserver/builds/bx7ydhghnlrfnsppduyva73/)
|
||||
|
||||
**Oauth2 based authn**:
|
||||
- [geonode/geoserver:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver/builds/bwca5rtexeoegzgroavftdr/)
|
||||
- [geonode/geoserver:2.10.x](https://hub.docker.com/r/geonode/geoserver/builds/bjohcnc29vm69acqjrvndxf/)
|
||||
- [geonode/geoserver:2.12.x](https://hub.docker.com/r/geonode/geoserver/builds/bh7pyw5atmkcljurwsnzbs7/)
|
||||
- [geonode/geoserver:2.13.x](https://hub.docker.com/r/geonode/geoserver/builds/btmjctbuvrjfnnrxrs4wyrs/)
|
||||
- [geonode/geoserver:2.14.x](https://hub.docker.com/r/geonode/geoserver/builds/bj53pi8he8uksz6ggvrs3wc/)
|
||||
|
||||
You can declare what version to use along with the data directory tag which corresponds to the same version.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Data volume
|
||||
|
||||
This GeoServer container keeps its configuration data at `/geoserver_data/data` which is exposed as volume in the dockerfile.
|
||||
The volume allows for stopping and starting new containers from the same image without losing all the data and custom configuration.
|
||||
|
||||
You may want to map this volume to a directory on the host. It will also ease the upgrade process in the future. Volumes can be mounted by passing the `-v` flag to the docker run command:
|
||||
|
||||
```bash
|
||||
-v /your/host/data/path:/geoserver_data/data
|
||||
```
|
||||
|
||||
### Data volume container
|
||||
|
||||
In case you are running Compose for automatically having GeoServer up and running then a data volume container will be mounted with a default preloaded *GEOSERVER_DATA_DIR* at the configuration data directory of the container.
|
||||
Make sure that the image from the repository [data-docker](https://github.com/GeoNode/data-docker) is available from the [GeoNode Docker Hub](https://hub.docker.com/u/geonode/) or has been built locally:
|
||||
|
||||
```bash
|
||||
docker build -t geonode/geoserver_data .
|
||||
```
|
||||
|
||||
#### Persistance behavior
|
||||
|
||||
If you run:
|
||||
|
||||
```bash
|
||||
docker-compose stop
|
||||
```
|
||||
|
||||
Data are retained in the *GEOSERVER_DATA_DIR* and can then be mounted in a new GeoServer instance by running again:
|
||||
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
If you run:
|
||||
|
||||
```bash
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
Data are completely gone but you can ever start from the base GeoServer Data Directory built for Geonode.
|
||||
|
||||
#### Data directory versions
|
||||
|
||||
There has to be a correspondence one-to-one between the data directory version and the tag of the GeoServer image used in the Docker compose file. So at the end you can consume these images below:
|
||||
|
||||
* **2.9.x**: [geonode/geoserver_data:2.9.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bsus6alnddg4bc7icwymevp/)
|
||||
* **2.9.x-oauth2**: [geonode/geoserver_data:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver_data/builds/bwkxcupsunvuitzusi9gsnt/)
|
||||
* **2.10.x**: [geonode/geoserver_data:2.10.x](https://hub.docker.com/r/geonode/geoserver_data/builds/b5jqhpzapkqxzyevjizccug/)
|
||||
* **2.12.x**: [geonode/geoserver_data:2.12.x](https://hub.docker.com/r/geonode/geoserver_data/builds/byaaalw3lnasunpveyg3x4i/)
|
||||
* **2.13.x**: [geonode/geoserver_data:2.13.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bunuqzq7a7dk65iumjhkbtc/)
|
||||
* **2.14.x**: [geonode/geoserver_data:2.14.x](https://hub.docker.com/r/geonode/geoserver_data/builds/blpdjzkrv7pm3stunzpn4pp/)
|
||||
|
||||
### Database
|
||||
|
||||
GeoServer recommends the usage of a spatial database
|
||||
|
||||
#### PostGIS container (PostgreSQL + GIS Extension)
|
||||
|
||||
If you want to use a [PostGIS](http://postgis.org/) container, you can link it to this image. You're free to use any PostGIS container.
|
||||
An example with [kartooza/postgis](https://registry.hub.docker.com/u/kartoza/postgis/) image:
|
||||
|
||||
```bash
|
||||
$ docker run -d --name="postgis" kartoza/postgis
|
||||
```
|
||||
|
||||
For further information see [kartooza/postgis](https://registry.hub.docker.com/u/kartoza/postgis/).
|
||||
|
||||
Now start the GeoServer instance by adding the `--link` option to the docker run command:
|
||||
|
||||
```bash
|
||||
--link postgis:postgis
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
version: '2.2'
|
||||
|
||||
services:
|
||||
|
||||
geoserver:
|
||||
image: geonode/geoserver:2.15.4
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
- DOCKERHOST
|
||||
- GEONODE_HOST_IP
|
||||
- PUBLIC_PORT=80
|
||||
links:
|
||||
- postgis
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
#- /srv/docker/geoserver/geoserver:/geoserver_data/data
|
||||
volumes_from:
|
||||
# reference to the service which has the volume
|
||||
# with the preloaded geoserver_data_dir
|
||||
- data_dir_conf # service for geoserver data volume
|
||||
environment:
|
||||
- DOCKERHOST
|
||||
- GEONODE_HOST_IP
|
||||
- PUBLIC_PORT=80
|
||||
- DOCKER_HOST_IP
|
||||
- DJANGO_URL=http://localhost/
|
||||
|
||||
data_dir_conf:
|
||||
image: geonode/geoserver_data:2.15.4
|
||||
container_name: geoserver_data_dir # named data container
|
||||
command: /bin/true
|
||||
volumes:
|
||||
- /geoserver_data/data
|
||||
|
||||
postgis:
|
||||
image: geonode/postgis
|
||||
ports:
|
||||
- "25432:5432"
|
||||
volumes:
|
||||
- /srv/docker/geoserver/postgis:/var/lib/postgresql
|
||||
#volumes_from:
|
||||
#- pgstore
|
||||
|
||||
volumes:
|
||||
# reference to the named data container that holds the preloaded geoserver data directory
|
||||
geoserver_data_dir:
|
||||
@@ -0,0 +1,103 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source /root/.bashrc
|
||||
|
||||
# control the value of DOCKER_HOST_IP variable
|
||||
if [ -z ${DOCKER_HOST_IP} ]
|
||||
then
|
||||
|
||||
echo "DOCKER_HOST_IP is empty so I'll run the python utility \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
echo export DOCKER_HOST_IP=`python /usr/local/tomcat/tmp/get_dockerhost_ip.py` >> /root/.override_env
|
||||
echo "The calculated value is now DOCKER_HOST_IP='$DOCKER_HOST_IP' \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
|
||||
else
|
||||
|
||||
echo "DOCKER_HOST_IP is filled so I'll leave the found value '$DOCKER_HOST_IP' \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
|
||||
fi
|
||||
|
||||
# control the values of LB settings if present
|
||||
if [ ${GEONODE_LB_HOST_IP} ]
|
||||
then
|
||||
|
||||
echo "GEONODE_LB_HOST_IP is filled so I replace the value of '$DOCKER_HOST_IP' with '$GEONODE_LB_HOST_IP' \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
echo export DOCKER_HOST_IP=${GEONODE_LB_HOST_IP} >> /root/.override_env
|
||||
|
||||
fi
|
||||
|
||||
if [ ${GEONODE_LB_PORT} ]
|
||||
then
|
||||
|
||||
echo "GEONODE_LB_PORT is filled so I replace the value of '$PUBLIC_PORT' with '$GEONODE_LB_PORT' \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
echo export PUBLIC_PORT=${GEONODE_LB_PORT} >> /root/.override_env
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -z "${GEOSERVER_JAVA_OPTS}" ]
|
||||
then
|
||||
|
||||
echo "GEOSERVER_JAVA_OPTS is filled so I replace the value of '$JAVA_OPTS' with '$GEOSERVER_JAVA_OPTS' \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
JAVA_OPTS=${GEOSERVER_JAVA_OPTS}
|
||||
|
||||
fi
|
||||
|
||||
# control the value of NGINX_BASE_URL variable
|
||||
if [ -z `echo ${NGINX_BASE_URL} | sed 's/http:\/\/\([^:]*\).*/\1/'` ]
|
||||
then
|
||||
echo "NGINX_BASE_URL is empty so I'll use the static nginx hostname \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
# echo export NGINX_BASE_URL=`python /usr/local/tomcat/tmp/get_nginxhost_ip.py` >> /root/.override_env
|
||||
# TODO rework get_nginxhost_ip to get URL with static hostname from nginx service name
|
||||
# + exposed port of that container i.e. http://geonode:80
|
||||
echo export NGINX_BASE_URL=http://geonode:80 >> /root/.override_env
|
||||
echo "The calculated value is now NGINX_BASE_URL='$NGINX_BASE_URL' \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
else
|
||||
echo "NGINX_BASE_URL is filled so I'll leave the found value '$NGINX_BASE_URL' \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
fi
|
||||
|
||||
# set basic tagname
|
||||
TAGNAME=( "baseUrl" )
|
||||
|
||||
if ! [ -f ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ]
|
||||
then
|
||||
|
||||
echo "Configuration file '$GEOSERVER_DATA_DIR'/security/auth/geonodeAuthProvider/config.xml is not available so it is gone to skip \n" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
|
||||
else
|
||||
|
||||
# backup geonodeAuthProvider config.xml
|
||||
cp ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml.orig
|
||||
# run the setting script for geonodeAuthProvider
|
||||
/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/ ${TAGNAME} >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
|
||||
fi
|
||||
|
||||
# backup geonode REST role service config.xml
|
||||
cp "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml.orig"
|
||||
# run the setting script for geonode REST role service
|
||||
/usr/local/tomcat/tmp/set_geoserver_auth.sh "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/" ${TAGNAME} >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
|
||||
# set oauth2 filter tagname
|
||||
TAGNAME=( "accessTokenUri" "userAuthorizationUri" "redirectUri" "checkTokenEndpointUrl" "logoutUri" )
|
||||
|
||||
# backup geonode-oauth2 config.xml
|
||||
cp ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml.orig
|
||||
# run the setting script for geonode-oauth2
|
||||
/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/ "${TAGNAME[@]}" >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
|
||||
# set global tagname
|
||||
TAGNAME=( "proxyBaseUrl" )
|
||||
|
||||
# backup global.xml
|
||||
cp ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/global.xml.orig
|
||||
# run the setting script for global configuration
|
||||
/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/ ${TAGNAME} >> /usr/local/tomcat/tmp/set_geoserver_auth.log
|
||||
|
||||
# set correct amqp broker url
|
||||
sed -i -e 's/localhost/rabbitmq/g' ${GEOSERVER_DATA_DIR}/notifier/notifier.xml
|
||||
|
||||
# exclude wrong dependencies
|
||||
sed -i -e 's/xom-\*\.jar/xom-\*\.jar,bcprov\*\.jar/g' /usr/local/tomcat/conf/catalina.properties
|
||||
|
||||
# start tomcat
|
||||
exec env JAVA_OPTS="${JAVA_OPTS}" catalina.sh run
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import logging
|
||||
|
||||
import docker
|
||||
|
||||
BOOTSTRAP_IMAGE_CHEIP = 'codenvy/che-ip:nightly'
|
||||
# AF: why call before definition? print _docker_host_ip()
|
||||
|
||||
def _docker_host_ip():
|
||||
client = docker.from_env()
|
||||
ip_list = client.containers.run(BOOTSTRAP_IMAGE_CHEIP,
|
||||
network_mode='host'
|
||||
).split("\n")
|
||||
if len(ip_list) > 1:
|
||||
logging.info("Docker daemon is running on more than one \
|
||||
address {0}".format(ip_list))
|
||||
logging.info("Only the first address:{0} will be returned!".format(
|
||||
ip_list[0]
|
||||
))
|
||||
else:
|
||||
logging.info("Docker daemon is running at the following \
|
||||
address {0}".format(ip_list[0]))
|
||||
return ip_list[0]
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import docker
|
||||
|
||||
client = docker.from_env()
|
||||
# print client.info()
|
||||
# TODO avoid this script can fail and fall in the loop where the geoserver
|
||||
# service is not available and consequently the nginx too which has geoserver
|
||||
# as a reference link
|
||||
for network in client.networks.list():
|
||||
if 'geonode' in network.name:
|
||||
geonode_network = network.name
|
||||
else:
|
||||
geonode_network = 'geonode_default'
|
||||
|
||||
try:
|
||||
containers = {
|
||||
c.attrs['Config']['Image']: c.attrs['NetworkSettings']['\
|
||||
Networks'][geonode_network]['\
|
||||
IPAddress'] for c in client.containers.list() if c.status in 'running'
|
||||
}
|
||||
for item in containers.items():
|
||||
if "geonode/nginx" in item[0]:
|
||||
ipaddr = item[1]
|
||||
|
||||
try:
|
||||
os.environ["NGINX_BASE_URL"] = "http://" + ipaddr + ":" + "80"
|
||||
nginx_base_url = "http://{}:80".format(ipaddr)
|
||||
except NameError as er:
|
||||
logging.info("NGINX container is not running maybe exited! Running\
|
||||
containers are:{0}".format(containers))
|
||||
except KeyError as ke:
|
||||
logging.info("There has been a problem with the docker\
|
||||
network which has raised the following exception: {0}".format(ke))
|
||||
else:
|
||||
# nginx_base_url = None
|
||||
pass
|
||||
finally:
|
||||
try:
|
||||
print nginx_base_url
|
||||
except NameError as ne:
|
||||
print "http://geonode:80"
|
||||
@@ -0,0 +1 @@
|
||||
docker==3.1.1
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
|
||||
auth_conf_source="$1"
|
||||
auth_conf_target="$2"
|
||||
# Creating a temporary file for sed to write the changes to
|
||||
temp_file="xml.tmp"
|
||||
touch $temp_file
|
||||
|
||||
source /root/.bashrc
|
||||
source /root/.override_env
|
||||
|
||||
test -z "$auth_conf_source" && echo "You must specify a source file" && exit 1
|
||||
test -z "$auth_conf_target" && echo "You must specify a target conf directory" && exit 1
|
||||
|
||||
test ! -f "$auth_conf_source" && echo "Source $auth_conf_source does not exist or is not a file" && exit 1
|
||||
test ! -d "$auth_conf_target" && echo "Target directory $auth_conf_target does not exist or is not a directory" && exit 1
|
||||
|
||||
# for debugging
|
||||
echo -e "NGINX_BASE_URL=${NGINX_BASE_URL}\n"
|
||||
if [ "$PUBLIC_PORT" == "443" ]; then
|
||||
SUBSTITUTION_URL="https://${DOCKER_HOST_IP}"
|
||||
if [ "$PUBLIC_PORT" != "443" ]; then
|
||||
SUBSTITUTION_URL="https://${DOCKER_HOST_IP}:${PUBLIC_PORT}"
|
||||
fi
|
||||
else
|
||||
SUBSTITUTION_URL="http://${DOCKER_HOST_IP}"
|
||||
if [ "$PUBLIC_PORT" != "80" ]; then
|
||||
SUBSTITUTION_URL="http://${DOCKER_HOST_IP}:${PUBLIC_PORT}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "SUBSTITUTION_URL=$SUBSTITUTION_URL\n"
|
||||
echo -e "auth_conf_source=$auth_conf_source\n"
|
||||
echo -e "auth_conf_target=$auth_conf_target\n"
|
||||
|
||||
# Elegance is the key -> adding an empty last line for Mr. “sed” to pick up
|
||||
echo " " >> "$auth_conf_source"
|
||||
|
||||
cat "$auth_conf_source"
|
||||
|
||||
tagname=( ${@:3:5} )
|
||||
|
||||
# for debugging
|
||||
for i in "${tagname[@]}"
|
||||
do
|
||||
echo "tagname=<$i>"
|
||||
done
|
||||
|
||||
echo "DEBUG: Starting... [Ok]\n"
|
||||
|
||||
for i in "${tagname[@]}"
|
||||
do
|
||||
echo "DEBUG: Working on '$auth_conf_source' for tagname <$i>"
|
||||
# Extracting the value from the <$tagname> element
|
||||
# echo -ne "<$i>$tagvalue</$i>" | xmlstarlet sel -t -m "//a" -v . -n
|
||||
tagvalue=`grep "<$i>.*<.$i>" "$auth_conf_source" | sed -e "s/^.*<$i/<$i/" | cut -f2 -d">"| cut -f1 -d"<"`
|
||||
|
||||
echo "DEBUG: Found the current value for the element <$i> - '$tagvalue'"
|
||||
|
||||
# Setting new substituted value
|
||||
case $i in
|
||||
proxyBaseUrl )
|
||||
if [ ${GEONODE_LB_HOST_IP} ]
|
||||
then
|
||||
echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$SUBSTITUTION_URL'"
|
||||
newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$SUBSTITUTION_URL@"`
|
||||
else
|
||||
echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$NGINX_BASE_URL'"
|
||||
newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$NGINX_BASE_URL@"`
|
||||
fi;;
|
||||
accessTokenUri | checkTokenEndpointUrl | baseUrl )
|
||||
echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$NGINX_BASE_URL'"
|
||||
newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$NGINX_BASE_URL@"`;;
|
||||
userAuthorizationUri | redirectUri | logoutUri )
|
||||
echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$SUBSTITUTION_URL'"
|
||||
newvalue=`echo -ne "$tagvalue" | sed -re "s@http://localhost(:8.*0)@$SUBSTITUTION_URL@"`;;
|
||||
*) echo -n "an unknown variable has been found";;
|
||||
esac
|
||||
|
||||
echo "DEBUG: Found the new value for the element <$i> - '$newvalue'"
|
||||
# Replacing element’s value with $SUBSTITUTION_URL
|
||||
# echo -ne "<$i>$tagvalue</$i>" | xmlstarlet sel -t -m "//a" -v . -n
|
||||
sed -e "s@<$i>$tagvalue<\/$i>@<$i>$newvalue<\/$i>@g" "$auth_conf_source" > "$temp_file"
|
||||
cp "$temp_file" "$auth_conf_source"
|
||||
done
|
||||
# Writing our changes back to the original file ($auth_conf_source)
|
||||
# no longer needed
|
||||
# mv $temp_file $auth_conf_source
|
||||
|
||||
echo "DEBUG: Finished... [Ok] --- Final xml file is \n"
|
||||
cat "$auth_conf_source"
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
sed -i.bak 's@<baseUrl>\([^<][^<]*\)</baseUrl>@<baseUrl>'"$DJANGO_URL"'</baseUrl>@'\
|
||||
/geoserver_data/data/security/auth/geonodeAuthProvider/config.xml
|
||||
@@ -0,0 +1,19 @@
|
||||
FROM alpine:3.8
|
||||
|
||||
# 1-2. Install system dependencies
|
||||
RUN apk add --no-cache certbot py-pip && pip install pyopenssl==16.0.0 # Need to downgrade PyOpenSSL to 16.0.0 to avoid conflicts and solve the cryptography error : https://github.com/plesk/letsencrypt-plesk/issues/117
|
||||
|
||||
# Installing scripts
|
||||
ADD docker-entrypoint.sh /docker-entrypoint.sh
|
||||
RUN chmod +x /docker-entrypoint.sh
|
||||
|
||||
# Installing cronjobs
|
||||
ADD crontab /crontab
|
||||
RUN /usr/bin/crontab /crontab && \
|
||||
rm /crontab
|
||||
|
||||
# Setup the entrypoint
|
||||
ENTRYPOINT ["./docker-entrypoint.sh"]
|
||||
|
||||
# We run cron in foreground to update the certificates
|
||||
CMD /usr/sbin/crond -f
|
||||
@@ -0,0 +1,16 @@
|
||||
ervice for SPCGeonode
|
||||
|
||||
This service generates SSL certificates to be used by Nginx.
|
||||
|
||||
## Let's Encrypt
|
||||
|
||||
Upon startup, it generates one SSL certificate from Let's Encrypt using Certbot. It then starts cron (in foreground) to renew the certificates using Certbot renew.
|
||||
|
||||
If for some reason getting the certificate fails, a placeholder certificate is generated. This certificate is invalid, but still allows to encrypt the data and to start the webserver.
|
||||
|
||||
To avoid hitting Let's Encrypt very low rate limits when developping or doing tests, LETSENCRYPT_MODE env var can be set to "disabled" (which will completely bypass Let'sEncrypt, simulating a failure) or to "staging" (using Let'sEncrypt test certificates with higher rates).
|
||||
|
||||
## Autoissued
|
||||
|
||||
An auto-issued certificate is also generate to be used on the LAN if needed. It is also renewed every now and then using the same cron process than above.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# .............. minute (0 - 59)
|
||||
# . .............. hour (0 - 23)
|
||||
# . . .............. day of month (1 - 31)
|
||||
# . . . .............. month (1 - 12)
|
||||
# . . . . .............. day of week (0 - 6) (Sunday to Saturday; 7 is also Sunday on some systems)
|
||||
# . . . . .
|
||||
|
||||
0 0,12 * * * date && echo "daily " && /docker-entrypoint.sh
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Exit script in case of error
|
||||
set -e
|
||||
|
||||
echo $"\n\n\n"
|
||||
echo "-----------------------------------------------------"
|
||||
echo "STARTING LETSENCRYPT ENTRYPOINT ---------------------"
|
||||
date
|
||||
|
||||
# We make the config dir
|
||||
mkdir -p "/geonode-certificates/$LETSENCRYPT_MODE"
|
||||
|
||||
# Do not exit script in case of error
|
||||
set +e
|
||||
|
||||
# We run the command
|
||||
if [ "$LETSENCRYPT_MODE" == "staging" ]; then
|
||||
printf "\nTrying to get STAGING certificate\n"
|
||||
certbot --config-dir "/geonode-certificates/$LETSENCRYPT_MODE" certonly --webroot -w "/geonode-certificates" -d "$HTTPS_HOST" -m "$ADMIN_EMAIL" --agree-tos --non-interactive --staging --server https://acme-v02.api.letsencrypt.org/directory
|
||||
elif [ "$LETSENCRYPT_MODE" == "production" ]; then
|
||||
printf "\nTrying to get PRODUCTION certificate\n"
|
||||
certbot --config-dir "/geonode-certificates/$LETSENCRYPT_MODE" certonly --webroot -w "/geonode-certificates" -d "$HTTPS_HOST" -m "$ADMIN_EMAIL" --agree-tos --non-interactive --server https://acme-v02.api.letsencrypt.org/directory
|
||||
else
|
||||
printf "\nNot trying to get certificate (simulating failure, because LETSENCRYPT_MODE variable was neither staging nor production\n"
|
||||
/bin/false
|
||||
fi
|
||||
|
||||
# If the certbot comand failed, we will create a placeholder certificate
|
||||
if [ ! $? -eq 0 ]; then
|
||||
# Exit script in case of error
|
||||
set -e
|
||||
|
||||
printf "\nFailed to get the certificates !\n"
|
||||
|
||||
printf "\nWaiting 30s to avoid hitting Letsencrypt rate limits before it's even possible to react\n"
|
||||
sleep 30
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf "\nCertificate have been created/renewed successfully\n"
|
||||
|
||||
echo "-----------------------------------------------------"
|
||||
echo "FINISHED LETSENCRYPT ENTRYPOINT ---------------------"
|
||||
echo "-----------------------------------------------------"
|
||||
|
||||
# Run the CMD
|
||||
exec "$@"
|
||||
@@ -0,0 +1,15 @@
|
||||
FROM nginx:1.17.2-alpine
|
||||
|
||||
RUN apk add --no-cache openssl inotify-tools
|
||||
|
||||
WORKDIR /etc/nginx/
|
||||
|
||||
ADD nginx.conf.envsubst nginx.https.available.conf.envsubst ./
|
||||
ADD geonode.conf ./sites-enabled/
|
||||
|
||||
ADD docker-autoreload.sh docker-entrypoint.sh /
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
RUN chmod +x /docker-autoreload.sh
|
||||
RUN chmod +x /docker-entrypoint.sh
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This will watch the /geonode-certificates folder and run nginx -s reload whenever there are some changes.
|
||||
# We use this to reload nginx config when certificates changed.
|
||||
|
||||
# inspired/copied from https://github.com/kubernetes/kubernetes/blob/master/examples/https-nginx/auto-reload-nginx.sh
|
||||
|
||||
while true
|
||||
do
|
||||
inotifywait -e create -e modify -e delete -e move -r --exclude "\\.certbot\\.lock|\\.well-known" "/geonode-certificates/$LETSENCRYPT_MODE"
|
||||
echo "Changes noticed in /geonode-certificates"
|
||||
|
||||
echo "Waiting 5s for additionnal changes"
|
||||
sleep 5
|
||||
|
||||
echo "Creating symbolic link for WAN host"
|
||||
# for some reason, the ln -f flag doesn't work below...
|
||||
rm -f /certificate_symlink
|
||||
if [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/fullchain.pem" ] && [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/privkey.pem" ]; then
|
||||
echo "Certbot certificate exists, we symlink to the live cert"
|
||||
ln -sf "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST" /certificate_symlink
|
||||
else
|
||||
echo "Certbot certificate does not exist, we symlink to autoissued"
|
||||
ln -sf "/geonode-certificates/autoissued" /certificate_symlink
|
||||
fi
|
||||
|
||||
# Test nginx configuration
|
||||
nginx -t
|
||||
# If it passes, we reload
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "Configuration valid, we reload..."
|
||||
nginx -s reload
|
||||
else
|
||||
echo "Configuration not valid, we do not reload."
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Exit script in case of error
|
||||
set -e
|
||||
|
||||
echo $"\n\n\n"
|
||||
echo "-----------------------------------------------------"
|
||||
echo "STARTING NGINX ENTRYPOINT ---------------------------"
|
||||
date
|
||||
|
||||
# We make the config dir
|
||||
mkdir -p "/geonode-certificates/$LETSENCRYPT_MODE"
|
||||
|
||||
echo "Creating autoissued certificates for HTTP host"
|
||||
if [ ! -f "/geonode-certificates/autoissued/privkey.pem" ] || [[ $(find /geonode-certificates/autoissued/privkey.pem -mtime +365 -print) ]]; then
|
||||
echo "Autoissued certificate does not exist or is too old, we generate one"
|
||||
mkdir -p "/geonode-certificates/autoissued/"
|
||||
openssl req -x509 -nodes -days 1825 -newkey rsa:2048 -keyout "/geonode-certificates/autoissued/privkey.pem" -out "/geonode-certificates/autoissued/fullchain.pem" -subj "/CN=${HTTP_HOST:-null}"
|
||||
else
|
||||
echo "Autoissued certificate already exists"
|
||||
fi
|
||||
|
||||
echo "Creating symbolic link for HTTPS certificate"
|
||||
# for some reason, the ln -f flag doesn't work below...
|
||||
# TODO : not DRY (reuse same scripts as docker-autoreload.sh)
|
||||
rm -f /certificate_symlink
|
||||
if [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/fullchain.pem" ] && [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/privkey.pem" ]; then
|
||||
echo "Certbot certificate exists, we symlink to the live cert"
|
||||
ln -sf "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST" /certificate_symlink
|
||||
else
|
||||
echo "Certbot certificate does not exist, we symlink to autoissued"
|
||||
ln -sf "/geonode-certificates/autoissued" /certificate_symlink
|
||||
fi
|
||||
|
||||
echo "Replacing environement variables"
|
||||
envsubst '\$HTTP_HOST \$HTTPS_HOST \$RESOLVER' < /etc/nginx/nginx.conf.envsubst > /etc/nginx/nginx.conf
|
||||
envsubst '\$HTTP_HOST \$HTTPS_HOST \$RESOLVER' < /etc/nginx/nginx.https.available.conf.envsubst > /etc/nginx/nginx.https.available.conf
|
||||
|
||||
echo "Enabling or not https configuration"
|
||||
if [ -z "${HTTPS_HOST}" ]; then
|
||||
echo "" > /etc/nginx/nginx.https.enabled.conf
|
||||
else
|
||||
ln -sf /etc/nginx/nginx.https.available.conf /etc/nginx/nginx.https.enabled.conf
|
||||
fi
|
||||
|
||||
echo "Loading nginx autoreloader"
|
||||
sh /docker-autoreload.sh &
|
||||
|
||||
echo "-----------------------------------------------------"
|
||||
echo "FINISHED NGINX ENTRYPOINT ---------------------------"
|
||||
echo "-----------------------------------------------------"
|
||||
|
||||
# Run the CMD
|
||||
exec "$@"
|
||||
@@ -0,0 +1,117 @@
|
||||
include /etc/nginx/mime.types;
|
||||
|
||||
# This is the main geonode conf
|
||||
charset utf-8;
|
||||
|
||||
# max upload size
|
||||
client_max_body_size 100G;
|
||||
client_body_buffer_size 256K;
|
||||
large_client_header_buffers 4 64k;
|
||||
proxy_read_timeout 600s;
|
||||
|
||||
fastcgi_hide_header Set-Cookie;
|
||||
|
||||
etag on;
|
||||
|
||||
# compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_http_version 1.1;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
gzip_buffers 16 8k;
|
||||
gzip_min_length 1100;
|
||||
gzip_comp_level 6;
|
||||
gzip_types
|
||||
text/css
|
||||
text/javascript
|
||||
text/xml
|
||||
text/plain
|
||||
application/xml
|
||||
application/xml+rss
|
||||
application/javascript
|
||||
application/x-javascript
|
||||
application/json;
|
||||
|
||||
# GeoServer
|
||||
location /geoserver {
|
||||
|
||||
# Using a variable is a trick to let Nginx start even if upstream host is not up yet
|
||||
# (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/)
|
||||
set $upstream geoserver:8080;
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
proxy_pass http://$upstream;
|
||||
}
|
||||
|
||||
# GeoNode
|
||||
location /static/ {
|
||||
alias /mnt/volumes/statics/static/;
|
||||
|
||||
location ~* \.(?:html|js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|txt|woff|woff2|svg|xml)$ {
|
||||
gzip_static always;
|
||||
expires 30d;
|
||||
access_log off;
|
||||
add_header Pragma "public";
|
||||
add_header Cache-Control "max-age=31536000, public";
|
||||
}
|
||||
}
|
||||
|
||||
location /uploaded/ {
|
||||
alias /mnt/volumes/statics/uploaded/;
|
||||
|
||||
location ~* \.(?:html|js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|txt|woff|woff2|svg|xml)$ {
|
||||
gzip_static always;
|
||||
expires 30d;
|
||||
access_log off;
|
||||
add_header Pragma "public";
|
||||
add_header Cache-Control "max-age=31536000, public";
|
||||
}
|
||||
}
|
||||
|
||||
location / {
|
||||
# Using a variable is a trick to let Nginx start even if upstream host is not up yet
|
||||
# (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/)
|
||||
set $upstream django:8000;
|
||||
|
||||
if ($request_method = OPTIONS) {
|
||||
add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, OPTIONS";
|
||||
add_header Access-Control-Allow-Headers "Authorization, Content-Type, Accept";
|
||||
add_header Access-Control-Allow-Credentials true;
|
||||
add_header Content-Length 0;
|
||||
add_header Content-Type text/plain;
|
||||
add_header Access-Control-Max-Age 1728000;
|
||||
return 200;
|
||||
}
|
||||
|
||||
add_header Access-Control-Allow-Credentials false;
|
||||
add_header Access-Control-Allow-Headers "Content-Type, Accept, Authorization, Origin, User-Agent";
|
||||
add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, OPTIONS";
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_connect_timeout 600;
|
||||
proxy_send_timeout 600;
|
||||
proxy_read_timeout 600;
|
||||
send_timeout 600;
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
|
||||
proxy_pass http://$upstream;
|
||||
|
||||
# uwsgi_params
|
||||
include /etc/nginx/uwsgi_params;
|
||||
|
||||
location ~* \.(?:js|jpg|jpeg|gif|png|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|woff|woff2|svg|xml)$ {
|
||||
gzip_static always;
|
||||
expires 30d;
|
||||
access_log off;
|
||||
add_header Pragma "public";
|
||||
add_header Cache-Control "max-age=31536000, public";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
# NOTE : $VARIABLES are env variables replaced by entrypoint.sh using envsubst
|
||||
# not to be mistaken for nginx variables (also starting with $, but usually lowercase)
|
||||
|
||||
worker_processes auto;
|
||||
|
||||
events {
|
||||
|
||||
}
|
||||
|
||||
http {
|
||||
server_names_hash_bucket_size 64;
|
||||
|
||||
# Allow Nginx to resolve Docker host names (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/)
|
||||
resolver $RESOLVER; # it seems rancher uses 169.254.169.250 instead of 127.0.0.11 which works well in docker-compose (see /etc/resolv.conf)
|
||||
|
||||
# https - listens on specific name - this uses letsencrypt cert
|
||||
# this includes a symlink that links either to nginx.https.available.conf if https in enabled
|
||||
# or to an empty file if https is disabled.
|
||||
include nginx.https.enabled.conf;
|
||||
|
||||
# http - listens to specific HTTP_HOST only - this is not encrypted (not ideal but admissible on LAN for instance)
|
||||
# even if not used (HTTP_HOST empty), we must keep it as it's used for internal API calls between django and geoserver
|
||||
# TODO : do not use unencrypted connection even on LAN, but is it possible to have browser not complaining about unknown authority ?
|
||||
server {
|
||||
listen 80;
|
||||
server_name $HTTP_HOST 127.0.0.1 geonode;
|
||||
|
||||
include sites-enabled/*.conf;
|
||||
}
|
||||
|
||||
# Default server closes the connection (we can connect use only HTTP_HOST and HTTPS HOST)
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen 443;
|
||||
server_name _;
|
||||
return 444;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# NOTE : $VARIABLES are env variables replaced by entrypoint.sh using envsubst
|
||||
# not to be mistaken for nginx variables (also starting with $, but usually lowercase)
|
||||
|
||||
# This file is to be included in the main nginx.conf configuration if HTTPS_HOST is set
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
# this is the actual HTTPS host
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name $HTTPS_HOST;
|
||||
keepalive_timeout 70;
|
||||
|
||||
ssl_certificate /certificate_symlink/fullchain.pem;
|
||||
ssl_certificate_key /certificate_symlink/privkey.pem;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
include sites-enabled/*.conf;
|
||||
}
|
||||
|
||||
# if we try to connect from http, we redirect to https
|
||||
server {
|
||||
listen 80;
|
||||
server_name $HTTPS_HOST $HTTP_HOST; # TODO : once geoserver supports relative urls, we should allow access though both HTTP and HTTPS at the same time and hence remove HTTP_HOST from this line
|
||||
|
||||
# Except for let's encrypt challenge
|
||||
location /.well-known {
|
||||
alias /geonode-certificates/.well-known;
|
||||
include /etc/nginx/mime.types;
|
||||
}
|
||||
|
||||
# Redirect to https
|
||||
location / {
|
||||
return 302 https://$HTTPS_HOST$request_uri; # TODO : we should use 301 (permanent redirect, but not practical for debug)
|
||||
}
|
||||
}
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
/usr/local/bin/invoke update >> /usr/src/haitidata/invoke.log
|
||||
|
||||
source $HOME/.bashrc
|
||||
source $HOME/.override_env
|
||||
|
||||
echo DATABASE_URL=$DATABASE_URL
|
||||
echo GEODATABASE_URL=$GEODATABASE_URL
|
||||
echo SITEURL=$SITEURL
|
||||
echo ALLOWED_HOSTS=$ALLOWED_HOSTS
|
||||
echo GEOSERVER_PUBLIC_LOCATION=$GEOSERVER_PUBLIC_LOCATION
|
||||
echo MONITORING_ENABLED=$MONITORING_ENABLED
|
||||
echo MONITORING_HOST_NAME=$MONITORING_HOST_NAME
|
||||
echo MONITORING_SERVICE_NAME=$MONITORING_SERVICE_NAME
|
||||
echo MONITORING_DATA_TTL=$MONITORING_DATA_TTL
|
||||
|
||||
/usr/local/bin/invoke waitfordbs >> /usr/src/haitidata/invoke.log
|
||||
echo "waitfordbs task done"
|
||||
|
||||
echo "running migrations"
|
||||
/usr/local/bin/invoke migrations >> /usr/src/haitidata/invoke.log
|
||||
echo "migrations task done"
|
||||
|
||||
cmd="$@"
|
||||
|
||||
echo DOCKER_ENV=$DOCKER_ENV
|
||||
|
||||
if [ -z ${DOCKER_ENV} ] || [ ${DOCKER_ENV} = "development" ]
|
||||
then
|
||||
echo "Executing standard Django server $cmd for Development"
|
||||
else
|
||||
if [ ${IS_CELERY} = "true" ] || [ ${IS_CELERY} = "True" ]
|
||||
then
|
||||
cmd=$CELERY_CMD
|
||||
echo "Executing Celery server $cmd for Production"
|
||||
else
|
||||
|
||||
/usr/local/bin/invoke prepare >> /usr/src/haitidata/invoke.log
|
||||
echo "prepare task done"
|
||||
|
||||
if [ ${IS_FIRST_START} = "true" ] || [ ${IS_FIRST_START} = "True" ] || [ ${FORCE_REINIT} = "true" ] || [ ${FORCE_REINIT} = "True" ] || [ ! -e "/mnt/volumes/statics/geonode_init.lock" ]; then
|
||||
/usr/local/bin/invoke updategeoip >> /usr/src/haitidata/invoke.log
|
||||
echo "updategeoip task done"
|
||||
/usr/local/bin/invoke fixtures >> /usr/src/haitidata/invoke.log
|
||||
echo "fixture task done"
|
||||
/usr/local/bin/invoke monitoringfixture >> /usr/src/haitidata/invoke.log
|
||||
echo "monitoringfixture task done"
|
||||
/usr/local/bin/invoke initialized >> /usr/src/haitidata/invoke.log
|
||||
echo "initialized"
|
||||
fi
|
||||
|
||||
echo "refresh static data"
|
||||
/usr/local/bin/invoke statics >> /usr/src/haitidata/invoke.log
|
||||
echo "static data refreshed"
|
||||
/usr/local/bin/invoke waitforgeoserver >> /usr/src/haitidata/invoke.log
|
||||
echo "waitforgeoserver task done"
|
||||
/usr/local/bin/invoke geoserverfixture >> /usr/src/haitidata/invoke.log
|
||||
echo "geoserverfixture task done"
|
||||
/usr/local/bin/invoke updateadmin >> /usr/src/haitidata/invoke.log
|
||||
echo "updateadmin task done"
|
||||
|
||||
cmd=$UWSGI_CMD
|
||||
echo "Executing UWSGI server $cmd for Production"
|
||||
fi
|
||||
fi
|
||||
echo 'got command ${cmd}'
|
||||
exec $cmd
|
||||
Whitespace-only changes.
@@ -1,3 +0,0 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -1,25 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('base', '24_to_26'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='RegionBBox',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('bbox_x0', models.DecimalField(null=True, max_digits=19, decimal_places=10, blank=True)),
|
||||
('bbox_x1', models.DecimalField(null=True, max_digits=19, decimal_places=10, blank=True)),
|
||||
('bbox_y0', models.DecimalField(null=True, max_digits=19, decimal_places=10, blank=True)),
|
||||
('bbox_y1', models.DecimalField(null=True, max_digits=19, decimal_places=10, blank=True)),
|
||||
('region', models.OneToOneField(to='base.Region')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('filter', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='regionbbox',
|
||||
name='srid',
|
||||
field=models.CharField(default=b'EPSG:4326', max_length=255),
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -1,12 +0,0 @@
|
||||
from django.db import models
|
||||
|
||||
from geonode.base.models import Region
|
||||
|
||||
|
||||
class RegionBBox(models.Model):
|
||||
region = models.OneToOneField(Region, on_delete=models.CASCADE)
|
||||
bbox_x0 = models.DecimalField(max_digits=19, decimal_places=10, blank=True, null=True)
|
||||
bbox_x1 = models.DecimalField(max_digits=19, decimal_places=10, blank=True, null=True)
|
||||
bbox_y0 = models.DecimalField(max_digits=19, decimal_places=10, blank=True, null=True)
|
||||
bbox_y1 = models.DecimalField(max_digits=19, decimal_places=10, blank=True, null=True)
|
||||
srid = models.CharField(max_length=255, default='EPSG:4326')
|
||||
@@ -1,86 +0,0 @@
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from geonode.api.resourcebase_api import CommonModelApi, CommonMetaApi
|
||||
from geonode.layers.models import Layer
|
||||
from geonode.base.models import Region
|
||||
|
||||
|
||||
class CommonModelApiExt(CommonModelApi):
|
||||
def apply_filters(self, request, applicable_filters):
|
||||
types = applicable_filters.pop('type', None)
|
||||
extent = applicable_filters.pop('extent', None)
|
||||
keywords = applicable_filters.pop('keywords__slug__in', None)
|
||||
region = applicable_filters.get('regions__name__in', None)
|
||||
region_bbox = None
|
||||
if region:
|
||||
print('region is ', region)
|
||||
try:
|
||||
region_obj = Region.objects.get(name=region[0])
|
||||
except Region.DoesNotExist:
|
||||
print 'it does not exists'
|
||||
else:
|
||||
print('db record', region_obj.name_en)
|
||||
try:
|
||||
regionbbox_obj = region_obj.regionbbox
|
||||
except ObjectDoesNotExist:
|
||||
print 'regionbbox does not exist'
|
||||
else:
|
||||
print(str(regionbbox_obj.bbox_x0))
|
||||
bbox = [regionbbox_obj.bbox_x0, regionbbox_obj.bbox_y0, regionbbox_obj.bbox_x1, regionbbox_obj.bbox_y1]
|
||||
bbox_valid = not any(coo is None for coo in bbox)
|
||||
if bbox_valid:
|
||||
region_bbox = ','.join([str(coo) for coo in bbox])
|
||||
del applicable_filters['regions__name__in']
|
||||
extent = None
|
||||
print region_bbox
|
||||
else:
|
||||
print 'bbox not valid'
|
||||
|
||||
semi_filtered = super(
|
||||
CommonModelApi,
|
||||
self).apply_filters(
|
||||
request,
|
||||
applicable_filters)
|
||||
filtered = None
|
||||
if types:
|
||||
for the_type in types:
|
||||
if the_type in LAYER_SUBTYPES.keys():
|
||||
if filtered:
|
||||
filtered = filtered | semi_filtered.filter(
|
||||
Layer___storeType=LAYER_SUBTYPES[the_type])
|
||||
else:
|
||||
filtered = semi_filtered.filter(
|
||||
Layer___storeType=LAYER_SUBTYPES[the_type])
|
||||
else:
|
||||
if filtered:
|
||||
filtered = filtered | semi_filtered.instance_of(
|
||||
FILTER_TYPES[the_type])
|
||||
else:
|
||||
filtered = semi_filtered.instance_of(
|
||||
FILTER_TYPES[the_type])
|
||||
else:
|
||||
filtered = semi_filtered
|
||||
|
||||
if extent:
|
||||
filtered = self.filter_bbox(filtered, extent)
|
||||
|
||||
if keywords:
|
||||
filtered = self.filter_h_keywords(filtered, keywords)
|
||||
|
||||
if region_bbox:
|
||||
filtered = self.filter_bbox(filtered, region_bbox)
|
||||
print 'filtering by bbox: ', region_bbox
|
||||
|
||||
return filtered
|
||||
|
||||
|
||||
class LayerExtResource(CommonModelApiExt):
|
||||
"""Layer Ext API"""
|
||||
|
||||
class Meta(CommonMetaApi):
|
||||
queryset = Layer.objects.distinct().order_by('-date')
|
||||
if settings.RESOURCE_PUBLISHING:
|
||||
queryset = queryset.filter(is_published=True)
|
||||
resource_name = 'layers'
|
||||
excludes = ['csw_anytext', 'metadata_xml']
|
||||
@@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -1,9 +0,0 @@
|
||||
from tastypie.api import Api
|
||||
|
||||
#from geonode.api.resourcebase_api import LayerResource
|
||||
from filter.resourcebase_api import LayerExtResource
|
||||
|
||||
|
||||
api_ext = Api(api_name='api')
|
||||
|
||||
api_ext.register(LayerExtResource())
|
||||
@@ -1,3 +0,0 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"fields": {
|
||||
"user": 1000,
|
||||
"key": "pyxW5djJ7XsjeFUXduAsGpR4xMGUwpeBGQRqTeT3",
|
||||
"created": "2018-06-28T14:54:51Z"
|
||||
},
|
||||
"model": "tastypie.apikey",
|
||||
"pk": 1
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"model": "oauth2_provider.application",
|
||||
"pk": 1001,
|
||||
"fields": {
|
||||
"skip_authorization": true,
|
||||
"created": "2018-05-31T10:00:31.661Z",
|
||||
"updated": "2018-05-31T11:30:31.245Z",
|
||||
"algorithm": "RS256",
|
||||
"redirect_uris": "http://localhost:8080/geoserver/index.html\nhttp://localhost/geoserver/index.html",
|
||||
"name": "GeoServer",
|
||||
"authorization_grant_type": "authorization-code",
|
||||
"client_type": "confidential",
|
||||
"client_id": "Jrchz2oPY3akmzndmgUTYrs9gczlgoV20YPSvqaV",
|
||||
"client_secret": "rCnp5txobUo83EpQEblM8fVj3QT5zb5qRfxNsuPzCqZaiRyIoxM4jdgMiZKFfePBHYXCLd7B8NlkfDBY9HKeIQPcy5Cp08KQNpRHQbjpLItDHv12GvkSeXp6OxaUETv3",
|
||||
"user": [
|
||||
"admin"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"model": "oauth2_provider.application",
|
||||
"pk": 1001,
|
||||
"fields": {
|
||||
"skip_authorization": true,
|
||||
"created": "2018-05-31T10:00:31.661Z",
|
||||
"updated": "2018-05-31T11:30:31.245Z",
|
||||
"algorithm": "RS256",
|
||||
"redirect_uris": "http://geonode/geoserver",
|
||||
"name": "GeoServer",
|
||||
"authorization_grant_type": "authorization-code",
|
||||
"client_type": "confidential",
|
||||
"client_id": "Jrchz2oPY3akmzndmgUTYrs9gczlgoV20YPSvqaV",
|
||||
"client_secret": "rCnp5txobUo83EpQEblM8fVj3QT5zb5qRfxNsuPzCqZaiRyIoxM4jdgMiZKFfePBHYXCLd7B8NlkfDBY9HKeIQPcy5Cp08KQNpRHQbjpLItDHv12GvkSeXp6OxaUETv3",
|
||||
"user": [
|
||||
"admin"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,18 @@
|
||||
[{
|
||||
"fields": {
|
||||
"date_joined": "2011-06-09 15:15:27",
|
||||
"email": "ad@m.in",
|
||||
"first_name": "",
|
||||
"groups": [],
|
||||
"is_active": true,
|
||||
"is_staff": true,
|
||||
"is_superuser": true,
|
||||
"last_login": "2011-06-09 15:45:34",
|
||||
"last_name": "",
|
||||
"password": "pbkdf2_sha256$30000$rjuGt0Obn8on$cxF75frIOSaitNklLZ0IJ/VonUW0fwEFVF96o0M+lGc=",
|
||||
"user_permissions": [],
|
||||
"username": "admin"
|
||||
},
|
||||
"model": "people.Profile",
|
||||
"pk": 1000
|
||||
}]
|
||||
@@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"fields": {
|
||||
"domain": "example.com",
|
||||
"name": "example.com"
|
||||
},
|
||||
"model": "sites.site",
|
||||
"pk": 1
|
||||
}
|
||||
]
|
||||
@@ -1,96 +0,0 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: haitidata
|
||||
Version: 0.2
|
||||
Summary: haitidata, based on GeoNode
|
||||
Home-page: https://github.com/haitidata/haitidata
|
||||
Author: UNKNOWN
|
||||
Author-email: UNKNOWN
|
||||
License: BSD
|
||||
Description: Haitidata
|
||||
========================
|
||||
|
||||
You should write some docs, it's good for the soul.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install geonode with::
|
||||
|
||||
$ sudo add-apt-repository ppa:geonode/stable
|
||||
|
||||
$ sudo apt-get update
|
||||
|
||||
$ sudo apt-get install geonode
|
||||
|
||||
Create a new template based on the geonode example project.::
|
||||
|
||||
$ django-admin startproject my_geonode --template=https://github.com/GeoNode/geonode-project/archive/2.6.zip -epy,rst
|
||||
$ sudo pip install -e my_geonode
|
||||
|
||||
.. note:: You should NOT use the name geonode for your project as it will conflict with the default geonode package name.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Rename the local_settings.py.sample to local_settings.py and edit it's content by setting the SITEURL and SITENAME.
|
||||
|
||||
Edit the file /etc/apache2/sites-available/geonode and change the following directive from:
|
||||
|
||||
WSGIScriptAlias / /var/www/geonode/wsgi/geonode.wsgi
|
||||
|
||||
to:
|
||||
|
||||
WSGIScriptAlias / /path/to/my_geonode/my_geonode/wsgi.py
|
||||
|
||||
To avoid having to grant apache permissions (i.e. www-data user and group) to your home dir where you likely setup the geonode-project; you may want to instead copy the wsgi.py file next to geonode.wsgi and replace the file name instead of the entire path.
|
||||
|
||||
$ cp /path/to/my_geonode/my_geonode/wsgi.py /var/www/geonode/wsgi/wsgi.py
|
||||
|
||||
Add the "Directory" directive for your folder like the following example:
|
||||
|
||||
<Directory "/home/vagrant/my_geonode/my_geonode/">
|
||||
|
||||
Order allow,deny
|
||||
|
||||
Options Indexes FollowSymLinks
|
||||
|
||||
Allow from all
|
||||
|
||||
Require all granted
|
||||
|
||||
IndexOptions FancyIndexing
|
||||
|
||||
</Directory>
|
||||
|
||||
Restart apache::
|
||||
|
||||
$ sudo service apache2 restart
|
||||
|
||||
Edit the templates in my_geonode/templates, the css and images to match your needs.
|
||||
|
||||
In the my_geonode folder run::
|
||||
|
||||
$ python manage.py collectstatic
|
||||
|
||||
Github Considerations
|
||||
------------------------
|
||||
|
||||
While it is helpful to recommit your django project wrapper back to a distributed version control repository.
|
||||
* It is also important to remember that production instances will store security information in the local_settings.py
|
||||
* Admin/Devs should always remember to exclude this file in the .gitignore file in the same folder as the .git::
|
||||
|
||||
$ nano .gitignore
|
||||
|
||||
/{project}/local_settings.py
|
||||
|
||||
save, make sure the file is also removed from git cache::
|
||||
|
||||
$ git rm -f --cache //local_settings.py
|
||||
|
||||
$ git status
|
||||
|
||||
confirm the file is no longer staged for the next commit or that if it is as "removed"
|
||||
|
||||
Keywords: haitidata geonode django
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 1 - Planning
|
||||
@@ -1,11 +0,0 @@
|
||||
README.rst
|
||||
haitidata/__init__.py
|
||||
haitidata/settings.py
|
||||
haitidata/urls.py
|
||||
haitidata/wsgi.py
|
||||
haitidata.egg-info/PKG-INFO
|
||||
haitidata.egg-info/SOURCES.txt
|
||||
haitidata.egg-info/dependency_links.txt
|
||||
haitidata.egg-info/not-zip-safe
|
||||
haitidata.egg-info/requires.txt
|
||||
haitidata.egg-info/top_level.txt
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
django-tastypie==0.13.0
|
||||
@@ -1 +0,0 @@
|
||||
haitidata
|
||||
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#########################################################################
|
||||
#
|
||||
# Copyright (C) 2017 OSGeo
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
import os
|
||||
|
||||
__version__ = (2, 10, 1, 'final', 0)
|
||||
|
||||
|
||||
default_app_config = "haitidata.apps.AppConfig"
|
||||
|
||||
|
||||
def get_version():
|
||||
import haitidata.version
|
||||
return haitidata.version.get_version(__version__)
|
||||
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#########################################################################
|
||||
#
|
||||
# Copyright (C) 2018 OSGeo
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#########################################################################
|
||||
from django.apps import AppConfig as BaseAppConfig
|
||||
|
||||
|
||||
def run_setup_hooks(*args, **kwargs):
|
||||
from django.conf import settings
|
||||
from .celeryapp import app as celeryapp
|
||||
if celeryapp not in settings.INSTALLED_APPS:
|
||||
settings.INSTALLED_APPS += (celeryapp, )
|
||||
|
||||
|
||||
class AppConfig(BaseAppConfig):
|
||||
|
||||
name = "haitidata"
|
||||
label = "haitidata"
|
||||
|
||||
def ready(self):
|
||||
super(AppConfig, self).ready()
|
||||
run_setup_hooks()
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#########################################################################
|
||||
#
|
||||
# Copyright (C) 2017 OSGeo
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
from celery import Celery
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'haitidata.settings')
|
||||
|
||||
app = Celery('haitidata')
|
||||
|
||||
# Using a string here means the worker will not have to
|
||||
# pickle the object when using Windows.
|
||||
app.config_from_object('django.conf:settings', namespace="CELERY")
|
||||
app.autodiscover_tasks()
|
||||
|
||||
|
||||
@app.task(bind=True)
|
||||
def debug_task(self):
|
||||
print("Request: {!r}".format(self.request))
|
||||
File renamed without changes.
Whitespace-only changes.
@@ -1,5 +0,0 @@
|
||||
from django.conf import settings # import the settings file
|
||||
|
||||
|
||||
def project_setting(request):
|
||||
return {'GEOSERVER_BASE_URL': settings.GEOSERVER_BASE_URL}
|
||||
@@ -0,0 +1,641 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#########################################################################
|
||||
#
|
||||
# Copyright (C) 2018 OSGeo
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
""" There are 3 ways to override GeoNode settings:
|
||||
1. Using environment variables, if your changes to GeoNode are minimal.
|
||||
2. Creating a downstream project, if you are doing a lot of customization.
|
||||
3. Override settings in a local_settings.py file, legacy.
|
||||
"""
|
||||
|
||||
import ast
|
||||
import os
|
||||
from urlparse import urlparse, urlunparse
|
||||
from geonode.settings import *
|
||||
|
||||
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
MEDIA_ROOT = os.getenv('MEDIA_ROOT', os.path.join(PROJECT_ROOT, "uploaded"))
|
||||
|
||||
STATIC_ROOT = os.getenv('STATIC_ROOT',
|
||||
os.path.join(PROJECT_ROOT, "static_root")
|
||||
)
|
||||
|
||||
# SECRET_KEY = '************************'
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = os.getenv('SECRET_KEY', "n(v@vf2rm!zcxaxey9(6ymhwayxnqzhlr)-f#$jkzt&2)way#*")
|
||||
|
||||
# per-deployment settings should go here
|
||||
SITE_HOST_NAME = os.getenv('SITE_HOST_NAME', 'localhost')
|
||||
SITE_HOST_PORT = os.getenv('SITE_HOST_PORT', None)
|
||||
_default_siteurl = "http://%s:%s/" % (SITE_HOST_NAME, SITE_HOST_PORT) if SITE_HOST_PORT else "http://%s/" % SITE_HOST_NAME
|
||||
SITEURL = os.getenv('SITEURL', _default_siteurl)
|
||||
|
||||
# we need hostname for deployed
|
||||
_surl = urlparse(SITEURL)
|
||||
HOSTNAME = _surl.hostname
|
||||
|
||||
# add trailing slash to site url. geoserver url will be relative to this
|
||||
if not SITEURL.endswith('/'):
|
||||
SITEURL = '{}/'.format(SITEURL)
|
||||
|
||||
try:
|
||||
# try to parse python notation, default in dockerized env
|
||||
ALLOWED_HOSTS = ast.literal_eval(os.getenv('ALLOWED_HOSTS'))
|
||||
except ValueError:
|
||||
# fallback to regular list of values separated with misc chars
|
||||
ALLOWED_HOSTS = [HOSTNAME, 'localhost', 'django', 'geonode'] if os.getenv('ALLOWED_HOSTS') is None \
|
||||
else re.split(r' *[,|:|;] *', os.getenv('ALLOWED_HOSTS'))
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
# Login and logout urls override
|
||||
LOGIN_URL = os.getenv('LOGIN_URL', '{}account/login/'.format(SITEURL))
|
||||
LOGOUT_URL = os.getenv('LOGOUT_URL', '{}account/logout/'.format(SITEURL))
|
||||
|
||||
ACCOUNT_LOGIN_REDIRECT_URL = os.getenv('LOGIN_REDIRECT_URL', SITEURL)
|
||||
ACCOUNT_LOGOUT_REDIRECT_URL = os.getenv('LOGOUT_REDIRECT_URL', SITEURL)
|
||||
|
||||
AVATAR_GRAVATAR_SSL = ast.literal_eval(os.getenv('AVATAR_GRAVATAR_SSL', 'True'))
|
||||
|
||||
# Backend
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': 'geonode',
|
||||
'USER': 'geonode',
|
||||
'PASSWORD': 'geonode',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '5432',
|
||||
'CONN_MAX_AGE': 5,
|
||||
'CONN_TOUT': 5,
|
||||
'OPTIONS': {
|
||||
'connect_timeout': 5,
|
||||
}
|
||||
},
|
||||
# vector datastore for uploads
|
||||
'datastore': {
|
||||
'ENGINE': 'django.contrib.gis.db.backends.postgis',
|
||||
# 'ENGINE': '', # Empty ENGINE name disables
|
||||
'NAME': 'geonode_data',
|
||||
'USER': 'geonode',
|
||||
'PASSWORD': 'geonode',
|
||||
'HOST': 'localhost',
|
||||
'PORT': '5432',
|
||||
'CONN_MAX_AGE': 5,
|
||||
'CONN_TOUT': 5,
|
||||
'OPTIONS': {
|
||||
'connect_timeout': 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GEOSERVER_LOCATION = os.getenv(
|
||||
'GEOSERVER_LOCATION', 'http://localhost:8080/geoserver/'
|
||||
)
|
||||
|
||||
GEOSERVER_PUBLIC_HOST = os.getenv(
|
||||
'GEOSERVER_PUBLIC_HOST', SITE_HOST_NAME
|
||||
)
|
||||
|
||||
GEOSERVER_PUBLIC_PORT = os.getenv(
|
||||
'GEOSERVER_PUBLIC_PORT', 8080
|
||||
)
|
||||
|
||||
_default_public_location = 'http://{}:{}/geoserver/'.format(GEOSERVER_PUBLIC_HOST, GEOSERVER_PUBLIC_PORT) if GEOSERVER_PUBLIC_PORT else 'http://{}/geoserver/'.format(GEOSERVER_PUBLIC_HOST)
|
||||
|
||||
GEOSERVER_WEB_UI_LOCATION = os.getenv(
|
||||
'GEOSERVER_WEB_UI_LOCATION', GEOSERVER_LOCATION
|
||||
)
|
||||
|
||||
GEOSERVER_PUBLIC_LOCATION = os.getenv(
|
||||
'GEOSERVER_PUBLIC_LOCATION', _default_public_location
|
||||
)
|
||||
|
||||
OGC_SERVER_DEFAULT_USER = os.getenv(
|
||||
'GEOSERVER_ADMIN_USER', 'admin'
|
||||
)
|
||||
|
||||
OGC_SERVER_DEFAULT_PASSWORD = os.getenv(
|
||||
'GEOSERVER_ADMIN_PASSWORD', 'geoserver'
|
||||
)
|
||||
|
||||
# OGC (WMS/WFS/WCS) Server Settings
|
||||
OGC_SERVER = {
|
||||
'default': {
|
||||
'BACKEND': 'geonode.geoserver',
|
||||
'LOCATION': GEOSERVER_LOCATION,
|
||||
'WEB_UI_LOCATION': GEOSERVER_WEB_UI_LOCATION,
|
||||
'LOGIN_ENDPOINT': 'j_spring_oauth2_geonode_login',
|
||||
'LOGOUT_ENDPOINT': 'j_spring_oauth2_geonode_logout',
|
||||
# PUBLIC_LOCATION needs to be kept like this because in dev mode
|
||||
# the proxy won't work and the integration tests will fail
|
||||
# the entire block has to be overridden in the local_settings
|
||||
'PUBLIC_LOCATION': GEOSERVER_PUBLIC_LOCATION,
|
||||
'USER': OGC_SERVER_DEFAULT_USER,
|
||||
'PASSWORD': OGC_SERVER_DEFAULT_PASSWORD,
|
||||
'MAPFISH_PRINT_ENABLED': True,
|
||||
'PRINT_NG_ENABLED': True,
|
||||
'GEONODE_SECURITY_ENABLED': True,
|
||||
'GEOFENCE_SECURITY_ENABLED': True,
|
||||
'WMST_ENABLED': False,
|
||||
'BACKEND_WRITE_ENABLED': True,
|
||||
'WPS_ENABLED': False,
|
||||
'LOG_FILE': '%s/geoserver/data/logs/geoserver.log' % os.path.abspath(os.path.join(PROJECT_ROOT, os.pardir)),
|
||||
# Set to dictionary identifier of database containing spatial data in DATABASES dictionary to enable
|
||||
'DATASTORE': 'datastore',
|
||||
'TIMEOUT': int(os.getenv('OGC_REQUEST_TIMEOUT', '30')),
|
||||
'MAX_RETRIES': int(os.getenv('OGC_REQUEST_MAX_RETRIES', '5')),
|
||||
'BACKOFF_FACTOR': float(os.getenv('OGC_REQUEST_BACKOFF_FACTOR', '0.3')),
|
||||
'POOL_MAXSIZE': int(os.getenv('OGC_REQUEST_POOL_MAXSIZE', '10')),
|
||||
'POOL_CONNECTIONS': int(os.getenv('OGC_REQUEST_POOL_CONNECTIONS', '10')),
|
||||
}
|
||||
}
|
||||
|
||||
# If you want to enable Mosaics use the following configuration
|
||||
UPLOADER = {
|
||||
# 'BACKEND': 'geonode.rest',
|
||||
'BACKEND': 'geonode.importer',
|
||||
'OPTIONS': {
|
||||
'TIME_ENABLED': True,
|
||||
'MOSAIC_ENABLED': False,
|
||||
},
|
||||
'SUPPORTED_CRS': [
|
||||
'EPSG:4326',
|
||||
'EPSG:3785',
|
||||
'EPSG:3857',
|
||||
'EPSG:32647',
|
||||
'EPSG:32736'
|
||||
],
|
||||
'SUPPORTED_EXT': [
|
||||
'.shp',
|
||||
'.csv',
|
||||
'.kml',
|
||||
'.kmz',
|
||||
'.json',
|
||||
'.geojson',
|
||||
'.tif',
|
||||
'.tiff',
|
||||
'.geotiff',
|
||||
'.gml',
|
||||
'.xml'
|
||||
]
|
||||
}
|
||||
|
||||
# CSW settings
|
||||
CATALOGUE = {
|
||||
'default': {
|
||||
# The underlying CSW implementation
|
||||
# default is pycsw in local mode (tied directly to GeoNode Django DB)
|
||||
'ENGINE': 'geonode.catalogue.backends.pycsw_local',
|
||||
# pycsw in non-local mode
|
||||
# 'ENGINE': 'geonode.catalogue.backends.pycsw_http',
|
||||
# GeoNetwork opensource
|
||||
# 'ENGINE': 'geonode.catalogue.backends.geonetwork',
|
||||
# deegree and others
|
||||
# 'ENGINE': 'geonode.catalogue.backends.generic',
|
||||
|
||||
# The FULLY QUALIFIED base url to the CSW instance for this GeoNode
|
||||
'URL': urljoin(SITEURL, '/catalogue/csw'),
|
||||
# 'URL': 'http://localhost:8080/geonetwork/srv/en/csw',
|
||||
# 'URL': 'http://localhost:8080/deegree-csw-demo-3.0.4/services',
|
||||
|
||||
# login credentials (for GeoNetwork)
|
||||
# 'USER': 'admin',
|
||||
# 'PASSWORD': 'admin',
|
||||
|
||||
# 'ALTERNATES_ONLY': True,
|
||||
}
|
||||
}
|
||||
|
||||
# pycsw settings
|
||||
PYCSW = {
|
||||
# pycsw configuration
|
||||
'CONFIGURATION': {
|
||||
# uncomment / adjust to override server config system defaults
|
||||
# 'server': {
|
||||
# 'maxrecords': '10',
|
||||
# 'pretty_print': 'true',
|
||||
# 'federatedcatalogues': 'http://catalog.data.gov/csw'
|
||||
# },
|
||||
'server': {
|
||||
'home': '.',
|
||||
'url': CATALOGUE['default']['URL'],
|
||||
'encoding': 'UTF-8',
|
||||
'language': LANGUAGE_CODE,
|
||||
'maxrecords': '20',
|
||||
'pretty_print': 'true',
|
||||
# 'domainquerytype': 'range',
|
||||
'domaincounts': 'true',
|
||||
'profiles': 'apiso,ebrim',
|
||||
},
|
||||
'manager': {
|
||||
# authentication/authorization is handled by Django
|
||||
'transactions': 'false',
|
||||
'allowed_ips': '*',
|
||||
# 'csw_harvest_pagesize': '10',
|
||||
},
|
||||
'metadata:main': {
|
||||
'identification_title': 'GeoNode Catalogue',
|
||||
'identification_abstract': 'GeoNode is an open source platform' \
|
||||
' that facilitates the creation, sharing, and collaborative use' \
|
||||
' of geospatial data',
|
||||
'identification_keywords': 'sdi, catalogue, discovery, metadata,' \
|
||||
' GeoNode',
|
||||
'identification_keywords_type': 'theme',
|
||||
'identification_fees': 'None',
|
||||
'identification_accessconstraints': 'None',
|
||||
'provider_name': 'Organization Name',
|
||||
'provider_url': SITEURL,
|
||||
'contact_name': 'Lastname, Firstname',
|
||||
'contact_position': 'Position Title',
|
||||
'contact_address': 'Mailing Address',
|
||||
'contact_city': 'City',
|
||||
'contact_stateorprovince': 'Administrative Area',
|
||||
'contact_postalcode': 'Zip or Postal Code',
|
||||
'contact_country': 'Country',
|
||||
'contact_phone': '+xx-xxx-xxx-xxxx',
|
||||
'contact_fax': '+xx-xxx-xxx-xxxx',
|
||||
'contact_email': 'Email Address',
|
||||
'contact_url': 'Contact URL',
|
||||
'contact_hours': 'Hours of Service',
|
||||
'contact_instructions': 'During hours of service. Off on ' \
|
||||
'weekends.',
|
||||
'contact_role': 'pointOfContact',
|
||||
},
|
||||
'metadata:inspire': {
|
||||
'enabled': 'true',
|
||||
'languages_supported': 'eng,gre',
|
||||
'default_language': 'eng',
|
||||
'date': 'YYYY-MM-DD',
|
||||
'gemet_keywords': 'Utility and governmental services',
|
||||
'conformity_service': 'notEvaluated',
|
||||
'contact_name': 'Organization Name',
|
||||
'contact_email': 'Email Address',
|
||||
'temp_extent': 'YYYY-MM-DD/YYYY-MM-DD',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# -- START Client Hooksets Setup
|
||||
|
||||
# GeoNode javascript client configuration
|
||||
|
||||
# default map projection
|
||||
# Note: If set to EPSG:4326, then only EPSG:4326 basemaps will work.
|
||||
DEFAULT_MAP_CRS = os.environ.get('DEFAULT_MAP_CRS', "EPSG:3857")
|
||||
|
||||
DEFAULT_LAYER_FORMAT = os.environ.get('DEFAULT_LAYER_FORMAT', "image/png8")
|
||||
|
||||
# Where should newly created maps be focused?
|
||||
DEFAULT_MAP_CENTER = (os.environ.get('DEFAULT_MAP_CENTER_X', 0), os.environ.get('DEFAULT_MAP_CENTER_Y', 0))
|
||||
|
||||
# How tightly zoomed should newly created maps be?
|
||||
# 0 = entire world;
|
||||
# maximum zoom is between 12 and 15 (for Google Maps, coverage varies by area)
|
||||
DEFAULT_MAP_ZOOM = int(os.environ.get('DEFAULT_MAP_ZOOM', 3))
|
||||
|
||||
MAPBOX_ACCESS_TOKEN = os.environ.get('MAPBOX_ACCESS_TOKEN', None)
|
||||
BING_API_KEY = os.environ.get('BING_API_KEY', None)
|
||||
GOOGLE_API_KEY = os.environ.get('GOOGLE_API_KEY', None)
|
||||
|
||||
GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY = os.getenv('GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', 'mapstore')
|
||||
|
||||
MAP_BASELAYERS = [{}]
|
||||
|
||||
"""
|
||||
To enable the REACT based Client:
|
||||
1. pip install pip install django-geonode-client==1.0.9
|
||||
2. enable those:
|
||||
"""
|
||||
|
||||
if GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY == 'react':
|
||||
GEONODE_CLIENT_HOOKSET = os.getenv('GEONODE_CLIENT_HOOKSET', 'geonode.client.hooksets.ReactHookSet')
|
||||
if 'geonode-client' not in INSTALLED_APPS:
|
||||
INSTALLED_APPS += ('geonode-client', )
|
||||
|
||||
"""
|
||||
To enable the Leaflet based Client:
|
||||
1. enable those:
|
||||
"""
|
||||
if GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY == 'leaflet':
|
||||
GEONODE_CLIENT_HOOKSET = os.getenv('GEONODE_CLIENT_HOOKSET', 'geonode.client.hooksets.LeafletHookSet')
|
||||
|
||||
LEAFLET_CONFIG = {
|
||||
'TILES': [
|
||||
# Find tiles at:
|
||||
# http://leaflet-extras.github.io/leaflet-providers/preview/
|
||||
|
||||
# Stamen toner lite.
|
||||
('Watercolor',
|
||||
'http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.png',
|
||||
'Map tiles by <a href="http://stamen.com">Stamen Design</a>, \
|
||||
<a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> \
|
||||
— Map data © \
|
||||
<a href="http://openstreetmap.org">OpenStreetMap</a> contributors, \
|
||||
<a href="http://creativecommons.org/licenses/by-sa/2.0/"> \
|
||||
CC-BY-SA</a>'),
|
||||
('Toner Lite',
|
||||
'http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png',
|
||||
'Map tiles by <a href="http://stamen.com">Stamen Design</a>, \
|
||||
<a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> \
|
||||
— Map data © \
|
||||
<a href="http://openstreetmap.org">OpenStreetMap</a> contributors, \
|
||||
<a href="http://creativecommons.org/licenses/by-sa/2.0/"> \
|
||||
CC-BY-SA</a>'),
|
||||
],
|
||||
'PLUGINS': {
|
||||
'esri-leaflet': {
|
||||
'js': 'lib/js/leaflet.js',
|
||||
'auto-include': True,
|
||||
},
|
||||
'leaflet-fullscreen': {
|
||||
'css': 'lib/css/leaflet.fullscreen.css',
|
||||
'js': 'lib/js/Leaflet.fullscreen.min.js',
|
||||
'auto-include': True,
|
||||
},
|
||||
'leaflet-opacity': {
|
||||
'css': 'lib/css/L.Control.Opacity.css',
|
||||
'js': 'lib/js/L.Control.Opacity.js',
|
||||
'auto-include': True,
|
||||
},
|
||||
'leaflet-navbar': {
|
||||
'css': 'lib/css/Leaflet.NavBar.css',
|
||||
'js': 'lib/js/index.js',
|
||||
'auto-include': True,
|
||||
},
|
||||
'leaflet-measure': {
|
||||
'css': 'lib/css/leaflet-measure.css',
|
||||
'js': 'lib/js/leaflet-measure.js',
|
||||
'auto-include': True,
|
||||
},
|
||||
},
|
||||
'SRID': 3857,
|
||||
'RESET_VIEW': False
|
||||
}
|
||||
|
||||
if not DEBUG_STATIC:
|
||||
# if not DEBUG_STATIC, use minified css and js
|
||||
LEAFLET_CONFIG['PLUGINS'] = {
|
||||
'leaflet-plugins': {
|
||||
'js': 'lib/js/leaflet-plugins.min.js',
|
||||
'css': 'lib/css/leaflet-plugins.min.css',
|
||||
'auto-include': True,
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
To enable the MapStore2 REACT based Client:
|
||||
1. pip install pip install django-geonode-mapstore-client==1.0
|
||||
2. enable those:
|
||||
"""
|
||||
if GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY == 'mapstore':
|
||||
GEONODE_CLIENT_HOOKSET = os.getenv('GEONODE_CLIENT_HOOKSET', 'geonode_mapstore_client.hooksets.MapStoreHookSet')
|
||||
|
||||
if 'geonode_mapstore_client' not in INSTALLED_APPS:
|
||||
INSTALLED_APPS += (
|
||||
'mapstore2_adapter',
|
||||
'geonode_mapstore_client',)
|
||||
|
||||
# This must be set to True in case you run the client in DEBUG mode with `npm run start`
|
||||
MAPSTORE_DEBUG = False
|
||||
|
||||
def get_geonode_catalogue_service():
|
||||
if PYCSW:
|
||||
pycsw_config = PYCSW["CONFIGURATION"]
|
||||
if pycsw_config:
|
||||
pycsw_catalogue = {
|
||||
("%s" % pycsw_config['metadata:main']['identification_title']): {
|
||||
"url": CATALOGUE['default']['URL'],
|
||||
"type": "csw",
|
||||
"title": pycsw_config['metadata:main']['identification_title'],
|
||||
"autoload": True
|
||||
}
|
||||
}
|
||||
return pycsw_catalogue
|
||||
return None
|
||||
|
||||
GEONODE_CATALOGUE_SERVICE = get_geonode_catalogue_service()
|
||||
|
||||
MAPSTORE_CATALOGUE_SERVICES = {
|
||||
"Demo WMS Service": {
|
||||
"url": "https://demo.geo-solutions.it/geoserver/wms",
|
||||
"type": "wms",
|
||||
"title": "Demo WMS Service",
|
||||
"autoload": False
|
||||
},
|
||||
"Demo WMTS Service": {
|
||||
"url": "https://demo.geo-solutions.it/geoserver/gwc/service/wmts",
|
||||
"type": "wmts",
|
||||
"title": "Demo WMTS Service",
|
||||
"autoload": False
|
||||
}
|
||||
}
|
||||
|
||||
MAPSTORE_CATALOGUE_SELECTED_SERVICE = "Demo WMS Service"
|
||||
|
||||
if GEONODE_CATALOGUE_SERVICE:
|
||||
MAPSTORE_CATALOGUE_SERVICES[list(GEONODE_CATALOGUE_SERVICE.keys())[0]] = GEONODE_CATALOGUE_SERVICE[list(GEONODE_CATALOGUE_SERVICE.keys())[0]]
|
||||
MAPSTORE_CATALOGUE_SELECTED_SERVICE = list(GEONODE_CATALOGUE_SERVICE.keys())[0]
|
||||
|
||||
DEFAULT_MS2_BACKGROUNDS = [
|
||||
{
|
||||
"type": "tileprovider",
|
||||
"title": "Stamen Watercolor",
|
||||
"provider": "Stamen.Watercolor",
|
||||
"name": "Stamen.Watercolor",
|
||||
"source": "Stamen",
|
||||
"group": "background",
|
||||
"thumbURL": "https://stamen-tiles-c.a.ssl.fastly.net/watercolor/0/0/0.jpg",
|
||||
"visibility": False
|
||||
},
|
||||
{
|
||||
"type": "tileprovider",
|
||||
"title": "Stamen Terrain",
|
||||
"provider": "Stamen.Terrain",
|
||||
"name": "Stamen.Terrain",
|
||||
"source": "Stamen",
|
||||
"group": "background",
|
||||
"thumbURL": "https://stamen-tiles-d.a.ssl.fastly.net/terrain/0/0/0.png",
|
||||
"visibility": False
|
||||
},
|
||||
{
|
||||
"type": "tileprovider",
|
||||
"title": "Stamen Toner",
|
||||
"provider": "Stamen.Toner",
|
||||
"name": "Stamen.Toner",
|
||||
"source": "Stamen",
|
||||
"group": "background",
|
||||
"thumbURL": "https://stamen-tiles-d.a.ssl.fastly.net/toner/0/0/0.png",
|
||||
"visibility": False
|
||||
},
|
||||
{
|
||||
"type": "osm",
|
||||
"title": "Open Street Map",
|
||||
"name": "mapnik",
|
||||
"source": "osm",
|
||||
"group": "background",
|
||||
"visibility": True
|
||||
},
|
||||
{
|
||||
"type": "tileprovider",
|
||||
"title": "OpenTopoMap",
|
||||
"provider": "OpenTopoMap",
|
||||
"name": "OpenTopoMap",
|
||||
"source": "OpenTopoMap",
|
||||
"group": "background",
|
||||
"visibility": False
|
||||
},
|
||||
{
|
||||
"type": "wms",
|
||||
"title": "Sentinel-2 cloudless - https://s2maps.eu",
|
||||
"format": "image/jpeg",
|
||||
"id": "s2cloudless",
|
||||
"name": "s2cloudless:s2cloudless",
|
||||
"url": "https://maps.geo-solutions.it/geoserver/wms",
|
||||
"group": "background",
|
||||
"thumbURL": "%sstatic/mapstorestyle/img/s2cloudless-s2cloudless.png" % SITEURL,
|
||||
"visibility": False
|
||||
},
|
||||
{
|
||||
"source": "ol",
|
||||
"group": "background",
|
||||
"id": "none",
|
||||
"name": "empty",
|
||||
"title": "Empty Background",
|
||||
"type": "empty",
|
||||
"visibility": False,
|
||||
"args": ["Empty Background", {"visibility": False}]
|
||||
}
|
||||
]
|
||||
|
||||
if MAPBOX_ACCESS_TOKEN:
|
||||
MAPBOX_BASEMAPS = {
|
||||
"type": "tileprovider",
|
||||
"title": "MapBox streets-v11",
|
||||
"provider": "MapBoxStyle",
|
||||
"name": "MapBox streets-v11",
|
||||
"accessToken": "%s" % MAPBOX_ACCESS_TOKEN,
|
||||
"source": "streets-v11",
|
||||
"thumbURL": "https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/256/6/33/23?access_token=%s" % MAPBOX_ACCESS_TOKEN,
|
||||
"group": "background",
|
||||
"visibility": True
|
||||
}
|
||||
DEFAULT_MS2_BACKGROUNDS = [MAPBOX_BASEMAPS,] + DEFAULT_MS2_BACKGROUNDS
|
||||
|
||||
if BING_API_KEY:
|
||||
BING_BASEMAPS = [
|
||||
{
|
||||
"type": "bing",
|
||||
"title": "Bing Aerial",
|
||||
"name": "AerialWithLabels",
|
||||
"source": "bing",
|
||||
"group": "background",
|
||||
"apiKey": "",
|
||||
"visibility": True
|
||||
},
|
||||
{
|
||||
"type": "bing",
|
||||
"title": "Bing RoadOnDemand",
|
||||
"name": "RoadOnDemand",
|
||||
"source": "bing",
|
||||
"group": "background",
|
||||
"apiKey": "",
|
||||
"thumbURL": "%sstatic/mapstorestyle/img/bing_road_on_demand.png" % SITEURL,
|
||||
"visibility": False
|
||||
},
|
||||
{
|
||||
"type": "bing",
|
||||
"title": "Bing AerialWithLabelsOnDemand",
|
||||
"name": "AerialWithLabelsOnDemand",
|
||||
"source": "bing",
|
||||
"group": "background",
|
||||
"apiKey": "",
|
||||
"thumbURL": "%sstatic/mapstorestyle/img/bing_aerial_w_labels.png" % SITEURL,
|
||||
"visibility": False
|
||||
},
|
||||
{
|
||||
"type": "bing",
|
||||
"title": "Bing CanvasDark",
|
||||
"name": "CanvasDark",
|
||||
"source": "bing",
|
||||
"group": "background",
|
||||
"apiKey": "",
|
||||
"thumbURL": "%sstatic/mapstorestyle/img/bing_canvas_dark.png" % SITEURL,
|
||||
"visibility": False
|
||||
}
|
||||
]
|
||||
DEFAULT_MS2_BACKGROUNDS = [BING_BASEMAPS, ] + DEFAULT_MS2_BACKGROUNDS
|
||||
|
||||
MAPSTORE_BASELAYERS = DEFAULT_MS2_BACKGROUNDS
|
||||
|
||||
# -- END Client Hooksets Setup
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': True,
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '%(levelname)s %(asctime)s %(module)s %(process)d '
|
||||
'%(thread)d %(message)s'
|
||||
},
|
||||
'simple': {
|
||||
'format': '%(message)s',
|
||||
},
|
||||
},
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'console': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'simple'
|
||||
},
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
}
|
||||
},
|
||||
"loggers": {
|
||||
"django": {
|
||||
"handlers": ["console"], "level": "ERROR", },
|
||||
"geonode": {
|
||||
"handlers": ["console"], "level": "INFO", },
|
||||
"geonode.qgis_server": {
|
||||
"handlers": ["console"], "level": "ERROR", },
|
||||
"geoserver-restconfig.catalog": {
|
||||
"handlers": ["console"], "level": "ERROR", },
|
||||
"owslib": {
|
||||
"handlers": ["console"], "level": "ERROR", },
|
||||
"pycsw": {
|
||||
"handlers": ["console"], "level": "INFO", },
|
||||
"celery": {
|
||||
'handlers': ["console"], 'level': 'ERROR', },
|
||||
},
|
||||
}
|
||||
|
||||
# Additional settings
|
||||
# X_FRAME_OPTIONS = 'ALLOW-FROM %s' % SITEURL
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
|
||||
GEOIP_PATH = "/usr/local/share/GeoIP"
|
||||
Binary file not shown.
@@ -1333,7 +1333,7 @@ msgstr "Risques et Aléa en Haïti"
|
||||
|
||||
#: haitidata/templates/site_index.html:22
|
||||
msgid "River Flood"
|
||||
msgstr "Inondation Riverine"
|
||||
msgstr "Inondation Riveraine"
|
||||
|
||||
#: haitidata/templates/site_index.html:26
|
||||
msgid "Cyclone"
|
||||
|
||||
+27
-182
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#########################################################################
|
||||
#
|
||||
# Copyright (C) 2012 OpenPlans
|
||||
# Copyright (C) 2017 OSGeo
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -19,210 +19,55 @@
|
||||
#########################################################################
|
||||
|
||||
# Django settings for the GeoNode project.
|
||||
import ast
|
||||
import os
|
||||
from geonode.settings import *
|
||||
from urlparse import urlparse, urlunparse
|
||||
# Load more settings from a file called local_settings.py if it exists
|
||||
try:
|
||||
from haitidata.local_settings import *
|
||||
# from geonode.local_settings import *
|
||||
except ImportError:
|
||||
from geonode.settings import *
|
||||
|
||||
from .utils import absolute_path
|
||||
#
|
||||
# General Django development settings
|
||||
#
|
||||
PROJECT_NAME = 'haitidata'
|
||||
|
||||
SITENAME = 'haitidata'
|
||||
# add trailing slash to site url. geoserver url will be relative to this
|
||||
if not SITEURL.endswith('/'):
|
||||
SITEURL = '{}/'.format(SITEURL)
|
||||
|
||||
TIME_ZONE = os.getenv('TIME_ZONE', "America/Port-au-Prince")
|
||||
SITENAME = os.getenv("SITENAME", 'haitidata')
|
||||
|
||||
# Defines the directory that contains the settings file as the LOCAL_ROOT
|
||||
# It is used for relative settings elsewhere.
|
||||
LOCAL_ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
WSGI_APPLICATION = "haitidata.wsgi.application"
|
||||
WSGI_APPLICATION = "{}.wsgi.application".format(PROJECT_NAME)
|
||||
|
||||
# Language code for this installation. All choices can be found here:
|
||||
# http://www.i18nguy.com/unicode/language-identifiers.html
|
||||
LANGUAGE_CODE = os.getenv('LANGUAGE_CODE', "en")
|
||||
|
||||
# Load more settings from a file called local_settings.py if it exists
|
||||
try:
|
||||
from local_settings import *
|
||||
except ImportError:
|
||||
pass
|
||||
if PROJECT_NAME not in INSTALLED_APPS:
|
||||
INSTALLED_APPS += (PROJECT_NAME,)
|
||||
|
||||
# Location of url mappings
|
||||
ROOT_URLCONF = os.getenv('ROOT_URLCONF', '{}.urls'.format(PROJECT_NAME))
|
||||
|
||||
# Additional directories which hold static files
|
||||
STATICFILES_DIRS.append(
|
||||
os.path.join(LOCAL_ROOT, "static"),
|
||||
)
|
||||
|
||||
CLIPPED_DIRECTORY = absolute_path('base', 'clipped_geotiff')
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [os.path.join(PROJECT_ROOT, "templates")],
|
||||
'APP_DIRS': False,
|
||||
'OPTIONS': {
|
||||
# List of callables that know how to import
|
||||
# templates from various sources.
|
||||
'loaders': [
|
||||
'django.template.loaders.filesystem.Loader',
|
||||
'django.template.loaders.app_directories.Loader',
|
||||
],
|
||||
'context_processors': [
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
"django.core.context_processors.debug",
|
||||
"django.core.context_processors.i18n",
|
||||
"django.core.context_processors.static",
|
||||
"django.core.context_processors.media",
|
||||
"django.core.context_processors.request",
|
||||
"django.core.context_processors.tz",
|
||||
'account.context_processors.account',
|
||||
'geonode.context_processors.resource_urls',
|
||||
"geonode.geoserver.context_processors.geoserver_urls",
|
||||
"haitidata.context_processors.clipped_geotiff.clipped_geotiff",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
# Location of url mappings
|
||||
ROOT_URLCONF = 'haitidata.urls'
|
||||
|
||||
# Location of locale files
|
||||
LOCALE_PATHS = (
|
||||
os.path.join(LOCAL_ROOT, 'locale'),
|
||||
os.path.join(PROJECT_ROOT, 'locale'),
|
||||
) + LOCALE_PATHS
|
||||
|
||||
INSTALLED_APPS = INSTALLED_APPS + (
|
||||
"django.contrib.redirects",
|
||||
'haitidata',
|
||||
'osgeo_importer',
|
||||
'geonode-client',
|
||||
'charts_app',
|
||||
'wfs_harvest',
|
||||
"clip-and-ship",
|
||||
'filter',
|
||||
'thumbnail'
|
||||
)
|
||||
|
||||
GEOSERVER_PUBLIC_LOCATION = os.environ.get(
|
||||
'GEOSERVER_PUBLIC_LOCATION', 'http://136.243.4.93:8080/geoserver/'
|
||||
)
|
||||
|
||||
# dynamic setting based on domain
|
||||
GEOSERVER_BASE_URL = os.environ.get(
|
||||
'GEOSERVER_BASE_URL',
|
||||
'http://136.243.4.93:8080/geoserver/'
|
||||
) # change this to geoserver container location
|
||||
|
||||
LAYER_PREVIEW_LIBRARY = 'react'
|
||||
|
||||
TEMPLATES[0]['DIRS'].insert(0, os.path.join(LOCAL_ROOT, "templates"))
|
||||
|
||||
IMPORT_HANDLERS = [
|
||||
# If GeoServer handlers are enabled, you must have an instance of geoserver running.
|
||||
# Warning: the order of the handlers here matters.
|
||||
'osgeo_importer.handlers.FieldConverterHandler',
|
||||
'osgeo_importer.handlers.geoserver.GeoserverPublishHandler',
|
||||
'osgeo_importer.handlers.geoserver.GeoserverPublishCoverageHandler',
|
||||
'osgeo_importer.handlers.geoserver.GeoServerTimeHandler',
|
||||
'osgeo_importer.handlers.geoserver.GeoWebCacheHandler',
|
||||
'osgeo_importer.handlers.geoserver.GeoServerBoundsHandler',
|
||||
'osgeo_importer.handlers.geoserver.GenericSLDHandler',
|
||||
'osgeo_importer.handlers.geonode.GeoNodePublishHandler',
|
||||
'osgeo_importer.handlers.mapproxy.publish_handler.MapProxyGPKGTilePublishHandler',
|
||||
'osgeo_importer.handlers.geoserver.GeoServerStyleHandler',
|
||||
'osgeo_importer.handlers.geonode.GeoNodeMetadataHandler'
|
||||
]
|
||||
|
||||
OSGEO_DATASTORE = 'datastore'
|
||||
OSGEO_IMPORTER_GEONODE_ENABLED = True
|
||||
OSGEO_IMPORTER_VALID_EXTENSIONS = [
|
||||
'shp', 'shx', 'prj', 'dbf', 'kml', 'geojson', 'json', 'tif', 'tiff',
|
||||
'gpkg', 'csv', 'zip', 'xml', 'sld'
|
||||
]
|
||||
|
||||
LOGGING['loggers']['osgeo_importer'] = {"handlers": ["console"], "level": "DEBUG"}
|
||||
#DATABASE_ROUTERS = ['.dbrouters.DefaultOnlyMigrations']
|
||||
|
||||
# # === MapProxy settings
|
||||
# # This is the location to place additional configuration files for mapproxy to work from.
|
||||
# # Currently it is only to allow tiles from gpkg files to be served.
|
||||
MAPPROXY_CONFIG_DIR = '/opt/geonode-mapproxy-config'
|
||||
# Name of the mapproxy config file to create for tile gpkg files.
|
||||
MAPPROXY_CONFIG_FILENAME = 'geonode.yaml'
|
||||
# This is the base URL for MapProxy WMS services
|
||||
# URLs will look like this: /geonode/tms/1.0.0/<layer_name>/<grid_name>/0/0/0.png and a <grid_name> will be
|
||||
# set as '<layer_name>_<projection_id>' (by conf_from_geopackage()).
|
||||
MAPPROXY_SERVER_LOCATION = 'http://localhost:8088/geonode/tms/1.0.0/{layer_name}/{grid_name}/'
|
||||
|
||||
#import pyproj
|
||||
#PROJECTION_DIRECTORY = os.path.join(os.path.dirname(pyproj.__file__), 'data/')
|
||||
PROJECTION_DIRECTORY = '/tmp/'
|
||||
|
||||
try:
|
||||
CELERY_IMPORTS = CELERY_IMPORTS + ('osgeo_importer.tasks',)
|
||||
except:
|
||||
CELERY_IMPORTS = ('osgeo_importer.tasks',)
|
||||
|
||||
LOCKDOWN_GEONODE = True
|
||||
|
||||
BROKER_URL = "amqp://guest@localhost:5672"
|
||||
CELERY_ALWAYS_EAGER = True
|
||||
IMPORT_TASK_SOFT_TIME_LIMIT = 90
|
||||
|
||||
# Force French as default language
|
||||
# Needs /usr/local/lib/python2.7/dist-packages/setmydefaultlanguage/__init__.py
|
||||
# See doc http://docs.geonode.org/en/master/tutorials/admin/default_lang/
|
||||
|
||||
LANGUAGE_CODE = 'fr'
|
||||
|
||||
MIDDLEWARE_CLASSES += (
|
||||
'setmydefaultlanguage.ForceDefaultLanguageMiddleware',
|
||||
)
|
||||
|
||||
_HAITI_LANGUAGES = (
|
||||
('en', 'English'),
|
||||
('fr', 'Français'),
|
||||
)
|
||||
|
||||
LANGUAGES = os.getenv('LANGUAGES', _HAITI_LANGUAGES)
|
||||
|
||||
# maximum clip size in bytes
|
||||
MAXIMUM_CLIP_SIZE = '40000000'
|
||||
|
||||
SOCIAL_ORIGINS = [{
|
||||
"label":"paper-plane-o",
|
||||
"url":"mailto:?subject={name}&body={url}",
|
||||
"css_class":"email"
|
||||
}, {
|
||||
"label":"facebook",
|
||||
"url":"http://www.facebook.com/sharer.php?u={url}",
|
||||
"css_class":"fb"
|
||||
}, {
|
||||
"label":"twitter",
|
||||
"url":"https://twitter.com/share?url={url}&hashtags={hashtags}",
|
||||
"css_class":"tw"
|
||||
}, {
|
||||
"label":"google-plus",
|
||||
"url":"https://plus.google.com/share?url={url}",
|
||||
"css_class":"gp"
|
||||
}]
|
||||
|
||||
WCS_DOWNLOADED_RATIO_SIZE = 1
|
||||
|
||||
MAX_CSV_RECORDS = 20000
|
||||
|
||||
UPLOADER = {
|
||||
'BACKEND': 'geonode.rest',
|
||||
'OPTIONS': {
|
||||
'TIME_ENABLED': False,
|
||||
'MOSAIC_ENABLED': True,
|
||||
'GEOGIG_ENABLED': False,
|
||||
}
|
||||
}
|
||||
|
||||
OFFICIAL_USERS = [
|
||||
'cnigs', 'ciat', 'ihsi', 'dpc', 'marndr', 'mairie-de-pap', 'faculte-de-science', 'undp-haiti', 'idb',
|
||||
'european-union', 'worldbank'
|
||||
]
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
loaders = TEMPLATES[0]['OPTIONS'].get('loaders') or ['django.template.loaders.filesystem.Loader','django.template.loaders.app_directories.Loader']
|
||||
# loaders.insert(0, 'apptemplates.Loader')
|
||||
TEMPLATES[0]['OPTIONS']['loaders'] = loaders
|
||||
TEMPLATES[0].pop('APP_DIRS', None)
|
||||
Regular → Executable
+12
@@ -1,8 +1,20 @@
|
||||
# Introduction
|
||||
|
||||
This directory is used to store static assets for your project. User media files
|
||||
(FileFields/ImageFields) are not stored here.
|
||||
|
||||
The convention for this directory is:
|
||||
|
||||
* css/ — stores CSS files
|
||||
* less/ - stores LESS files
|
||||
* js/ — stores Javascript files
|
||||
* img/ — stores image files
|
||||
|
||||
# Gulp
|
||||
|
||||
Gulp can be used to automatically build css from LESS files. The gulp process will
|
||||
watch you LESS files for changes and recompile. To install gulp do
|
||||
the following 2 steps:
|
||||
|
||||
1. cd into the project directory and install dependencies with `npm install`
|
||||
2. install gulp command line globally with `sudo npm install -g gulp`
|
||||
Vendored
-6723
File diff suppressed because it is too large.
Load diff
-6723
File diff suppressed because it is too large.
Load diff
@@ -1,48 +0,0 @@
|
||||
.media {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.media:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.media,
|
||||
.media-body {
|
||||
zoom: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
.media-body {
|
||||
width: 10000px;
|
||||
}
|
||||
.media-object {
|
||||
display: block;
|
||||
}
|
||||
.media-object.img-thumbnail {
|
||||
max-width: none;
|
||||
}
|
||||
.media-right,
|
||||
.media > .pull-right {
|
||||
padding-left: 10px;
|
||||
}
|
||||
.media-left,
|
||||
.media > .pull-left {
|
||||
padding-right: 10px;
|
||||
}
|
||||
.media-left,
|
||||
.media-right,
|
||||
.media-body {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
}
|
||||
.media-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.media-bottom {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.media-heading {
|
||||
margin-top: 0;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.media-list {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Loaded 100 of 436 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user