forked from gergely/calendar-social
Compare commits
1 Commits
test-cover
...
vagrant
Author | SHA1 | Date | |
---|---|---|---|
60ad2c7ae2 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -4,5 +4,5 @@ __pycache__/
|
||||
/calsocial/translations/*/LC_MESSAGES/*.mo
|
||||
/.pytest_cache/
|
||||
/.env
|
||||
/.coverage
|
||||
/htmlcov/
|
||||
/.vagrant/
|
||||
/ansible/*.retry
|
||||
|
1
Pipfile
1
Pipfile
@@ -18,7 +18,6 @@ flask-caching = "*"
|
||||
[dev-packages]
|
||||
pylint = "*"
|
||||
pytest = "*"
|
||||
pytest-cov = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
|
66
Pipfile.lock
generated
66
Pipfile.lock
generated
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "01a306fc25c75731af3fcf119a20d92c24fe5be9ddd8be2901b830df10bfb294"
|
||||
"sha256": "e4313bc9baef5cb187176951d45094fe1de4ccba0d15ab58efbac21b6434f255"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@@ -284,10 +284,10 @@
|
||||
"develop": {
|
||||
"astroid": {
|
||||
"hashes": [
|
||||
"sha256:0a0c484279a5f08c9bcedd6fa9b42e378866a7dcc695206b92d59dc9f2d9760d",
|
||||
"sha256:218e36cf8d98a42f16214e8670819ce307fa707d1dcf7f9af84c7aede1febc7f"
|
||||
"sha256:8704779744963d56a2625ec2949eb150bd499fc099510161ddbb2b64e2d98138",
|
||||
"sha256:add3fd690e7c1fe92436d17be461feeaa173e6f33e0789734310334da0f30027"
|
||||
],
|
||||
"version": "==2.0.1"
|
||||
"version": "==2.0"
|
||||
},
|
||||
"atomicwrites": {
|
||||
"hashes": [
|
||||
@@ -303,50 +303,6 @@
|
||||
],
|
||||
"version": "==18.1.0"
|
||||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
"sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba",
|
||||
"sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed",
|
||||
"sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a",
|
||||
"sha256:10a46017fef60e16694a30627319f38a2b9b52e90182dddb6e37dcdab0f4bf95",
|
||||
"sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd",
|
||||
"sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640",
|
||||
"sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2",
|
||||
"sha256:23d341cdd4a0371820eb2b0bd6b88f5003a7438bbedb33688cd33b8eae59affd",
|
||||
"sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162",
|
||||
"sha256:2a5b73210bad5279ddb558d9a2bfedc7f4bf6ad7f3c988641d83c40293deaec1",
|
||||
"sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508",
|
||||
"sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249",
|
||||
"sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694",
|
||||
"sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a",
|
||||
"sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287",
|
||||
"sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1",
|
||||
"sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000",
|
||||
"sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1",
|
||||
"sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e",
|
||||
"sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5",
|
||||
"sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062",
|
||||
"sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba",
|
||||
"sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc",
|
||||
"sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc",
|
||||
"sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99",
|
||||
"sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653",
|
||||
"sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c",
|
||||
"sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558",
|
||||
"sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f",
|
||||
"sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4",
|
||||
"sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91",
|
||||
"sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d",
|
||||
"sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9",
|
||||
"sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd",
|
||||
"sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d",
|
||||
"sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6",
|
||||
"sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77",
|
||||
"sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80",
|
||||
"sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e"
|
||||
],
|
||||
"version": "==4.5.1"
|
||||
},
|
||||
"isort": {
|
||||
"hashes": [
|
||||
"sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af",
|
||||
@@ -421,11 +377,11 @@
|
||||
},
|
||||
"pylint": {
|
||||
"hashes": [
|
||||
"sha256:2c90a24bee8fae22ac98061c896e61f45c5b73c2e0511a4bf53f99ba56e90434",
|
||||
"sha256:454532779425098969b8f54ab0f056000b883909f69d05905ea114df886e3251"
|
||||
"sha256:248a7b19138b22e6390cba71adc0cb03ac6dd75a25d3544f03ea1728fa20e8f4",
|
||||
"sha256:9cd70527ef3b099543eeabeb5c80ff325d86b477aa2b3d49e264e12d12153bc8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.0.1"
|
||||
"version": "==2.0.0"
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
@@ -435,14 +391,6 @@
|
||||
"index": "pypi",
|
||||
"version": "==3.6.3"
|
||||
},
|
||||
"pytest-cov": {
|
||||
"hashes": [
|
||||
"sha256:03aa752cf11db41d281ea1d807d954c4eda35cfa1b21d6971966cc041bbf6e2d",
|
||||
"sha256:890fe5565400902b0c78b5357004aab1c814115894f4f21370e2433256a3eeec"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.5.1"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
|
||||
|
74
Vagrantfile
vendored
Normal file
74
Vagrantfile
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
# -*- mode: ruby -*-
|
||||
# vi: set ft=ruby :
|
||||
|
||||
# All Vagrant configuration is done below. The "2" in Vagrant.configure
|
||||
# configures the configuration version (we support older styles for
|
||||
# backwards compatibility). Please don't change it unless you know what
|
||||
# you're doing.
|
||||
Vagrant.configure("2") do |config|
|
||||
# The most common configuration options are documented and commented below.
|
||||
# For a complete reference, please see the online documentation at
|
||||
# https://docs.vagrantup.com.
|
||||
|
||||
# Every Vagrant development environment requires a box. You can search for
|
||||
# boxes at https://vagrantcloud.com/search.
|
||||
config.vm.box = 'fedora/28-cloud-base'
|
||||
|
||||
# Disable automatic box update checking. If you disable this, then
|
||||
# boxes will only be checked for updates when the user runs
|
||||
# `vagrant box outdated`. This is not recommended.
|
||||
# config.vm.box_check_update = false
|
||||
|
||||
# Create a forwarded port mapping which allows access to a specific port
|
||||
# within the machine from a port on the host machine. In the example below,
|
||||
# accessing "localhost:8080" will access port 80 on the guest machine.
|
||||
# NOTE: This will enable public access to the opened port
|
||||
config.vm.network "forwarded_port", guest: 80, host: 8080
|
||||
|
||||
# Create a forwarded port mapping which allows access to a specific port
|
||||
# within the machine from a port on the host machine and only allow access
|
||||
# via 127.0.0.1 to disable public access
|
||||
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
|
||||
|
||||
# Create a private network, which allows host-only access to the machine
|
||||
# using a specific IP.
|
||||
# config.vm.network "private_network", ip: "192.168.33.10"
|
||||
|
||||
# Create a public network, which generally matched to bridged network.
|
||||
# Bridged networks make the machine appear as another physical device on
|
||||
# your network.
|
||||
# config.vm.network "public_network"
|
||||
|
||||
config.vm.synced_folder './', '/vagrant', type: 'sshfs'
|
||||
|
||||
# Share an additional folder to the guest VM. The first argument is
|
||||
# the path on the host to the actual folder. The second argument is
|
||||
# the path on the guest to mount the folder. And the optional third
|
||||
# argument is a set of non-required options.
|
||||
# config.vm.synced_folder "../data", "/vagrant_data"
|
||||
|
||||
# Provider-specific configuration so you can fine-tune various
|
||||
# backing providers for Vagrant. These expose provider-specific options.
|
||||
# Example for VirtualBox:
|
||||
#
|
||||
# config.vm.provider "virtualbox" do |vb|
|
||||
# # Display the VirtualBox GUI when booting the machine
|
||||
# vb.gui = true
|
||||
#
|
||||
# # Customize the amount of memory on the VM:
|
||||
# vb.memory = "1024"
|
||||
# end
|
||||
#
|
||||
# View the documentation for the provider you are using for more
|
||||
# information on available options.
|
||||
|
||||
# Enable provisioning with a shell script. Additional provisioners such as
|
||||
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
|
||||
# documentation for more information about their specific syntax and use.
|
||||
config.vm.provision "ansible_local" do |ansible|
|
||||
ansible.compatibility_mode = '2.0'
|
||||
ansible.install = true
|
||||
ansible.provisioning_path = '/vagrant/ansible'
|
||||
ansible.playbook = 'dev.yml'
|
||||
end
|
||||
end
|
23
ansible/dev.yml
Normal file
23
ansible/dev.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
|
||||
- name: Configuration for local development on Vagrant
|
||||
hosts: all
|
||||
become: yes
|
||||
vars:
|
||||
user_name: vagrant
|
||||
group_name: vagrant
|
||||
|
||||
roles:
|
||||
- common
|
||||
- python
|
||||
- role: gunicorn
|
||||
autostart: false
|
||||
enabled: false
|
||||
- role: nginx
|
||||
use_ssl: false
|
||||
enabled: false
|
||||
|
||||
tasks:
|
||||
- name: Allow virtualenv python to bind to port 80
|
||||
command: setcap cap_net_bind_service=ep /usr/bin/python3.6
|
||||
changed_when: false
|
12
ansible/install.sh
Normal file
12
ansible/install.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
if [ ! -f /etc/ansible/hosts ]
|
||||
then
|
||||
echo "Installing Ansible..."
|
||||
sudo dnf remove ansible
|
||||
sudo dnf install ansible-python3
|
||||
|
||||
printf 'localhost\n' | sudo tee /etc/ansible/hosts > /dev/null
|
||||
fi
|
||||
|
||||
echo "Ansible is installed."
|
8
ansible/roles/common/tasks/main.yml
Normal file
8
ansible/roles/common/tasks/main.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
|
||||
- name: Install required packages
|
||||
dnf:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- libselinux-python
|
10
ansible/roles/common/vars/main.yml
Normal file
10
ansible/roles/common/vars/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
|
||||
# Project name
|
||||
project_name: calendar.social
|
||||
|
||||
# Project path
|
||||
project_path: /vagrant
|
||||
|
||||
# Flask app path
|
||||
application_path: /vagrant/app
|
56
ansible/roles/gunicorn/tasks/main.yml
Normal file
56
ansible/roles/gunicorn/tasks/main.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
|
||||
- name: Install Supervisor
|
||||
dnf:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- supervisor
|
||||
|
||||
- name: Start supervisord
|
||||
service:
|
||||
name: supervisord
|
||||
state: restarted
|
||||
|
||||
- name: Create the Gunicorn config directory
|
||||
file:
|
||||
path: /etc/gunicorn
|
||||
state: directory
|
||||
owner: "{{ user_name }}"
|
||||
group: "{{ group_name }}"
|
||||
mode: 0700
|
||||
|
||||
- name: Create the Gunicorn config file in /etc/gunicorn
|
||||
template:
|
||||
src: gunicorn.conf.j2
|
||||
dest: /etc/gunicorn/gunicorn.conf
|
||||
|
||||
- name: Create the Gunicorn log directory
|
||||
file:
|
||||
path: /var/log/gunicorn
|
||||
state: directory
|
||||
owner: "{{ user_name }}"
|
||||
group: "{{ group_name }}"
|
||||
mode: 0700
|
||||
|
||||
- name: Create the Supervisor config file for Gunicorn
|
||||
template:
|
||||
src: supervisor.conf.j2
|
||||
dest: /etc/supervisord.d/gunicorn.ini
|
||||
|
||||
- name: Re-read the Supervisor config files
|
||||
supervisorctl:
|
||||
name: gunicorn
|
||||
state: present
|
||||
|
||||
- name: Start Gunicorn with supervisord
|
||||
supervisorctl:
|
||||
name: gunicorn
|
||||
state: restarted
|
||||
when: enabled
|
||||
|
||||
- name: Stop Gunicorn for local dev
|
||||
supervisorctl:
|
||||
name: gunicorn
|
||||
state: stopped
|
||||
when: not enabled
|
9
ansible/roles/gunicorn/templates/gunicorn.conf.j2
Normal file
9
ansible/roles/gunicorn/templates/gunicorn.conf.j2
Normal file
@@ -0,0 +1,9 @@
|
||||
import multiprocessing
|
||||
|
||||
workers = multiprocessing.cpu_count() * 2 + 1
|
||||
proc_name = 'gunicorn'
|
||||
bind = '127.0.0.1:8000'
|
||||
errorlog = '/var/log/gunicorn/gunicorn-error.log'
|
||||
accesslog = '/var/log/gunicorn/gunicorn-access.log'
|
||||
loglevel = 'warning'
|
||||
timeout = 60
|
8
ansible/roles/gunicorn/templates/supervisor.conf.j2
Normal file
8
ansible/roles/gunicorn/templates/supervisor.conf.j2
Normal file
@@ -0,0 +1,8 @@
|
||||
[program:gunicorn]
|
||||
command=pipenv run gunicorn wsgi:app -c /etc/gunicorn/gunicorn.conf --pythonpath {{ application_path }}
|
||||
directory={{ application_path }}
|
||||
user={{ user_name }}
|
||||
group={{ group_name }}
|
||||
autorestart=true
|
||||
autostart={{ autostart | bool | lower }}
|
||||
redirect_stderr=true
|
11
ansible/roles/nginx/handlers/main.yml
Normal file
11
ansible/roles/nginx/handlers/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
|
||||
- name: Reload Nginx
|
||||
service:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
|
||||
- name: Stop Nginx
|
||||
service:
|
||||
name: nginx
|
||||
state: stopped
|
42
ansible/roles/nginx/tasks/main.yml
Normal file
42
ansible/roles/nginx/tasks/main.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
|
||||
- name: Install Nginx
|
||||
dnf:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- nginx
|
||||
|
||||
- name: Create the Nginx configuration file for SSL
|
||||
template:
|
||||
src: site-ssl.conf.j2
|
||||
dest: /etc/nginx/conf.d/{{ project_name }}-ssl.conf
|
||||
when: use_ssl
|
||||
notify: Reload Nginx
|
||||
|
||||
- name: Create the Nginx configuration file (non-SSL)
|
||||
template:
|
||||
src: site.conf.j2
|
||||
dest: /etc/nginx/conf.d/{{ project_name }}.conf
|
||||
when: not use_ssl
|
||||
notify: Reload Nginx
|
||||
|
||||
- name: Ensure that the default site is removed
|
||||
file:
|
||||
path: /etc/nginx/conf.d/default.conf
|
||||
state: absent
|
||||
|
||||
- name: Ensure Nginx service is started, enable service on restart
|
||||
service:
|
||||
name: nginx
|
||||
state: restarted
|
||||
enabled: yes
|
||||
when: enabled
|
||||
|
||||
- name: Stop nginx for local dev, disable service
|
||||
service:
|
||||
name: nginx
|
||||
state: stopped
|
||||
enabled: no
|
||||
notify: Stop Nginx
|
||||
when: not enabled
|
41
ansible/roles/nginx/templates/site-ssl.conf.j2
Normal file
41
ansible/roles/nginx/templates/site-ssl.conf.j2
Normal file
@@ -0,0 +1,41 @@
|
||||
upstream appserver {
|
||||
server localhost:8000 fail_timeout=0;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl deferred;
|
||||
server_name {{ host_name }};
|
||||
|
||||
ssl_certificate {{ home_path }}/{{ project_name }}.crt;
|
||||
ssl_certificate_key {{ home_path }}/{{ project_name }}.key;
|
||||
ssl_session_cache shared:SSL:32m;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
access_log /var/log/nginx/{{ project_name }}.access.log;
|
||||
error_log /var/log/nginx/{{ project_name }}.error.log info;
|
||||
|
||||
keepalive_timeout 5;
|
||||
|
||||
location /static {
|
||||
alias {{ project_path }}/static;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
proxy_read_timeout 180s;
|
||||
|
||||
if (!-f $request_filename) {
|
||||
proxy_pass http://appserver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
29
ansible/roles/nginx/templates/site.conf.j2
Normal file
29
ansible/roles/nginx/templates/site.conf.j2
Normal file
@@ -0,0 +1,29 @@
|
||||
upstream appserver {
|
||||
server localhost:8000 fail_timeout=0;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name {{ host_name }};
|
||||
|
||||
access_log /var/log/nginx/{{ project_name }}.access.log;
|
||||
error_log /var/log/nginx/{{ project_name }}.error.log info;
|
||||
|
||||
keepalive_timeout 5;
|
||||
|
||||
location /static {
|
||||
alias {{ project_path }}/static;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
proxy_read_timeout 180s;
|
||||
|
||||
if (-f $request_filename) {
|
||||
proxy_pass http://appserver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
3
ansible/roles/nginx/vars/main.yml
Normal file
3
ansible/roles/nginx/vars/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
|
||||
host_name: calendar-social.local
|
22
ansible/roles/python/tasks/main.yml
Normal file
22
ansible/roles/python/tasks/main.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
|
||||
- name: Install common python packages
|
||||
dnf:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- pipenv
|
||||
|
||||
- name: Delete Python cache files
|
||||
command: find . -type d -name __pycache__ -exec rm -r {} +
|
||||
args:
|
||||
chdir: "{{ project_path }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Install packages
|
||||
command: pipenv install --python=/usr/bin/python3.6m --three --system --deploy
|
||||
|
||||
- name: Install development related packages
|
||||
command: pipenv install --python=/usr/bin/python3.6m --three --system --deploy --dev
|
||||
args:
|
||||
chdir: "{{ project_path }}"
|
@@ -107,7 +107,7 @@ class CalendarSocialApp(Flask, RoutedMixin):
|
||||
|
||||
if current_user.is_authenticated and \
|
||||
not current_user.profile and \
|
||||
request.endpoint != 'account.first_steps':
|
||||
request.endpoint != 'first_steps':
|
||||
return redirect(url_for('account.first_steps'))
|
||||
|
||||
return None
|
||||
|
@@ -6,4 +6,4 @@ from calsocial import CalendarSocialApp
|
||||
|
||||
app = CalendarSocialApp('calsocial')
|
||||
|
||||
app.run()
|
||||
app.run(host='0.0.0.0', port=80)
|
||||
|
@@ -46,7 +46,7 @@ class AccountBlueprint(Blueprint, RoutedMixin):
|
||||
app.register_blueprint(self, url_prefix=url_prefix)
|
||||
|
||||
@staticmethod
|
||||
@RoutedMixin.route('/register', methods=['POST', 'GET'])
|
||||
@RoutedMixin.route('/register')
|
||||
def register_account():
|
||||
"""View for user registration
|
||||
|
||||
|
@@ -21,7 +21,7 @@ from datetime import timedelta
|
||||
import pickle
|
||||
from uuid import uuid4
|
||||
|
||||
from flask import has_request_context, request as flask_request, session as flask_session
|
||||
from flask import current_app, has_request_context, request, session
|
||||
from flask.sessions import SessionInterface, SessionMixin
|
||||
from flask_caching import Cache
|
||||
from werkzeug.datastructures import CallbackDict
|
||||
@@ -46,7 +46,7 @@ class CachedSession(CallbackDict, SessionMixin): # pylint: disable=too-many-anc
|
||||
self.__modifying = True
|
||||
|
||||
if has_request_context():
|
||||
self['ip'] = flask_request.remote_addr
|
||||
self['ip'] = request.remote_addr
|
||||
|
||||
self.modified = True
|
||||
|
||||
@@ -59,9 +59,6 @@ class CachedSession(CallbackDict, SessionMixin): # pylint: disable=too-many-anc
|
||||
|
||||
@property
|
||||
def user(self):
|
||||
"""The user this session belongs to
|
||||
"""
|
||||
|
||||
from calsocial.models import User
|
||||
|
||||
if 'user_id' not in self:
|
||||
@@ -90,11 +87,11 @@ class CachedSessionInterface(SessionInterface):
|
||||
return str(uuid4())
|
||||
|
||||
@staticmethod
|
||||
def get_cache_expiration_time(app, sess):
|
||||
def get_cache_expiration_time(app, session):
|
||||
"""Get the expiration time of the cache entry
|
||||
"""
|
||||
|
||||
if sess.permanent:
|
||||
if session.permanent:
|
||||
return app.permanent_session_lifetime
|
||||
|
||||
return timedelta(days=1)
|
||||
@@ -150,10 +147,7 @@ class CachedSessionInterface(SessionInterface):
|
||||
domain=domain)
|
||||
|
||||
def delete_session(self, sid):
|
||||
"""Delete the session with ``sid`` as its session ID
|
||||
"""
|
||||
|
||||
if has_request_context() and flask_session.sid == sid:
|
||||
if has_request_context() and session.sid == sid:
|
||||
raise ValueError('Will not delete the current session')
|
||||
|
||||
cache.delete(self.prefix + sid)
|
||||
|
@@ -219,7 +219,7 @@ class GregorianCalendar(CalendarSystem):
|
||||
end_timestamp = start_timestamp + timedelta(days=1)
|
||||
|
||||
events = events.filter((Event.start_time <= end_timestamp) &
|
||||
(Event.end_time >= start_timestamp)) \
|
||||
(Event.end_time >= start_timestamp)) \
|
||||
.order_by('start_time', 'end_time')
|
||||
|
||||
if user is None:
|
||||
|
@@ -89,9 +89,6 @@ class RoutedMixin:
|
||||
"""
|
||||
|
||||
def register_routes(self):
|
||||
"""Register all routes that were marked with :meth:`route`
|
||||
"""
|
||||
|
||||
for attr_name in self.__dir__():
|
||||
attr = getattr(self, attr_name)
|
||||
|
||||
|
@@ -17,8 +17,6 @@
|
||||
"""Helper functions and fixtures for testing
|
||||
"""
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
import pytest
|
||||
|
||||
import calsocial
|
||||
@@ -72,22 +70,3 @@ def database():
|
||||
yield db
|
||||
|
||||
db.drop_all()
|
||||
|
||||
|
||||
@contextmanager
|
||||
def alter_config(app, **kwargs):
|
||||
saved = {}
|
||||
|
||||
for key, value in kwargs.items():
|
||||
if key in app.config:
|
||||
saved[key] = app.config[key]
|
||||
|
||||
app.config[key] = value
|
||||
|
||||
yield
|
||||
|
||||
for key, value in kwargs.items():
|
||||
if key in saved:
|
||||
app.config[key] = saved[key]
|
||||
else:
|
||||
del app.config[key]
|
||||
|
@@ -25,4 +25,4 @@ def test_index_no_login(client):
|
||||
"""
|
||||
|
||||
page = client.get('/')
|
||||
assert b'Peek inside' in page.data
|
||||
assert b'Welcome to Calendar.social' in page.data
|
||||
|
@@ -23,6 +23,14 @@ from calsocial.models import db, User
|
||||
from helpers import client, login
|
||||
|
||||
|
||||
def test_index_no_login(client):
|
||||
"""Test the main page without logging in
|
||||
"""
|
||||
|
||||
page = client.get('/')
|
||||
assert b'Welcome to Calendar.social' in page.data
|
||||
|
||||
|
||||
def test_login_invalid_user(client):
|
||||
"""Test logging in with a non-existing user
|
||||
"""
|
||||
@@ -73,4 +81,4 @@ def test_login_first_steps(client):
|
||||
assert page.location == 'http://localhost/'
|
||||
|
||||
page = client.get('/')
|
||||
assert page.location == 'http://localhost/accounts/first-steps'
|
||||
assert page.location == 'http://localhost/first-steps'
|
||||
|
@@ -20,28 +20,28 @@
|
||||
import calsocial
|
||||
from calsocial.models import db, User
|
||||
|
||||
from helpers import alter_config, client
|
||||
from helpers import client
|
||||
|
||||
|
||||
def test_register_page(client):
|
||||
"""Test the registration page
|
||||
"""
|
||||
|
||||
page = client.get('/accounts/register')
|
||||
page = client.get('/register')
|
||||
assert b'Register</button>' in page.data
|
||||
|
||||
def test_register_post_empty(client):
|
||||
"""Test sending empty registration data
|
||||
"""
|
||||
|
||||
page = client.post('/accounts/register', data={})
|
||||
page = client.post('/register', data={})
|
||||
assert b'This field is required' in page.data
|
||||
|
||||
def test_register_invalid_email(client):
|
||||
"""Test sending an invalid email address
|
||||
"""
|
||||
|
||||
page = client.post('/accounts/register', data={
|
||||
page = client.post('/register', data={
|
||||
'username': 'test',
|
||||
'email': 'test',
|
||||
'password': 'password',
|
||||
@@ -53,7 +53,7 @@ def test_register_password_mismatch(client):
|
||||
"""Test sending different password for registration
|
||||
"""
|
||||
|
||||
page = client.post('/accounts/register', data={
|
||||
page = client.post('/register', data={
|
||||
'username': 'test',
|
||||
'email': 'test@example.com',
|
||||
'password': 'password',
|
||||
@@ -65,12 +65,13 @@ def test_register(client):
|
||||
"""Test user registration
|
||||
"""
|
||||
|
||||
page = client.post('/accounts/register', data={
|
||||
page = client.post('/register', data={
|
||||
'username': 'test',
|
||||
'email': 'test@example.com',
|
||||
'password': 'password',
|
||||
'password_retype': 'password',
|
||||
})
|
||||
print(page.data)
|
||||
assert page.status_code == 302
|
||||
assert page.location == 'http://localhost/'
|
||||
|
||||
@@ -89,7 +90,7 @@ def test_register_existing_username(client):
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
|
||||
page = client.post('/accounts/register', data={
|
||||
page = client.post('/register', data={
|
||||
'username': 'test',
|
||||
'email': 'test2@example.com',
|
||||
'password': 'password',
|
||||
@@ -106,16 +107,10 @@ def test_register_existing_email(client):
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
|
||||
page = client.post('/accounts/register', data={
|
||||
page = client.post('/register', data={
|
||||
'username': 'tester',
|
||||
'email': 'test@example.com',
|
||||
'password': 'password',
|
||||
'password_retype': 'password',
|
||||
})
|
||||
assert b'This email address can not be used' in page.data
|
||||
|
||||
|
||||
def test_registration_disabled(client):
|
||||
with alter_config(calsocial.app, REGISTRATION_ENABLED=False):
|
||||
page = client.get('/accounts/register')
|
||||
assert b'Registration is disabled' in page.data
|
||||
|
Reference in New Issue
Block a user