diff --git a/config.go b/config.go index 9de65b5..923d4f5 100644 --- a/config.go +++ b/config.go @@ -19,10 +19,10 @@ type ServerConfig struct { type UserConfig struct { Name string - Devices map[string]*DeviceConfig + Clients map[string]*ClientConfig } -type DeviceConfig struct { +type ClientConfig struct { Name string PrivateKey string PublicKey string @@ -74,21 +74,21 @@ func (cfg *ServerConfig) GetUserConfig(user string) *UserConfig { log.WithField("user", user).Info("No such user. Creating one.") c = &UserConfig{ Name: user, - Devices: make(map[string]*DeviceConfig), + Clients: make(map[string]*ClientConfig), } cfg.Users[user] = c } return c } -func NewDeviceConfig(ip net.IP) *DeviceConfig { +func NewClientConfig(ip net.IP) *ClientConfig { key, err := wgtypes.GeneratePrivateKey() if err != nil { log.Fatal(err) } - cfg := DeviceConfig{ - Name: "Unnamed Device", + cfg := ClientConfig{ + Name: "Unnamed Client", PrivateKey: key.String(), PublicKey: key.PublicKey().String(), IP: ip, diff --git a/go.mod b/go.mod index e0699d5..a594974 100644 --- a/go.mod +++ b/go.mod @@ -7,14 +7,18 @@ require ( github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect github.com/ddollar/forego v0.16.1 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible + github.com/dln/luxaforce v0.0.0-20180531194703-db2a6b5fc72d // indirect github.com/elazarl/go-bindata-assetfs v1.0.0 + github.com/futurenda/google-auth-id-token-verifier v0.0.0-20170311140316-2a5b89f28b7e // indirect github.com/google/nftables v0.0.0-20190430150743-07c974e3643d github.com/julienschmidt/httprouter v1.2.0 github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d // indirect github.com/mattn/goreman v0.2.1 // indirect github.com/mdlayher/wireguardctrl v0.0.0-20190419142446-a4a944b88a6b github.com/sirupsen/logrus v1.4.1 + github.com/toqueteos/webbrowser v1.1.0 // indirect github.com/vishvananda/netlink v1.0.0 github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc + google.golang.org/grpc v1.22.0 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 ) diff --git a/go.sum b/go.sum index 4e1fe36..ce5fb1e 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,28 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/EmbarkStudios/src v0.0.0-20190708074312-9ce83ae72fd4 h1:DemX5XAjzL1lvIuLVAMfX2grfxjZo7CQ9JH7FnB+3VQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/ddollar/forego v0.16.1 h1:HbAl3XyEdU1lw17PvZzqMzcx7b8BKZshEsdb4+1TI3Y= github.com/ddollar/forego v0.16.1/go.mod h1:moJFK5OqWdZeLVEYHynQRJqoKImixOuxgQBFCtoe0bU= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dln/luxaforce v0.0.0-20180531194703-db2a6b5fc72d h1:0MwrV1xaSUg0I5dzeoRuc6tg0UQACo98/ABwQcOFJg4= +github.com/dln/luxaforce v0.0.0-20180531194703-db2a6b5fc72d/go.mod h1:CahaXJvJI62kC6ikqP63GWz40sAB1igBuQDPlxY3qnk= github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/futurenda/google-auth-id-token-verifier v0.0.0-20170311140316-2a5b89f28b7e h1:qFV0nTBo/TC3ckN/VvyT0B1/VZb94AvSANfU7XR5lcM= +github.com/futurenda/google-auth-id-token-verifier v0.0.0-20170311140316-2a5b89f28b7e/go.mod h1:EX5Jbcw/PxsrlV7D2o77gpzcJevkXl3DQjkF8a0xNMI= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/nftables v0.0.0-20190430150743-07c974e3643d h1:TC4HtISCtWOTUVPQmq4CAqe0+8R2fvnkJlQn47ep2hI= @@ -43,6 +56,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/toqueteos/webbrowser v1.1.0 h1:Prj1okiysRgHPoe3B1bOIVxcv+UuSt525BDQmR5W0x0= +github.com/toqueteos/webbrowser v1.1.0/go.mod h1:Hqqqmzj8AHn+VlZyVjaRWY20i25hoOZGAABCcg2el4A= github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM= github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= @@ -50,8 +65,13 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190419010253-1f3472d942ba h1:h0zCzEL5UW1mERvwTN6AXcc75PpLkY6OcReia6Dq1BM= golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180925112736-b09afc3d579e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -59,9 +79,18 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be h1:mI+jhqkn68ybP0ORJqunXn+fq+Eeb4hHKqLQcFICjAc= golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.22.0 h1:J0UbZOIrCAl+fpTOf8YLs4dJo8L/owV4LYVtAXQoPkw= +google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/server.go b/server.go index b0b3427..0b8e68d 100644 --- a/server.go +++ b/server.go @@ -183,7 +183,7 @@ func (s *Server) allocateIP() net.IP { allocated := make(map[string]bool) allocated[s.ipAddr.String()] = true for _, cfg := range s.Config.Users { - for _, dev := range cfg.Devices { + for _, dev := range cfg.Clients { allocated[dev.IP.String()] = true } } @@ -235,7 +235,7 @@ func (s *Server) configureWireguard() error { peers := make([]wgtypes.PeerConfig, 0) for user, cfg := range s.Config.Users { - for id, dev := range cfg.Devices { + for id, dev := range cfg.Clients { pubKey, err := wgtypes.ParseKey(dev.PublicKey) if err != nil { return err @@ -249,7 +249,7 @@ func (s *Server) configureWireguard() error { AllowedIPs: allowedIPs, } - log.WithFields(log.Fields{"user": user, "device": id, "key": dev.PublicKey, "allowedIPs": peer.AllowedIPs}).Debug("Adding wireguard peer") + log.WithFields(log.Fields{"user": user, "client": id, "key": dev.PublicKey, "allowedIPs": peer.AllowedIPs}).Debug("Adding wireguard peer") peers = append(peers, peer) } @@ -278,11 +278,11 @@ func (s *Server) Start() error { } router := httprouter.New() - router.GET("/api/v1/users/:user/devices/:device", s.withAuth(s.GetDevice)) - router.PUT("/api/v1/users/:user/devices/:device", s.withAuth(s.EditDevice)) - router.DELETE("/api/v1/users/:user/devices/:device", s.withAuth(s.DeleteDevice)) - router.GET("/api/v1/users/:user/devices", s.withAuth(s.GetDevices)) - router.POST("/api/v1/users/:user/devices", s.withAuth(s.CreateDevice)) + router.GET("/api/v1/users/:user/clients/:client", s.withAuth(s.GetClient)) + router.PUT("/api/v1/users/:user/clients/:client", s.withAuth(s.EditClient)) + router.DELETE("/api/v1/users/:user/clients/:client", s.withAuth(s.DeleteClient)) + router.GET("/api/v1/users/:user/clients", s.withAuth(s.GetClients)) + router.POST("/api/v1/users/:user/clients", s.withAuth(s.CreateClient)) if *devUIServer != "" { log.Debug("Serving static assets proxying from development server: ", *devUIServer) @@ -361,17 +361,17 @@ func (s *Server) withAuth(handler httprouter.Handle) httprouter.Handle { } } -func (s *Server) GetDevices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - user := r.Context().Value("user") +func (s *Server) GetClients(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + user := r.Context().Value("user").(string) log.Debug(user) - err := json.NewEncoder(w).Encode(s.Config) + err := json.NewEncoder(w).Encode(s.Config.Users[user].Clients) if err != nil { log.Error(err) w.WriteHeader(http.StatusInternalServerError) } } -func (s *Server) GetDevice(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { +func (s *Server) GetClient(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { user := r.Context().Value("user").(string) usercfg := s.Config.Users[user] if usercfg == nil { @@ -379,8 +379,8 @@ func (s *Server) GetDevice(w http.ResponseWriter, r *http.Request, ps httprouter return } - device := usercfg.Devices[ps.ByName("device")] - if device == nil { + client := usercfg.Clients[ps.ByName("client")] + if client == nil { w.WriteHeader(http.StatusNotFound) return } @@ -400,11 +400,11 @@ DNS = %s PublicKey = %s AllowedIPs = %s Endpoint = %s -`, device.IP.String(), device.PrivateKey, "8.8.8.8", s.Config.PublicKey, allowedIPs, *wgEndpoint) +`, client.IP.String(), client.PrivateKey, "8.8.8.8", s.Config.PublicKey, allowedIPs, *wgEndpoint) return } - err := json.NewEncoder(w).Encode(device) + err := json.NewEncoder(w).Encode(client) if err != nil { log.Error(err) w.WriteHeader(http.StatusInternalServerError) @@ -412,7 +412,7 @@ Endpoint = %s } } -func (s *Server) EditDevice(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { +func (s *Server) EditClient(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { user := r.Context().Value("user").(string) usercfg := s.Config.Users[user] if usercfg == nil { @@ -420,13 +420,13 @@ func (s *Server) EditDevice(w http.ResponseWriter, r *http.Request, ps httproute return } - device := usercfg.Devices[ps.ByName("device")] - if device == nil { + client := usercfg.Clients[ps.ByName("client")] + if client == nil { w.WriteHeader(http.StatusNotFound) return } - cfg := DeviceConfig{} + cfg := ClientConfig{} if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil { log.Warn("Error parsing request: ", err) @@ -434,23 +434,23 @@ func (s *Server) EditDevice(w http.ResponseWriter, r *http.Request, ps httproute return } - log.Debugf("EditDevice: %#v", cfg) + log.Debugf("EditClient: %#v", cfg) if cfg.Name != "" { - device.Name = cfg.Name + client.Name = cfg.Name } s.reconfigure() w.WriteHeader(http.StatusOK) - if err := json.NewEncoder(w).Encode(device); err != nil { + if err := json.NewEncoder(w).Encode(client); err != nil { log.Error(err) w.WriteHeader(http.StatusInternalServerError) return } } -func (s *Server) DeleteDevice(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { +func (s *Server) DeleteClient(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { user := r.Context().Value("user").(string) usercfg := s.Config.Users[user] if usercfg == nil { @@ -458,32 +458,32 @@ func (s *Server) DeleteDevice(w http.ResponseWriter, r *http.Request, ps httprou return } - device := ps.ByName("device") - if usercfg.Devices[device] == nil { + client := ps.ByName("client") + if usercfg.Clients[client] == nil { w.WriteHeader(http.StatusNotFound) return } - delete(usercfg.Devices, device) + delete(usercfg.Clients, client) s.reconfigure() - log.WithField("user", user).Debug("Deleted device: ", device) + log.WithField("user", user).Debug("Deleted client: ", client) w.WriteHeader(http.StatusOK) } -func (s *Server) CreateDevice(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { +func (s *Server) CreateClient(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { s.mutex.Lock() defer s.mutex.Unlock() user := r.Context().Value("user").(string) - log.WithField("user", user).Debug("CreateDevice") + log.WithField("user", user).Debug("CreateClient") c := s.Config.GetUserConfig(user) log.Debugf("user config: %#v", c) i := 0 - for k := range c.Devices { + for k := range c.Clients { n, err := strconv.Atoi(k) if err != nil { log.Error(err) @@ -497,12 +497,12 @@ func (s *Server) CreateDevice(w http.ResponseWriter, r *http.Request, ps httprou i = i + 1 ip := s.allocateIP() - device := NewDeviceConfig(ip) - c.Devices[strconv.Itoa(i)] = device + client := NewClientConfig(ip) + c.Clients[strconv.Itoa(i)] = client s.reconfigure() - err := json.NewEncoder(w).Encode(device) + err := json.NewEncoder(w).Encode(client) if err != nil { log.Error(err) w.WriteHeader(http.StatusInternalServerError) diff --git a/ui/package-lock.json b/ui/package-lock.json index faa9e65..310457e 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -2861,9 +2861,15 @@ } }, "svelte": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.4.4.tgz", - "integrity": "sha512-O9tzroEWVPOQe1QITW1jP8LAJwXmCfDDGdkOCa9Y6NlJ+gQwn+/rhFbMQ+vu2PWPLZt1gxN8DjTFM4nOBuMLFg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.5.1.tgz", + "integrity": "sha512-iMnuyteFGQ8Yl68G/DHTHY1sLwoAMya1eS0ZOHIm/dqn2etR8WEe8hUAoluLryde4Cft4gvMhtHV3NhE60nBmQ==", + "dev": true + }, + "svelte-routing": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/svelte-routing/-/svelte-routing-1.2.0.tgz", + "integrity": "sha512-bOWejHnBor46uvQAz6u3HpN+EXNnNvQFY8Qja4aIbg+BVN0QmrdkCyR35/KVf1Mq/Jjp9juRZfiYcble+TErGg==", "dev": true }, "terser": { diff --git a/ui/package.json b/ui/package.json index 2fb9e19..d804ae9 100644 --- a/ui/package.json +++ b/ui/package.json @@ -11,7 +11,8 @@ "rollup-plugin-svelte": "^5.0.3", "rollup-plugin-terser": "^5.0.0", "sirv-cli": "^0.4.3", - "svelte": "^3.4.4" + "svelte": "^3.5.1", + "svelte-routing": "1.2.0" }, "scripts": { "build": "rollup -c", diff --git a/ui/public/global.css b/ui/public/global.css index 9d682a3..cbceade 100644 --- a/ui/public/global.css +++ b/ui/public/global.css @@ -1,61 +1,4 @@ -html, body { - position: relative; - width: 100%; - height: 100%; -} - body { - color: #333; - margin: 0; - padding: 8px; - box-sizing: border-box; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + padding-top: 5rem; } -a { - color: rgb(0,100,200); - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -a:visited { - color: rgb(0,80,160); -} - -label { - display: block; -} - -input, button, select, textarea { - font-family: inherit; - font-size: inherit; - padding: 0.4em; - margin: 0 0 0.5em 0; - box-sizing: border-box; - border: 1px solid #ccc; - border-radius: 2px; -} - -input:disabled { - color: #ccc; -} - -input[type="range"] { - height: 0; -} - -button { - background-color: #f4f4f4; - outline: none; -} - -button:active { - background-color: #ddd; -} - -button:focus { - border-color: #666; -} \ No newline at end of file diff --git a/ui/public/index.html b/ui/public/index.html index 3d6b697..642f404 100644 --- a/ui/public/index.html +++ b/ui/public/index.html @@ -1,11 +1,13 @@ - +
-+{client} +
diff --git a/ui/src/Nav.svelte b/ui/src/Nav.svelte new file mode 100644 index 0000000..1a29c67 --- /dev/null +++ b/ui/src/Nav.svelte @@ -0,0 +1,21 @@ + + +