diff --git a/.gitignore b/.gitignore index 04be071..8f6a93c 100644 --- a/.gitignore +++ b/.gitignore @@ -96,5 +96,11 @@ ENV/ *.rdb *.swp +collected_static/ + # For hide SECRET_KEY secret.json +pw.txt +nginx/local_nginx.conf +.prepared + diff --git a/.travis.yml b/.travis.yml index 566a1ab..00a4994 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,6 @@ install: - "pip install flake8" script: - - "python secret_key_gen.py" - "python manage.py migrate" + - "python manage.py createsuperuserauto" - "flake8 --count --ignore=E501,E302,W293,F841 --exclude ./docs,./manage_room/diff_match_patch,./manage_room/migrations,./manage_chat/migrations,./manage.py" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5914923 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +OS := $(shell uname) + +default: start +.PHONY: start stop uninstall + + +include Makefile.deps +include Makefile.prepare + + +start: \.prepared deps-start + python3 manage.py runworker & + daphne -b 0.0.0.0 -p 8001 coding_night_live.asgi:channel_layer & + + +stop: deps-stop + -killall -9 daphne + -killall -9 python3 + -killall -9 python # FIXME: daphne at MAC OS + + +uninstall: stop clean deps-uninstall diff --git a/Makefile.deps b/Makefile.deps new file mode 100644 index 0000000..151d3cb --- /dev/null +++ b/Makefile.deps @@ -0,0 +1,77 @@ +.PHONY: sudo deps-install deps-uninstall deps-start deps-stop prepare-nginx + + +sudo: + sudo -v + + +deps-install: sudo +ifeq ($(OS),Linux) + sudo apt-get install redis-server + sudo apt-get install nginx +else ifeq ($(OS),Darwin) + brew list redis > /dev/null || brew install redis --build-from-source # FIXME: Homebrew/homebrew-core#11134 + brew list nginx > /dev/null || brew install nginx +else + echo 'ACITON REQUIRED) Need to install redis and nginx before this.' +endif + + +deps-uninstall: sudo +ifeq ($(OS),Linux) + # TODO + echo 'ACITON REQUIRED) Need to uninstall redis and nginx after this.' +else ifeq ($(OS),Darwin) + -brew list redis > /dev/null && brew uninstall redis + -brew list nginx > /dev/null && brew uninstall nginx +else + echo 'ACITON REQUIRED) Need to uninstall redis and nginx after this.' +endif + + +deps-start: sudo +ifeq ($(OS),Linux) + sudo service redis-server start +else ifeq ($(OS),Darwin) + brew services run redis +else + sudo redis-server & +endif +ifeq ($(OS),Linux) + sudo service nginx start +else + sudo nginx & +endif + + +deps-stop: sudo +ifeq ($(OS),Linux) + sudo service nginx stop +else ifeq ($(OS),Darwin) + -sudo killall -9 'nginx: master process nginx' + -sudo killall -9 'nginx: worker process' + -sudo killall -9 nginx +else + -sudo killall -9 'nginx: master process nginx' + -sudo killall -9 'nginx: worker process' + -sudo killall -9 nginx +endif +ifeq ($(OS),Linux) + -sudo service redis-server stop +else ifeq ($(OS),Darwin) + -brew services stop redis +else + -sudo killall -9 redis-server +endif + + +prepare-nginx: sudo nginx/local_nginx.conf +ifeq ($(OS),Linux) + sudo rm -f /etc/nginx/sites-enabled/local_nginx.conf + sudo ln -s `pwd`/nginx/local_nginx.conf /etc/nginx/sites-enabled/ +else ifeq ($(OS),Darwin) + rm -f /usr/local/etc/nginx/servers/local_nginx.conf + ln -s `pwd`/nginx/local_nginx.conf /usr/local/etc/nginx/servers/ +else + # FIXME ln -s `pwd`/nginx/local_nginx.conf /usr/local/etc/nginx/servers/ +endif \ No newline at end of file diff --git a/Makefile.prepare b/Makefile.prepare new file mode 100644 index 0000000..8d0c756 --- /dev/null +++ b/Makefile.prepare @@ -0,0 +1,36 @@ +.PHONY: prepare clean + +db.sqlite3: + python3 manage.py migrate + +pw.txt: db.sqlite3 + python3 manage.py createsuperuserauto + +collected_static/: + yes yes | python3 manage.py collectstatic + +secret.json: db.sqlite3 + python3 manage.py autodeploy + +nginx/local_nginx.conf: secret.json + python3 manage.py nginxconfgenerator > nginx/local_nginx.conf + +prepare \.prepared: \ + deps-install\ + db.sqlite3\ + pw.txt\ + collected_static/\ + secret.json\ + nginx/local_nginx.conf\ + prepare-nginx\ + + touch .prepared + +clean: + -rm \ + secret.json\ + db.sqlite3\ + pw.txt\ + nginx/local_nginx.conf\ + .prepared\ + -rm -r collected_static diff --git a/coding_night_live/management/commands/autodeploy.py b/coding_night_live/management/commands/autodeploy.py new file mode 100644 index 0000000..984bc25 --- /dev/null +++ b/coding_night_live/management/commands/autodeploy.py @@ -0,0 +1,88 @@ +import json + +from django.core.management.base import BaseCommand +from django.contrib.sites.models import Site +from django.db.utils import OperationalError +from django.utils.crypto import get_random_string + +from allauth.socialaccount.models import SocialApp + + +class AutoDeployException(Exception): + pass + + +class AutoDeploySecretNotFound(AutoDeployException): + pass + + +class AutoDeployDatabaseNotPrepared(AutoDeployException): + @staticmethod + def checker(suspiciousFunc): + def _runtime_checker(*args, **kwargs): + try: + return suspiciousFunc(*args, **kwargs) + except OperationalError: + raise AutoDeployDatabaseNotPrepared('ACTION REQUIRED) RUN `python manage.py migrate` FIRST!') + return _runtime_checker + + +def loadSecret(): + secret = {} + try: + with open('secret.json', 'r') as f: # FIXME: PATH + secret.update(json.loads(f.read())) + except FileNotFoundError: + raise AutoDeploySecretNotFound('ACITON REQUIRED) RUN `python manage.py autodeploy` FIRST!') + return secret + + +class Command(BaseCommand): + requires_migrations_checks = True + + def open_secret(self): + print('* Please write your OAuth Client ID') + client_id = input('>') + print('** Please write your OAuth Secret') + secret = input('>') + print('*** Please write your Server Domain (ex. example.com)') + domain = input('>') + + chars = 'qwertyuiopasdfghjklzxcvbnm0987654321!@#$%^&*(-_=+)' + SECRET_KEY = get_random_string(50, chars) + + result = {} + + result['CLIENT_ID'] = str(client_id) + result['SECRET'] = str(secret) + result['DOMAIN'] = str(domain) + result['SECRET_KEY'] = SECRET_KEY + + with open('secret.json', 'w') as f: + json.dump(result, f) + + secret = loadSecret() + self.social_app_setting(secret['DOMAIN'], secret['CLIENT_ID'], secret['SECRET']) + + @AutoDeployDatabaseNotPrepared.checker + def social_app_setting(self, domain, client_id, secret): + default_site_1 = Site.objects.get(id=1) + default_site_1.domain = domain + default_site_1.name = domain + default_site_1.save() + + new_social_app = SocialApp( + id=1, + provider='google', + name=domain, + client_id=client_id, + secret=secret, + key='', + ) + + new_social_app.save() + new_social_app.sites.add(default_site_1) + new_social_app.save() + + def handle(self, *args, **options): + self.open_secret() diff --git a/coding_night_live/management/commands/createsuperuserauto.py b/coding_night_live/management/commands/createsuperuserauto.py index d5cc281..8d56984 100644 --- a/coding_night_live/management/commands/createsuperuserauto.py +++ b/coding_night_live/management/commands/createsuperuserauto.py @@ -6,6 +6,10 @@ class Command(BaseCommand): def handle(self, *args, **options): password = get_random_string() + + with open('pw.txt', 'w') as pwfile: + pwfile.write(password) + print('Generated root password : %s' % (password,)) admin = User.objects.create_superuser( email='root@localhost', diff --git a/coding_night_live/management/commands/nginxconfgenerator.py b/coding_night_live/management/commands/nginxconfgenerator.py new file mode 100644 index 0000000..4d246c1 --- /dev/null +++ b/coding_night_live/management/commands/nginxconfgenerator.py @@ -0,0 +1,57 @@ +from django.core.management.base import BaseCommand +from django.conf import settings +from django.template import Template, Context + +from .autodeploy import loadSecret + + +NGINX_CONF_TEMPLATE = Template(''' +# /etc/nginx/ may not your nginx installation path. please check your installation path before. + +# You need to run the script below! +# sudo ln -s coding-night-live/coding-night-live_nginx.conf /etc/nginx/sites-enabled/ +# ex) sudo ln -s /home/punk/coding-night-live/collected_static /etc/nginx/sites-enabled/ + +server { + listen 80; + server_name {{ SERVER_NAME }}; + charset utf-8; + client_max_body_size 20M; + + location /static/ { + alias {{ BASE_DIR }}/collected_static/; + } + + location / { + proxy_pass http://0.0.0.0:8001; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + 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; + } +} +''') + + +def _dontBelieve(conf, key, _defaultValue): + believableValue = conf.get(key, None) + if believableValue: + return believableValue + return _defaultValue + + +class Command(BaseCommand): + def handle(self, *args, **options): + secret = loadSecret() + variables = Context({ + 'BASE_DIR': settings.BASE_DIR, + 'SERVER_NAME': _dontBelieve(secret, 'DOMAIN', 'localhost'), + 'PROXY_PASS': None, + 'PORT': None, + }) + self.stdout.write(NGINX_CONF_TEMPLATE.render(variables)) diff --git a/coding_night_live/settings.py b/coding_night_live/settings.py index f42bbb0..73a3bab 100644 --- a/coding_night_live/settings.py +++ b/coding_night_live/settings.py @@ -24,11 +24,12 @@ # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -secret_file = os.path.join(BASE_DIR, 'secret.json') - -with open(secret_file, 'r') as f: - secret = json.loads(f.read()) - +try: + secret_file = os.path.join(BASE_DIR, 'secret.json') + with open(secret_file, 'r') as f: + secret = json.loads(f.read()) +except FileNotFoundError: + secret = {'SECRET_KEY': True} def get_secret(setting, secret=secret): try: diff --git a/deploy_helper.py b/deploy_helper.py new file mode 100644 index 0000000..8a52589 --- /dev/null +++ b/deploy_helper.py @@ -0,0 +1,28 @@ +import os +import sys + + +# Check OS +platform = sys.platform +if platform in ('win32', 'win64'): + print('Error: Cannot run in Windows..') + exit(-1) + +cmd = 'python3' + +# Check Python Version (3 or 2) +if sys.version_info[0] == 2: + print('Error: Cannot run in Python 2.x..') + exit(-1) + +# Install python packages +try: + import pip +except ImportError: + print("Installing pip...") + if platform == 'linux': + os.system('sudo apt-get install python3-pip') + import pip +pip.main(['install', '-r', 'requirements.txt']) + +os.system('make') diff --git a/local_nginx.conf b/local_nginx.conf deleted file mode 100644 index 84858b6..0000000 --- a/local_nginx.conf +++ /dev/null @@ -1,34 +0,0 @@ -# /etc/nginx/ may not your nginx installation path. please check your installation path before. - -# You need to run the script below! -# sudo ln -s {{ your_path }}/coding-night-live/coding-night-live_nginx.conf /etc/nginx/sites-enabled/ -# ex) sudo ln -s /home/punk/coding-night-live/collected_static /etc/nginx/sites-enabled/ - -server { - listen 80; - server_name localhost; - # ex1) server_name localhost; - # ex2) server_name coding-night-live.cloudapp.net; - charset utf-8; - client_max_body_size 20M; - - location /static/ { - alias /opt/coding-night-live/collected_static/; # Please edit this line! - # ex) alias /home/punk/Documents/coding-night-live/collected_static/; - } - - location / { - #localhost deploy -> proxy_pass http:/localhost:8000; - # 80 deploy -> proxy_pass http://0.0.0.0:8000; - proxy_pass http://localhost:8000; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - 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; - } -} diff --git a/requirements.txt b/requirements.txt index 39ac11b..0062c5e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,4 +15,4 @@ asgi_redis pyhaikunator django-redis raven -Twisted==16.0.0 # Issue #54. Not worked with Twisted==17.0.0 +Twisted diff --git a/secret_key_gen.py b/secret_key_gen.py deleted file mode 100644 index 4fa14ec..0000000 --- a/secret_key_gen.py +++ /dev/null @@ -1,15 +0,0 @@ -import json -from django.utils.crypto import get_random_string - -# When you first download our project, you need to run this script. - -chars = 'qwertyuiopasdfghjklzxcvbnm0987654321!@#$%^&*(-_=+)' -SECRET_KEY = get_random_string(50, chars) - -value = {"SECRET_KEY": SECRET_KEY} - -with open('secret.json', 'w') as result_file: - json.dump(value, result_file, ensure_ascii=False) - -print('Generated SECRET_KEY result : ' + SECRET_KEY) -print('Check if "secret.json" file is generated at the same directory with manage.py')