Add REST API handler tests for zones, records, and middleware
Cover all REST handlers with httptest-based tests using real SQLite: zones (list, get, create, update, delete), records (list, get, create, update, delete with validation/conflict cases), requireAdmin middleware (admin, non-admin, missing context), and utility functions (writeJSON, writeError, extractBearerToken, tokenInfoFromContext). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
// protoc v6.32.1
|
||||
// source: proto/mcns/v1/admin.proto
|
||||
|
||||
package v1
|
||||
package mcnsv1
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
@@ -110,7 +110,7 @@ const file_proto_mcns_v1_admin_proto_rawDesc = "" +
|
||||
"\x0eHealthResponse\x12\x16\n" +
|
||||
"\x06status\x18\x01 \x01(\tR\x06status2I\n" +
|
||||
"\fAdminService\x129\n" +
|
||||
"\x06Health\x12\x16.mcns.v1.HealthRequest\x1a\x17.mcns.v1.HealthResponseB(Z&git.wntrmute.dev/kyle/mcns/gen/mcns/v1b\x06proto3"
|
||||
"\x06Health\x12\x16.mcns.v1.HealthRequest\x1a\x17.mcns.v1.HealthResponseB/Z-git.wntrmute.dev/kyle/mcns/gen/mcns/v1;mcnsv1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_proto_mcns_v1_admin_proto_rawDescOnce sync.Once
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// - protoc v6.32.1
|
||||
// source: proto/mcns/v1/admin.proto
|
||||
|
||||
package v1
|
||||
package mcnsv1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
@@ -25,6 +25,8 @@ const (
|
||||
// AdminServiceClient is the client API for AdminService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// AdminService exposes server health and administrative operations.
|
||||
type AdminServiceClient interface {
|
||||
Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error)
|
||||
}
|
||||
@@ -50,6 +52,8 @@ func (c *adminServiceClient) Health(ctx context.Context, in *HealthRequest, opts
|
||||
// AdminServiceServer is the server API for AdminService service.
|
||||
// All implementations must embed UnimplementedAdminServiceServer
|
||||
// for forward compatibility.
|
||||
//
|
||||
// AdminService exposes server health and administrative operations.
|
||||
type AdminServiceServer interface {
|
||||
Health(context.Context, *HealthRequest) (*HealthResponse, error)
|
||||
mustEmbedUnimplementedAdminServiceServer()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// protoc v6.32.1
|
||||
// source: proto/mcns/v1/auth.proto
|
||||
|
||||
package v1
|
||||
package mcnsv1
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
@@ -22,10 +22,11 @@ const (
|
||||
)
|
||||
|
||||
type LoginRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||
TotpCode string `protobuf:"bytes,3,opt,name=totp_code,json=totpCode,proto3" json:"totp_code,omitempty"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
|
||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||
// TOTP code for two-factor authentication, if enabled on the account.
|
||||
TotpCode string `protobuf:"bytes,3,opt,name=totp_code,json=totpCode,proto3" json:"totp_code,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -221,7 +222,7 @@ const file_proto_mcns_v1_auth_proto_rawDesc = "" +
|
||||
"\x0eLogoutResponse2\x80\x01\n" +
|
||||
"\vAuthService\x126\n" +
|
||||
"\x05Login\x12\x15.mcns.v1.LoginRequest\x1a\x16.mcns.v1.LoginResponse\x129\n" +
|
||||
"\x06Logout\x12\x16.mcns.v1.LogoutRequest\x1a\x17.mcns.v1.LogoutResponseB(Z&git.wntrmute.dev/kyle/mcns/gen/mcns/v1b\x06proto3"
|
||||
"\x06Logout\x12\x16.mcns.v1.LogoutRequest\x1a\x17.mcns.v1.LogoutResponseB/Z-git.wntrmute.dev/kyle/mcns/gen/mcns/v1;mcnsv1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_proto_mcns_v1_auth_proto_rawDescOnce sync.Once
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// - protoc v6.32.1
|
||||
// source: proto/mcns/v1/auth.proto
|
||||
|
||||
package v1
|
||||
package mcnsv1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
@@ -26,6 +26,8 @@ const (
|
||||
// AuthServiceClient is the client API for AuthService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// AuthService handles authentication by delegating to MCIAS.
|
||||
type AuthServiceClient interface {
|
||||
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
|
||||
Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error)
|
||||
@@ -62,6 +64,8 @@ func (c *authServiceClient) Logout(ctx context.Context, in *LogoutRequest, opts
|
||||
// AuthServiceServer is the server API for AuthService service.
|
||||
// All implementations must embed UnimplementedAuthServiceServer
|
||||
// for forward compatibility.
|
||||
//
|
||||
// AuthService handles authentication by delegating to MCIAS.
|
||||
type AuthServiceServer interface {
|
||||
Login(context.Context, *LoginRequest) (*LoginResponse, error)
|
||||
Logout(context.Context, *LogoutRequest) (*LogoutResponse, error)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// protoc v6.32.1
|
||||
// source: proto/mcns/v1/record.proto
|
||||
|
||||
package v1
|
||||
package mcnsv1
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
@@ -23,10 +23,12 @@ const (
|
||||
)
|
||||
|
||||
type Record struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Zone string `protobuf:"bytes,2,opt,name=zone,proto3" json:"zone,omitempty"`
|
||||
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
// Zone name this record belongs to (e.g. "example.com.").
|
||||
Zone string `protobuf:"bytes,2,opt,name=zone,proto3" json:"zone,omitempty"`
|
||||
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// DNS record type (A, AAAA, CNAME, MX, TXT, etc.).
|
||||
Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Value string `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"`
|
||||
Ttl int32 `protobuf:"varint,6,opt,name=ttl,proto3" json:"ttl,omitempty"`
|
||||
@@ -123,10 +125,12 @@ func (x *Record) GetUpdatedAt() *timestamppb.Timestamp {
|
||||
}
|
||||
|
||||
type ListRecordsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Zone string `protobuf:"bytes,1,opt,name=zone,proto3" json:"zone,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Zone string `protobuf:"bytes,1,opt,name=zone,proto3" json:"zone,omitempty"`
|
||||
// Optional filter by record name.
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// Optional filter by record type (A, AAAA, CNAME, etc.).
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -227,12 +231,13 @@ func (x *ListRecordsResponse) GetRecords() []*Record {
|
||||
}
|
||||
|
||||
type CreateRecordRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Zone string `protobuf:"bytes,1,opt,name=zone,proto3" json:"zone,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
|
||||
Ttl int32 `protobuf:"varint,5,opt,name=ttl,proto3" json:"ttl,omitempty"`
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Zone name the record will be created in; must reference an existing zone.
|
||||
Zone string `protobuf:"bytes,1,opt,name=zone,proto3" json:"zone,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
|
||||
Ttl int32 `protobuf:"varint,5,opt,name=ttl,proto3" json:"ttl,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -546,7 +551,7 @@ const file_proto_mcns_v1_record_proto_rawDesc = "" +
|
||||
"\fCreateRecord\x12\x1c.mcns.v1.CreateRecordRequest\x1a\x0f.mcns.v1.Record\x127\n" +
|
||||
"\tGetRecord\x12\x19.mcns.v1.GetRecordRequest\x1a\x0f.mcns.v1.Record\x12=\n" +
|
||||
"\fUpdateRecord\x12\x1c.mcns.v1.UpdateRecordRequest\x1a\x0f.mcns.v1.Record\x12K\n" +
|
||||
"\fDeleteRecord\x12\x1c.mcns.v1.DeleteRecordRequest\x1a\x1d.mcns.v1.DeleteRecordResponseB(Z&git.wntrmute.dev/kyle/mcns/gen/mcns/v1b\x06proto3"
|
||||
"\fDeleteRecord\x12\x1c.mcns.v1.DeleteRecordRequest\x1a\x1d.mcns.v1.DeleteRecordResponseB/Z-git.wntrmute.dev/kyle/mcns/gen/mcns/v1;mcnsv1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_proto_mcns_v1_record_proto_rawDescOnce sync.Once
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// - protoc v6.32.1
|
||||
// source: proto/mcns/v1/record.proto
|
||||
|
||||
package v1
|
||||
package mcnsv1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
@@ -29,6 +29,8 @@ const (
|
||||
// RecordServiceClient is the client API for RecordService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// RecordService manages DNS records within zones.
|
||||
type RecordServiceClient interface {
|
||||
ListRecords(ctx context.Context, in *ListRecordsRequest, opts ...grpc.CallOption) (*ListRecordsResponse, error)
|
||||
CreateRecord(ctx context.Context, in *CreateRecordRequest, opts ...grpc.CallOption) (*Record, error)
|
||||
@@ -98,6 +100,8 @@ func (c *recordServiceClient) DeleteRecord(ctx context.Context, in *DeleteRecord
|
||||
// RecordServiceServer is the server API for RecordService service.
|
||||
// All implementations must embed UnimplementedRecordServiceServer
|
||||
// for forward compatibility.
|
||||
//
|
||||
// RecordService manages DNS records within zones.
|
||||
type RecordServiceServer interface {
|
||||
ListRecords(context.Context, *ListRecordsRequest) (*ListRecordsResponse, error)
|
||||
CreateRecord(context.Context, *CreateRecordRequest) (*Record, error)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// protoc v6.32.1
|
||||
// source: proto/mcns/v1/zone.proto
|
||||
|
||||
package v1
|
||||
package mcnsv1
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
@@ -595,7 +595,7 @@ const file_proto_mcns_v1_zone_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"UpdateZone\x12\x1a.mcns.v1.UpdateZoneRequest\x1a\r.mcns.v1.Zone\x12E\n" +
|
||||
"\n" +
|
||||
"DeleteZone\x12\x1a.mcns.v1.DeleteZoneRequest\x1a\x1b.mcns.v1.DeleteZoneResponseB(Z&git.wntrmute.dev/kyle/mcns/gen/mcns/v1b\x06proto3"
|
||||
"DeleteZone\x12\x1a.mcns.v1.DeleteZoneRequest\x1a\x1b.mcns.v1.DeleteZoneResponseB/Z-git.wntrmute.dev/kyle/mcns/gen/mcns/v1;mcnsv1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_proto_mcns_v1_zone_proto_rawDescOnce sync.Once
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// - protoc v6.32.1
|
||||
// source: proto/mcns/v1/zone.proto
|
||||
|
||||
package v1
|
||||
package mcnsv1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
@@ -29,6 +29,8 @@ const (
|
||||
// ZoneServiceClient is the client API for ZoneService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
//
|
||||
// ZoneService manages DNS zones and their SOA parameters.
|
||||
type ZoneServiceClient interface {
|
||||
ListZones(ctx context.Context, in *ListZonesRequest, opts ...grpc.CallOption) (*ListZonesResponse, error)
|
||||
CreateZone(ctx context.Context, in *CreateZoneRequest, opts ...grpc.CallOption) (*Zone, error)
|
||||
@@ -98,6 +100,8 @@ func (c *zoneServiceClient) DeleteZone(ctx context.Context, in *DeleteZoneReques
|
||||
// ZoneServiceServer is the server API for ZoneService service.
|
||||
// All implementations must embed UnimplementedZoneServiceServer
|
||||
// for forward compatibility.
|
||||
//
|
||||
// ZoneService manages DNS zones and their SOA parameters.
|
||||
type ZoneServiceServer interface {
|
||||
ListZones(context.Context, *ListZonesRequest) (*ListZonesResponse, error)
|
||||
CreateZone(context.Context, *CreateZoneRequest) (*Zone, error)
|
||||
|
||||
Reference in New Issue
Block a user