1
1
import json
2
2
import os
3
3
import platform
4
- import shutil
5
4
import subprocess
6
5
import sys
7
- import urllib .request
8
6
from importlib .util import find_spec
9
7
from pathlib import Path
10
8
15
13
from plain .runtime import APP_PATH , settings
16
14
17
15
from .db import cli as db_cli
16
+ from .mkcert import MkcertManager
18
17
from .pid import Pid
19
18
from .services import Services
20
19
from .utils import has_pyproject_toml , plainpackage_installed
@@ -62,25 +61,20 @@ def __init__(self, *, port):
62
61
}
63
62
self .project_name = os .path .basename (os .getcwd ())
64
63
self .domain = f"{ self .project_name } .localhost"
65
-
66
- # Paths for mkcert and certificates
67
- self .mkcert_dir = Path .home () / ".plain" / "dev"
68
- self .mkcert_bin = self .mkcert_dir / "mkcert"
69
- self .certs_dir = (
70
- Path (settings .PLAIN_TEMP_PATH ) / "dev" / "certs"
71
- ) # Local project directory for certs
72
-
73
- # Define certificate and key paths with clear filenames
74
- self .cert_path = self .certs_dir / f"{ self .domain } -cert.pem"
75
- self .key_path = self .certs_dir / f"{ self .domain } -key.pem"
64
+ self .ssl_cert_path = None
65
+ self .ssl_key_path = None
76
66
77
67
def run (self ):
78
68
pid = Pid ()
79
69
pid .write ()
80
70
81
71
try :
82
- self .setup_mkcert ()
83
- self .generate_certs ()
72
+ mkcert_manager = MkcertManager ()
73
+ mkcert_manager .setup_mkcert (install_path = Path .home () / ".plain" / "dev" )
74
+ self .ssl_cert_path , self .ssl_key_path = mkcert_manager .generate_certs (
75
+ domain = self .domain ,
76
+ storage_path = Path (settings .PLAIN_TEMP_PATH ) / "dev" / "certs" ,
77
+ )
84
78
self .modify_hosts_file ()
85
79
self .add_csrf_trusted_origins ()
86
80
self .add_allowed_hosts ()
@@ -103,84 +97,6 @@ def run(self):
103
97
finally :
104
98
pid .rm ()
105
99
106
- def setup_mkcert (self ):
107
- """Set up mkcert by checking if it's installed or downloading the binary and installing the local CA."""
108
- if mkcert_path := shutil .which ("mkcert" ):
109
- # mkcert is already installed somewhere
110
- self .mkcert_bin = mkcert_path
111
- else :
112
- self .mkcert_dir .mkdir (parents = True , exist_ok = True )
113
- if not self .mkcert_bin .exists ():
114
- system = platform .system ()
115
- arch = platform .machine ()
116
-
117
- # Map platform.machine() to mkcert's expected architecture strings
118
- arch_map = {
119
- "x86_64" : "amd64" ,
120
- "amd64" : "amd64" ,
121
- "AMD64" : "amd64" ,
122
- "arm64" : "arm64" ,
123
- "aarch64" : "arm64" ,
124
- }
125
- arch = arch_map .get (
126
- arch .lower (), "amd64"
127
- ) # Default to amd64 if unknown
128
-
129
- if system == "Darwin" :
130
- os_name = "darwin"
131
- elif system == "Linux" :
132
- os_name = "linux"
133
- elif system == "Windows" :
134
- os_name = "windows"
135
- else :
136
- click .secho ("Unsupported OS" , fg = "red" )
137
- sys .exit (1 )
138
-
139
- mkcert_url = f"https://dl.filippo.io/mkcert/latest?for={ os_name } /{ arch } "
140
- click .secho (f"Downloading mkcert from { mkcert_url } ..." , bold = True )
141
- urllib .request .urlretrieve (mkcert_url , self .mkcert_bin )
142
- self .mkcert_bin .chmod (0o755 )
143
- self .mkcert_bin = str (self .mkcert_bin ) # Convert Path object to string
144
-
145
- if not self .is_mkcert_ca_installed ():
146
- click .secho (
147
- "Installing mkcert local CA. You may be prompted for your password." ,
148
- bold = True ,
149
- )
150
- subprocess .run ([self .mkcert_bin , "-install" ], check = True )
151
-
152
- def is_mkcert_ca_installed (self ):
153
- """Check if mkcert local CA is already installed using mkcert -check."""
154
- try :
155
- result = subprocess .run ([self .mkcert_bin , "-check" ], capture_output = True )
156
- output = result .stdout .decode () + result .stderr .decode ()
157
- if "The local CA is not installed" in output :
158
- return False
159
- return True
160
- except Exception as e :
161
- click .secho (f"Error checking mkcert CA installation: { e } " , fg = "red" )
162
- return False
163
-
164
- def generate_certs (self ):
165
- if self .cert_path .exists () and self .key_path .exists ():
166
- return
167
-
168
- self .certs_dir .mkdir (parents = True , exist_ok = True )
169
-
170
- # Generate SSL certificates using mkcert
171
- click .secho (f"Generating SSL certificates for { self .domain } ..." , bold = True )
172
- subprocess .run (
173
- [
174
- self .mkcert_bin ,
175
- "-cert-file" ,
176
- str (self .cert_path ),
177
- "-key-file" ,
178
- str (self .key_path ),
179
- self .domain ,
180
- ],
181
- check = True ,
182
- )
183
-
184
100
def modify_hosts_file (self ):
185
101
"""Modify the hosts file to map the custom domain to 127.0.0.1."""
186
102
entry_identifier = "# Added by plain"
@@ -284,9 +200,9 @@ def add_gunicorn(self):
284
200
"--bind" ,
285
201
f"{ self .domain } :{ self .port } " ,
286
202
"--certfile" ,
287
- str (self .cert_path ),
203
+ str (self .ssl_cert_path ),
288
204
"--keyfile" ,
289
- str (self .key_path ),
205
+ str (self .ssl_key_path ),
290
206
"--reload" ,
291
207
"plain.wsgi:app" ,
292
208
"--timeout" ,
0 commit comments