Skip to content

Commit 1d93b6d

Browse files
committed
add generator for scripts;
add ui for making new nodes
1 parent 634d17f commit 1d93b6d

File tree

7 files changed

+268
-16
lines changed

7 files changed

+268
-16
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ Next new public nodes require increasing number of additional operations (+N ope
5050

5151
With simple UI (available on your VPN address with port 1655 by default)
5252

53-
![image](https://user-images.githubusercontent.com/6597086/66372742-5719e280-e9d9-11e9-9942-4577a47e913a.png)
53+
![image](https://user-images.githubusercontent.com/6597086/66646721-92c2df80-ec59-11e9-90b3-153b50dd38be.png)
54+
5455

5556

5657
## Installation

domain/monitor/assets.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

domain/monitor/assets/nodes.gotemplate

+173-1
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,26 @@
1010
display: flex;
1111
justify-content: center;
1212
}
13+
1314
.card {
1415
margin: 16px;
1516
padding: 5px;
1617
min-height: 30px;
1718
border-radius: 3px;
1819
box-shadow: 0px 1px 3px #777777;
1920
}
21+
2022
.name {
2123
font-size: large;
2224
font-weight: bold;
2325
padding-top: 3px;
2426
padding-bottom: 5px;
2527
}
28+
2629
.subnet {
2730
font-family: monospace;
2831
}
32+
2933
.status-pending {
3034
float: right;
3135
padding: 3px;
@@ -35,6 +39,7 @@
3539
color: #336699;
3640
text-decoration: none;
3741
}
42+
3843
.hostfile {
3944
float: right;
4045
padding: 3px;
@@ -45,15 +50,18 @@
4550
color: white;
4651
text-decoration: none;
4752
}
53+
4854
.container {
4955
display: block;
5056
vertical-align: middle;
5157
width: 800px;
5258
}
59+
5360
.public {
5461
font-weight: 100 !important;
5562
color: #84a3e1;
5663
}
64+
5765
.meta {
5866
margin: 16px;
5967
color: #84a3e1;
@@ -72,13 +80,107 @@
7280
.meta > a:hover {
7381
text-decoration: underline;
7482
}
83+
84+
hr {
85+
border: 1px solid #336699;
86+
border-radius: 2px;
87+
box-shadow: 0px 1px 2px #777777;
88+
margin: 16px;
89+
}
90+
91+
form {
92+
border-radius: 2px;
93+
box-shadow: 0px 1px 3px #777777;
94+
margin: 16px;
95+
padding: 6px;
96+
}
97+
98+
label {
99+
font-weight: bold;
100+
font-size: small;
101+
display: inline-block;
102+
padding: 3px;
103+
margin-bottom: 3px;
104+
}
105+
106+
input {
107+
display: inline-block;
108+
border: none;
109+
border-bottom: 1px dashed #777777;
110+
}
111+
112+
.gen {
113+
border-radius: 3px 3px 3px 3px;
114+
padding: 6px;
115+
background-color: #336699;
116+
color: white;
117+
border: none;
118+
font-size: large;
119+
width: 100%;
120+
}
121+
122+
.footer {
123+
text-align: center;
124+
}
125+
126+
select {
127+
display: inline-block;
128+
border: none;
129+
border-bottom: 1px dashed #777777;
130+
background-color: white;
131+
}
132+
133+
.err {
134+
border-radius: 2px;
135+
box-shadow: 0px 1px 3px #777777;
136+
margin: 16px;
137+
padding: 6px;
138+
border-left: 4px solid #ff0000;
139+
}
140+
141+
.warn {
142+
border-radius: 2px;
143+
box-shadow: 0px 1px 3px #777777;
144+
margin: 16px;
145+
padding: 6px;
146+
border-left: 4px solid #ffaa00;
147+
}
148+
149+
.add {
150+
border-radius: 3px 3px 3px 3px;
151+
padding: 6px;
152+
background-color: #84a3e1;
153+
color: white;
154+
border: none;
155+
margin: 1px;
156+
}
157+
75158
</style>
76159
</head>
77160
<body>
78161

79162
<div class="container">
163+
{{with .Error}}
164+
<div class="err">
165+
<h3>Error</h3>
166+
<p>{{.}}</p>
167+
</div>
168+
{{end}}
169+
{{with .Warning}}
170+
<div class="warn">
171+
<h3>Warning</h3>
172+
<p>{{.}}</p>
173+
</div>
174+
{{end}}
175+
{{if not .HasPublic}}
176+
<div class="warn">
177+
<h3>Warning</h3>
178+
<p>no public nodes available in the network</p>
179+
</div>
180+
{{end}}
80181
<div class="meta">
81-
<a href="../" download="{{.Service.Config.Name}}">{{.Service.Config.Name}}</a>, <span class="meta-address">{{.Service.Address}}</span>
182+
<a href="../" download="{{.Service.Config.Name}}">{{.Service.Config.Name}}</a>, <span
183+
class="meta-address">{{.Service.Address}}</span>
82184
</div>
83185
{{range .Nodes}}
84186
{{if .Fetched}}
@@ -95,6 +197,76 @@
95197
</div>
96198
{{end}}
97199
{{end}}
200+
{{if .HasPublic}}
201+
<form method="POST">
202+
<h2>Generate node script</h2>
203+
<label>
204+
Unique node name (required)
205+
<input type="text" placeholder="Node name" pattern="[a-z0-9]+" name="name"/>
206+
</label>
207+
<br/>
208+
<br/>
209+
<label>
210+
Platform
211+
<select name="platform">
212+
<option value="amd64" selected>x86-64</option>
213+
<option value="i386">x86-32</option>
214+
<option value="arm64">ARM64</option>
215+
<option value="armv7">ARM-7</option>
216+
<option value="armv6">ARM-6</option>
217+
<option value="armv5">ARM-5</option>
218+
</select>
219+
</label>
220+
<label>
221+
Prefix
222+
<input type="text" placeholder="x.y.z.t" name="prefix" value="172.173"/>
223+
</label>
224+
<label>
225+
Mask
226+
<input type="number" placeholder="8, 16, 24, 32" name="mask" value="16" pattern="[0-9]+" min="8"
227+
max="32"/>
228+
</label>
229+
<label>
230+
Port
231+
<input type="number" placeholder="random" name="port" value="" pattern="[0-9]+" min="0"
232+
max="65535"/>
233+
</label>
234+
<br/>
235+
<div>
236+
<ul id="publics">
237+
</ul>
238+
<button type="button" onclick="addPublic()" class="add">
239+
Add public address
240+
</button>
241+
</div>
242+
<br/>
243+
<div class="footer">
244+
<button type="submit" class="gen">Generate</button>
245+
</div>
246+
</form>
247+
{{end}}
98248
</div>
249+
<script>
250+
251+
function addPublic() {
252+
var li = document.createElement('li');
253+
var inp = document.createElement('input');
254+
li.appendChild(inp);
255+
inp.setAttribute("type", "text");
256+
inp.setAttribute("name", "public");
257+
inp.setAttribute("placeholder", "public address");
258+
259+
var btn = document.createElement("button");
260+
li.append(btn);
261+
btn.setAttribute("type", "button");
262+
btn.setAttribute("class", "add");
263+
btn.innerText = "remove";
264+
btn.onclick = function () {
265+
document.getElementById("publics").removeChild(li);
266+
};
267+
268+
document.getElementById("publics").appendChild(li);
269+
}
270+
</script>
99271
</body>
100272
</html>

domain/monitor/http_api.go

+50-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package monitor
33
import (
44
"bytes"
55
"github.com/gin-gonic/gin"
6+
"github.com/reddec/tinc-boot/domain/generator"
67
"github.com/reddec/tinc-boot/types"
78
"html/template"
89
"io/ioutil"
10+
"log"
911
"net/http"
1012
"path/filepath"
1113
)
@@ -20,6 +22,7 @@ func (ms *service) createAPI() *gin.Engine {
2022

2123
engine.GET("/", ms.apiServeHostFile)
2224
engine.GET("/ui", ms.apiUiNodes)
25+
engine.POST("/ui", ms.apiUiAddNode)
2326
engine.POST("/rpc/watch", ms.apiWatchNode)
2427
engine.POST("/rpc/forget", ms.apiForgetNode)
2528
engine.POST("/rpc/kill", ms.apiKillNode)
@@ -96,12 +99,56 @@ func (ms *service) apiGetNodeFile(gctx *gin.Context) {
9699
gctx.File(filepath.Join(ms.cfg.Hosts(), node))
97100
}
98101

102+
func (ms *service) apiUiAddNode(gctx *gin.Context) {
103+
var params = generator.Config{
104+
Network: ms.cfg.Network(),
105+
}
106+
if err := gctx.Bind(&params); err != nil {
107+
return
108+
}
109+
assembly, err := params.Generate(ms.cfg.Dir)
110+
if err != nil {
111+
ms.renderMainPage(gctx, err, "")
112+
return
113+
}
114+
var atLeastOnePublic bool
115+
for _, node := range ms.nodes.Copy() {
116+
if err := node.Client().PushNodeFile(params.Name, assembly.PublicKey); err != nil {
117+
log.Println("UI", err)
118+
} else if node.Public {
119+
atLeastOnePublic = true
120+
}
121+
}
122+
123+
if !atLeastOnePublic {
124+
ms.renderMainPage(gctx, nil, "can't distribute even to one public node")
125+
return
126+
}
127+
128+
gctx.Header("Content-Disposition", "attachment; filename=\""+params.Name+".sh\"")
129+
gctx.Data(http.StatusOK, "application/bash", assembly.Script)
130+
}
131+
99132
//go:generate go-bindata -o assets.go -pkg monitor --prefix assets/ assets/
100133
func (ms *service) apiUiNodes(gctx *gin.Context) {
101-
nodes := ms.nodes.Copy()
134+
ms.renderMainPage(gctx, nil, "")
135+
}
136+
137+
func (ms *service) renderMainPage(gctx *gin.Context, responseErr error, warn string) {
138+
list := ms.nodes.Copy()
139+
var hasPublic bool
140+
for _, n := range list {
141+
if n.Public {
142+
hasPublic = true
143+
break
144+
}
145+
}
102146
ms.renderTemplate(gctx, "nodes.gotemplate", gin.H{
103-
"Nodes": nodes,
104-
"Service": ms,
147+
"Nodes": list,
148+
"Service": ms,
149+
"Error": responseErr,
150+
"Warning": warn,
151+
"HasPublic": hasPublic,
105152
})
106153
}
107154

0 commit comments

Comments
 (0)