Mercurial > piecrust2
comparison piecrust/commands/builtin/admin.py @ 886:dcdec4b951a1
admin: Get the admin panel working again.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 20 Jun 2017 21:13:08 -0700 |
parents | 4850f8c21b6e |
children | 33a89139c284 |
comparison
equal
deleted
inserted
replaced
885:13e8b50a2113 | 886:dcdec4b951a1 |
---|---|
1 import os | 1 import os |
2 import os.path | 2 import os.path |
3 import logging | 3 import logging |
4 from piecrust import CACHE_DIR | 4 from piecrust import CACHE_DIR, CONFIG_PATH |
5 from piecrust.commands.base import ChefCommand | 5 from piecrust.commands.base import ChefCommand |
6 from piecrust.pathutil import SiteNotFoundError | 6 from piecrust.pathutil import SiteNotFoundError |
7 | 7 |
8 | 8 |
9 logger = logging.getLogger(__name__) | 9 logger = logging.getLogger(__name__) |
20 subparsers = parser.add_subparsers() | 20 subparsers = parser.add_subparsers() |
21 | 21 |
22 p = subparsers.add_parser( | 22 p = subparsers.add_parser( |
23 'init', | 23 'init', |
24 help="Creates a new administration panel website.") | 24 help="Creates a new administration panel website.") |
25 p.set_defaults(sub_func=self._initFoodTruck) | 25 p.set_defaults(sub_func=self._initAdminSite) |
26 | 26 |
27 p = subparsers.add_parser( | 27 p = subparsers.add_parser( |
28 'genpass', | 28 'genpass', |
29 help=("Generates the hashed password for use as an " | 29 help=("Generates the hashed password for use as an " |
30 "admin password")) | 30 "admin password")) |
45 p.add_argument( | 45 p.add_argument( |
46 '--no-assets', | 46 '--no-assets', |
47 help="Don't process and monitor the asset folder(s).", | 47 help="Don't process and monitor the asset folder(s).", |
48 dest='monitor_assets', | 48 dest='monitor_assets', |
49 action='store_false') | 49 action='store_false') |
50 p.set_defaults(sub_func=self._runFoodTruck) | 50 p.add_argument( |
51 '--use-reloader', | |
52 help="Restart the server when PieCrust code changes", | |
53 action='store_true') | |
54 p.add_argument( | |
55 '--use-debugger', | |
56 help="Show the debugger when an error occurs", | |
57 action='store_true') | |
58 p.set_defaults(sub_func=self._runAdminSite) | |
51 | 59 |
52 def checkedRun(self, ctx): | 60 def checkedRun(self, ctx): |
53 if ctx.app.root_dir is None: | 61 if ctx.app.root_dir is None: |
54 raise SiteNotFoundError(theme=ctx.app.theme_site) | 62 raise SiteNotFoundError(theme=ctx.app.theme_site) |
55 | 63 |
56 if not hasattr(ctx.args, 'sub_func'): | 64 if not hasattr(ctx.args, 'sub_func'): |
57 ctx.parser.parse_args(['admin', '--help']) | 65 ctx.parser.parse_args(['admin', '--help']) |
58 return | 66 return |
59 return ctx.args.sub_func(ctx) | 67 return ctx.args.sub_func(ctx) |
60 | 68 |
61 def _runFoodTruck(self, ctx): | 69 def _runAdminSite(self, ctx): |
62 # See `_run_sse_check` in `piecrust.serving.wrappers` for an | 70 # See `_run_sse_check` in `piecrust.serving.wrappers` for an |
63 # explanation of this check. | 71 # explanation of this check. |
64 if (ctx.args.monitor_assets and ( | 72 if (ctx.args.monitor_assets and ( |
65 not ctx.args.debug or | 73 not (ctx.args.debug or ctx.args.use_reloader) or |
66 os.environ.get('WERKZEUG_RUN_MAIN') == 'true')): | 74 os.environ.get('WERKZEUG_RUN_MAIN') == 'true')): |
67 from piecrust.serving.procloop import ProcessingLoop | 75 from piecrust.serving.procloop import ProcessingLoop |
68 out_dir = os.path.join( | 76 out_dir = os.path.join( |
69 ctx.app.root_dir, CACHE_DIR, 'foodtruck', 'server') | 77 ctx.app.root_dir, CACHE_DIR, 'admin', 'server') |
70 proc_loop = ProcessingLoop(ctx.appfactory, out_dir) | 78 proc_loop = ProcessingLoop(ctx.appfactory, out_dir) |
71 proc_loop.start() | 79 proc_loop.start() |
72 | 80 |
73 es = { | 81 es = { |
74 'FOODTRUCK_CMDLINE_MODE': True, | 82 'FOODTRUCK_CMDLINE_MODE': True, |
75 'FOODTRUCK_ROOT': ctx.app.root_dir} | 83 'FOODTRUCK_ROOT': ctx.app.root_dir, |
76 from piecrust.admin.main import run_foodtruck | 84 'FOODTRUCK_URL_PREFIX': '', |
85 'SECRET_KEY': os.urandom(22), | |
86 'LOGIN_DISABLED': True} | |
87 if ctx.args.debug or ctx.args.use_debugger: | |
88 es['DEBUG'] = True | |
89 | |
77 run_foodtruck( | 90 run_foodtruck( |
78 host=ctx.args.address, | 91 host=ctx.args.address, |
79 port=ctx.args.port, | 92 port=ctx.args.port, |
80 debug=ctx.args.debug, | 93 use_reloader=ctx.args.use_reloader, |
81 extra_settings=es) | 94 extra_settings=es) |
82 | 95 |
83 def _initFoodTruck(self, ctx): | 96 def _initAdminSite(self, ctx): |
97 import io | |
84 import getpass | 98 import getpass |
85 from piecrust.admin import bcryptfallback as bcrypt | 99 from piecrust.admin import bcryptfallback as bcrypt |
86 | 100 |
87 secret_key = os.urandom(22) | 101 secret_key = os.urandom(22) |
88 admin_username = input("Admin username (admin): ") or 'admin' | 102 admin_username = input("Admin username (admin): ") or 'admin' |
89 admin_password = getpass.getpass("Admin password: ") | 103 admin_password = getpass.getpass("Admin password: ") |
90 if not admin_password: | 104 if not admin_password: |
91 logger.warning("No administration password set!") | 105 logger.warning("No administration password set!") |
92 logger.warning("Don't make this instance of FoodTruck public.") | 106 logger.warning("Don't make this instance of the PieCrust " |
107 "administration panel public.") | |
93 logger.info("You can later set an admin password by editing " | 108 logger.info("You can later set an admin password by editing " |
94 "the `foodtruck.yml` file and using the " | 109 "the `admin.cfg` file and using the " |
95 "`chef admin genpass` command.") | 110 "`chef admin genpass` command.") |
96 else: | 111 else: |
97 binpw = admin_password.encode('utf8') | 112 binpw = admin_password.encode('utf8') |
98 hashpw = bcrypt.hashpw(binpw, bcrypt.gensalt()).decode('utf8') | 113 hashpw = bcrypt.hashpw(binpw, bcrypt.gensalt()).decode('utf8') |
99 admin_password = hashpw | 114 admin_password = hashpw |
100 | 115 |
101 ft_config = """ | 116 ft_config = """ |
102 security: | 117 admin: |
118 secret_key: %(secret_key)s | |
103 username: %(username)s | 119 username: %(username)s |
104 # You can generate another hashed password with `chef admin genpass`. | 120 # You can generate another hashed password with `chef admin genpass`. |
105 password: %(password)s | 121 password: %(password)s |
106 """ | 122 """ |
107 ft_config = ft_config % { | 123 ft_config = ft_config % { |
124 'secret_key': secret_key, | |
108 'username': admin_username, | 125 'username': admin_username, |
109 'password': admin_password | 126 'password': admin_password |
110 } | 127 } |
111 with open('foodtruck.yml', 'w', encoding='utf8') as fp: | 128 |
129 config_path = os.path.join(ctx.app.root_dir, CONFIG_PATH) | |
130 with open(config_path, 'a+', encoding='utf8') as fp: | |
131 fp.seek(0, io.SEEK_END) | |
132 fp.write('\n') | |
112 fp.write(ft_config) | 133 fp.write(ft_config) |
113 | |
114 flask_config = """ | |
115 SECRET_KEY = %(secret_key)s | |
116 """ | |
117 flask_config = flask_config % {'secret_key': secret_key} | |
118 with open('app.cfg', 'w', encoding='utf8') as fp: | |
119 fp.write(flask_config) | |
120 | 134 |
121 def _generatePassword(self, ctx): | 135 def _generatePassword(self, ctx): |
122 from piecrust.admin import bcryptfallback as bcrypt | 136 from piecrust.admin import bcryptfallback as bcrypt |
123 binpw = ctx.args.password.encode('utf8') | 137 binpw = ctx.args.password.encode('utf8') |
124 hashpw = bcrypt.hashpw(binpw, bcrypt.gensalt()).decode('utf8') | 138 hashpw = bcrypt.hashpw(binpw, bcrypt.gensalt()).decode('utf8') |
125 logger.info(hashpw) | 139 logger.info(hashpw) |
126 | 140 |
141 | |
142 def run_foodtruck(host=None, port=None, use_reloader=False, | |
143 extra_settings=None): | |
144 es = {} | |
145 if extra_settings: | |
146 es.update(extra_settings) | |
147 | |
148 # Disable PIN protection with Werkzeug's debugger. | |
149 os.environ['WERKZEUG_DEBUG_PIN'] = 'off' | |
150 | |
151 try: | |
152 from piecrust.admin.web import create_foodtruck_app | |
153 app = create_foodtruck_app(es) | |
154 app.run(host=host, port=port, use_reloader=use_reloader, | |
155 threaded=True) | |
156 except SystemExit: | |
157 # This is needed for Werkzeug's code reloader to be able to correctly | |
158 # shutdown the child process in order to restart it (otherwise, SSE | |
159 # generators will keep it alive). | |
160 try: | |
161 from . import pubutil | |
162 logger.debug("Shutting down SSE generators from main...") | |
163 pubutil.server_shutdown = True | |
164 except ImportError: | |
165 pass | |
166 raise | |
167 |