diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..71adc916
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "docker/database"]
+ path = docker/database
+ url = https://github.com/Banno/docker-postgresql-8.4/
+ branch = postgres-8.4
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..b1dcd914
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,35 @@
+FROM tozd/runit:ubuntu-xenial
+
+EXPOSE 80/tcp
+ENV DJANGO_SETTINGS_MODULE mainpage.settings
+#Set secrets by uncommenting lines below
+#ENV DB_PASSWORD ...
+#Make this unique, and don't share it with anybody.
+#ENV SECRET_KEY ...
+#You can find them at: https://www.google.com/recaptcha/admin
+#ENV RECAPTCHA_PUBLIC_KEY ...
+#ENV RECAPTCHA_PRIVATE_KEY ...
+#ENV PAYPAL_IDENTITY_TOKEN_PRODUCTION ...
+
+# Update packages
+RUN apt-get update -q -q && \
+ apt-get install --no-install-recommends -y git curl python python-dev python-pip python-setuptools build-essential libgeoip-dev libpq-dev swig libxml2-dev libxslt1-dev subversion mercurial libaprutil1 apache2-dev python2.7-dev nginx
+RUN pip install --upgrade pip setuptools wheel six requests
+
+RUN ln -sf /dev/stdout /var/log/nginx/access.log
+RUN ln -sf /dev/stdout /var/log/nginx/error.log
+
+ADD ./requirements.txt /code/requirements.txt
+ADD ./requirements-production.txt /code/requirements-production.txt
+
+# Install Python package dependencies
+RUN pip install -r /code/requirements-production.txt
+
+# Remove unneeded build-time dependencies
+RUN apt-get purge python-dev build-essential -y && \
+ apt-get autoremove -y && \
+rm -f /code/packages.txt /code/requirements.txt
+COPY ./etc /etc
+# Add the current version of the code (needed for production deployments)
+WORKDIR /code
+ADD . /code
\ No newline at end of file
diff --git a/README.rst b/README.rst
index 805fc0e4..00bd1c20 100644
--- a/README.rst
+++ b/README.rst
@@ -1,37 +1,46 @@
-*wlan slovenija* main webpage
-=============================
+Mainpage
+========
-Development installation
-------------------------
+This is a repository for wlan-si web-page docker, it contains:
-1. Clone from GitHub_ both webpage and nodewatcher_ repositories::
+- Web container for: django, uwgsi, nginx
+- Database container with postgresql
- git clone https://github.com/wlanslovenija/mainpage.git
- git clone https://github.com/wlanslovenija/nodewatcher.git
+Installation
+------------
- You can also use SSH-based URLs or URLs of your forks.
+Mainpage requires `docker `__ and
+`docker-compose `__ to run.
-2. Create and activate new `Python virtual environment`_::
+Download the repository to disk and run docker-compose build.
- virtualenv --no-site-packages --distribute ~/.virtualenv/mainpage
- source ~/.virtualenv/mainpage/bin/activate
-
-3. Move to location where you cloned webpage repository and run ``devsetup``
- script::
+.. code:: sh
- python scripts/devsetup.py
-
- This script will install all requirements and import database dump to local database.
+ git clone https://github.com/wlanslovenija/mainpage
+ cd mainpage
+ docker-compose build
-4. Run::
+Then just run the docker-compose up, which will set up the database
+create media and static folders, merge the database, and bring up the
+production server for mainpage.
- python manage.py runserver
+.. code:: sh
- and start developing!
+ docker-compose up
-You can safely rerun the ``devsetup`` as needed, but be advised that local
-database content **will NOT be preserved**.
+About
+-----
-.. _GitHub: https://github.com/
-.. _nodewatcher: http://dev.wlan-si.net/wiki/Nodewatcher
-.. _Python virtual environment: http://www.virtualenv.org
+This repository was a big part of my 2017 Gsoc project, it was suppose
+to revive the unmaintained repository of wlan-si.net web-page, which had
+a lot of broken dependencies, outdated dependencies and was not yet
+running inside of a docker container.
+
+I managed to successfully create docker containers for both website and
+database but my lack of django knowledge left me short of actually
+fixing the django project that was suppose to run.
+
+Future
+------
+
+All that is left is for someone to fix the broken django project.
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..8d8196e8
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,22 @@
+version: '3'
+services:
+ web:
+ build: .
+ command: "service nginx start; scripts/docker-wait-pgsql; python scripts/migrate.py; uwsgi --socket /var/tmp/nodewatcher.sock --wsgi-file /code/mainpage/wsgi.py --uid www-data --gid www-data"
+ entrypoint: scripts/docker-run
+ environment:
+ PYTHONUNBUFFERED: 1
+ volumes:
+ - .:/code
+ ports:
+ - "80:80"
+ db:
+ build:
+ context: docker/database/
+ dockerfile: Dockerfile
+ environment:
+ POSTGRESQL_USER: wlansi_cms
+ POSTGRESQL_PASS: mainpage
+ POSTGRESQL_DB: wlansi
+ expose:
+ - 5432
\ No newline at end of file
diff --git a/docker/database/Dockerfile b/docker/database/Dockerfile
new file mode 100644
index 00000000..03486b6d
--- /dev/null
+++ b/docker/database/Dockerfile
@@ -0,0 +1,25 @@
+FROM ubuntu:14.04
+
+RUN apt-get update && apt-get install -y wget
+
+ADD pgdg.list /etc/apt/sources.list.d/pgdg.list
+RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
+
+RUN apt-get -qq update && LC_ALL=en_US.UTF-8 DEBIAN_FRONTEND=noninteractive apt-get install -y -q postgresql-8.4 libpq-dev
+
+# /etc/ssl/private can't be accessed from within container for some reason
+# (@andrewgodwin says it's something AUFS related)
+RUN mkdir /etc/ssl/private-copy; mv /etc/ssl/private/* /etc/ssl/private-copy/; rm -r /etc/ssl/private; mv /etc/ssl/private-copy /etc/ssl/private; chmod -R 0700 /etc/ssl/private; chown -R postgres /etc/ssl/private
+
+## Add over config files
+ADD postgresql.conf /etc/postgresql/8.4/main/postgresql.conf
+ADD pg_hba.conf /etc/postgresql/8.4/main/pg_hba.conf
+RUN chown postgres:postgres /etc/postgresql/8.4/main/*.conf
+ADD init-postgresql /usr/local/bin/init-postgresql
+RUN chmod +x /usr/local/bin/init-postgresql
+
+VOLUME ["/var/lib/postgresql"]
+EXPOSE 5432
+
+CMD ["/usr/local/bin/init-postgresql"]
+
diff --git a/etc/nginx/sites-enabled/default b/etc/nginx/sites-enabled/default
new file mode 100644
index 00000000..5657f0d3
--- /dev/null
+++ b/etc/nginx/sites-enabled/default
@@ -0,0 +1,25 @@
+upstream mainpage {
+ server unix:/var/tmp/nodewatcher.sock;
+}
+access_log /var/log/nginx/access.log;
+error_log /var/log/nginx/error.log;
+server {
+ listen 80 default_server;
+ server_name _;
+ charset utf-8;
+ root /tmp;
+
+ location /static {
+ alias /code/mainpage/wlansi/static;
+ }
+
+ location /media {
+ alias /code/mainpage/media/;
+ }
+
+ location / {
+ uwsgi_pass mainpage;
+ include /etc/nginx/uwsgi_params;
+ }
+}
+
diff --git a/etc/nginx/uwsgi_params b/etc/nginx/uwsgi_params
new file mode 100644
index 00000000..f539451b
--- /dev/null
+++ b/etc/nginx/uwsgi_params
@@ -0,0 +1,16 @@
+
+uwsgi_param QUERY_STRING $query_string;
+uwsgi_param REQUEST_METHOD $request_method;
+uwsgi_param CONTENT_TYPE $content_type;
+uwsgi_param CONTENT_LENGTH $content_length;
+
+uwsgi_param REQUEST_URI $request_uri;
+uwsgi_param PATH_INFO $document_uri;
+uwsgi_param DOCUMENT_ROOT $document_root;
+uwsgi_param SERVER_PROTOCOL $server_protocol;
+uwsgi_param HTTPS $https if_not_empty;
+
+uwsgi_param REMOTE_ADDR $remote_addr;
+uwsgi_param REMOTE_PORT $remote_port;
+uwsgi_param SERVER_PORT $server_port;
+uwsgi_param SERVER_NAME $server_name;
diff --git a/etc/service/nginx/run b/etc/service/nginx/run
new file mode 100755
index 00000000..2e401399
--- /dev/null
+++ b/etc/service/nginx/run
@@ -0,0 +1,4 @@
+#!/bin/bash -e
+
+exec /usr/sbin/nginx -g 'daemon off;' 2>&1
+
diff --git a/etc/service/postgresql/run.initialization b/etc/service/postgresql/run.initialization
new file mode 100644
index 00000000..088d9af2
--- /dev/null
+++ b/etc/service/postgresql/run.initialization
@@ -0,0 +1,2 @@
+apt -y install postgresql-9.6-ip4r
+psql -c "create extension ip4r" wlansi
\ No newline at end of file
diff --git a/etc/service/uwsgi/log/run b/etc/service/uwsgi/log/run
new file mode 100755
index 00000000..7ae04bc3
--- /dev/null
+++ b/etc/service/uwsgi/log/run
@@ -0,0 +1,7 @@
+#!/bin/bash -e
+
+mkdir -p /var/log/uwsgi
+chown nobody:nogroup /var/log/uwsgi
+
+exec chpst -u nobody:nogroup svlogd -tt /var/log/uwsgi
+
diff --git a/etc/service/uwsgi/run b/etc/service/uwsgi/run
new file mode 100755
index 00000000..e041c237
--- /dev/null
+++ b/etc/service/uwsgi/run
@@ -0,0 +1,13 @@
+#!/bin/bash -e
+
+mkdir -p /media
+chown -R www-data:www-data /media
+
+mkdir -p /static
+cd /
+
+python manage.py collectstatic --noinput
+python manage.py migrate --noinput
+
+exec /usr/bin/uwsgi --plugin python --ini /etc/uwsgi/nodewatcher.ini 2>&1
+
diff --git a/etc/uwsgi/mainpage.ini b/etc/uwsgi/mainpage.ini
new file mode 100644
index 00000000..a65d545f
--- /dev/null
+++ b/etc/uwsgi/mainpage.ini
@@ -0,0 +1,10 @@
+[uwsgi]
+uid = www-data
+gid = www-data
+chdir = /code
+module = mainpage.wsgi
+master = true
+processes = 10
+socket = /var/tmp/mainpage.sock
+harakiri = 120
+max-requests = 1000
diff --git a/mainpage/frontend/__init__.py b/mainpage/frontend/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/mainpage/frontend/account/__init__.py b/mainpage/frontend/account/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/mainpage/frontend/account/geo_fields.py b/mainpage/frontend/account/geo_fields.py
new file mode 100644
index 00000000..f75e21cc
--- /dev/null
+++ b/mainpage/frontend/account/geo_fields.py
@@ -0,0 +1,366 @@
+# Based on http://code.djangoproject.com/ticket/5446
+# Should be changed to use upstream code once it has been merged into it.
+
+from django.conf import settings
+from django.contrib.gis import utils as gis_utils
+from django.db.models import fields
+from django.utils import encoding as utils_encoding
+from django.utils import translation
+from django.utils.translation import ugettext_lazy as _
+
+# Countries list - ISO 3166-1
+# http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
+# http://en.wikipedia.org/wiki/List_of_national_capitals
+
+COUNTRIES = (
+ ('AD', _('Andorra'), _('Andorra la Vella')),
+ ('AE', _('United Arab Emirates'), _('Abu Dhabi')),
+ ('AF', _('Afghanistan'), _('Kabul')),
+ ('AG', _('Antigua and Barbuda'), _("St. John's")),
+ ('AI', _('Anguilla'), _('The Valley')),
+ ('AL', _('Albania'), _('Tirana')),
+ ('AM', _('Armenia'), _('Yerevan')),
+ ('AN', _('Netherlands Antilles'), _('Willemstad')),
+ ('AO', _('Angola'), _('Luanda')),
+ ('AQ', _('Antarctica'), ''),
+ ('AR', _('Argentina'), _('Buenos Aires')),
+ ('AS', _('American Samoa'), _('Pago Pago')),
+ ('AT', _('Austria'), _('Vienna')),
+ ('AU', _('Australia'), _('Canberra')),
+ ('AW', _('Aruba'), _('Oranjestad')),
+ ('AX', _('Aland Islands'), _('Mariehamn')),
+ ('AZ', _('Azerbaijan'), _('Baku')),
+ ('BA', _('Bosnia and Herzegovina'), _('Sarajevo')),
+ ('BB', _('Barbados'), _('Bridgetown')),
+ ('BD', _('Bangladesh'), _('Dhaka')),
+ ('BE', _('Belgium'), _('Brussels')),
+ ('BF', _('Burkina Faso'), _('Ouagadougou')),
+ ('BG', _('Bulgaria'), _('Sofia')),
+ ('BH', _('Bahrain'), _('Manama')),
+ ('BI', _('Burundi'), _('Bujumbura')),
+ ('BJ', _('Benin'), _('Porto-Novo')),
+ ('BL', _('Saint Barthelemy'), _('Gustavia')),
+ ('BM', _('Bermuda'), _('Hamilton')),
+ ('BN', _('Brunei'), _('Bandar Seri Begawan')),
+ ('BO', _('Bolivia'), _('Sucre')),
+ ('BR', _('Brazil'), _('Brasilia')),
+ ('BS', _('Bahamas'), _('Nassau')),
+ ('BT', _('Bhutan'), _('Thimphu')),
+ ('BV', _('Bouvet Island'), ''),
+ ('BW', _('Botswana'), _('Gaborone')),
+ ('BY', _('Belarus'), _('Minsk')),
+ ('BZ', _('Belize'), _('Belmopan')),
+ ('CA', _('Canada'), _('Ottawa')),
+ ('CC', _('Cocos (Keeling) Islands'), _('West Island')),
+ ('CD', _('Congo, the Democratic Republic of the'), _('Kinshasa')),
+ ('CF', _('Central African Republic'), _('Bangui')),
+ ('CG', _('Congo, the Republic of the'), _('Brazzaville')),
+ ('CH', _('Switzerland'), _('Bern')),
+ ('CI', _('Ivory Coast'), _('Yamoussoukro')),
+ ('CK', _('Cook Islands'), _('Avarua')),
+ ('CL', _('Chile'), _('Santiago')),
+ ('CM', _('Cameroon'), _('Yaounde')),
+ ('CN', _('China'), _('Beijing')),
+ ('CO', _('Colombia'), _('Bogota')),
+ ('CR', _('Costa Rica'), _('San Jose')),
+ ('CU', _('Cuba'), _('Havana')),
+ ('CV', _('Cape Verde'), _('Praia')),
+ ('CX', _('Christmas Island'), _('Flying Fish Cove')),
+ ('CY', _('Cyprus'), _('Nicosia')),
+ ('CZ', _('Czech Republic'), _('Prague')),
+ ('DE', _('Germany'), _('Berlin')),
+ ('DJ', _('Djibouti'), _('Djibouti')),
+ ('DK', _('Denmark'), _('Copenhagen')),
+ ('DM', _('Dominica'), _('Roseau')),
+ ('DO', _('Dominican Republic'), _('Santo Domingo')),
+ ('DZ', _('Algeria'), _('Algiers')),
+ ('EC', _('Ecuador'), _('Quito')),
+ ('EE', _('Estonia'), _('Tallinn')),
+ ('EG', _('Egypt'), _('Cairo')),
+ ('EH', _('Western Sahara'), _('El Aaiun')),
+ ('ER', _('Eritrea'), _('Asmara')),
+ ('ES', _('Spain'), _('Madrid')),
+ ('ET', _('Ethiopia'), _('Addis Ababa')),
+ ('FI', _('Finland'), _('Helsinki')),
+ ('FJ', _('Fiji'), _('Suva')),
+ ('FK', _('Falkland Islands'), _('Stanley')),
+ ('FM', _('Micronesia'), _('Palikir')),
+ ('FO', _('Faroe Islands'), _('Torshavn')),
+ ('FR', _('France'), _('Paris')),
+ ('GA', _('Gabon'), _('Libreville')),
+ ('GB', _('United Kingdom'), _('London')),
+ ('GD', _('Grenada'), _("St. George's")),
+ ('GE', _('Georgia'), _('Tbilisi')),
+ ('GF', _('French Guiana'), _('Cayenne')),
+ ('GG', _('Guernsey'), _('Saint Peter Port')),
+ ('GH', _('Ghana'), _('Accra')),
+ ('GI', _('Gibraltar'), _('Gibraltar')),
+ ('GL', _('Greenland'), _('Nuuk')),
+ ('GM', _('Gambia'), _('Banjul')),
+ ('GN', _('Guinea'), _('Conakry')),
+ ('GP', _('Guadeloupe'), _('Basse-Terre')),
+ ('GQ', _('Equatorial Guinea'), _('Malabo')),
+ ('GR', _('Greece'), _('Athens')),
+ ('GS', _('South Georgia and the South Sandwich Islands'), _('Grytviken')),
+ ('GT', _('Guatemala'), _('Guatemala City')),
+ ('GU', _('Guam'), _('Hagatna')),
+ ('GW', _('Guinea-Bissau'), _('Bissau')),
+ ('GY', _('Guyana'), _('Georgetown')),
+ ('HK', _('Hong Kong'), _('Hong Kong')),
+ ('HM', _('Heard Island and McDonald Islands'), ''),
+ ('HN', _('Honduras'), _('Tegucigalpa')),
+ ('HR', _('Croatia'), _('Zagreb')),
+ ('HT', _('Haiti'), _('Port-au-Prince')),
+ ('HU', _('Hungary'), _('Budapest')),
+ ('ID', _('Indonesia'), _('Jakarta')),
+ ('IE', _('Ireland'), _('Dublin')),
+ ('IL', _('Israel'), _('Jerusalem')),
+ ('IM', _('Isle of Man'), _('Douglas')),
+ ('IN', _('India'), _('New Delhi')),
+ ('IO', _('British Indian Ocean Territory'), _('Diego Garcia')),
+ ('IQ', _('Iraq'), _('Iraq')),
+ ('IR', _('Iran'), _('Tehran')),
+ ('IS', _('Iceland'), _('Reykjavik')),
+ ('IT', _('Italy'), _('Rome')),
+ ('JE', _('Jersey'), _('Saint Helier')),
+ ('JM', _('Jamaica'), _('Kingston')),
+ ('JO', _('Jordan'), _('Amman')),
+ ('JP', _('Japan'), _('Tokyo')),
+ ('KE', _('Kenya'), _('Nairobi')),
+ ('KG', _('Kyrgyzstan'), _('Bishkek')),
+ ('KH', _('Cambodia'), _('Phnom Penh')),
+ ('KI', _('Kiribati'), _('South Tarawa')),
+ ('KM', _('Comoros'), _('Moroni')),
+ ('KN', _('Saint Kitts and Nevis'), _('Basseterre')),
+ ('KP', _('North Korea'), _('Pyongyang')),
+ ('KR', _('South Korea'), _('Seoul')),
+ ('KW', _('Kuwait'), _('Kuwait City')),
+ ('KY', _('Cayman Islands'), _('George Town')),
+ ('KZ', _('Kazakhstan'), _('Astana')),
+ ('LA', _('Laos'), _('Vientiane')),
+ ('LB', _('Lebanon'), _('Beirut')),
+ ('LC', _('Saint Lucia'), _('Castries')),
+ ('LI', _('Liechtenstein'), _('Vaduz')),
+ ('LK', _('Sri Lanka'), _('Sri Jayawardenepura Kotte')),
+ ('LR', _('Liberia'), _('Monrovia')),
+ ('LS', _('Lesotho'), _('Maseru')),
+ ('LT', _('Lithuania'), _('Vilnius')),
+ ('LU', _('Luxembourg'), _('Luxembourg City')),
+ ('LV', _('Latvia'), _('Riga')),
+ ('LY', _('Libya'), _('Tripoli')),
+ ('MA', _('Morocco'), _('Rabat')),
+ ('MC', _('Monaco'), _('Monaco')),
+ ('MD', _('Moldova'), _('Chisinau')),
+ ('ME', _('Montenegro'), _('Podgorica')),
+ ('MG', _('Madagascar'), _('Antananarivo')),
+ ('MH', _('Marshall Islands'), _('Majuro')),
+ ('MK', _('Macedonia'), _('Skopje')),
+ ('ML', _('Mali'), _('Bamako')),
+ ('MM', _('Myanmar'), _('Naypyidaw')),
+ ('MN', _('Mongolia'), _('Ulaanbaatar')),
+ ('MO', _('Macao'), _('Macao')),
+ ('MP', _('Northern Mariana Islands'), _('Saipan')),
+ ('MQ', _('Martinique'), _('Fort-de-France')),
+ ('MR', _('Mauritania'), _('Nouakchott')),
+ ('MS', _('Montserrat'), _('Brades')),
+ ('MT', _('Malta'), _('Valletta')),
+ ('MU', _('Mauritius'), _('Port Louis')),
+ ('MV', _('Maldives'), _('Male')),
+ ('MW', _('Malawi'), _('Lilongwe')),
+ ('MX', _('Mexico'), _('Mexico City')),
+ ('MY', _('Malaysia'), _('Putrajaya')),
+ ('MZ', _('Mozambique'), _('Maputo')),
+ ('NA', _('Namibia'), _('Windhoek')),
+ ('NC', _('New Caledonia'), _('Noumea')),
+ ('NE', _('Niger'), _('Niamey')),
+ ('NF', _('Norfolk Island'), _('Kingston')),
+ ('NG', _('Nigeria'), _('Abuja')),
+ ('NI', _('Nicaragua'), _('Managua')),
+ ('NL', _('Netherlands'), _('Amsterdam')),
+ ('NO', _('Norway'), _('Oslo')),
+ ('NP', _('Nepal'), _('Kathmandu')),
+ ('NR', _('Nauru'), _('Yaren')),
+ ('NU', _('Niue'), _('Alofi')),
+ ('NZ', _('New Zealand'), _('Wellington')),
+ ('OM', _('Oman'), _('Muscat')),
+ ('PA', _('Panama'), _('Panama City')),
+ ('PE', _('Peru'), _('Lima')),
+ ('PF', _('French Polynesia'), _('Papeete')),
+ ('PG', _('Papua New Guinea'), _('Port Moresby')),
+ ('PH', _('Philippines'), _('Manila')),
+ ('PK', _('Pakistan'), _('Islamabad')),
+ ('PL', _('Poland'), _('Warsaw')),
+ ('PM', _('Saint Pierre and Miquelon'), _('St. Pierre')),
+ ('PN', _('Pitcairn Islands'), _('Adamstown')),
+ ('PR', _('Puerto Rico'), _('San Juan')),
+ ('PS', _('Palestine'), _('Jerusalem')),
+ ('PT', _('Portugal'), _('Lisbon')),
+ ('PW', _('Palau'), _('Ngerulmud')),
+ ('PY', _('Paraguay'), _('Asuncion')),
+ ('QA', _('Qatar'), _('Doha')),
+ ('RE', _('Reunion'), _('Saint-Denis')),
+ ('RO', _('Romania'), _('Bucharest')),
+ ('RS', _('Serbia'), _('Belgrade')),
+ ('RU', _('Russia'), _('Moscow')),
+ ('RW', _('Rwanda'), _('Kigali')),
+ ('SA', _('Saudi Arabia'), _('Riyadh')),
+ ('SB', _('Solomon Islands'), _('Honiara')),
+ ('SC', _('Seychelles'), _('Victoria')),
+ ('SD', _('Sudan'), _('Khartoum')),
+ ('SE', _('Sweden'), _('Stockholm')),
+ ('SG', _('Singapore'), _('Singapore')),
+ ('SH', _('Saint Helena'), _('Jamestown')),
+ ('SI', _('Slovenia'), _('Ljubljana')),
+ ('SJ', _('Svalbard and Jan Mayen'), _('Longyearbyen')),
+ ('SK', _('Slovakia'), _('Bratislava')),
+ ('SL', _('Sierra Leone'), _('Freetown')),
+ ('SM', _('San Marino'), _('San Marino')),
+ ('SN', _('Senegal'), _('Dakar')),
+ ('SO', _('Somalia'), _('Mogadishu')),
+ ('SR', _('Suriname'), _('Paramaribo')),
+ ('ST', _('Sao Tome and Principe'), _('Sao Tome')),
+ ('SV', _('El Salvador'), _('San Salvador')),
+ ('SY', _('Syria'), _('Damascus')),
+ ('SZ', _('Swaziland'), _('Mbabane')),
+ ('TC', _('Turks and Caicos Islands'), _('Cockburn Town')),
+ ('TD', _('Chad'), _("N'Djamena")),
+ ('TF', _('French Southern Territories'), _('Port-aux-Francais')),
+ ('TG', _('Togo'), _('Lome')),
+ ('TH', _('Thailand'), _('Bangkok')),
+ ('TJ', _('Tajikistan'), _('Dushanbe')),
+ ('TK', _('Tokelau'), _('Nukunonu')),
+ ('TL', _('Timor-Leste'), _('Dili')),
+ ('TM', _('Turkmenistan'), _('Ashgabat')),
+ ('TN', _('Tunisia'), _('Tunis')),
+ ('TO', _('Tonga'), _("Nuku'alofa")),
+ ('TR', _('Turkey'), _('Ankara')),
+ ('TT', _('Trinidad and Tobago'), _('Port of Spain')),
+ ('TV', _('Tuvalu'), _('Funafuti')),
+ ('TW', _('Taiwan'), _('Taipei')),
+ ('TZ', _('Tanzania'), _('Dodoma')),
+ ('UA', _('Ukraine'), _('Kiev')),
+ ('UG', _('Uganda'), _('Kampala')),
+ ('UM', _('United States Minor Outlying Islands'), _('Wake Island')),
+ ('US', _('United States'), _('Washington, D.C.')),
+ ('UY', _('Uruguay'), _('Montevideo')),
+ ('UZ', _('Uzbekistan'), _('Tashkent')),
+ ('VA', _('Vatican City'), _('Vatican City')),
+ ('VC', _('Saint Vincent and the Grenadines'), _('Kingstown')),
+ ('VE', _('Venezuela'), _('Caracas')),
+ ('VG', _('Virgin Islands, British'), _('Road Town')),
+ ('VI', _('Virgin Islands, United States'), _('Charlotte Amalie')),
+ ('VN', _('Vietnam'), _('Hanoi')),
+ ('VU', _('Vanuatu'), _('Port Vila')),
+ ('WF', _('Wallis and Futuna'), _('Mata-Utu')),
+ ('WS', _('Samoa'), _('Apia')),
+ ('YE', _('Yemen'), _('Sanaa')),
+ ('YT', _('Mayotte'), _('Mamoudzou')),
+ ('ZA', _('South Africa'), _('Pretoria')),
+ ('ZM', _('Zambia'), _('Lusaka')),
+ ('ZW', _('Zimbabwe'), _('Harare')),
+ ('ZZ', _('Unknown or unspecified country'), ''),
+)
+
+
+def sorted_countries(countries):
+ """
+ Sort countries for a given language.
+
+ Assume ZZ is the last entry, keep it last.
+ """
+
+ c = [c[0:2] for c in countries[:-1]]
+ c.sort(key=lambda x: x[1])
+ c.append(countries[-1][0:2])
+ return tuple(c)
+
+
+countries_choices = sorted_countries(COUNTRIES)
+languages_choices = map(lambda (code, name): (code, _(name)), settings.LANGUAGES) # We have to translate names
+countries_cities = dict([(c[0], c[2]) for c in COUNTRIES[:-1]])
+
+CITIES = sorted(countries_cities.values())
+
+if gis_utils.HAS_GEOIP:
+ geoip_resolver = gis_utils.GeoIP()
+else:
+ geoip_resolver = None
+ import logging
+
+ logging.warning("GeoIP library not available.")
+
+
+def get_initial_country(request=None):
+ """
+ Returns a contry code based on a client's remote address or settings.
+ """
+
+ if request:
+ country = geoip_resolver and geoip_resolver.country_code(request.META['REMOTE_ADDR'])
+ if country and country.upper() in countries_cities:
+ return country.upper()
+ return settings.DEFAULT_COUNTRY
+
+
+def get_initial_city(request=None):
+ """
+ Returns a city name based on a client's remote address or a default city from her country.
+ """
+
+ # We force unicode here so that default value in a field is a proper unicode string and not a lazy one
+ # Otherwise psycopg2 raises an "can't adapt" error: http://code.djangoproject.com/ticket/13965
+
+ if request:
+ city = geoip_resolver and geoip_resolver.city(request.META['REMOTE_ADDR'])
+ if city and city.get('city'):
+ return city['city']
+ return utils_encoding.force_unicode(countries_cities[get_initial_country(request)]) or getattr(settings,
+ 'DEFUALT_CITY',
+ None)
+ return getattr(settings, 'DEFUALT_CITY', None) or utils_encoding.force_unicode(
+ countries_cities[get_initial_country()])
+
+
+def get_initial_language(request=None):
+ """
+ Returns language code based on a request or settings.
+ """
+
+ if request:
+ return translation.get_language_from_request(request)
+ return settings.LANGUAGE_CODE
+
+
+class CountryField(fields.CharField):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('max_length', 2)
+ kwargs.setdefault('choices', countries_choices)
+ kwargs.setdefault('default', get_initial_country)
+
+ super(fields.CharField, self).__init__(*args, **kwargs)
+
+ def get_internal_type(self):
+ return "CharField"
+
+
+class CityField(fields.CharField):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('max_length', 150)
+ kwargs.setdefault('default', get_initial_city)
+
+ super(fields.CharField, self).__init__(*args, **kwargs)
+
+ def get_internal_type(self):
+ return "CharField"
+
+
+class LanguageField(fields.CharField):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault('max_length', 5)
+ kwargs.setdefault('choices', languages_choices)
+ kwargs.setdefault('default', get_initial_language)
+
+ super(fields.CharField, self).__init__(*args, **kwargs)
+
+ def get_internal_type(self):
+ return "CharField"
diff --git a/mainpage/settings.py b/mainpage/settings.py
index 59f0c807..6e018998 100644
--- a/mainpage/settings.py
+++ b/mainpage/settings.py
@@ -5,10 +5,9 @@
settings_dir = os.path.abspath(os.path.dirname(__file__))
database_file = os.path.join(settings_dir, 'db.sqlite')
-# Website requires nodewatcher, so for easier development we assume
-# it is accessible in the same directory website repository is
-nodewatcher_dir = os.path.abspath(os.path.join(settings_dir, '..', '..', 'nodewatcher', 'nodewatcher'))
-sys.path.insert(0, nodewatcher_dir)
+
+sys.path.append("/code/mainpage/")
+
# Dummy function, so that "makemessages" can find strings which should be translated.
_ = lambda s: s
@@ -20,19 +19,20 @@
# DEBUG=False and a view raises an exception, Django will e-mail these
# people with the full exception information. Each member of the tuple
# should be a tuple of (Full name, e-mail address).
-ADMINS = (
-)
+ADMINS = ()
MANAGERS = ADMINS
+DB_PASSWORD = os.environ.get('DB_PASSWORD', 'mainpage')
+
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.sqlite3', # 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME': database_file, # Or path to database file if using sqlite3.
- 'USER': '', # Not used with sqlite3.
- 'PASSWORD': '', # Not used with sqlite3.
- 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
- 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ 'ENGINE': 'django.db.backends.postgresql_psycopg2',
+ 'NAME': 'wlansi',
+ 'USER': 'wlansi_cms',
+ 'PASSWORD': DB_PASSWORD,
+ 'HOST': 'db',
+ 'PORT': '',
},
}
@@ -55,13 +55,12 @@
)
LOCALE_PATHS = (
- os.path.join(settings_dir, 'locale'),
+ "code/mainpage/locale",
)
ADMIN_LANGUAGE_CODE = 'en'
-import frontend
-GEOIP_PATH = os.path.abspath(os.path.join(os.path.dirname(frontend.__file__), '..', 'geoip'))
+GEOIP_PATH = 'libs/geoip/'
DEFAULT_COUNTRY = 'SI'
URL_VALIDATOR_USER_AGENT = 'Django'
@@ -205,9 +204,6 @@
'cmsplugin_markup_tracwiki',
# Ours are first so that we can override default templates in other apps
- 'frontend.account',
- 'frontend.dns',
- 'frontend.nodes',
'mainpage.wlansi',
'mainpage.wlansi.accounting',
'mainpage.wlansi.buynow',
@@ -294,7 +290,7 @@
LOGOUT_URL = '/admin/'
AUTHENTICATION_BACKENDS = (
- 'frontend.account.auth.ModelBackend',
+ 'django.contrib.auth.backends.ModelBackend',
)
CACHES = {
diff --git a/mainpage/settings_production.py b/mainpage/settings_production.py
index fa925932..47e96434 100644
--- a/mainpage/settings_production.py
+++ b/mainpage/settings_production.py
@@ -4,9 +4,6 @@
from .settings import *
-# Secrets are in a separate file so they are not visible in public repository
-from .secrets import *
-
DEBUG = False
TEMPLATE_DEBUG = DEBUG
@@ -16,9 +13,8 @@
MANAGERS = ADMINS
-# We set search path to include nodewatcher's schema, so we can share some
-# tables (like users) between them. The idea is that we delete users table from
-# mainpage's schema so that it is found in nodewatcher's schema.
+#DB_PASSWORD is defined in Dockerfile
+DB_PASSWORD = os.environ.get('DB_PASSWORD', 'mainpage')
DATABASES = {
'default': {
@@ -26,13 +22,13 @@
'NAME': 'wlansi',
'USER': 'wlansi_cms',
'PASSWORD': DB_PASSWORD,
- 'HOST': 'localhost',
+ 'HOST': 'db',
'PORT': '',
- 'SCHEMA_SEARCH_PATH': ('wlansi_cms', 'wlansi_nw'),
},
}
-# SECRET_KEY is in secrets
+# SECRET_KEY is defined in Dockerfile
+SECRET_KEY = os.environ.get('SECRET_KEY', 'ilikejimmyjams')
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
@@ -52,8 +48,10 @@
},
}
-# RECAPTCHA_PUBLIC_KEY is in secrets
-# RECAPTCHA_PRIVATE_KEY is in secrets
+# RECAPTCHA_PUBLIC_KEY is defined in Dockerfile
+RECAPTCHA_PUBLIC_KEY = os.environ.get('RECAPTCHA_PUBLIC_KEY')
+# RECAPTCHA_PRIVATE_KEY is defined in Dockerfile
+RECAPTCHA_PRIVATE_KEY = os.environ.get('RECAPTCHA_PRIVATE_KEY')
CMS_MARKUP_TRAC_COMPONENTS += (
'tracdashessyntax.plugin.DashesSyntaxPlugin',
@@ -99,8 +97,8 @@
if not DEBUG:
PAYPAL_TEST = DEBUG
PAYPAL_DEBUG = PAYPAL_TEST
- # PAYPAL_IDENTITY_TOKEN_PRODUCTION is in secrets
- PAYPAL_IDENTITY_TOKEN = PAYPAL_IDENTITY_TOKEN_PRODUCTION
+ # PAYPAL_IDENTITY_TOKEN is defined in Dockerfile
+ PAYPAL_IDENTITY_TOKEN = os.environ.get('PAYPAL_IDENTITY_TOKEN_PRODUCTION')
PAYPAL_RECEIVER_EMAIL = 'mitar@tnode.com'
PAYPAL_RECEIVER_EMAIL_ALIAS = 'order@wlan-si.net'
PAYPAL_RECEIVER_EMAIL_DONATION_ALIAS = 'donate@wlan-si.net'
@@ -110,3 +108,5 @@
PAYPAL_CERT_ID = 'EWMRL6RHUA6NE'
USE_HTTPS = True
+
+ALLOWED_HOSTS = ["*"]
\ No newline at end of file
diff --git a/mainpage/wlansi/context_processors.py b/mainpage/wlansi/context_processors.py
index 04f64e44..53c3e974 100644
--- a/mainpage/wlansi/context_processors.py
+++ b/mainpage/wlansi/context_processors.py
@@ -8,13 +8,16 @@ def global_vars(request):
"""
supporters_images = {}
- for supporter in foldermodels.Folder.objects.get(name=settings.SUPPORTERS_FILER_FOLDER_NAME).files.instance_of(imagemodels.Image).filter(is_public=True).order_by('name'):
- if '-color' in supporter.label:
- name = supporter.label.replace('-color', '')
- supporters_images.setdefault(name, {})['color'] = supporter
- elif '-gray' in supporter.label:
- name = supporter.label.replace('-gray', '')
- supporters_images.setdefault(name, {})['gray'] = supporter
+ try:
+ for supporter in foldermodels.Folder.objects.get(name=settings.SUPPORTERS_FILER_FOLDER_NAME).files.instance_of(imagemodels.Image).filter(is_public=True).order_by('name'):
+ if '-color' in supporter.label:
+ name = supporter.label.replace('-color', '')
+ supporters_images.setdefault(name, {})['color'] = supporter
+ elif '-gray' in supporter.label:
+ name = supporter.label.replace('-gray', '')
+ supporters_images.setdefault(name, {})['gray'] = supporter
+ except Exception, e:
+ print e
supporters = []
for name, images in supporters_images.items():
diff --git a/mainpage/wlansi/inmedia/models.py b/mainpage/wlansi/inmedia/models.py
index ed72f5b9..74ce99f6 100644
--- a/mainpage/wlansi/inmedia/models.py
+++ b/mainpage/wlansi/inmedia/models.py
@@ -6,6 +6,7 @@
from frontend.account import geo_fields
+
class InMediaEntry(models.Model):
date = models.DateField()
link = models.URLField(blank=True, help_text=_("URL of official publication, if available."))
@@ -39,6 +40,7 @@ def get_language(self):
def __unicode__(self):
return unicode(_(u"%(source)s on %(date)s" % {'source': self.source(), 'date': self.date}))
+
class InMediaLocalCopy(models.Model):
entry = models.ForeignKey(InMediaEntry, related_name='local_copies')
local_copy = file.FilerFileField(help_text=_("Because official publications often disappear, we try to make also local copies (PDFs, audio and video recordings, etc.)."))
@@ -52,6 +54,7 @@ class Meta:
def __unicode__(self):
return unicode(self.local_copy)
+
class InMediaDescription(models.Model):
entry = models.ForeignKey(InMediaEntry, related_name='descriptions')
language = geo_fields.LanguageField()
diff --git a/requirements-production-python26.txt b/requirements-production-python26.txt
deleted file mode 100644
index a20a1713..00000000
--- a/requirements-production-python26.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-importlib==1.0.2
--r requirements-production.txt
diff --git a/requirements-production.txt b/requirements-production.txt
index a2fe3226..e176e8e7 100644
--- a/requirements-production.txt
+++ b/requirements-production.txt
@@ -1,11 +1,6 @@
-GeoIP-Python==1.2.7
--e svn+http://trac-hacks.org/svn/footnotemacro/trunk@11926#egg=FootNoteMacro-dev_r11926
+-r /code/requirements.txt
+GeoIP==1.3.2
GitPython==0.3.2.RC1
--e git+https://github.com/mitar/trac-mathjax.git@e5b2bcbd8ec74685407c6fb2e71fb56cc2f47484#egg=MathJaxPlugin-dev
--e svn+http://trac-hacks.org/svn/dashessyntaxplugin/0.11@8543#egg=TracDashesSyntaxPlugin-dev_r8543
--e hg+https://bitbucket.org/kisielk/tracmathplugin@05cd705cc9eadf322d5b8395fad1ffb0a6efeab5#egg=TracMath-dev
gitdb==0.5.4
-psycopg2==2.2.1
-python-aprmd5==0.2
-M2Crypto==0.21.1
--r requirements.txt
+psycopg2==2.4.3
+M2Crypto==0.26.0
diff --git a/requirements.txt b/requirements.txt
index 37a290a4..92c42a05 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
-Django==1.4
+Django==1.4.0
Genshi==0.6
Markdown==2.1.1
-PIL==1.1.7
+Pillow==4.2.1
PyYAML==3.10
Pygments==1.5
South==0.7.5
@@ -10,16 +10,11 @@ amqplib==1.0.2
anyjson==0.3.1
async==0.6.1
chardet==1.0.1
--e git+https://github.com/wlanslovenija/cmsplugin-blog.git@0829d67e47934ab021206661ad5df7e7e1573b89#egg=cmsplugin_blog-dev
--e git+https://github.com/maccesch/cmsplugin-contact.git@ea95740655582faf603cb2f0f772f3600f952a6b#egg=cmsplugin_contact-dev
--e git+https://github.com/stefanfoulis/cmsplugin-filer.git@9f2e5959c25b849ba64d4a6be10d6ccd7278e050#egg=cmsplugin_filer-dev
cmsplugin-markup==0.2.2
cmsplugin-markup-tracwiki==0.2.2
-distribute==0.6.27
+distribute==0.7.3
django-appconf==0.5
django-classy-tags==0.3.4.1
--e git+https://github.com/mitar/django-cms.git@0bcf0409d5a052f136850cd03f6b54149a3983c5#egg=django_cms-dev
--e git+https://github.com/mitar/django-filer.git@d9917b1458c5abd41f47bc98c56d197d4ccd6fa0#egg=django_filer-dev
django-missing==0.1.11
django-mptt==0.5.2
django-paypal==0.1.2
@@ -46,7 +41,18 @@ python-dateutil==1.5
python-memcached==1.48
pytz==2012c
recaptcha-client==1.0.6
--e git+https://github.com/wlanslovenija/simple-translation.git@94c5e5639532411e070e9746c0ebd802e142b208#egg=simple_translation-dev
smmap==0.8.2
textile==2.1.5
wsgiref==0.1.2
+uwsgi==2.0.15
+svn+https://trac-hacks.org/svn/footnotemacro/trunk/#egg=tracfootnotemacro
+git+https://github.com/mitar/trac-mathjax.git@e5b2bcbd8ec74685407c6fb2e71fb56cc2f47484#egg=mathjaxplugin
+svn+https://trac-hacks.org/svn/dashessyntaxplugin/0.11/#egg=TracDashesSyntaxPlugin
+hg+https://bitbucket.org/kisielk/tracmathplugin#egg=tracmath
+git+https://github.com/herzbube/python-aprmd5.git#egg=python-aprmd5
+git+https://github.com/maccesch/cmsplugin-contact.git@ea95740655582faf603cb2f0f772f3600f952a6b#egg=cmsplugin-contact
+git+https://github.com/stefanfoulis/cmsplugin-filer.git@9f2e5959c25b849ba64d4a6be10d6ccd7278e050#egg=cmsplugin_filer
+git+https://github.com/mitar/django-cms.git@0bcf0409d5a052f136850cd03f6b54149a3983c5#egg=django_cms
+git+https://github.com/mitar/django-filer.git#egg=django_filer
+git+https://github.com/wlanslovenija/simple-translation.git@94c5e5639532411e070e9746c0ebd802e142b208#egg=simple_translation
+git+https://github.com/wlanslovenija/cmsplugin-blog.git@0829d67e47934ab021206661ad5df7e7e1573b89#egg=cmsplugin_blog
diff --git a/scripts/docker-init-db b/scripts/docker-init-db
new file mode 100755
index 00000000..a40e5b96
--- /dev/null
+++ b/scripts/docker-init-db
@@ -0,0 +1,6 @@
+#!/bin/bash
+su - postgres
+scripts/docker-wait-pgsql
+psql -d template1 -c 'create extension ip4r;'
+psql --command "CREATE USER wlansi_cms WITH SUPERUSER PASSWORD 'mainpage';"
+createdb -O wlansi_cms wlansi
diff --git a/scripts/docker-run b/scripts/docker-run
new file mode 100755
index 00000000..cecd20c3
--- /dev/null
+++ b/scripts/docker-run
@@ -0,0 +1,2 @@
+#!/bin/bash
+exec /bin/bash -i -c "$*"
\ No newline at end of file
diff --git a/scripts/docker-run-db b/scripts/docker-run-db
new file mode 100755
index 00000000..a9bf588e
--- /dev/null
+++ b/scripts/docker-run-db
@@ -0,0 +1 @@
+#!/bin/bash
diff --git a/scripts/docker-wait-pgsql b/scripts/docker-wait-pgsql
new file mode 100755
index 00000000..c0acc349
--- /dev/null
+++ b/scripts/docker-wait-pgsql
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+sleep 30s
\ No newline at end of file
diff --git a/scripts/migrate.py b/scripts/migrate.py
new file mode 100755
index 00000000..ddd164b5
--- /dev/null
+++ b/scripts/migrate.py
@@ -0,0 +1,47 @@
+import os, subprocess, tempfile, urllib, tarfile, sqlite3
+
+root = os.path.join(os.path.dirname(__file__), '..')
+
+manage_script = os.path.abspath(os.path.join(root, 'manage.py'))
+database_file = os.path.abspath(os.path.join(root, 'mainpage', 'db.sqlite'))
+
+print "\nSetting up the database:\n"
+if os.path.isfile(database_file):
+ print "Removing old database.\n"
+ os.remove(database_file)
+
+subprocess.check_call(('python', manage_script, 'syncdb', '--noinput'))
+subprocess.check_call(('python', manage_script, 'migrate'))
+subprocess.check_call(('python', manage_script, 'reset', '--noinput', 'contenttypes'))
+
+print "\nDownloading and importing database dump:\n"
+tempFile = tempfile.NamedTemporaryFile(delete=False)
+webFile = urllib.urlopen('http://bindist.wlan-si.net/data/dumpcms.yaml.bz2')
+tempFile.write(webFile.read())
+webFile.close()
+tempFile.close()
+os.rename(tempFile.name, tempFile.name + '.yaml.bz2')
+subprocess.check_call(('python', manage_script, 'loaddata', tempFile.name))
+os.remove(tempFile.name + '.yaml.bz2')
+
+(filename, _) = urllib.urlretrieve('http://bindist.wlan-si.net/data/dumpcms-nodewatcher.tar.bz2')
+file = tarfile.open(filename)
+file.extract('data.json')
+subprocess.check_call(('python', manage_script, 'loaddata', 'data.json'))
+os.remove('data.json')
+
+connection = sqlite3.connect(database_file)
+cursor = connection.cursor()
+cursor.execute("""UPDATE cmsplugin_blog_entrytitle SET author_id=1""")
+connection.commit()
+cursor.close()
+
+print "\nPreparing directories."
+
+for path in (('media', 'files'), ('media', 'thumbnails'), ('smedia', 'files'), ('smedia', 'thumbnails')):
+ try:
+ os.makedirs(os.path.join(root, 'mainpage', *path))
+ except OSError:
+ pass
+
+print "\nAll done!"
\ No newline at end of file