/ cgi-bin / seed
seed
  1  #!/usr/bin/python3
  2  
  3  import html
  4  from urllib.parse import quote_plus
  5  import time
  6  from util import *
  7  from config import *
  8  
  9  sys.excepthook = lambda t,v,tb: print('<pre>'+html.escape(''.join(traceback.format_exception(t,v,tb)))+'</pre>')
 10  
 11  def print_error(msg):
 12      print('<p class="error-message">'+html.escape(msg)+'</p>')
 13  
 14  def print_info(msg):
 15      print('<p>'+html.escape(msg)+'</p>')
 16  
 17  HTML_HEAD='''
 18  <!doctype html>
 19  <html lang="en">
 20    <head>
 21      <meta charset="utf-8">
 22      <meta name="viewport" content="width=device-width, initial-scale=1">
 23      <title>Cradicle - Seed</title>
 24      <link href="/css/bootstrap/bootstrap.min.css" rel="stylesheet">
 25      <style>
 26        .bd-placeholder-img {
 27  	  font-size: 1.125rem;
 28  	  text-anchor: middle;
 29  	  -webkit-user-select: none;
 30  	  -moz-user-select: none;
 31  	  user-select: none;
 32        }
 33  
 34        @media (min-width: 768px) {
 35  	  .bd-placeholder-img-lg {
 36  	      font-size: 3.5rem;
 37  	  }
 38        }
 39  
 40        .b-example-divider {
 41  	  height: 3rem;
 42  	  background-color: rgba(0, 0, 0, .1);
 43  	  border: solid rgba(0, 0, 0, .15);
 44  	  border-width: 1px 0;
 45  	  box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
 46        }
 47  
 48        .b-example-vr {
 49  	  flex-shrink: 0;
 50  	  width: 1.5rem;
 51  	  height: 100vh;
 52        }
 53  
 54        .bi {
 55  	  vertical-align: -.125em;
 56  	  fill: currentColor;
 57        }
 58  
 59        .nav-scroller {
 60  	  position: relative;
 61  	  z-index: 2;
 62  	  height: 2.75rem;
 63  	  overflow-y: hidden;
 64        }
 65  
 66        .nav-scroller .nav {
 67  	  display: flex;
 68  	  flex-wrap: nowrap;
 69  	  padding-bottom: 1rem;
 70  	  margin-top: -1px;
 71  	  overflow-x: auto;
 72  	  text-align: center;
 73  	  white-space: nowrap;
 74  	  -webkit-overflow-scrolling: touch;
 75        }
 76      </style>
 77      <link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
 78      <link rel="icon" type="image/png" href="/favicon.png">
 79  '''
 80  
 81  print(HTML_HEAD)
 82  
 83  form = FormData()
 84  rid = form.getvalue('rid')
 85  node = form.getvalue('node')
 86  tor = form.getvalue('tor')
 87  
 88  ret,out,err = exec_command(crad_bin,["self","--alias"])
 89  self_alias = 'unknown user'
 90  if not ret:
 91      self_alias = html.escape(out.strip())
 92  ret,out,err = exec_command(crad_bin,["self","--did"])
 93  self_did = ''
 94  if not ret:
 95      self_did = html.escape(out.strip())
 96  
 97  node_on = False
 98  ret,out,err = exec_command(rad_node_status_wrapped_bin,['--only','nid'])
 99  if not ret:
100      node_on = True
101  tor_on = False
102  ret,out,err = exec_command(crad_bin,['self','--network-mode'])
103  if not ret and out.strip() == 'tor':
104      tor_on = True
105  
106  if tor == 'on' and not tor_on:
107      set_config_tor(True)
108      if node_on and node != 'off':
109          node = 'restart'
110  elif tor == 'off' and tor_on:
111      set_config_tor(False)
112      if node_on and node != 'off':
113          node = 'restart'
114  
115  if node == 'on' and not node_on:
116      exec_command_bg(radicle_node_wrapped_bin,[])
117      time.sleep(8)
118  elif node == 'off' and node_on:
119      ret,out,err = exec_command(rad_node_stop_wrapped_bin,[])
120  elif node == 'restart':
121      if node_on:
122          ret,out,err = exec_command(rad_node_stop_wrapped_bin,[])
123      exec_command_bg(radicle_node_wrapped_bin,[])
124      time.sleep(8)
125  
126  ret,out,err = exec_command(rad_node_status_wrapped_bin,['--only','nid'])
127  if not ret:
128      node_on = True
129      node_switch_url='&node=off'
130      node_title='click to disconnect from network'
131  else:
132      node_on = False
133      node_switch_url ='&node=on'
134      node_title ='click to connect to network'
135  
136  tor_on = False
137  tor_switch_url = '&tor=on'
138  tor_title = 'click to route through Tor network'
139  ret,out,err = exec_command(crad_bin,["self","--network-mode"])
140  if not ret and out.strip() == 'tor':
141      tor_on = True
142      tor_switch_url = '&tor=off'
143      tor_title = 'click to disconnect from Tor network'
144  
145  class_node_icon = ' icon-off'
146  class_tor_icon = ' icon-off'
147  if node_on:
148      class_node_icon = ' icon-on'
149  if tor_on:
150      class_tor_icon = ' icon-on'
151  
152  HTML_DASHBOARD_START=f'''
153                  <link href="/css/dashboard.css" rel="stylesheet">
154                  </head>
155                  <body>
156                  <header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
157                    <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="/">Cradicle</a>
158                    <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
159                      <span class="navbar-toggler-icon"></span>
160                    </button>
161                    <input class="form-control form-control-dark w-100 rounded-0 border-0" type="text" placeholder="Search" aria-label="Search">
162                    <div class="navbar-nav flex-row">
163                      <div class="nav-item text-nowrap">
164                        <a class="nav-link px-3 active" title="{node_title}" href="/cgi-bin/seed?{node_switch_url}"><i class="fa-solid fa-circle-nodes{class_node_icon}"></i></a>
165                      </div>
166                      <div class="nav-item text-nowrap">
167                        <a class="nav-link px-3 active" title="{tor_title}" href="/cgi-bin/seed?{tor_switch_url}"><i class="ft-onion{class_tor_icon}"></i></a>
168                      </div>
169                      <div class="nav-item text-nowrap">
170                        <a class="nav-link px-3 active" aria_current="page" href="/">{self_alias[:12]}-{self_did[8:20]}</a>
171                      </div>
172                      <div class="nav-item text-nowrap">
173                        <a class="nav-link px-3" href="/cgi-bin/settings"><i class="fa-solid fa-gear"></i> Settings</a>
174                      </div>
175                      <div class="nav-item text-nowrap">
176                        <a class="nav-link px-3" href="/cgi-bin/signout"><i class="fa-solid fa-sign-out"></i> Sign out</a>
177                      </div>
178                    </div>
179                  </header>
180                  <div class="container-fluid">
181                    <div class="row">
182                      <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-dark sidebar collapse">
183                        <div class="position-sticky pt-3 sidebar-sticky">
184                          <ul class="nav flex-column">
185                          <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted text-uppercase">
186                            <span></span>
187                          </h6>
188                          <ul class="nav flex-column mb-2">
189                          </ul>
190                        </div>
191                      </nav>
192                  <main class="col-md-9 ms-sm-auto col-lg-10">
193                    <div class="container px-1 py-3">
194          '''
195  HTML_DASHBOARD_END = '''
196  </div>
197  </main>
198  </div>
199  </div>
200  '''
201  
202  HTML_AUTH_START = '''
203  <link href="/css/signin.css" rel="stylesheet">
204  </head>
205  <body class="text-center">
206  <main class="form-signin w-100 m-auto">
207  <form action="/" method="post">
208  <div class="mb-4" width="100%" style="font-size:2.5rem; font-weight:bold; color:#2470dc;">Cradicle</div>
209  '''
210  
211  HTML_AUTH_END_CREATE='''
212  <div class="form-floating">
213  <input type="text" class="form-control" id="floatingInput" name="alias" placeholder="user">
214  <label for="floatingInput">Alias</label>
215  </div>
216  <div class="form-floating" style="margin-top:10px;">
217  <input type="password" class="form-control" id="floatingPassword" name="password" placeholder="">
218  <label for="floatingPassword">Password</label>
219  </div>
220  <div class="form-floating">
221  <input type="password" class="form-control" id="floatingPassword2" name="password2" placeholder="">
222  <label for="floatingPassword2">Repeat Password</label>
223  </div>
224  <button class="w-100 btn btn-lg btn-primary" type="submit">Create</button>
225  </form>
226  </main>
227  '''
228  
229  HTML_AUTH_END_LOGIN='''
230  <div class="form-floating">
231  <input type="password" class="form-control" id="floatingPassword" name="password" placeholder="">
232  <label for="floatingPassword">Password</label>
233  </div>
234  <button class="w-100 btn btn-lg btn-primary" type="submit">Sign in</button>
235  </form>
236  </main>
237  '''
238  
239  dashboard_content = ''
240  dashboard_content += '<h4 class="text-center">Seed a Repo</h4>'
241  
242  # If RID was submitted, run crad seed
243  if rid and len(rid.strip()):
244      rid_clean = rid.strip()
245      ret,out,err = exec_command(crad_bin,['seed',rid_clean])
246      if ret:
247          dashboard_content += f'<div class="error-message">{html.escape(err)}</div>'
248      else:
249          dashboard_content += f'<div class="alert alert-success">Seeded {html.escape(rid_clean)} successfully</div>'
250  
251  # Seed form
252  dashboard_content += '''
253  <form method="get" action="/cgi-bin/seed">
254  <div class="input-group mt-3" style="max-width:600px;">
255  <input type="text" class="form-control" name="rid" placeholder="rad:z..." aria-label="Repository ID">
256  <button class="btn btn-primary" type="submit">Seed</button>
257  </div>
258  </form>
259  '''
260  
261  ret,out,err = exec_command(crad_bin,["self","--alias"])
262  ret2,out2,err2 = exec_command(crad_bin,["self","--authed"])
263  if ret:
264      print(HTML_AUTH_START)
265      print('<h1 class="h3 mb-3 fw-normal">Create a new identity</h1>')
266      print(HTML_AUTH_END_CREATE)
267  elif ret2:
268      print(HTML_AUTH_START)
269      print('<h1 class="h3 mb-3 fw-normal">Hello <i>'+html.escape(out)+'</i></h1>')
270      print(HTML_AUTH_END_LOGIN)
271  else:
272      print(HTML_DASHBOARD_START)
273      print(dashboard_content)
274      print(HTML_DASHBOARD_END)
275  
276  HTML_FOOTER='''
277  </body>
278  </html>
279  '''
280  
281  print(HTML_FOOTER)