admins can now delete devices

pull/69/head
James Batt 4 years ago
parent a569920d28
commit ddd030864c

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [next]
### Added
- Admin users can now delete devices from the "all devices" page (issue [#57](https://github.com/Place1/wg-access-server/issues/57))
### Bug Fixes
- Fixes website routing to solve 404s (issue [#56](https://github.com/Place1/wg-access-server/issues/56))

@ -56,7 +56,17 @@ func (d *DeviceService) DeleteDevice(ctx context.Context, req *proto.DeleteDevic
return nil, status.Errorf(codes.PermissionDenied, "not authenticated")
}
if err := d.DeviceManager.DeleteDevice(user.Subject, req.GetName()); err != nil {
deviceOwner := user.Subject
if req.Owner != nil {
if user.Claims.Contains("admin") {
deviceOwner = req.Owner.Value
} else {
return nil, status.Errorf(codes.PermissionDenied, "must be an admin")
}
}
if err := d.DeviceManager.DeleteDevice(deviceOwner, req.GetName()); err != nil {
ctxlogrus.Extract(ctx).Error(err)
return nil, status.Errorf(codes.Internal, "failed to delete device")
}

@ -2,6 +2,7 @@ syntax = "proto3";
package proto;
import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
@ -45,6 +46,11 @@ message ListDevicesRes {
message DeleteDeviceReq {
string name = 1;
// admin's may delete a device owned
// by someone other than the current user
// if empty, defaults to the current user
google.protobuf.StringValue owner = 2;
}
message ListAllDevicesReq {

@ -9,6 +9,7 @@ import (
proto "github.com/golang/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
wrappers "github.com/golang/protobuf/ptypes/wrappers"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
@ -280,6 +281,10 @@ func (m *ListDevicesRes) GetItems() []*Device {
type DeleteDeviceReq struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// admin's may delete a device owned
// by someone other than the current user
// if empty, defaults to the current user
Owner *wrappers.StringValue `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -317,6 +322,13 @@ func (m *DeleteDeviceReq) GetName() string {
return ""
}
func (m *DeleteDeviceReq) GetOwner() *wrappers.StringValue {
if m != nil {
return m.Owner
}
return nil
}
type ListAllDevicesReq struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
@ -400,40 +412,42 @@ func init() {
func init() { proto.RegisterFile("devices.proto", fileDescriptor_6d27ec3f2c0e2043) }
var fileDescriptor_6d27ec3f2c0e2043 = []byte{
// 513 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xdb, 0x6e, 0xd3, 0x40,
0x10, 0x8d, 0x93, 0xe6, 0xe2, 0x49, 0x5c, 0xe8, 0x04, 0xaa, 0x95, 0x01, 0x35, 0x72, 0x55, 0x29,
0x4f, 0xa9, 0x08, 0x42, 0x82, 0x07, 0x24, 0x82, 0x5a, 0x84, 0x00, 0x21, 0x64, 0xf1, 0x6e, 0x39,
0xde, 0xa1, 0x5d, 0xd5, 0xb7, 0x7a, 0xb7, 0x41, 0xf9, 0x00, 0xbe, 0x93, 0x5f, 0x41, 0xbb, 0xeb,
0xa4, 0x49, 0x5a, 0x2e, 0x4f, 0xf6, 0x9c, 0x73, 0xe6, 0x76, 0xc6, 0x06, 0x8f, 0xd3, 0x42, 0x24,
0x24, 0x27, 0x65, 0x55, 0xa8, 0x02, 0xdb, 0xe6, 0xe1, 0x1f, 0x5d, 0x14, 0xc5, 0x45, 0x4a, 0xa7,
0x26, 0x9a, 0xdf, 0x7c, 0x3f, 0x55, 0x22, 0x23, 0xa9, 0xe2, 0xac, 0xb4, 0x3a, 0xff, 0xc9, 0xae,
0x80, 0xb2, 0x52, 0x2d, 0x2d, 0x19, 0xfc, 0x6a, 0x41, 0xe7, 0xcc, 0x94, 0x45, 0x84, 0xbd, 0x3c,
0xce, 0x88, 0x39, 0x23, 0x67, 0xec, 0x86, 0xe6, 0x1d, 0x1f, 0x41, 0xbb, 0xf8, 0x91, 0x53, 0xc5,
0x9a, 0x06, 0xb4, 0x01, 0x3e, 0x03, 0x28, 0x6f, 0xe6, 0xa9, 0x48, 0xa2, 0x2b, 0x5a, 0xb2, 0x96,
0xa1, 0x5c, 0x8b, 0x7c, 0xa2, 0x25, 0x32, 0xe8, 0xc6, 0x9c, 0x57, 0x24, 0x25, 0xdb, 0x33, 0xdc,
0x2a, 0xc4, 0xd7, 0x00, 0x49, 0x45, 0xb1, 0x22, 0x1e, 0xc5, 0x8a, 0xb5, 0x47, 0xce, 0xb8, 0x3f,
0xf5, 0x27, 0x76, 0xbe, 0xc9, 0x6a, 0xbe, 0xc9, 0xb7, 0xd5, 0x02, 0xa1, 0x5b, 0xab, 0x67, 0x0a,
0x9f, 0x82, 0x9b, 0x14, 0x79, 0x4e, 0x89, 0x22, 0xce, 0x3a, 0x23, 0x67, 0xdc, 0x0b, 0x6f, 0x01,
0xfc, 0x08, 0xc3, 0x34, 0x96, 0x2a, 0xba, 0x8c, 0x73, 0x2e, 0x2f, 0xe3, 0x2b, 0x8a, 0xb4, 0x0b,
0xac, 0xfb, 0xcf, 0x0e, 0x07, 0x3a, 0xed, 0xc3, 0x2a, 0x4b, 0xe3, 0x78, 0x0c, 0x5e, 0x45, 0x09,
0x89, 0x05, 0x45, 0xf3, 0xa5, 0x22, 0xc9, 0x7a, 0x23, 0x67, 0xdc, 0x0a, 0x07, 0x35, 0xf8, 0x4e,
0x63, 0x78, 0x02, 0xfb, 0xaa, 0x8a, 0x73, 0x99, 0x09, 0x55, 0xab, 0x5c, 0xa3, 0xf2, 0x56, 0xa8,
0x95, 0xf9, 0xd0, 0xa3, 0x9c, 0x97, 0x85, 0xc8, 0x15, 0x03, 0xe3, 0xc5, 0x3a, 0xd6, 0x2e, 0x1a,
0x3b, 0x23, 0xe3, 0x7a, 0xdf, 0xba, 0x68, 0x90, 0x2f, 0xda, 0xfa, 0x23, 0xe8, 0x5b, 0x9a, 0xb2,
0x58, 0xa4, 0x6c, 0x60, 0x78, 0x9b, 0x71, 0xae, 0x11, 0x3d, 0x82, 0x15, 0x94, 0x55, 0xb1, 0x10,
0x9c, 0x2a, 0xe6, 0x19, 0x8d, 0x67, 0xd0, 0xaf, 0x35, 0x18, 0xcc, 0x60, 0x30, 0xe3, 0xdc, 0xde,
0x38, 0xa4, 0xeb, 0x7b, 0xcf, 0xbc, 0x7d, 0xd0, 0xe6, 0xce, 0x41, 0x83, 0x87, 0xb0, 0xff, 0x59,
0x48, 0x65, 0x6b, 0xc8, 0x90, 0xae, 0x83, 0x97, 0x3b, 0x88, 0xc4, 0x63, 0x68, 0x0b, 0x45, 0x99,
0x64, 0xce, 0xa8, 0x35, 0xee, 0x4f, 0x3d, 0x6b, 0xf6, 0xa4, 0xee, 0x6b, 0xb9, 0xe0, 0x04, 0x1e,
0x9c, 0x51, 0x4a, 0x8a, 0xfe, 0x3a, 0x4e, 0x30, 0x84, 0x03, 0x5d, 0x7d, 0x96, 0xa6, 0x1b, 0x2d,
0x5f, 0xdd, 0x05, 0xff, 0xaf, 0xeb, 0xf4, 0x67, 0x13, 0xba, 0x75, 0x0e, 0x3e, 0x07, 0x77, 0xed,
0x06, 0x0e, 0x6b, 0xf9, 0xa6, 0x3f, 0xfe, 0x76, 0x8d, 0xa0, 0x81, 0x6f, 0xa0, 0xbf, 0xb1, 0x2b,
0x3e, 0xae, 0xf9, 0x6d, 0x47, 0xfc, 0x7b, 0x61, 0x19, 0x34, 0xf0, 0x2d, 0x0c, 0x36, 0x77, 0xc6,
0xc3, 0x75, 0xfd, 0x2d, 0x23, 0xfc, 0xc3, 0x3b, 0x5f, 0xe9, 0xb9, 0xfe, 0x4f, 0x83, 0x06, 0xbe,
0xb7, 0x66, 0xdf, 0x6e, 0x8e, 0x6c, 0xa3, 0xd9, 0x96, 0x4b, 0xfe, 0x9f, 0x18, 0x19, 0x34, 0xe6,
0x1d, 0x43, 0xbd, 0xf8, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x89, 0x1c, 0x7b, 0x9d, 0x48, 0x04, 0x00,
0x00,
// 548 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0xdb, 0x6e, 0xd3, 0x4e,
0x10, 0xc6, 0xe3, 0xa6, 0x39, 0x78, 0x1c, 0xf7, 0xff, 0xef, 0x06, 0xaa, 0x95, 0x29, 0x34, 0x72,
0x85, 0x94, 0xab, 0x54, 0x04, 0x21, 0xc1, 0x05, 0x12, 0x41, 0x2d, 0x42, 0x80, 0x10, 0x32, 0x08,
0x89, 0x2b, 0x6b, 0x63, 0x0f, 0xa9, 0x55, 0x9f, 0xba, 0xbb, 0x49, 0x95, 0x07, 0xe0, 0x39, 0x79,
0x15, 0xe4, 0xdd, 0x4d, 0xea, 0x24, 0xe5, 0x70, 0x95, 0xec, 0xf7, 0x7d, 0xb3, 0x33, 0xfe, 0x8d,
0x0d, 0x6e, 0x8c, 0x8b, 0x24, 0x42, 0x31, 0x2a, 0x79, 0x21, 0x0b, 0xd2, 0x52, 0x3f, 0xde, 0xa3,
0x59, 0x51, 0xcc, 0x52, 0x3c, 0x53, 0xa7, 0xe9, 0xfc, 0xfb, 0xd9, 0x0d, 0x67, 0x65, 0x89, 0xdc,
0xc4, 0xbc, 0x93, 0x6d, 0x5f, 0x26, 0x19, 0x0a, 0xc9, 0xb2, 0xd2, 0x04, 0x1e, 0x6c, 0x07, 0x30,
0x2b, 0xe5, 0x52, 0x9b, 0xfe, 0xcf, 0x26, 0xb4, 0xcf, 0x55, 0x5b, 0x42, 0x60, 0x3f, 0x67, 0x19,
0x52, 0x6b, 0x60, 0x0d, 0xed, 0x40, 0xfd, 0x27, 0xf7, 0xa0, 0x55, 0xdc, 0xe4, 0xc8, 0xe9, 0x9e,
0x12, 0xf5, 0x81, 0x3c, 0x04, 0x28, 0xe7, 0xd3, 0x34, 0x89, 0xc2, 0x2b, 0x5c, 0xd2, 0xa6, 0xb2,
0x6c, 0xad, 0xbc, 0xc7, 0x25, 0xa1, 0xd0, 0x61, 0x71, 0xcc, 0x51, 0x08, 0xba, 0xaf, 0xbc, 0xd5,
0x91, 0xbc, 0x00, 0x88, 0x38, 0x32, 0x89, 0x71, 0xc8, 0x24, 0x6d, 0x0d, 0xac, 0xa1, 0x33, 0xf6,
0x46, 0x7a, 0xbe, 0xd1, 0x6a, 0xbe, 0xd1, 0x97, 0xd5, 0x03, 0x04, 0xb6, 0x49, 0x4f, 0x24, 0x39,
0x06, 0x3b, 0x2a, 0xf2, 0x1c, 0x23, 0x89, 0x31, 0x6d, 0x0f, 0xac, 0x61, 0x37, 0xb8, 0x15, 0xc8,
0x3b, 0xe8, 0xa7, 0x4c, 0xc8, 0xf0, 0x92, 0xe5, 0xb1, 0xb8, 0x64, 0x57, 0x18, 0x56, 0x14, 0x68,
0xe7, 0xaf, 0x1d, 0x0e, 0xab, 0xb2, 0xb7, 0xab, 0xaa, 0x4a, 0x27, 0xa7, 0xe0, 0x72, 0x8c, 0x30,
0x59, 0x60, 0x38, 0x5d, 0x4a, 0x14, 0xb4, 0x3b, 0xb0, 0x86, 0xcd, 0xa0, 0x67, 0xc4, 0xd7, 0x95,
0x46, 0x1e, 0xc3, 0x81, 0xe4, 0x2c, 0x17, 0x59, 0x22, 0x4d, 0xca, 0x56, 0x29, 0x77, 0xa5, 0xea,
0x98, 0x07, 0x5d, 0xcc, 0xe3, 0xb2, 0x48, 0x72, 0x49, 0x41, 0xb1, 0x58, 0x9f, 0x2b, 0x8a, 0x0a,
0x67, 0xa8, 0xa8, 0x3b, 0x9a, 0xa2, 0x52, 0x3e, 0x56, 0xe8, 0x4f, 0xc0, 0xd1, 0x36, 0x66, 0x2c,
0x49, 0x69, 0x4f, 0xf9, 0xba, 0xe2, 0xa2, 0x52, 0xaa, 0x11, 0x74, 0xa0, 0xe4, 0xc5, 0x22, 0x89,
0x91, 0x53, 0x57, 0x65, 0x5c, 0xa5, 0x7e, 0x32, 0xa2, 0x3f, 0x81, 0xde, 0x24, 0x8e, 0xf5, 0x8e,
0x03, 0xbc, 0xbe, 0x73, 0xcd, 0x9b, 0x0b, 0xdd, 0xdb, 0x5a, 0xa8, 0xff, 0x3f, 0x1c, 0x7c, 0x48,
0x84, 0xd4, 0x77, 0x88, 0x00, 0xaf, 0xfd, 0x67, 0x5b, 0x8a, 0x20, 0xa7, 0xd0, 0x4a, 0x24, 0x66,
0x82, 0x5a, 0x83, 0xe6, 0xd0, 0x19, 0xbb, 0x1a, 0xf6, 0xc8, 0xf4, 0xd5, 0x9e, 0xff, 0x0d, 0xfe,
0x3b, 0xc7, 0x14, 0x25, 0xfe, 0x79, 0x9c, 0x71, 0xfd, 0xad, 0x73, 0xc6, 0xc7, 0x3b, 0xfb, 0xfb,
0x2c, 0x79, 0x92, 0xcf, 0xbe, 0xb2, 0x74, 0x8e, 0xe6, 0x9d, 0xf4, 0xfb, 0x70, 0x58, 0x4d, 0x34,
0x49, 0xd3, 0xda, 0x98, 0xcf, 0x77, 0xc5, 0x7f, 0x9b, 0x74, 0xfc, 0x63, 0x0f, 0x3a, 0xa6, 0x86,
0x3c, 0x01, 0x7b, 0x4d, 0x90, 0xf4, 0x4d, 0xbc, 0xce, 0xd4, 0xdb, 0xbc, 0xc3, 0x6f, 0x90, 0x97,
0xe0, 0xd4, 0xf8, 0x90, 0xfb, 0xc6, 0xdf, 0xa4, 0xe8, 0xdd, 0x29, 0x0b, 0xbf, 0x41, 0x5e, 0x41,
0xaf, 0xce, 0x89, 0x1c, 0xad, 0xef, 0xdf, 0x80, 0xe7, 0x1d, 0xed, 0x90, 0xb9, 0xa8, 0xbe, 0x6d,
0xbf, 0x41, 0xde, 0xe8, 0x05, 0xdd, 0x3e, 0x39, 0xa1, 0xb5, 0x66, 0x1b, 0x94, 0xbc, 0xdf, 0x39,
0xc2, 0x6f, 0x4c, 0xdb, 0xca, 0x7a, 0xfa, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x66, 0x8c, 0x07, 0x7b,
0x9c, 0x04, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

@ -7,7 +7,7 @@ const backend = window.location.origin + '/api';
export const grpc = {
server: new Server(backend),
devices: new Devices(backend),
}
};
// https://github.com/SafetyCulture/grpc-web-devtools
const devtools = (window as any).__GRPCWEB_DEVTOOLS__;

@ -2,11 +2,7 @@ import React from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';
import Box from '@material-ui/core/Box';
import Navigation from './components/Navigation';
import {
BrowserRouter as Router,
Switch,
Route,
} from 'react-router-dom';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { observer } from 'mobx-react';
import { grpc } from './Api';
import { AppState } from './AppState';
@ -15,14 +11,13 @@ import { AllDevices } from './pages/admin/AllDevices';
@observer
export class App extends React.Component {
async componentDidMount() {
AppState.info = await grpc.server.info({});
}
render() {
if (!AppState.info) {
return <p>loading...</p>
return <p>loading...</p>;
}
return (
<Router>
@ -31,11 +26,11 @@ export class App extends React.Component {
<Box component="div" m={2}>
<Switch>
<Route exact path="/" component={YourDevices} />
{AppState.info.isAdmin &&
{AppState.info.isAdmin && (
<>
<Route exact path="/admin/all-devices" component={AllDevices} />
</>
}
)}
</Switch>
</Box>
</Router>

@ -2,10 +2,8 @@ import { observable } from 'mobx';
import { InfoRes } from './sdk/server_pb';
class GlobalAppState {
@observable
info?: InfoRes.AsObject;
}
export const AppState = new GlobalAppState();
@ -15,5 +13,5 @@ console.info('see global app state by typing "window.AppState"');
Object.assign(window as any, {
get AppState() {
return JSON.parse(JSON.stringify(AppState));
}
},
});

@ -1,8 +1,8 @@
import formatDistance from "date-fns/formatDistance";
import formatDistance from 'date-fns/formatDistance';
import timestamp_pb from 'google-protobuf/google/protobuf/timestamp_pb';
import { toDate } from "./Api";
import { fromResource, lazyObservable } from "mobx-utils";
import { toast } from "./components/Toast";
import { toDate } from './Api';
import { fromResource, lazyObservable } from 'mobx-utils';
import { toast } from './components/Toast';
export function sleep(seconds: number) {
return new Promise((resolve) => {
@ -22,7 +22,7 @@ export function lastSeen(timestamp: timestamp_pb.Timestamp.AsObject | undefined)
}
export function lazy<T>(cb: () => Promise<T>) {
const resource = lazyObservable<T>(async sink => {
const resource = lazyObservable<T>(async (sink) => {
sink(await cb());
});
@ -41,7 +41,7 @@ export function autorefresh<T>(seconds: number, cb: () => Promise<T>) {
let sink: ((next: T) => void) | undefined;
const resource = fromResource<T>(
async s => {
async (s) => {
sink = s;
running = true;
while (running) {
@ -51,7 +51,7 @@ export function autorefresh<T>(seconds: number, cb: () => Promise<T>) {
},
() => {
running = false;
}
},
);
return {

@ -28,7 +28,6 @@ interface Props {
@observer
export class AddDevice extends React.Component<Props> {
@observable
dialogOpen = false;
@ -81,25 +80,22 @@ export class AddDevice extends React.Component<Props> {
this.configFileUri = URL.createObjectURL(new Blob([configFile]));
this.dialogOpen = true;
this.reset();
} catch (error) {
console.log(error);
// TODO: unwrap grpc error message
this.error = 'failed';
}
}
};
reset = () => {
this.formState.name = '';
}
};
render() {
return (
<>
<Card>
<CardHeader
title="Add A Device"
/>
<CardHeader title="Add A Device" />
<CardContent>
<form onSubmit={this.submit}>
<FormControl error={!!this.error} fullWidth>
@ -107,47 +103,29 @@ export class AddDevice extends React.Component<Props> {
<Input
id="device-name"
value={this.formState.name}
onChange={(event) => this.formState.name = event.currentTarget.value}
onChange={(event) => (this.formState.name = event.currentTarget.value)}
aria-describedby="device-name-text"
/>
<FormHelperText id="device-name-text">{this.error}</FormHelperText>
</FormControl>
<Typography component="div" align="right">
<Button
color="secondary"
type="button"
onClick={this.reset}
>
<Button color="secondary" type="button" onClick={this.reset}>
Cancel
</Button>
<Button
color="primary"
variant="contained"
endIcon={<AddIcon />}
type="submit"
>
<Button color="primary" variant="contained" endIcon={<AddIcon />} type="submit">
Add
</Button>
</Typography>
</form>
</CardContent>
</Card>
<Dialog
disableBackdropClick
disableEscapeKeyDown
maxWidth="xl"
open={this.dialogOpen}
>
<Dialog disableBackdropClick disableEscapeKeyDown maxWidth="xl" open={this.dialogOpen}>
<DialogTitle>Get Connected</DialogTitle>
<DialogContent>
<GetConnected
qrCodeUri={this.qrCode!}
configFile={this.configFile!}
configFileUri={this.configFileUri!}
/>
<GetConnected qrCodeUri={this.qrCode!} configFile={this.configFile!} configFileUri={this.configFileUri!} />
</DialogContent>
<DialogActions>
<Button color="secondary" variant="outlined" onClick={() => this.dialogOpen = false}>
<Button color="secondary" variant="outlined" onClick={() => (this.dialogOpen = false)}>
Done
</Button>
</DialogActions>

@ -11,7 +11,7 @@ import { lastSeen } from '../Util';
import { AppState } from '../AppState';
import { IconMenu } from './IconMenu';
import { PopoverDisplay } from './PopoverDisplay';
import { Device } from '../sdk/devices_pb'
import { Device } from '../sdk/devices_pb';
import { grpc } from '../Api';
import { observer } from 'mobx-react';
@ -42,10 +42,7 @@ export class DeviceListItem extends React.Component<Props> {
avatar={
<Avatar style={{ backgroundColor: device.connected ? '#76de8a' : '#bdbdbd' }}>
{/* <DonutSmallIcon /> */}
{device.connected
? <WifiIcon />
: <WifiOffIcon />
}
{device.connected ? <WifiIcon /> : <WifiOffIcon />}
</Avatar>
}
action={
@ -59,7 +56,7 @@ export class DeviceListItem extends React.Component<Props> {
<CardContent>
<table cellPadding="5">
<tbody>
{AppState.info?.metadataEnabled && device.connected &&
{AppState.info?.metadataEnabled && device.connected && (
<>
<tr>
<td>Endpoint</td>
@ -74,8 +71,8 @@ export class DeviceListItem extends React.Component<Props> {
<td>{numeral(device.receiveBytes).format('0b')}</td>
</tr>
</>
}
{AppState.info?.metadataEnabled && !device.connected &&
)}
{AppState.info?.metadataEnabled && !device.connected && (
<>
<tr>
<td>Disconnected</td>
@ -85,10 +82,12 @@ export class DeviceListItem extends React.Component<Props> {
<td>{lastSeen(device.lastHandshakeTime)}</td>
</tr>
</>
}
)}
<tr>
<td>Public key</td>
<td><PopoverDisplay label="show">{device.publicKey}</PopoverDisplay></td>
<td>
<PopoverDisplay label="show">{device.publicKey}</PopoverDisplay>
</td>
</tr>
</tbody>
</table>

@ -9,7 +9,6 @@ import { AddDevice } from './AddDevice';
@observer
export class Devices extends React.Component {
@observable
devices = autorefresh(5, async () => {
return (await grpc.devices.listDevices({})).items;
@ -21,7 +20,7 @@ export class Devices extends React.Component {
render() {
if (!this.devices.current) {
return <p>loading...</p>
return <p>loading...</p>;
}
return (
<Grid container spacing={3} justify="center">

@ -7,7 +7,7 @@ import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import Typography from '@material-ui/core/Typography';
import DescriptionOutlined from '@material-ui/icons/DescriptionOutlined'
import DescriptionOutlined from '@material-ui/icons/DescriptionOutlined';
import { MacOSIcon, IosIcon, WindowsIcon, LinuxIcon, AndroidIcon } from './Icons';
import { TabPanel } from './TabPanel';
import { Platform, getPlatform } from '../Platform';
@ -182,10 +182,7 @@ export class GetConnected extends React.Component<Props> {
<Typography variant="body1" component="pre" style={{ maxWidth: '100%', overflow: 'auto' }}>
{this.props.configFile}
</Typography>
<Button
color="primary"
onClick={() => setClipboard(this.props.configFile)}
>
<Button color="primary" onClick={() => setClipboard(this.props.configFile)}>
Copy To Clipboard
</Button>
</Grid>

@ -10,7 +10,7 @@ import Link from '@material-ui/core/Link';
import Button from '@material-ui/core/Button';
import Chip from '@material-ui/core/Chip';
const useStyles = makeStyles(theme => ({
const useStyles = makeStyles((theme) => ({
title: {
flexGrow: 1,
},
@ -23,27 +23,31 @@ export default function Navigation() {
<AppBar position="static">
<Toolbar>
<Typography variant="h6" className={classes.title}>
<span>Welcome</span>
{AppState.info?.isAdmin &&
<Chip label="admin" color="secondary" variant="outlined" size="small" style={{ marginLeft: 20, background: 'white' }} />
}
<Link to="/" color="inherit" component={NavLink}>
Welcome
</Link>
{AppState.info?.isAdmin && (
<Chip
label="admin"
color="secondary"
variant="outlined"
size="small"
style={{ marginLeft: 20, background: 'white' }}
/>
)}
</Typography>
{AppState.info?.isAdmin &&
{AppState.info?.isAdmin && (
<Link to="/admin/all-devices" color="inherit" component={NavLink}>
<Button color="inherit">
All Devices
</Button>
<Button color="inherit">All Devices</Button>
</Link>
}
)}
{hasAuthCookie &&
{hasAuthCookie && (
<Link href="/signout" color="inherit">
<Button color="inherit">
Logout
</Button>
<Button color="inherit">Logout</Button>
</Link>
}
)}
</Toolbar>
</AppBar>
);

@ -15,7 +15,13 @@ export class PopoverDisplay extends React.Component<Props> {
render() {
return (
<React.Fragment>
<Button size="small" variant="outlined" color="secondary" style={{padding: 0}} onClick={event => this.setState({ anchorEl: event.currentTarget })}>
<Button
size="small"
variant="outlined"
color="secondary"
style={{ padding: 0 }}
onClick={(event) => this.setState({ anchorEl: event.currentTarget })}
>
{this.props.label}
</Button>
<Popover

@ -0,0 +1,40 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import Dialog from '@material-ui/core/Dialog';
import Typography from '@material-ui/core/Typography';
import DialogTitle from '@material-ui/core/DialogTitle';
import DialogContent from '@material-ui/core/DialogContent';
import DialogActions from '@material-ui/core/DialogActions';
import Button from '@material-ui/core/Button';
import DialogContentText from '@material-ui/core/DialogContentText';
export function present<T>(content: (close: (result: T) => void) => React.ReactNode) {
const root = document.createElement('div');
document.body.appendChild(root);
return new Promise<T>((resolve) => {
const close = (result: T) => {
unmountComponentAtNode(root);
resolve(result);
};
render(<>{content(close)}</>, root);
});
}
export function confirm(msg: string): Promise<boolean> {
return present<boolean>((close) => (
<Dialog open={true} onClose={() => close(false)}>
<DialogTitle>Confirm</DialogTitle>
<DialogContent>
<DialogContentText>{msg}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => close(false)} variant="contained" color="primary" autoFocus>
Cancel
</Button>
<Button onClick={() => close(true)} variant="outlined" color="secondary">
Ok
</Button>
</DialogActions>
</Dialog>
));
}

@ -3,8 +3,6 @@ import { Devices } from '../components/Devices';
export class YourDevices extends React.Component {
render() {
return (
<Devices />
);
return <Devices />;
}
}

@ -5,21 +5,33 @@ import TableCell from '@material-ui/core/TableCell';
import TableContainer from '@material-ui/core/TableContainer';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Button from '@material-ui/core/Button';
import { observer } from 'mobx-react';
import { grpc } from '../../Api';
import { lastSeen, lazy } from '../../Util';
import { Device } from '../../sdk/devices_pb';
import { confirm } from '../../components/Present';
@observer
export class AllDevices extends React.Component {
devices = lazy(async () => {
const res = await grpc.devices.listAllDevices({});
return res.items;
});
deleteDevice = async (device: Device.AsObject) => {
if (await confirm('Are you sure?')) {
await grpc.devices.deleteDevice({
name: device.name,
owner: { value: device.owner },
});
await this.devices.refresh();
}
};
render() {
if (!this.devices.current) {
return <p>loading...</p>
return <p>loading...</p>;
}
const rows = this.devices.current;
@ -27,7 +39,7 @@ export class AllDevices extends React.Component {
// show the provider column
// when there is more than 1 provider in use
// i.e. not all devices are from the same auth provider.
const showProviderCol = rows.length >= 2 && rows.some(r => r.ownerProvider !== rows[0].ownerProvider);
const showProviderCol = rows.length >= 2 && rows.some((r) => r.ownerProvider !== rows[0].ownerProvider);
return (
<TableContainer>
@ -35,12 +47,11 @@ export class AllDevices extends React.Component {
<TableHead>
<TableRow>
<TableCell>Owner</TableCell>
{showProviderCol &&
<TableCell>Auth Provider</TableCell>
}
{showProviderCol && <TableCell>Auth Provider</TableCell>}
<TableCell>Device</TableCell>
<TableCell>Connected</TableCell>
<TableCell>Last Seen</TableCell>
<TableCell>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
@ -49,12 +60,15 @@ export class AllDevices extends React.Component {
<TableCell component="th" scope="row">
{row.ownerName || row.ownerEmail || row.owner}
</TableCell>
{showProviderCol &&
<TableCell>{row.ownerProvider}</TableCell>
}
{showProviderCol && <TableCell>{row.ownerProvider}</TableCell>}
<TableCell>{row.name}</TableCell>
<TableCell>{row.connected ? 'yes' : 'no'}</TableCell>
<TableCell>{lastSeen(row.lastHandshakeTime)}</TableCell>
<TableCell>
<Button variant="outlined" color="secondary" onClick={() => this.deleteDevice(row)}>
Delete
</Button>
</TableCell>
</TableRow>
))}
</TableBody>

@ -5,11 +5,11 @@
import * as jspb from 'google-protobuf';
import * as grpcWeb from 'grpc-web';
import * as googleProtobufWrappers from 'google-protobuf/google/protobuf/wrappers_pb';
import * as googleProtobufTimestamp from 'google-protobuf/google/protobuf/timestamp_pb';
import * as googleProtobufEmpty from 'google-protobuf/google/protobuf/empty_pb';
export class Devices {
private client_ = new grpcWeb.GrpcWebClientBase({
format: 'text',
});
@ -17,31 +17,28 @@ export class Devices {
private methodInfoAddDevice = new grpcWeb.AbstractClientBase.MethodInfo(
Device,
(req: AddDeviceReq) => req.serializeBinary(),
Device.deserializeBinary
Device.deserializeBinary,
);
private methodInfoListDevices = new grpcWeb.AbstractClientBase.MethodInfo(
ListDevicesRes,
(req: ListDevicesReq) => req.serializeBinary(),
ListDevicesRes.deserializeBinary
ListDevicesRes.deserializeBinary,
);
private methodInfoDeleteDevice = new grpcWeb.AbstractClientBase.MethodInfo(
googleProtobufEmpty.Empty,
(req: DeleteDeviceReq) => req.serializeBinary(),
googleProtobufEmpty.Empty.deserializeBinary
googleProtobufEmpty.Empty.deserializeBinary,
);
private methodInfoListAllDevices = new grpcWeb.AbstractClientBase.MethodInfo(
ListAllDevicesRes,
(req: ListAllDevicesReq) => req.serializeBinary(),
ListAllDevicesRes.deserializeBinary
ListAllDevicesRes.deserializeBinary,
);
constructor(
private hostname: string,
private defaultMetadata?: () => grpcWeb.Metadata,
) { }
constructor(private hostname: string, private defaultMetadata?: () => grpcWeb.Metadata) {}
addDevice(req: AddDeviceReq.AsObject, metadata?: grpcWeb.Metadata): Promise<Device.AsObject> {
return new Promise((resolve, reject) => {
@ -81,7 +78,10 @@ export class Devices {
});
}
deleteDevice(req: DeleteDeviceReq.AsObject, metadata?: grpcWeb.Metadata): Promise<googleProtobufEmpty.Empty.AsObject> {
deleteDevice(
req: DeleteDeviceReq.AsObject,
metadata?: grpcWeb.Metadata,
): Promise<googleProtobufEmpty.Empty.AsObject> {
return new Promise((resolve, reject) => {
const message = DeleteDeviceReqFromObject(req);
this.client_.rpcCall(
@ -118,44 +118,36 @@ export class Devices {
);
});
}
}
export declare namespace Device {
export type AsObject = {
name: string,
owner: string,
publicKey: string,
address: string,
createdAt?: googleProtobufTimestamp.Timestamp.AsObject,
connected: boolean,
lastHandshakeTime?: googleProtobufTimestamp.Timestamp.AsObject,
receiveBytes: number,
transmitBytes: number,
endpoint: string,
ownerName: string,
ownerEmail: string,
ownerProvider: string,
}
name: string;
owner: string;
publicKey: string;
address: string;
createdAt?: googleProtobufTimestamp.Timestamp.AsObject;
connected: boolean;
lastHandshakeTime?: googleProtobufTimestamp.Timestamp.AsObject;
receiveBytes: number;
transmitBytes: number;
endpoint: string;
ownerName: string;
ownerEmail: string;
ownerProvider: string;
};
}
export class Device extends jspb.Message {
private static repeatedFields_ = [
];
private static repeatedFields_ = [];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, Device.repeatedFields_, null);
}
getName(): string {
return jspb.Message.getFieldWithDefault(this, 1, "");
return jspb.Message.getFieldWithDefault(this, 1, '');
}
setName(value: string): void {
@ -163,7 +155,7 @@ export class Device extends jspb.Message {
}
getOwner(): string {
return jspb.Message.getFieldWithDefault(this, 2, "");
return jspb.Message.getFieldWithDefault(this, 2, '');
}
setOwner(value: string): void {
@ -171,7 +163,7 @@ export class Device extends jspb.Message {
}
getPublicKey(): string {
return jspb.Message.getFieldWithDefault(this, 3, "");
return jspb.Message.getFieldWithDefault(this, 3, '');
}
setPublicKey(value: string): void {
@ -179,7 +171,7 @@ export class Device extends jspb.Message {
}
getAddress(): string {
return jspb.Message.getFieldWithDefault(this, 4, "");
return jspb.Message.getFieldWithDefault(this, 4, '');
}
setAddress(value: string): void {
@ -227,7 +219,7 @@ export class Device extends jspb.Message {
}
getEndpoint(): string {
return jspb.Message.getFieldWithDefault(this, 10, "");
return jspb.Message.getFieldWithDefault(this, 10, '');
}
setEndpoint(value: string): void {
@ -235,7 +227,7 @@ export class Device extends jspb.Message {
}
getOwnerName(): string {
return jspb.Message.getFieldWithDefault(this, 11, "");
return jspb.Message.getFieldWithDefault(this, 11, '');
}
setOwnerName(value: string): void {
@ -243,7 +235,7 @@ export class Device extends jspb.Message {
}
getOwnerEmail(): string {
return jspb.Message.getFieldWithDefault(this, 12, "");
return jspb.Message.getFieldWithDefault(this, 12, '');
}
setOwnerEmail(value: string): void {
@ -251,7 +243,7 @@ export class Device extends jspb.Message {
}
getOwnerProvider(): string {
return jspb.Message.getFieldWithDefault(this, 13, "");
return jspb.Message.getFieldWithDefault(this, 13, '');
}
setOwnerProvider(value: string): void {
@ -266,7 +258,8 @@ export class Device extends jspb.Message {
toObject(): Device.AsObject {
let f: any;
return {name: this.getName(),
return {
name: this.getName(),
owner: this.getOwner(),
publicKey: this.getPublicKey(),
address: this.getAddress(),
@ -279,7 +272,6 @@ export class Device extends jspb.Message {
ownerName: this.getOwnerName(),
ownerEmail: this.getOwnerEmail(),
ownerProvider: this.getOwnerProvider(),
};
}
@ -352,19 +344,19 @@ export class Device extends jspb.Message {
const field = reader.getFieldNumber();
switch (field) {
case 1:
const field1 = reader.readString()
const field1 = reader.readString();
message.setName(field1);
break;
case 2:
const field2 = reader.readString()
const field2 = reader.readString();
message.setOwner(field2);
break;
case 3:
const field3 = reader.readString()
const field3 = reader.readString();
message.setPublicKey(field3);
break;
case 4:
const field4 = reader.readString()
const field4 = reader.readString();
message.setAddress(field4);
break;
case 5:
@ -373,7 +365,7 @@ export class Device extends jspb.Message {
message.setCreatedAt(field5);
break;
case 6:
const field6 = reader.readBool()
const field6 = reader.readBool();
message.setConnected(field6);
break;
case 7:
@ -382,27 +374,27 @@ export class Device extends jspb.Message {
message.setLastHandshakeTime(field7);
break;
case 8:
const field8 = reader.readInt64()
const field8 = reader.readInt64();
message.setReceiveBytes(field8);
break;
case 9:
const field9 = reader.readInt64()
const field9 = reader.readInt64();
message.setTransmitBytes(field9);
break;
case 10:
const field10 = reader.readString()
const field10 = reader.readString();
message.setEndpoint(field10);
break;
case 11:
const field11 = reader.readString()
const field11 = reader.readString();
message.setOwnerName(field11);
break;
case 12:
const field12 = reader.readString()
const field12 = reader.readString();
message.setOwnerEmail(field12);
break;
case 13:
const field13 = reader.readString()
const field13 = reader.readString();
message.setOwnerProvider(field13);
break;
default:
@ -412,29 +404,24 @@ export class Device extends jspb.Message {
}
return message;
}
}
export declare namespace AddDeviceReq {
export type AsObject = {
name: string,
publicKey: string,
}
name: string;
publicKey: string;
};
}
export class AddDeviceReq extends jspb.Message {
private static repeatedFields_ = [
];
private static repeatedFields_ = [];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, AddDeviceReq.repeatedFields_, null);
}
getName(): string {
return jspb.Message.getFieldWithDefault(this, 1, "");
return jspb.Message.getFieldWithDefault(this, 1, '');
}
setName(value: string): void {
@ -442,7 +429,7 @@ export class AddDeviceReq extends jspb.Message {
}
getPublicKey(): string {
return jspb.Message.getFieldWithDefault(this, 2, "");
return jspb.Message.getFieldWithDefault(this, 2, '');
}
setPublicKey(value: string): void {
@ -457,10 +444,7 @@ export class AddDeviceReq extends jspb.Message {
toObject(): AddDeviceReq.AsObject {
let f: any;
return {name: this.getName(),
publicKey: this.getPublicKey(),
};
return { name: this.getName(), publicKey: this.getPublicKey() };
}
static serializeBinaryToWriter(message: AddDeviceReq, writer: jspb.BinaryWriter): void {
@ -488,11 +472,11 @@ export class AddDeviceReq extends jspb.Message {
const field = reader.getFieldNumber();
switch (field) {
case 1:
const field1 = reader.readString()
const field1 = reader.readString();
message.setName(field1);
break;
case 2:
const field2 = reader.readString()
const field2 = reader.readString();
message.setPublicKey(field2);
break;
default:
@ -502,25 +486,19 @@ export class AddDeviceReq extends jspb.Message {
}
return message;
}
}
export declare namespace ListDevicesReq {
export type AsObject = {
}
export type AsObject = {};
}
export class ListDevicesReq extends jspb.Message {
private static repeatedFields_ = [
];
private static repeatedFields_ = [];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, ListDevicesReq.repeatedFields_, null);
}
serializeBinary(): Uint8Array {
const writer = new jspb.BinaryWriter();
ListDevicesReq.serializeBinaryToWriter(this, writer);
@ -529,12 +507,10 @@ export class ListDevicesReq extends jspb.Message {
toObject(): ListDevicesReq.AsObject {
let f: any;
return {
};
return {};
}
static serializeBinaryToWriter(message: ListDevicesReq, writer: jspb.BinaryWriter): void {
}
static serializeBinaryToWriter(message: ListDevicesReq, writer: jspb.BinaryWriter): void {}
static deserializeBinary(bytes: Uint8Array): ListDevicesReq {
var reader = new jspb.BinaryReader(bytes);
@ -556,26 +532,21 @@ export class ListDevicesReq extends jspb.Message {
}
return message;
}
}
export declare namespace ListDevicesRes {
export type AsObject = {
items: Array<Device.AsObject>,
}
items: Array<Device.AsObject>;
};
}
export class ListDevicesRes extends jspb.Message {
private static repeatedFields_ = [
1,
];
private static repeatedFields_ = [1];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, ListDevicesRes.repeatedFields_, null);
}
getItems(): Array<Device> {
return jspb.Message.getRepeatedWrapperField(this, Device, 1);
}
@ -633,34 +604,38 @@ export class ListDevicesRes extends jspb.Message {
}
return message;
}
}
export declare namespace DeleteDeviceReq {
export type AsObject = {
name: string,
}
name: string;
owner?: googleProtobufWrappers.StringValue.AsObject;
};
}
export class DeleteDeviceReq extends jspb.Message {
private static repeatedFields_ = [
];
private static repeatedFields_ = [];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, DeleteDeviceReq.repeatedFields_, null);
}
getName(): string {
return jspb.Message.getFieldWithDefault(this, 1, "");
return jspb.Message.getFieldWithDefault(this, 1, '');
}
setName(value: string): void {
(jspb.Message as any).setProto3StringField(this, 1, value);
}
getOwner(): googleProtobufWrappers.StringValue {
return jspb.Message.getWrapperField(this, googleProtobufWrappers.StringValue, 2);
}
setOwner(value?: googleProtobufWrappers.StringValue): void {
(jspb.Message as any).setWrapperField(this, 2, value);
}
serializeBinary(): Uint8Array {
const writer = new jspb.BinaryWriter();
DeleteDeviceReq.serializeBinaryToWriter(this, writer);
@ -669,9 +644,7 @@ export class DeleteDeviceReq extends jspb.Message {
toObject(): DeleteDeviceReq.AsObject {
let f: any;
return {name: this.getName(),
};
return { name: this.getName(), owner: (f = this.getOwner()) && f.toObject() };
}
static serializeBinaryToWriter(message: DeleteDeviceReq, writer: jspb.BinaryWriter): void {
@ -679,6 +652,10 @@ export class DeleteDeviceReq extends jspb.Message {
if (field1.length > 0) {
writer.writeString(1, field1);
}
const field2 = message.getOwner();
if (field2 != null) {
writer.writeMessage(2, field2, googleProtobufWrappers.StringValue.serializeBinaryToWriter);
}
}
static deserializeBinary(bytes: Uint8Array): DeleteDeviceReq {
@ -695,9 +672,14 @@ export class DeleteDeviceReq extends jspb.Message {
const field = reader.getFieldNumber();
switch (field) {
case 1:
const field1 = reader.readString()
const field1 = reader.readString();
message.setName(field1);
break;
case 2:
const field2 = new googleProtobufWrappers.StringValue();
reader.readMessage(field2, googleProtobufWrappers.StringValue.deserializeBinaryFromReader);
message.setOwner(field2);
break;
default:
reader.skipField();
break;
@ -705,25 +687,19 @@ export class DeleteDeviceReq extends jspb.Message {
}
return message;
}
}
export declare namespace ListAllDevicesReq {
export type AsObject = {
}
export type AsObject = {};
}
export class ListAllDevicesReq extends jspb.Message {
private static repeatedFields_ = [
];
private static repeatedFields_ = [];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, ListAllDevicesReq.repeatedFields_, null);
}
serializeBinary(): Uint8Array {
const writer = new jspb.BinaryWriter();
ListAllDevicesReq.serializeBinaryToWriter(this, writer);
@ -732,12 +708,10 @@ export class ListAllDevicesReq extends jspb.Message {
toObject(): ListAllDevicesReq.AsObject {
let f: any;
return {
};
return {};
}
static serializeBinaryToWriter(message: ListAllDevicesReq, writer: jspb.BinaryWriter): void {
}
static serializeBinaryToWriter(message: ListAllDevicesReq, writer: jspb.BinaryWriter): void {}
static deserializeBinary(bytes: Uint8Array): ListAllDevicesReq {
var reader = new jspb.BinaryReader(bytes);
@ -759,26 +733,21 @@ export class ListAllDevicesReq extends jspb.Message {
}
return message;
}
}
export declare namespace ListAllDevicesRes {
export type AsObject = {
items: Array<Device.AsObject>,
}
items: Array<Device.AsObject>;
};
}
export class ListAllDevicesRes extends jspb.Message {
private static repeatedFields_ = [
1,
];
private static repeatedFields_ = [1];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, ListAllDevicesRes.repeatedFields_, null);
}
getItems(): Array<Device> {
return jspb.Message.getRepeatedWrapperField(this, Device, 1);
}
@ -836,10 +805,8 @@ export class ListAllDevicesRes extends jspb.Message {
}
return message;
}
}
function DeviceFromObject(obj: Device.AsObject | undefined): Device | undefined {
if (obj === undefined) {
return undefined;
@ -861,7 +828,9 @@ function DeviceFromObject(obj: Device.AsObject | undefined): Device | undefined
return message;
}
function TimestampFromObject(obj: googleProtobufTimestamp.Timestamp.AsObject | undefined): googleProtobufTimestamp.Timestamp | undefined {
function TimestampFromObject(
obj: googleProtobufTimestamp.Timestamp.AsObject | undefined,
): googleProtobufTimestamp.Timestamp | undefined {
if (obj === undefined) {
return undefined;
}
@ -894,9 +863,7 @@ function ListDevicesResFromObject(obj: ListDevicesRes.AsObject | undefined): Lis
return undefined;
}
const message = new ListDevicesRes();
(obj.items || [])
.map((item) => DeviceFromObject(item))
.forEach((item) => message.addItems(item));
(obj.items || []).map((item) => DeviceFromObject(item)).forEach((item) => message.addItems(item));
return message;
}
@ -906,6 +873,18 @@ function DeleteDeviceReqFromObject(obj: DeleteDeviceReq.AsObject | undefined): D
}
const message = new DeleteDeviceReq();
message.setName(obj.name);
message.setOwner(StringValueFromObject(obj.owner));
return message;
}
function StringValueFromObject(
obj: googleProtobufWrappers.StringValue.AsObject | undefined,
): googleProtobufWrappers.StringValue | undefined {
if (obj === undefined) {
return undefined;
}
const message = new googleProtobufWrappers.StringValue();
message.setValue(obj.value);
return message;
}
@ -922,9 +901,7 @@ function ListAllDevicesResFromObject(obj: ListAllDevicesRes.AsObject | undefined
return undefined;
}
const message = new ListAllDevicesRes();
(obj.items || [])
.map((item) => DeviceFromObject(item))
.forEach((item) => message.addItems(item));
(obj.items || []).map((item) => DeviceFromObject(item)).forEach((item) => message.addItems(item));
return message;
}
@ -935,4 +912,3 @@ function EmptyFromObject(obj: googleProtobufEmpty.Empty.AsObject | undefined): g
const message = new googleProtobufEmpty.Empty();
return message;
}

@ -8,7 +8,6 @@ import * as grpcWeb from 'grpc-web';
import * as googleProtobufWrappers from 'google-protobuf/google/protobuf/wrappers_pb';
export class Server {
private client_ = new grpcWeb.GrpcWebClientBase({
format: 'text',
});
@ -16,13 +15,10 @@ export class Server {
private methodInfoInfo = new grpcWeb.AbstractClientBase.MethodInfo(
InfoRes,
(req: InfoReq) => req.serializeBinary(),
InfoRes.deserializeBinary
InfoRes.deserializeBinary,
);
constructor(
private hostname: string,
private defaultMetadata?: () => grpcWeb.Metadata,
) { }
constructor(private hostname: string, private defaultMetadata?: () => grpcWeb.Metadata) {}
info(req: InfoReq.AsObject, metadata?: grpcWeb.Metadata): Promise<InfoRes.AsObject> {
return new Promise((resolve, reject) => {
@ -42,29 +38,20 @@ export class Server {
);
});
}
}
export declare namespace InfoReq {
export type AsObject = {
}
export type AsObject = {};
}
export class InfoReq extends jspb.Message {
private static repeatedFields_ = [
];
private static repeatedFields_ = [];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, InfoReq.repeatedFields_, null);
}
serializeBinary(): Uint8Array {
const writer = new jspb.BinaryWriter();
InfoReq.serializeBinaryToWriter(this, writer);
@ -73,12 +60,10 @@ export class InfoReq extends jspb.Message {
toObject(): InfoReq.AsObject {
let f: any;
return {
};
return {};
}
static serializeBinaryToWriter(message: InfoReq, writer: jspb.BinaryWriter): void {
}
static serializeBinaryToWriter(message: InfoReq, writer: jspb.BinaryWriter): void {}
static deserializeBinary(bytes: Uint8Array): InfoReq {
var reader = new jspb.BinaryReader(bytes);
@ -100,36 +85,31 @@ export class InfoReq extends jspb.Message {
}
return message;
}
}
export declare namespace InfoRes {
export type AsObject = {
publicKey: string,
host?: googleProtobufWrappers.StringValue.AsObject,
port: number,
hostVpnIp: string,
metadataEnabled: boolean,
isAdmin: boolean,
allowedIps: string,
dnsEnabled: boolean,
dnsAddress: string,
}
publicKey: string;
host?: googleProtobufWrappers.StringValue.AsObject;
port: number;
hostVpnIp: string;
metadataEnabled: boolean;
isAdmin: boolean;
allowedIps: string;
dnsEnabled: boolean;
dnsAddress: string;
};
}
export class InfoRes extends jspb.Message {
private static repeatedFields_ = [
];
private static repeatedFields_ = [];
constructor(data?: jspb.Message.MessageArray) {
super();
jspb.Message.initialize(this, data || [], 0, -1, InfoRes.repeatedFields_, null);
}
getPublicKey(): string {
return jspb.Message.getFieldWithDefault(this, 1, "");
return jspb.Message.getFieldWithDefault(this, 1, '');
}
setPublicKey(value: string): void {
@ -153,7 +133,7 @@ export class InfoRes extends jspb.Message {
}
getHostVpnIp(): string {
return jspb.Message.getFieldWithDefault(this, 4, "");
return jspb.Message.getFieldWithDefault(this, 4, '');
}
setHostVpnIp(value: string): void {
@ -177,7 +157,7 @@ export class InfoRes extends jspb.Message {
}
getAllowedIps(): string {
return jspb.Message.getFieldWithDefault(this, 7, "");
return jspb.Message.getFieldWithDefault(this, 7, '');
}
setAllowedIps(value: string): void {
@ -193,7 +173,7 @@ export class InfoRes extends jspb.Message {
}
getDnsAddress(): string {
return jspb.Message.getFieldWithDefault(this, 9, "");
return jspb.Message.getFieldWithDefault(this, 9, '');
}
setDnsAddress(value: string): void {
@ -208,7 +188,8 @@ export class InfoRes extends jspb.Message {
toObject(): InfoRes.AsObject {
let f: any;
return {publicKey: this.getPublicKey(),
return {
publicKey: this.getPublicKey(),
host: (f = this.getHost()) && f.toObject(),
port: this.getPort(),
hostVpnIp: this.getHostVpnIp(),
@ -217,7 +198,6 @@ export class InfoRes extends jspb.Message {
allowedIps: this.getAllowedIps(),
dnsEnabled: this.getDnsEnabled(),
dnsAddress: this.getDnsAddress(),
};
}
@ -274,7 +254,7 @@ export class InfoRes extends jspb.Message {
const field = reader.getFieldNumber();
switch (field) {
case 1:
const field1 = reader.readString()
const field1 = reader.readString();
message.setPublicKey(field1);
break;
case 2:
@ -283,31 +263,31 @@ export class InfoRes extends jspb.Message {
message.setHost(field2);
break;
case 3:
const field3 = reader.readInt32()
const field3 = reader.readInt32();
message.setPort(field3);
break;
case 4:
const field4 = reader.readString()
const field4 = reader.readString();
message.setHostVpnIp(field4);
break;
case 5:
const field5 = reader.readBool()
const field5 = reader.readBool();
message.setMetadataEnabled(field5);
break;
case 6:
const field6 = reader.readBool()
const field6 = reader.readBool();
message.setIsAdmin(field6);
break;
case 7:
const field7 = reader.readString()
const field7 = reader.readString();
message.setAllowedIps(field7);
break;
case 8:
const field8 = reader.readBool()
const field8 = reader.readBool();
message.setDnsEnabled(field8);
break;
case 9:
const field9 = reader.readString()
const field9 = reader.readString();
message.setDnsAddress(field9);
break;
default:
@ -317,10 +297,8 @@ export class InfoRes extends jspb.Message {
}
return message;
}
}
function InfoReqFromObject(obj: InfoReq.AsObject | undefined): InfoReq | undefined {
if (obj === undefined) {
return undefined;
@ -346,7 +324,9 @@ function InfoResFromObject(obj: InfoRes.AsObject | undefined): InfoRes | undefin
return message;
}
function StringValueFromObject(obj: googleProtobufWrappers.StringValue.AsObject | undefined): googleProtobufWrappers.StringValue | undefined {
function StringValueFromObject(
obj: googleProtobufWrappers.StringValue.AsObject | undefined,
): googleProtobufWrappers.StringValue | undefined {
if (obj === undefined) {
return undefined;
}
@ -354,4 +334,3 @@ function StringValueFromObject(obj: googleProtobufWrappers.StringValue.AsObject
message.setValue(obj.value);
return message;
}

Loading…
Cancel
Save