服务启动方式被manage.py托管

publicsignpoll
youngS 3 years ago
parent 0bac3e55f4
commit 1e1385da84
  1. 12
      fir_admin/src/router/index.js
  2. 2
      fir_admin/src/store/modules/user.js
  3. 28
      fir_ser/admin/views/celery_flower.py
  4. 0
      fir_ser/api/management/__init__.py
  5. 0
      fir_ser/api/management/commands/__init__.py
  6. 10
      fir_ser/api/management/commands/expire_caches.py
  7. 6
      fir_ser/api/management/commands/restart.py
  8. 0
      fir_ser/api/management/commands/services/__init__.py
  9. 146
      fir_ser/api/management/commands/services/command.py
  10. 28
      fir_ser/api/management/commands/services/hands.py
  11. 5
      fir_ser/api/management/commands/services/services/__init__.py
  12. 233
      fir_ser/api/management/commands/services/services/base.py
  13. 31
      fir_ser/api/management/commands/services/services/beat.py
  14. 39
      fir_ser/api/management/commands/services/services/celery_base.py
  15. 10
      fir_ser/api/management/commands/services/services/celery_default.py
  16. 36
      fir_ser/api/management/commands/services/services/flower.py
  17. 35
      fir_ser/api/management/commands/services/services/gunicorn.py
  18. 45
      fir_ser/api/management/commands/services/services/uwsgi.py
  19. 141
      fir_ser/api/management/commands/services/utils.py
  20. 6
      fir_ser/api/management/commands/start.py
  21. 6
      fir_ser/api/management/commands/status.py
  22. 6
      fir_ser/api/management/commands/stop.py
  23. 4
      fir_ser/api/tasks.py
  24. 11
      fir_ser/api/utils/auth.py
  25. 6
      fir_ser/api/utils/pay/util.py
  26. 4
      fir_ser/api/utils/sendmsg/sendmsg.py
  27. 6
      fir_ser/api/utils/storage/storage.py
  28. 19
      fir_ser/api/views/thirdlogin.py
  29. 18
      fir_ser/config.py
  30. 25
      fir_ser/fir_ser/settings.py
  31. 4
      fir_ser/fir_ser/urls.py
  32. 12
      fir_ser/nginx-vhost.conf
  33. 6
      fir_ser/requirements.txt

@ -3,6 +3,8 @@ import Router from 'vue-router'
Vue.use(Router)
const celery_flower = process.env.VUE_APP_BASE_API.split('/')
/* Layout */
import Layout from '@/layout'
@ -373,6 +375,16 @@ export const constantRoutes = [
}
]
},
{
path: 'celery-flower-link',
component: Layout,
children: [
{
path: celery_flower[0] + '//' + celery_flower[2] + '/flower',
meta: { title: '任务监控', icon: 'link' }
}
]
},
// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }

@ -1,7 +1,7 @@
import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { resetRouter } from '@/router'
const Base64 = require('js-base64').Base64;
const Base64 = require('js-base64').Base64
const getDefaultState = () => {
return {

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
#
from django.http import HttpResponse
from django.conf import settings
from django.utils.translation import ugettext as _
from proxy.views import proxy_view
from rest_framework.views import APIView
from api.utils.auth import AdminTokenAuthentication
flower_url = f'{settings.CELERY_FLOWER_HOST}:{settings.CELERY_FLOWER_PORT}'
class CeleryFlowerView(APIView):
authentication_classes = [AdminTokenAuthentication, ]
def get(self, request, path):
remote_url = 'http://{}/flower/{}'.format(flower_url, path)
try:
response = proxy_view(request, remote_url)
except Exception as e:
msg = _("<h1>Flower service unavailable, check it</h1>") + \
'<br><br> <div>{}</div>'.format(e)
response = HttpResponse(msg)
return response
def post(self, request, path):
return self.get(request, path)

@ -0,0 +1,10 @@
from django.core.management.base import BaseCommand
from api.tasks import start_api_sever_do_clean
class Command(BaseCommand):
help = 'Expire caches'
def handle(self, *args, **options):
start_api_sever_do_clean()

@ -0,0 +1,6 @@
from .services.command import BaseActionCommand, Action
class Command(BaseActionCommand):
help = 'Restart services'
action = Action.restart.value

@ -0,0 +1,146 @@
from django.core.management.base import BaseCommand, CommandError
from django.db.models import TextChoices
from .utils import ServicesUtil
from .hands import *
class Services(TextChoices):
# gunicorn = 'gunicorn', 'gunicorn'
uwsgi = 'uwsgi', 'uwsgi'
celery = 'celery', 'celery'
beat = 'beat', 'beat'
flower = 'flower', 'flower'
task = 'task', 'task'
all = 'all', 'all'
@classmethod
def get_service_object_class(cls, name):
from . import services
services_map = {
cls.flower: services.FlowerService,
cls.celery: services.CeleryDefaultService,
cls.beat: services.BeatService,
cls.uwsgi: services.UwsgiService
}
return services_map.get(name)
@classmethod
def api_services(cls):
return [cls.uwsgi]
@classmethod
def flower_services(cls):
return [cls.flower]
@classmethod
def beat_services(cls):
return [cls.beat]
@classmethod
def celery_services(cls):
return [cls.celery]
@classmethod
def task_services(cls):
return cls.celery_services() + cls.beat_services() + cls.flower_services()
@classmethod
def all_services(cls):
return cls.task_services() + cls.api_services()
@classmethod
def export_services_values(cls):
return [cls.all.value, cls.uwsgi.value, cls.task.value, cls.celery.value, cls.flower.value, cls.beat.value]
@classmethod
def get_service_objects(cls, service_names, **kwargs):
services = set()
for name in service_names:
method_name = f'{name}_services'
if hasattr(cls, method_name):
_services = getattr(cls, method_name)()
elif hasattr(cls, name):
_services = [getattr(cls, name)]
else:
continue
services.update(set(_services))
service_objects = []
for s in services:
service_class = cls.get_service_object_class(s.value)
if not service_class:
continue
kwargs.update({
'name': s.value
})
service_object = service_class(**kwargs)
service_objects.append(service_object)
return service_objects
class Action(TextChoices):
start = 'start', 'start'
status = 'status', 'status'
stop = 'stop', 'stop'
restart = 'restart', 'restart'
class BaseActionCommand(BaseCommand):
help = 'Service Base Command'
action = None
util = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def add_arguments(self, parser):
parser.add_argument(
'services', nargs='+', choices=Services.export_services_values(), help='Service',
)
parser.add_argument('-d', '--daemon', nargs="?", const=True)
parser.add_argument('-up', '--uwsgi_processes', type=int, nargs="?", default=4)
parser.add_argument('-ut', '--uwsgi_threads', type=int, nargs="?", default=2)
parser.add_argument('-usm', '--uwsgi_socket_mode', nargs="?", const=True,
help='run to bind socket mode, default http mode, only uwsgi service')
parser.add_argument('-f', '--force', nargs="?", const=True)
parser.add_argument('-u', '--uid', nargs="?", default='root', type=str)
parser.add_argument('-g', '--gid', nargs="?", default='root', type=str)
def initial_util(self, *args, **options):
service_names = options.get('services')
service_kwargs = {
'uwsgi_processes': options.get('uwsgi_processes'),
'uwsgi_threads': options.get('uwsgi_threads'),
'uwsgi_socket_mode': options.get('uwsgi_socket_mode'),
'uid': options.get('uid'),
'gid': options.get('gid'),
}
services = Services.get_service_objects(service_names=service_names, **service_kwargs)
kwargs = {
'services': services,
'run_daemon': options.get('daemon', False),
'stop_daemon': self.action == Action.stop.value and Services.all.value in service_names,
'force_stop': options.get('force') or False,
}
self.util = ServicesUtil(**kwargs)
def handle(self, *args, **options):
self.initial_util(*args, **options)
assert self.action in Action.values, f'The action {self.action} is not in the optional list'
_handle = getattr(self, f'_handle_{self.action}', lambda: None)
_handle()
def _handle_start(self):
self.util.start_and_watch()
os._exit(0)
def _handle_stop(self):
self.util.stop()
def _handle_restart(self):
self.util.restart()
def _handle_status(self):
self.util.show_status()

@ -0,0 +1,28 @@
import os
import sys
import logging
from django.conf import settings
from config import BASECONF
try:
from apps.jumpserver import const
__version__ = const.VERSION
except ImportError as e:
print("Not found __version__: {}".format(e))
print("Python is: ")
logging.info(sys.executable)
__version__ = 'Unknown'
SOCKET_HOST = BASECONF.SERVER_BIND_HOST or '127.0.0.1'
SOCKET_PORT = BASECONF.SERVER_LISTEN_PORT or 8080
CELERY_FLOWER_HOST = BASECONF.CELERY_FLOWER_HOST or '127.0.0.1'
CELERY_FLOWER_PORT = BASECONF.CELERY_FLOWER_PORT or 5555
DEBUG = BASECONF.DEBUG or False
BASE_DIR = settings.BASE_DIR
APPS_DIR = BASE_DIR
LOG_DIR = os.path.join(BASE_DIR, 'logs')
TMP_DIR = os.path.join(BASE_DIR, 'tmp')

@ -0,0 +1,5 @@
from .beat import *
from .flower import *
from .gunicorn import *
from .celery_default import *
from .uwsgi import *

@ -0,0 +1,233 @@
import abc
import time
import shutil
import psutil
import datetime
import threading
import subprocess
import pwd
from ..hands import *
def get_user_id(uid):
if uid.isdigit():
try:
return pwd.getpwuid(int(uid)).pw_uid
except:
...
else:
try:
return pwd.getpwnam(uid).pw_uid
except:
...
class BaseService(object):
def __init__(self, **kwargs):
self.name = kwargs['name']
self.uid = kwargs['uid']
self.gid = kwargs['gid']
self._process = None
self.STOP_TIMEOUT = 10
self.max_retry = 0
self.retry = 3
self.LOG_KEEP_DAYS = 7
self.EXIT_EVENT = threading.Event()
@property
@abc.abstractmethod
def cmd(self):
return []
@property
@abc.abstractmethod
def cwd(self):
return ''
@property
def is_running(self):
if self.pid == 0:
return False
try:
os.kill(self.pid, 0)
except (OSError, ProcessLookupError):
return False
else:
return True
def show_status(self):
if self.is_running:
msg = f'{self.name} is running: {self.pid}.'
else:
msg = f'{self.name} is stopped.'
print(msg)
# -- log --
@property
def log_filename(self):
return f'{self.name}.log'
@property
def log_filepath(self):
return os.path.join(LOG_DIR, self.log_filename)
@property
def log_file(self):
return open(self.log_filepath, 'a')
@property
def log_dir(self):
return os.path.dirname(self.log_filepath)
# -- end log --
# -- pid --
@property
def pid_filepath(self):
return os.path.join(TMP_DIR, f'{self.name}.pid')
@property
def pid(self):
if not os.path.isfile(self.pid_filepath):
return 0
with open(self.pid_filepath) as f:
try:
pid = int(f.read().strip())
except ValueError:
pid = 0
return pid
def write_pid(self):
with open(self.pid_filepath, 'w') as f:
f.write(str(self.process.pid))
def remove_pid(self):
if os.path.isfile(self.pid_filepath):
os.unlink(self.pid_filepath)
# -- end pid --
# -- process --
@property
def process(self):
if not self._process:
try:
self._process = psutil.Process(self.pid)
except:
pass
return self._process
# -- end process --
# -- action --
def open_subprocess(self):
self.set_work_dir_owner()
kwargs = {'cwd': self.cwd, 'stderr': self.log_file, 'stdout': self.log_file}
self._process = subprocess.Popen(self.cmd, **kwargs)
def start(self):
if self.is_running:
self.show_status()
return
self.remove_pid()
self.open_subprocess()
self.write_pid()
self.start_other()
def start_other(self):
pass
def set_work_dir_owner(self):
uid = get_user_id(self.uid)
gid = get_user_id(self.gid)
u_gid = uid if uid else gid
if u_gid:
for (dir_path, dir_names, filenames) in os.walk(LOG_DIR):
for filename in filenames + dir_names:
os.chown(uid=u_gid, gid=u_gid, path=os.path.join(dir_path, filename))
else:
logging.error(f'uid: {self.uid} gid:{self.gid} is not exists')
def stop(self, force=False):
if not self.is_running:
self.show_status()
# self.remove_pid()
return
print(f'Stop service: {self.name}', end='')
sig = 9 if force else 15
os.kill(self.pid, sig)
if self.process is None:
print("\033[31m No process found\033[0m")
return
try:
self.process.wait(5)
except:
pass
for i in range(self.STOP_TIMEOUT):
if i == self.STOP_TIMEOUT - 1:
print("\033[31m Error\033[0m")
if not self.is_running:
print("\033[32m Ok\033[0m")
self.remove_pid()
break
else:
time.sleep(1)
continue
def watch(self):
self._check()
if not self.is_running:
self._restart()
self._rotate_log()
def _check(self):
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(f"{now} Check service status: {self.name} -> ", end='')
if self.process:
try:
self.process.wait(1) # 不wait,子进程可能无法回收
except:
pass
if self.is_running:
print(f'running at {self.pid}')
else:
print(f'stopped at {self.pid}')
def _restart(self):
if self.retry > self.max_retry:
logging.info(f"Service {self.name} start failed, exit")
self.EXIT_EVENT.set()
return
self.retry += 1
logging.info(f'> Find {self.name} stopped, retry {self.retry}, {self.pid}')
self.start()
def _rotate_log(self):
now = datetime.datetime.now()
_time = now.strftime('%H:%M')
if _time != '23:59':
return
backup_date = now.strftime('%Y-%m-%d')
backup_log_dir = os.path.join(self.log_dir, backup_date)
if not os.path.exists(backup_log_dir):
os.mkdir(backup_log_dir)
backup_log_path = os.path.join(backup_log_dir, self.log_filename)
if os.path.isfile(self.log_filepath) and not os.path.isfile(backup_log_path):
logging.info(f'Rotate log file: {self.log_filepath} => {backup_log_path}')
shutil.copy(self.log_filepath, backup_log_path)
with open(self.log_filepath, 'w') as f:
pass
to_delete_date = now - datetime.timedelta(days=self.LOG_KEEP_DAYS)
to_delete_dir = os.path.join(LOG_DIR, to_delete_date.strftime('%Y-%m-%d'))
if os.path.exists(to_delete_dir):
logging.info(f'Remove old log: {to_delete_dir}')
shutil.rmtree(to_delete_dir, ignore_errors=True)
# -- end action --

@ -0,0 +1,31 @@
from ..hands import *
from .base import BaseService
from django.core.cache import cache
__all__ = ['BeatService']
class BeatService(BaseService):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.lock = cache.lock('beat-distribute-start-lock', timeout=60)
@property
def cmd(self):
scheduler = "django_celery_beat.schedulers:DatabaseScheduler"
print("\n- Start Beat as Periodic Task Scheduler")
cmd = [
'celery', '-A',
'fir_ser', 'beat',
'-l', 'INFO',
'--uid', self.uid,
'--gid', self.gid,
'--scheduler', scheduler,
'--max-interval', '60'
]
return cmd
@property
def cwd(self):
return APPS_DIR

@ -0,0 +1,39 @@
from ..hands import *
from .base import BaseService
class CeleryBaseService(BaseService):
def __init__(self, queue, num=10, **kwargs):
super().__init__(**kwargs)
self.queue = queue
self.num = num
@property
def cmd(self):
print('\n- Start Celery as Distributed Task Queue: {}'.format(self.queue.capitalize()))
os.environ.setdefault('PYTHONOPTIMIZE', '1')
os.environ.setdefault('ANSIBLE_FORCE_COLOR', 'True')
if os.getuid() == 0:
os.environ.setdefault('C_FORCE_ROOT', '1')
server_hostname = os.environ.get("SERVER_HOSTNAME")
if not server_hostname:
server_hostname = '%n'
cmd = [
'celery', '-A',
'fir_ser', 'worker',
'-l', 'INFO',
'--uid', self.uid,
'--gid', self.gid,
'-c', str(self.num),
'-Q', self.queue,
'-n', f'{self.queue}@{server_hostname}'
]
return cmd
@property
def cwd(self):
return APPS_DIR

@ -0,0 +1,10 @@
from .celery_base import CeleryBaseService
__all__ = ['CeleryDefaultService']
class CeleryDefaultService(CeleryBaseService):
def __init__(self, **kwargs):
kwargs['queue'] = 'celery'
super().__init__(**kwargs)

@ -0,0 +1,36 @@
from ..hands import *
from .base import BaseService
__all__ = ['FlowerService']
class FlowerService(BaseService):
def __init__(self, **kwargs):
super().__init__(**kwargs)
@property
def cmd(self):
print("\n- Start Flower as Task Monitor")
if os.getuid() == 0:
os.environ.setdefault('C_FORCE_ROOT', '1')
cmd = [
'celery', '-A',
'fir_ser', 'flower',
'-l', 'INFO',
'--uid', self.uid,
'--gid', self.gid,
'--url_prefix=/flower',
'--auto_refresh=False',
'--max_tasks=1000',
f'--address={CELERY_FLOWER_HOST}',
f'--port={CELERY_FLOWER_PORT}',
# '--basic_auth=flower:ninevenxxx'
# '--tasks_columns=uuid,name,args,state,received,started,runtime,worker'
]
return cmd
@property
def cwd(self):
return APPS_DIR

@ -0,0 +1,35 @@
from ..hands import *
from .base import BaseService
__all__ = ['GunicornService']
class GunicornService(BaseService):
def __init__(self, **kwargs):
self.worker = kwargs['worker_gunicorn']
super().__init__(**kwargs)
@property
def cmd(self):
print("\n- Start Gunicorn WSGI HTTP Server")
log_format = '%(h)s %(t)s %(L)ss "%(r)s" %(s)s %(b)s '
bind = f'{HTTP_HOST}:{HTTP_PORT}'
cmd = [
'gunicorn', 'fir_ser.wsgi',
'-b', bind,
'-k', 'gthread',
'--threads', '10',
'-w', str(self.worker),
'--max-requests', '4096',
'--access-logformat', log_format,
'--access-logfile', '-'
]
if DEBUG:
cmd.append('--reload')
return cmd
@property
def cwd(self):
return APPS_DIR

@ -0,0 +1,45 @@
from ..hands import *
from .base import BaseService
__all__ = ['UwsgiService']
class UwsgiService(BaseService):
def __init__(self, **kwargs):
self.processes = kwargs['uwsgi_processes']
self.threads = kwargs['uwsgi_threads']
self.uwsgi_socket_mode = kwargs['uwsgi_socket_mode']
super().__init__(**kwargs)
@property
def cmd(self):
if os.getuid() == 0:
os.environ.setdefault('C_FORCE_ROOT', '1')
print("\n- Start Uwsgi WSGI HTTP Server")
bind = f'{SOCKET_HOST}:{SOCKET_PORT}'
cmd = [
'uwsgi',
'--uid', self.uid,
'--gid', self.gid,
'--processes', f'{self.processes}',
'--threads', f'{self.threads}',
'--wsgi-file', f"{BASE_DIR}/fir_ser/wsgi.py",
'--listen', '512',
'--chdir', BASE_DIR,
'--buffer-size', '65536',
'--vacuum',
'--enable-threads',
]
if self.uwsgi_socket_mode:
cmd.extend(['--socket', bind])
else:
cmd.extend(['--http', bind])
if DEBUG:
cmd.extend(['--touch-reload', BASE_DIR])
return cmd
@property
def cwd(self):
return APPS_DIR

@ -0,0 +1,141 @@
import threading
import signal
import time
import daemon
from daemon import pidfile
from .hands import *
from .hands import __version__
from .services.base import BaseService
class ServicesUtil(object):
def __init__(self, services, run_daemon=False, force_stop=False, stop_daemon=False):
self._services = services
self.run_daemon = run_daemon
self.force_stop = force_stop
self.stop_daemon = stop_daemon
self.EXIT_EVENT = threading.Event()
self.check_interval = 30
self.files_preserve_map = {}
def restart(self):
self.stop()
time.sleep(5)
self.start_and_watch()
def start_and_watch(self):
logging.info(time.ctime())
logging.info(f'FlyApps version {__version__}, more see https://flyapps.cn')
self.start()
if self.run_daemon:
self.show_status()
with self.daemon_context:
self.watch()
else:
self.watch()
def start(self):
for service in self._services:
service: BaseService
service.start()
self.files_preserve_map[service.name] = service.log_file
time.sleep(1)
def stop(self):
for service in self._services:
service: BaseService
service.stop(force=self.force_stop)
if self.stop_daemon:
self._stop_daemon()
# -- watch --
def watch(self):
while not self.EXIT_EVENT.is_set():
try:
_exit = self._watch()
if _exit:
break
time.sleep(self.check_interval)
except KeyboardInterrupt:
print('Start stop services')
break
self.clean_up()
def _watch(self):
for service in self._services:
service: BaseService
service.watch()
if service.EXIT_EVENT.is_set():
self.EXIT_EVENT.set()
return True
return False
# -- end watch --
def clean_up(self):
if not self.EXIT_EVENT.is_set():
self.EXIT_EVENT.set()
self.stop()
def show_status(self):
for service in self._services:
service: BaseService
service.show_status()
# -- daemon --
def _stop_daemon(self):
if self.daemon_pid and self.daemon_is_running:
os.kill(self.daemon_pid, 15)
self.remove_daemon_pid()
def remove_daemon_pid(self):
if os.path.isfile(self.daemon_pid_filepath):
os.unlink(self.daemon_pid_filepath)
@property
def daemon_pid(self):
if not os.path.isfile(self.daemon_pid_filepath):
return 0
with open(self.daemon_pid_filepath) as f:
try:
pid = int(f.read().strip())
except ValueError:
pid = 0
return pid
@property
def daemon_is_running(self):
try:
os.kill(self.daemon_pid, 0)
except (OSError, ProcessLookupError):
return False
else:
return True
@property
def daemon_pid_filepath(self):
return os.path.join(TMP_DIR, 'flyapps.pid')
@property
def daemon_log_filepath(self):
return os.path.join(LOG_DIR, 'flyApps.log')
@property
def daemon_context(self):
daemon_log_file = open(self.daemon_log_filepath, 'a')
context = daemon.DaemonContext(
pidfile=pidfile.TimeoutPIDLockFile(self.daemon_pid_filepath),
signal_map={
signal.SIGTERM: lambda x, y: self.clean_up(),
signal.SIGHUP: 'terminate',
},
stdout=daemon_log_file,
stderr=daemon_log_file,
files_preserve=list(self.files_preserve_map.values()),
detach_process=True,
)
return context
# -- end daemon --

@ -0,0 +1,6 @@
from .services.command import BaseActionCommand, Action
class Command(BaseActionCommand):
help = 'Start services'
action = Action.start.value

@ -0,0 +1,6 @@
from .services.command import BaseActionCommand, Action
class Command(BaseActionCommand):
help = 'Show services status'
action = Action.status.value

@ -0,0 +1,6 @@
from .services.command import BaseActionCommand, Action
class Command(BaseActionCommand):
help = 'Stop services'
action = Action.stop.value

@ -15,6 +15,7 @@ from api.utils.app.supersignutils import IosUtils, resign_by_app_id
from api.utils.crontab.ctasks import sync_download_times, auto_clean_upload_tmp_file, auto_delete_ios_mobile_tmp_file, \
auto_check_ios_developer_active
from api.utils.geetest.geetest_utils import check_bypass_status
from api.views.login import get_login_type
from fir_ser.celery import app
@ -85,4 +86,5 @@ def auto_check_ios_developer_active_job():
@app.task
def sync_wx_access_token_job():
sync_wx_access_token()
if get_login_type().get('third', '').get('wxp'):
sync_wx_access_token()

@ -9,9 +9,17 @@ from rest_framework.exceptions import AuthenticationFailed
from api.models import UserInfo
from rest_framework.permissions import BasePermission
from fir_ser.settings import CACHE_KEY_TEMPLATE
from django.http.cookie import parse_cookie
import base64
def get_cookie_token(request):
cookies = request.META.get('HTTP_COOKIE')
if cookies:
cookie_dict = parse_cookie(cookies)
return cookie_dict.get('auth_token')
def get_user_from_api_token(request):
if request.method == "OPTIONS":
return None
@ -29,7 +37,8 @@ def get_user_from_request_auth(request):
if request.method == "OPTIONS":
return None
request_token = request.META.get("HTTP_AUTHORIZATION",
request.META.get("HTTP_X_TOKEN", request.query_params.get("token", None)))
request.META.get("HTTP_X_TOKEN",
request.query_params.get("token", get_cookie_token(request))))
if request_token:
try:
format_token = base64.b64decode(request_token).decode()

@ -4,13 +4,13 @@
# author: NinEveN
# date: 2021/4/18
from fir_ser.settings import PAY_CONFIG
from fir_ser.settings import PAY_CONFIG_KEY_INFO
from api.utils.pay.ali import Alipay
from api.utils.pay.wx import Weixinpay
def get_pay_obj_form_name(pay_name):
for pay_info in PAY_CONFIG:
for pay_info in PAY_CONFIG_KEY_INFO:
if pay_name == pay_info.get('NAME', '') and pay_info.get('ENABLED', False):
auth_info = pay_info.get('AUTH', None)
p_type = pay_info.get('TYPE', '')
@ -25,7 +25,7 @@ def get_pay_obj_form_name(pay_name):
def get_enable_pay_choices():
pay_choices = []
for pay_info in PAY_CONFIG:
for pay_info in PAY_CONFIG_KEY_INFO:
if pay_info.get('ENABLED', False):
pay_choices.append({'type': pay_info.get('TYPE'), 'name': pay_info.get('NAME', '')})
return pay_choices

@ -7,7 +7,7 @@
from .aliyunApi import AliMsgSender
from .emailApi import EmailMsgSender
from .jiguangApi import JiGuangMsgSender
from fir_ser.settings import THIRD_PART_CONFIG
from fir_ser.settings import THIRD_PART_CONFIG_KEY_INFO
import logging
logger = logging.getLogger(__name__)
@ -20,7 +20,7 @@ def get_default_sender(send_type):
1: 阿里云
2: 极光
"""
sender_lists = THIRD_PART_CONFIG.get('sender')
sender_lists = THIRD_PART_CONFIG_KEY_INFO.get('sender_key')
for sender in sender_lists:
if sender.get("active", None):
sender_type = sender.get('type', None)

@ -10,7 +10,7 @@ from .qiniuApi import QiNiuOss
from .localApi import LocalStorage
import json, time, base64
from api.utils.baseutils import get_dict_from_filter_fields
from fir_ser.settings import THIRD_PART_CONFIG, CACHE_KEY_TEMPLATE
from fir_ser.settings import THIRD_PART_CONFIG_KEY_INFO, CACHE_KEY_TEMPLATE
from django.core.cache import cache
import logging
@ -146,7 +146,7 @@ class Storage(object):
def get_local_storage(clean_cache=False):
storage_lists = THIRD_PART_CONFIG.get('storage')
storage_lists = THIRD_PART_CONFIG_KEY_INFO.get('storage_key')
for storage in storage_lists:
storage_type = storage.get('type', None)
if storage_type == 0:
@ -169,7 +169,7 @@ def get_local_storage(clean_cache=False):
def get_storage_form_conf(user):
storage_lists = THIRD_PART_CONFIG.get('storage', [])
storage_lists = THIRD_PART_CONFIG_KEY_INFO.get('storage_key', [])
for storage in storage_lists:
if storage.get("active", None):
storage_type = storage.get('type', None)

@ -138,13 +138,11 @@ class ValidWxChatToken(APIView):
if rec_msg.Eventkey == 'query_bind':
if wx_user_obj:
user_obj = wx_user_obj.user_id
content = f'绑定用户 {user_obj.first_name}\n'
content = f'绑定用户 {user_obj.first_name} '
if user_obj.email:
content += f' 登录邮箱:{user_obj.email}\n'
content += f' 登录邮箱:{user_obj.email} '
if user_obj.mobile:
content += f' 登录手机:{user_obj.mobile}'
if content.endswith('\n'):
content = content[0:-1]
user_cert_obj = UserCertificationInfo.objects.filter(user_id=user_obj,
status=1).first()
if user_cert_obj:
@ -202,12 +200,13 @@ class ValidWxChatToken(APIView):
content = f'账户已经被 {wx_user_obj.user_id.first_name} 绑定'
WxTemplateMsg().bind_failed_msg(to_user, wx_user_obj.nickname, content)
else:
wx_user_info = update_or_create_wx_userinfo(to_user, user_obj)
content = f'账户绑定 {wx_user_obj.user_id.first_name} 成功'
WxTemplateMsg().bind_success_msg(to_user, wx_user_info.get('nickname', ''),
user_obj.first_name)
set_wx_ticket_login_info_cache(rec_msg.Ticket, {'pk': user_obj.pk})
if user_obj:
wx_user_info = update_or_create_wx_userinfo(to_user, user_obj)
content = f'账户绑定 {wx_user_obj.user_id.first_name} 成功'
WxTemplateMsg().bind_success_msg(to_user, wx_user_info.get('nickname', ''),
user_obj.first_name)
if user_obj:
set_wx_ticket_login_info_cache(rec_msg.Ticket, {'pk': user_obj.pk})
reply_msg = reply.TextMsg(to_user, from_user, content)
result = reply_msg.send()
else:

@ -17,7 +17,17 @@ class BASECONF(object):
SECRET_KEY = 'j!g@^bc(z(a3*i&kp$_@bgb)bug&^#3=amch!3lz&1x&s6ss6t'
ALLOWED_HOSTS = ['127.0.0.1', 'synchrotron', '172.16.133.34', 'ali.cdn.flyapp.dvcloud.xin',
'api.src.flyapp.dvcloud.xin']
'api.src.flyapp.dvcloud.xin', 'app.hehelucky.cn']
# When Django start it will bind this host and port
# ./manage.py runserver 127.0.0.1:8080
# uwsgi运行时绑定端口
SERVER_BIND_HOST = '127.0.0.1'
SERVER_LISTEN_PORT = 8898
# celery flower 任务监控配置
CELERY_FLOWER_PORT = 5566
CELERY_FLOWER_HOST = '127.0.0.1'
SERVER_DOMAIN = {
'IOS_PMFILE_DOWNLOAD_DOMAIN': {
@ -81,7 +91,7 @@ class THIRDLOGINCONF(object):
class AUTHCONF(object):
# 注册方式,如果启用sms或者email 需要配置 THIRD_PART_CONFIG.sender 信息
# 注册方式,如果启用sms或者email 需要配置 THIRD_PART_CONFIG_KEY_INFO.sender 信息
REGISTER = {
"enable": True,
"captcha": False, # 是否开启注册字母验证码
@ -117,7 +127,7 @@ class AUTHCONF(object):
}
class STORAGECONF(object):
class STORAGEKEYCONF(object):
STORAGE = [
{
'name': 'local',
@ -247,7 +257,7 @@ class IPACONF(object):
class PAYCONF(object):
PAY_SUCCESS_URL = '%s/user/orders' % WEB_DOMAIN # 前端页面,支付成功跳转页面
PAY_CONFIG = [
PAY_CONFIG_KEY_INFO = [
{
'NAME': 'alipay',
'TYPE': 'ALI',

@ -184,16 +184,16 @@ GEETEST_CYCLE_TIME = BASECONF.GEETEST_CYCLE_TIME
GEETEST_BYPASS_STATUS_KEY = BASECONF.GEETEST_BYPASS_STATUS_KEY
GEETEST_BYPASS_URL = BASECONF.GEETEST_BYPASS_URL
# 注册方式,如果启用sms或者email 需要配置 THIRD_PART_CONFIG.sender 信息
# 注册方式,如果启用sms或者email 需要配置 THIRD_PART_CONFIG_KEY_INFO.sender 信息
REGISTER = AUTHCONF.REGISTER
# 个人资料修改修改也会使用该配置
CHANGER = AUTHCONF.CHANGER
LOGIN = AUTHCONF.LOGIN
THIRD_PART_CONFIG = {
THIRD_PART_CONFIG_KEY_INFO = {
# APP存储配置
'storage': STORAGECONF.STORAGE,
'sender': SENDERCONF.SENDER
'storage_key': STORAGEKEYCONF.STORAGE,
'sender_key': SENDERCONF.SENDER
}
CACHE_KEY_TEMPLATE = {
'user_can_download_key': 'user_can_download',
@ -256,7 +256,9 @@ SESSION_CACHE_ALIAS = "default"
CAPTCHA_TIMEOUT = 5 # Minutes
CAPTCHA_LENGTH = 6 # Chars
BASE_LOG_DIR = os.path.join(BASE_DIR, "logs")
BASE_LOG_DIR = os.path.join(BASE_DIR, "logs", "flyapp")
if not os.path.isdir(BASE_LOG_DIR):
os.makedirs(BASE_LOG_DIR)
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
@ -325,7 +327,7 @@ LOGGING = {
'propagate': True,
},
'pay': { # 默认的logger应用如下配置
'handlers': ['pay'], # 上线之后可以把'console'移除
'handlers': ['pay'],
'level': 'DEBUG',
'propagate': True,
},
@ -333,7 +335,7 @@ LOGGING = {
}
PAY_SUCCESS_URL = PAYCONF.PAY_SUCCESS_URL
PAY_CONFIG = PAYCONF.PAY_CONFIG
PAY_CONFIG_KEY_INFO = PAYCONF.PAY_CONFIG_KEY_INFO
# 结果存放到Django|redis
# CELERY_RESULT_BACKEND = 'django-db'
@ -352,7 +354,7 @@ CELERY_BROKER_URL = 'redis://:%s@%s/2' % (
#: Only add pickle to this list if your broker is secured
CELERYD_CONCURRENCY = 4 # worker并发数
CELERYD_CONCURRENCY = 10 # worker并发数
CELERYD_FORCE_EXECV = True # 非常重要,有些情况下可以防止死
CELERY_TASK_RESULT_EXPIRES = 3600 # 任务结果过期时间
@ -415,3 +417,10 @@ MSGTEMPLATE = {
'ERROR_DEVELOPER': '用户 %s 你好,应用 %s 签名失败了,苹果开发者 %s 信息异常,请重新检查苹果开发者状态是否正常。感谢有你!',
'AUTO_CHECK_DEVELOPER': '用户 %s 你好,苹果开发者 %s 信息异常,请重新检查苹果开发者状态是否正常。感谢有你!',
}
## listen port
SERVER_BIND_HOST = BASECONF.SERVER_BIND_HOST
SERVER_LISTEN_PORT = BASECONF.SERVER_LISTEN_PORT
CELERY_FLOWER_PORT = BASECONF.CELERY_FLOWER_PORT
CELERY_FLOWER_HOST = BASECONF.CELERY_FLOWER_HOST

@ -16,6 +16,8 @@ Including another URLconf
from django.contrib import admin
from django.urls import re_path, include
from django.views.static import serve
from admin.views.celery_flower import CeleryFlowerView
from fir_ser import settings
from api.views.download import DownloadView, InstallView
from api.views.receiveudids import IosUDIDView, ShowUdidView
@ -32,5 +34,5 @@ urlpatterns = [
re_path("install/(?P<app_id>\w+)$", InstallView.as_view(), name="install"),
re_path("^udid/(?P<short>\w+)$", IosUDIDView.as_view()),
re_path("^show_udid$", ShowUdidView.as_view()),
re_path(r'flower/(?P<path>.*)', CeleryFlowerView.as_view()),
]

@ -1,9 +1,11 @@
upstream synchrotron {
least_conn ;
#server 127.0.0.1:8899;
server 127.0.0.1:8898;
#server 127.0.0.1:8897;
#server 127.0.0.1:8896;
#hash $remote_addr consistent;
server 127.0.0.1:8896 max_fails=1 fail_timeout=10s;
server 127.0.0.1:8897 max_fails=1 fail_timeout=10s;
server 127.0.0.1:8898 max_fails=1 fail_timeout=10s;
server 127.0.0.1:8899 backup; # 将服务器标记为备份服务器。当主服务器不可用时,将传递与备份服务器的连接
}
proxy_set_header X-Forwarded-For $remote_addr;
@ -48,7 +50,7 @@ server
uwsgi_connect_timeout 300; # 指定连接到后端uWSGI的超时时间。
uwsgi_read_timeout 300; # 指定接收uWSGI应答的超时时间,完成握手后接收uWSGI应答的超时时间。
include uwsgi_params;
uwsgi_pass 127.0.0.1:8899;
uwsgi_pass synchrotron;
uwsgi_param UWSGI_SCRIPT wsgi;
}

@ -15,4 +15,8 @@ xmltodict==0.12.0
pyOpenSSL==20.0.1
paramiko==2.7.2
PyJWT==2.1.0
drf-extensions==0.7.0
drf-extensions==0.7.0
python-daemon==2.2.3
psutil==5.6.6
flower==1.0.0
django-proxy==1.2.1
Loading…
Cancel
Save