mirror of
https://github.com/juanfont/headscale.git
synced 2026-08-13 19:00:43 +09:00
83fb0a4548
Register, Get, List, Delete, Rename, Expire, SetTags, SetApprovedRoutes (with exit-route expansion), BackfillNodeIPs, DebugCreateNode over the state layer. Tagged nodes present as TaggedDevices; client errors map to 4xx.
148 lines
4.1 KiB
Go
148 lines
4.1 KiB
Go
package apiv1
|
|
|
|
import (
|
|
oas "github.com/juanfont/headscale/gen/api/v1"
|
|
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
)
|
|
|
|
// This file bridges the existing proto response builders (the Proto() methods
|
|
// on the state types) to the ogen API types. Reusing Proto() guarantees the
|
|
// new HTTP API surfaces exactly the same data the gRPC/gateway stack did
|
|
// (username fallback, masked key prefixes, online computation, the
|
|
// TaggedDevices substitution, …) without reimplementing it.
|
|
//
|
|
// Unlike grpc-gateway (which marshalled with EmitUnpopulated), these converters
|
|
// omit zero-value and absent fields — empty strings, false booleans, zero
|
|
// numbers, empty arrays, nil timestamps/objects, and the unspecified register
|
|
// method. See docs/v1-ogen/CHANGES.md. When the proto stack is removed, these
|
|
// converters are rewritten to read the state types directly.
|
|
//
|
|
// Converters are added here as each resource group is migrated.
|
|
|
|
func optString(s string) oas.OptString {
|
|
if s == "" {
|
|
return oas.OptString{}
|
|
}
|
|
|
|
return oas.NewOptString(s)
|
|
}
|
|
|
|
func optUint64(v uint64) oas.OptUint64 {
|
|
if v == 0 {
|
|
return oas.OptUint64{}
|
|
}
|
|
|
|
return oas.NewOptUint64(v)
|
|
}
|
|
|
|
func optTime(ts *timestamppb.Timestamp) oas.OptDateTime {
|
|
if ts == nil {
|
|
return oas.OptDateTime{}
|
|
}
|
|
|
|
return oas.NewOptDateTime(ts.AsTime())
|
|
}
|
|
|
|
func optBool(b bool) oas.OptBool {
|
|
if !b {
|
|
return oas.OptBool{}
|
|
}
|
|
|
|
return oas.NewOptBool(b)
|
|
}
|
|
|
|
// strs normalises an empty slice to nil so it is omitted from the response
|
|
// rather than emitted as an empty array.
|
|
func strs(s []string) []string {
|
|
if len(s) == 0 {
|
|
return nil
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func optUser(u *v1.User) oas.OptUser {
|
|
if u == nil {
|
|
return oas.OptUser{}
|
|
}
|
|
|
|
return oas.NewOptUser(oasUser(u))
|
|
}
|
|
|
|
func oasPreAuthKey(k *v1.PreAuthKey) oas.PreAuthKey {
|
|
return oas.PreAuthKey{
|
|
User: optUser(k.GetUser()),
|
|
ID: optUint64(k.GetId()),
|
|
Key: optString(k.GetKey()),
|
|
Reusable: optBool(k.GetReusable()),
|
|
Ephemeral: optBool(k.GetEphemeral()),
|
|
Used: optBool(k.GetUsed()),
|
|
Expiration: optTime(k.GetExpiration()),
|
|
CreatedAt: optTime(k.GetCreatedAt()),
|
|
AclTags: strs(k.GetAclTags()),
|
|
}
|
|
}
|
|
|
|
func optPreAuthKey(k *v1.PreAuthKey) oas.OptPreAuthKey {
|
|
if k == nil {
|
|
return oas.OptPreAuthKey{}
|
|
}
|
|
|
|
return oas.NewOptPreAuthKey(oasPreAuthKey(k))
|
|
}
|
|
|
|
func optRegisterMethod(rm v1.RegisterMethod) oas.OptRegisterMethod {
|
|
if rm == v1.RegisterMethod_REGISTER_METHOD_UNSPECIFIED {
|
|
return oas.OptRegisterMethod{}
|
|
}
|
|
|
|
return oas.NewOptRegisterMethod(oas.RegisterMethod(rm.String()))
|
|
}
|
|
|
|
func oasNode(n *v1.Node) oas.Node {
|
|
return oas.Node{
|
|
ID: optUint64(n.GetId()),
|
|
MachineKey: optString(n.GetMachineKey()),
|
|
NodeKey: optString(n.GetNodeKey()),
|
|
DiscoKey: optString(n.GetDiscoKey()),
|
|
IpAddresses: strs(n.GetIpAddresses()),
|
|
Name: optString(n.GetName()),
|
|
User: optUser(n.GetUser()),
|
|
LastSeen: optTime(n.GetLastSeen()),
|
|
Expiry: optTime(n.GetExpiry()),
|
|
PreAuthKey: optPreAuthKey(n.GetPreAuthKey()),
|
|
CreatedAt: optTime(n.GetCreatedAt()),
|
|
RegisterMethod: optRegisterMethod(n.GetRegisterMethod()),
|
|
GivenName: optString(n.GetGivenName()),
|
|
Online: optBool(n.GetOnline()),
|
|
ApprovedRoutes: strs(n.GetApprovedRoutes()),
|
|
AvailableRoutes: strs(n.GetAvailableRoutes()),
|
|
SubnetRoutes: strs(n.GetSubnetRoutes()),
|
|
Tags: strs(n.GetTags()),
|
|
}
|
|
}
|
|
|
|
func oasAPIKey(k *v1.ApiKey) oas.ApiKey {
|
|
return oas.ApiKey{
|
|
ID: optUint64(k.GetId()),
|
|
Prefix: optString(k.GetPrefix()),
|
|
Expiration: optTime(k.GetExpiration()),
|
|
CreatedAt: optTime(k.GetCreatedAt()),
|
|
LastSeen: optTime(k.GetLastSeen()),
|
|
}
|
|
}
|
|
|
|
func oasUser(u *v1.User) oas.User {
|
|
return oas.User{
|
|
ID: optUint64(u.GetId()),
|
|
Name: optString(u.GetName()),
|
|
CreatedAt: optTime(u.GetCreatedAt()),
|
|
DisplayName: optString(u.GetDisplayName()),
|
|
Email: optString(u.GetEmail()),
|
|
ProviderId: optString(u.GetProviderId()),
|
|
Provider: optString(u.GetProvider()),
|
|
ProfilePicUrl: optString(u.GetProfilePicUrl()),
|
|
}
|
|
}
|