mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-08 09:49:54 +00:00
[client/ui-wails] Add Forwarding service for the exposed-services list
Surfaces the daemon's existing ForwardingRules RPC as a Wails service so
the React frontend can render the reverse-proxy / exposed-services list
in the planned dashboard.
Forwarding.List() returns one ForwardingRule per active rule with
protocol, destination port (single or range), translated address /
hostname, and translated port. The PortInfo oneof from the proto is
flattened to a `{port?: number, range?: {start, end}}` shape so TS
consumers don't have to peek at proto-internal type discriminators.
Regenerate frontend/bindings (forwarding.ts, models.ts, index.ts) so
the React side picks up the new service. peers.ts churn is a doc
comment refresh only — no API change.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
/**
|
||||
* Forwarding groups the daemon RPCs that surface exposed/forwarded services.
|
||||
* @module
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import * as $models from "./models.js";
|
||||
|
||||
/**
|
||||
* List returns the current set of forwarding rules from the daemon's
|
||||
* reverse proxy. The frontend renders these as the "exposed services" list.
|
||||
*/
|
||||
export function List(): $CancellablePromise<$models.ForwardingRule[]> {
|
||||
return $Call.ByID(3893357601).then(($result: any) => {
|
||||
return $$createType1($result);
|
||||
});
|
||||
}
|
||||
|
||||
// Private type creation functions
|
||||
const $$createType0 = $models.ForwardingRule.createFrom;
|
||||
const $$createType1 = $Create.Array($$createType0);
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import * as Connection from "./connection.js";
|
||||
import * as Debug from "./debug.js";
|
||||
import * as Forwarding from "./forwarding.js";
|
||||
import * as Networks from "./networks.js";
|
||||
import * as Peers from "./peers.js";
|
||||
import * as Profiles from "./profiles.js";
|
||||
@@ -11,6 +12,7 @@ import * as Update from "./update.js";
|
||||
export {
|
||||
Connection,
|
||||
Debug,
|
||||
Forwarding,
|
||||
Networks,
|
||||
Peers,
|
||||
Profiles,
|
||||
@@ -25,6 +27,7 @@ export {
|
||||
DebugBundleParams,
|
||||
DebugBundleResult,
|
||||
Features,
|
||||
ForwardingRule,
|
||||
LocalPeer,
|
||||
LogLevel,
|
||||
LoginParams,
|
||||
@@ -33,6 +36,8 @@ export {
|
||||
Network,
|
||||
PeerLink,
|
||||
PeerStatus,
|
||||
PortInfo,
|
||||
PortRange,
|
||||
Profile,
|
||||
ProfileRef,
|
||||
SelectNetworksParams,
|
||||
|
||||
@@ -291,6 +291,55 @@ export class Features {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ForwardingRule is one entry from the daemon's reverse-proxy table —
|
||||
* what we ship to the frontend's "exposed services" view.
|
||||
*/
|
||||
export class ForwardingRule {
|
||||
"protocol": string;
|
||||
"destinationPort": PortInfo;
|
||||
"translatedAddress": string;
|
||||
"translatedHostname": string;
|
||||
"translatedPort": PortInfo;
|
||||
|
||||
/** Creates a new ForwardingRule instance. */
|
||||
constructor($$source: Partial<ForwardingRule> = {}) {
|
||||
if (!("protocol" in $$source)) {
|
||||
this["protocol"] = "";
|
||||
}
|
||||
if (!("destinationPort" in $$source)) {
|
||||
this["destinationPort"] = (new PortInfo());
|
||||
}
|
||||
if (!("translatedAddress" in $$source)) {
|
||||
this["translatedAddress"] = "";
|
||||
}
|
||||
if (!("translatedHostname" in $$source)) {
|
||||
this["translatedHostname"] = "";
|
||||
}
|
||||
if (!("translatedPort" in $$source)) {
|
||||
this["translatedPort"] = (new PortInfo());
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ForwardingRule instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): ForwardingRule {
|
||||
const $$createField1_0 = $$createType0;
|
||||
const $$createField4_0 = $$createType0;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("destinationPort" in $$parsedSource) {
|
||||
$$parsedSource["destinationPort"] = $$createField1_0($$parsedSource["destinationPort"]);
|
||||
}
|
||||
if ("translatedPort" in $$parsedSource) {
|
||||
$$parsedSource["translatedPort"] = $$createField4_0($$parsedSource["translatedPort"]);
|
||||
}
|
||||
return new ForwardingRule($$parsedSource as Partial<ForwardingRule>);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LocalPeer mirrors LocalPeerState — what this client looks like on the mesh.
|
||||
*/
|
||||
@@ -322,7 +371,7 @@ export class LocalPeer {
|
||||
* Creates a new LocalPeer instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): LocalPeer {
|
||||
const $$createField3_0 = $$createType0;
|
||||
const $$createField3_0 = $$createType1;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("networks" in $$parsedSource) {
|
||||
$$parsedSource["networks"] = $$createField3_0($$parsedSource["networks"]);
|
||||
@@ -503,8 +552,8 @@ export class Network {
|
||||
* Creates a new Network instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): Network {
|
||||
const $$createField3_0 = $$createType0;
|
||||
const $$createField4_0 = $$createType1;
|
||||
const $$createField3_0 = $$createType1;
|
||||
const $$createField4_0 = $$createType2;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("domains" in $$parsedSource) {
|
||||
$$parsedSource["domains"] = $$createField3_0($$parsedSource["domains"]);
|
||||
@@ -631,7 +680,7 @@ export class PeerStatus {
|
||||
* Creates a new PeerStatus instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): PeerStatus {
|
||||
const $$createField16_0 = $$createType0;
|
||||
const $$createField16_0 = $$createType1;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("networks" in $$parsedSource) {
|
||||
$$parsedSource["networks"] = $$createField16_0($$parsedSource["networks"]);
|
||||
@@ -640,6 +689,61 @@ export class PeerStatus {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PortInfo carries the destination or translated port for a forwarding rule.
|
||||
* Exactly one of Port or Range is populated, mirroring the daemon's oneof.
|
||||
*/
|
||||
export class PortInfo {
|
||||
"port"?: number | null;
|
||||
"range"?: PortRange | null;
|
||||
|
||||
/** Creates a new PortInfo instance. */
|
||||
constructor($$source: Partial<PortInfo> = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PortInfo instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): PortInfo {
|
||||
const $$createField1_0 = $$createType4;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("range" in $$parsedSource) {
|
||||
$$parsedSource["range"] = $$createField1_0($$parsedSource["range"]);
|
||||
}
|
||||
return new PortInfo($$parsedSource as Partial<PortInfo>);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PortRange describes a contiguous port range. Both ends are inclusive.
|
||||
*/
|
||||
export class PortRange {
|
||||
"start": number;
|
||||
"end": number;
|
||||
|
||||
/** Creates a new PortRange instance. */
|
||||
constructor($$source: Partial<PortRange> = {}) {
|
||||
if (!("start" in $$source)) {
|
||||
this["start"] = 0;
|
||||
}
|
||||
if (!("end" in $$source)) {
|
||||
this["end"] = 0;
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PortRange instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): PortRange {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new PortRange($$parsedSource as Partial<PortRange>);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile is one named daemon profile.
|
||||
*/
|
||||
@@ -725,7 +829,7 @@ export class SelectNetworksParams {
|
||||
* Creates a new SelectNetworksParams instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): SelectNetworksParams {
|
||||
const $$createField0_0 = $$createType0;
|
||||
const $$createField0_0 = $$createType1;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("networkIds" in $$parsedSource) {
|
||||
$$parsedSource["networkIds"] = $$createField0_0($$parsedSource["networkIds"]);
|
||||
@@ -837,11 +941,11 @@ export class Status {
|
||||
* Creates a new Status instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): Status {
|
||||
const $$createField2_0 = $$createType2;
|
||||
const $$createField3_0 = $$createType2;
|
||||
const $$createField4_0 = $$createType3;
|
||||
const $$createField5_0 = $$createType5;
|
||||
const $$createField6_0 = $$createType7;
|
||||
const $$createField2_0 = $$createType5;
|
||||
const $$createField3_0 = $$createType5;
|
||||
const $$createField4_0 = $$createType6;
|
||||
const $$createField5_0 = $$createType8;
|
||||
const $$createField6_0 = $$createType10;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("management" in $$parsedSource) {
|
||||
$$parsedSource["management"] = $$createField2_0($$parsedSource["management"]);
|
||||
@@ -905,7 +1009,7 @@ export class SystemEvent {
|
||||
* Creates a new SystemEvent instance from a string or object.
|
||||
*/
|
||||
static createFrom($$source: any = {}): SystemEvent {
|
||||
const $$createField6_0 = $$createType8;
|
||||
const $$createField6_0 = $$createType11;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("metadata" in $$parsedSource) {
|
||||
$$parsedSource["metadata"] = $$createField6_0($$parsedSource["metadata"]);
|
||||
@@ -1056,12 +1160,15 @@ export class WaitSSOParams {
|
||||
}
|
||||
|
||||
// Private type creation functions
|
||||
const $$createType0 = $Create.Array($Create.Any);
|
||||
const $$createType1 = $Create.Map($Create.Any, $$createType0);
|
||||
const $$createType2 = PeerLink.createFrom;
|
||||
const $$createType3 = LocalPeer.createFrom;
|
||||
const $$createType4 = PeerStatus.createFrom;
|
||||
const $$createType5 = $Create.Array($$createType4);
|
||||
const $$createType6 = SystemEvent.createFrom;
|
||||
const $$createType7 = $Create.Array($$createType6);
|
||||
const $$createType8 = $Create.Map($Create.Any, $Create.Any);
|
||||
const $$createType0 = PortInfo.createFrom;
|
||||
const $$createType1 = $Create.Array($Create.Any);
|
||||
const $$createType2 = $Create.Map($Create.Any, $$createType1);
|
||||
const $$createType3 = PortRange.createFrom;
|
||||
const $$createType4 = $Create.Nullable($$createType3);
|
||||
const $$createType5 = PeerLink.createFrom;
|
||||
const $$createType6 = LocalPeer.createFrom;
|
||||
const $$createType7 = PeerStatus.createFrom;
|
||||
const $$createType8 = $Create.Array($$createType7);
|
||||
const $$createType9 = SystemEvent.createFrom;
|
||||
const $$createType10 = $Create.Array($$createType9);
|
||||
const $$createType11 = $Create.Map($Create.Any, $Create.Any);
|
||||
|
||||
@@ -25,9 +25,16 @@ export function Get(): $CancellablePromise<$models.Status> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch starts the background loops that feed the frontend: a status
|
||||
* stream (push-driven on connection-state change) and an event stream
|
||||
* (DNS / network / auth / connectivity / update notifications).
|
||||
* Watch starts the background loops that feed the frontend:
|
||||
* - statusStreamLoop: push-driven snapshots on connection-state change
|
||||
* (Connected/Disconnected/Connecting, peer list, address). Drives the
|
||||
* tray icon, Status page, and Peers page.
|
||||
* - toastStreamLoop: DNS / network / auth / connectivity / update
|
||||
* SystemEvent stream. Drives OS notifications, the Recent Events
|
||||
* list, and the update-overlay flag. The daemon-side RPC is named
|
||||
* SubscribeEvents — only the loop's local alias differs to keep the
|
||||
* two streams distinguishable in this file.
|
||||
*
|
||||
* Safe to call once at boot; both loops self-restart on stream errors
|
||||
* via exponential backoff.
|
||||
*/
|
||||
|
||||
@@ -99,6 +99,7 @@ func main() {
|
||||
app.RegisterService(application.NewService(connection))
|
||||
app.RegisterService(application.NewService(settings))
|
||||
app.RegisterService(application.NewService(services.NewNetworks(conn)))
|
||||
app.RegisterService(application.NewService(services.NewForwarding(conn)))
|
||||
app.RegisterService(application.NewService(profiles))
|
||||
app.RegisterService(application.NewService(services.NewDebug(conn)))
|
||||
app.RegisterService(application.NewService(update))
|
||||
|
||||
87
client/ui-wails/services/forwarding.go
Normal file
87
client/ui-wails/services/forwarding.go
Normal file
@@ -0,0 +1,87 @@
|
||||
//go:build !android && !ios && !freebsd && !js
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/netbirdio/netbird/client/proto"
|
||||
)
|
||||
|
||||
// PortRange describes a contiguous port range. Both ends are inclusive.
|
||||
type PortRange struct {
|
||||
Start uint32 `json:"start"`
|
||||
End uint32 `json:"end"`
|
||||
}
|
||||
|
||||
// PortInfo carries the destination or translated port for a forwarding rule.
|
||||
// Exactly one of Port or Range is populated, mirroring the daemon's oneof.
|
||||
type PortInfo struct {
|
||||
Port *uint32 `json:"port,omitempty"`
|
||||
Range *PortRange `json:"range,omitempty"`
|
||||
}
|
||||
|
||||
// ForwardingRule is one entry from the daemon's reverse-proxy table —
|
||||
// what we ship to the frontend's "exposed services" view.
|
||||
type ForwardingRule struct {
|
||||
Protocol string `json:"protocol"`
|
||||
DestinationPort PortInfo `json:"destinationPort"`
|
||||
TranslatedAddress string `json:"translatedAddress"`
|
||||
TranslatedHostname string `json:"translatedHostname"`
|
||||
TranslatedPort PortInfo `json:"translatedPort"`
|
||||
}
|
||||
|
||||
// Forwarding groups the daemon RPCs that surface exposed/forwarded services.
|
||||
type Forwarding struct {
|
||||
conn DaemonConn
|
||||
}
|
||||
|
||||
func NewForwarding(conn DaemonConn) *Forwarding {
|
||||
return &Forwarding{conn: conn}
|
||||
}
|
||||
|
||||
// List returns the current set of forwarding rules from the daemon's
|
||||
// reverse proxy. The frontend renders these as the "exposed services" list.
|
||||
func (s *Forwarding) List(ctx context.Context) ([]ForwardingRule, error) {
|
||||
cli, err := s.conn.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := cli.ForwardingRules(ctx, &proto.EmptyRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make([]ForwardingRule, 0, len(resp.GetRules()))
|
||||
for _, r := range resp.GetRules() {
|
||||
out = append(out, forwardingRuleFromProto(r))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func forwardingRuleFromProto(r *proto.ForwardingRule) ForwardingRule {
|
||||
return ForwardingRule{
|
||||
Protocol: r.GetProtocol(),
|
||||
DestinationPort: portInfoFromProto(r.GetDestinationPort()),
|
||||
TranslatedAddress: r.GetTranslatedAddress(),
|
||||
TranslatedHostname: r.GetTranslatedHostname(),
|
||||
TranslatedPort: portInfoFromProto(r.GetTranslatedPort()),
|
||||
}
|
||||
}
|
||||
|
||||
func portInfoFromProto(p *proto.PortInfo) PortInfo {
|
||||
if p == nil {
|
||||
return PortInfo{}
|
||||
}
|
||||
switch sel := p.GetPortSelection().(type) {
|
||||
case *proto.PortInfo_Port:
|
||||
port := sel.Port
|
||||
return PortInfo{Port: &port}
|
||||
case *proto.PortInfo_Range_:
|
||||
r := sel.Range
|
||||
if r == nil {
|
||||
return PortInfo{}
|
||||
}
|
||||
return PortInfo{Range: &PortRange{Start: r.GetStart(), End: r.GetEnd()}}
|
||||
}
|
||||
return PortInfo{}
|
||||
}
|
||||
Reference in New Issue
Block a user