Skip to content

Commit

Permalink
Merge branch 'v3.26' into fix/frontend-claiming
Browse files Browse the repository at this point in the history
  • Loading branch information
kschiffer authored Jun 26, 2023
2 parents 5dd086c + 98e65a7 commit b501fd4
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 92 deletions.
13 changes: 8 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ For details about compatibility between different releases, see the **Commitment

- Fix payload formatter page launching malformed requests in the Console.
- Fix end device claiming issues in the Console and improve error messaging.
- HTTP API routes for parsing QR codes for the QR Generator service. We exercise our right to break compatibility with third party HTTP clients since this is a bug.
- `/qr-code/end-devices/parse` is changed to `/qr-codes/end-devices/parse`.
- `/qr-code/end-devices/{format_id}/parse` is changed to `/qr-codes/end-devices/{format_id}/parse`.

### Security

Expand Down Expand Up @@ -120,7 +123,7 @@ For details about compatibility between different releases, see the **Commitment
- Device claiming that transfer devices between applications is now deprecated and will be removed in a future version of The Things Stack. Device claiming on Join Servers, including The Things Join Server, remains functional. This deprecates the following components:
- API for managing application claim authorization (`EndDeviceClaimingServer.AuthorizeApplication` and `EndDeviceClaimingServer.UnauthorizeApplication`)
- CLI commands to manage application claim settings (`ttn-lw-cli application claim [authorize|unauthorize]`)
- CLI command to claim end devices (`ttn-lw-cli devices claim`)
- CLI command to claim end devices (`ttn-lw-cli devices claim`)

### Fixed

Expand Down Expand Up @@ -254,10 +257,10 @@ For details about compatibility between different releases, see the **Commitment
### Changed

- Option to ignore logs from selected gRPC methods now supports ignoring logs for selected errors on method.
Examples:
- `--grpc.log-ignore-methods="/ttn.lorawan.v3.GsNs/HandleUplink"`: log is skipped when no error occurs.
- `--grpc.log-ignore-methods="/ttn.lorawan.v3.GsNs/HandleUplink:pkg/networkserver:duplicate_uplink;pkg/networkserver:device_not_found"`: log is skipped when either `pkg/networkserver:duplicate_uplink` or `pkg/networkserver:device_not_found` error occurs (but not on success).
- `--grpc.log-ignore-methods="/ttn.lorawan.v3.GsNs/HandleUplink:;pkg/networkserver:duplicate_uplink"`: log is skipped on success or when `pkg/networkserver:duplicate_uplink` error occurs.
Examples:
- `--grpc.log-ignore-methods="/ttn.lorawan.v3.GsNs/HandleUplink"`: log is skipped when no error occurs.
- `--grpc.log-ignore-methods="/ttn.lorawan.v3.GsNs/HandleUplink:pkg/networkserver:duplicate_uplink;pkg/networkserver:device_not_found"`: log is skipped when either `pkg/networkserver:duplicate_uplink` or `pkg/networkserver:device_not_found` error occurs (but not on success).
- `--grpc.log-ignore-methods="/ttn.lorawan.v3.GsNs/HandleUplink:;pkg/networkserver:duplicate_uplink"`: log is skipped on success or when `pkg/networkserver:duplicate_uplink` error occurs.
- The Gateway Server now takes into consideration the extra duty cycle checks present in the LoRa Basics Station forwarder. Previously the Gateway Server may accept the scheduling of downlinks which the packet forwarder would silently drop.
- Note that in some rare cases in which the LoRa Basics Station duty cycle is stricter than the windowed approach used by The Things Stack, the scheduling will fail and this will be visible via `ns.down.data.schedule.fail` events. Note that this is actually a positive outcome - it allows the Network Server to schedule the downlink via another gateway, while previously the downlink would be scheduled but get silently dropped on the gateway.

Expand Down
4 changes: 2 additions & 2 deletions api/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8675,8 +8675,8 @@ The Pba service allows clients to manage peering through Packet Broker.
| `GetFormat` | `GET` | `/api/v3/qr-codes/end-devices/formats/{format_id}` | |
| `ListFormats` | `GET` | `/api/v3/qr-codes/end-devices/formats` | |
| `Generate` | `POST` | `/api/v3/qr-codes/end-devices` | `*` |
| `Parse` | `POST` | `/api/v3/qr-code/end-devices/parse` | `*` |
| `Parse` | `POST` | `/api/v3/qr-code/end-devices/{format_id}/parse` | `*` |
| `Parse` | `POST` | `/api/v3/qr-codes/end-devices/parse` | `*` |
| `Parse` | `POST` | `/api/v3/qr-codes/end-devices/{format_id}/parse` | `*` |

## <a name="lorawan-stack/api/regional.proto">File `lorawan-stack/api/regional.proto`</a>

Expand Down
110 changes: 55 additions & 55 deletions api/api.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -13846,15 +13846,15 @@
]
}
},
"/qr-code/end-devices/parse": {
"/qr-codes/end-devices": {
"post": {
"summary": "Parse QR Codes of known formats and return the information contained within.",
"operationId": "EndDeviceQRCodeGenerator_Parse",
"summary": "Generates a QR code.",
"operationId": "EndDeviceQRCodeGenerator_Generate",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v3ParseEndDeviceQRCodeResponse"
"$ref": "#/definitions/v3GenerateQRCodeResponse"
}
},
"default": {
Expand All @@ -13870,7 +13870,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v3ParseEndDeviceQRCodeRequest"
"$ref": "#/definitions/v3GenerateEndDeviceQRCodeRequest"
}
}
],
Expand All @@ -13879,15 +13879,15 @@
]
}
},
"/qr-code/end-devices/{format_id}/parse": {
"post": {
"summary": "Parse QR Codes of known formats and return the information contained within.",
"operationId": "EndDeviceQRCodeGenerator_Parse2",
"/qr-codes/end-devices/formats": {
"get": {
"summary": "Returns the supported formats.",
"operationId": "EndDeviceQRCodeGenerator_ListFormats",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v3ParseEndDeviceQRCodeResponse"
"$ref": "#/definitions/v3QRCodeFormats"
}
},
"default": {
Expand All @@ -13897,44 +13897,20 @@
}
}
},
"parameters": [
{
"name": "format_id",
"description": "QR code format identifier.\nEnumerate available formats with the rpc `ListFormats`.\nIf this field is not specified, the server will attempt to parse the data with each known format.",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"type": "object",
"properties": {
"qr_code": {
"type": "string",
"format": "byte",
"description": "Raw QR code contents."
}
}
}
}
],
"tags": [
"EndDeviceQRCodeGenerator"
]
}
},
"/qr-codes/end-devices": {
"post": {
"summary": "Generates a QR code.",
"operationId": "EndDeviceQRCodeGenerator_Generate",
"/qr-codes/end-devices/formats/{format_id}": {
"get": {
"summary": "Return the QR code format.",
"operationId": "EndDeviceQRCodeGenerator_GetFormat",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v3GenerateQRCodeResponse"
"$ref": "#/definitions/v3QRCodeFormat"
}
},
"default": {
Expand All @@ -13946,28 +13922,27 @@
},
"parameters": [
{
"name": "body",
"in": "body",
"name": "format_id",
"description": "QR code format identifier. Enumerate available formats with rpc ListFormats in the EndDeviceQRCodeGenerator service.",
"in": "path",
"required": true,
"schema": {
"$ref": "#/definitions/v3GenerateEndDeviceQRCodeRequest"
}
"type": "string"
}
],
"tags": [
"EndDeviceQRCodeGenerator"
]
}
},
"/qr-codes/end-devices/formats": {
"get": {
"summary": "Returns the supported formats.",
"operationId": "EndDeviceQRCodeGenerator_ListFormats",
"/qr-codes/end-devices/parse": {
"post": {
"summary": "Parse QR Codes of known formats and return the information contained within.",
"operationId": "EndDeviceQRCodeGenerator_Parse",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v3QRCodeFormats"
"$ref": "#/definitions/v3ParseEndDeviceQRCodeResponse"
}
},
"default": {
Expand All @@ -13977,20 +13952,30 @@
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/v3ParseEndDeviceQRCodeRequest"
}
}
],
"tags": [
"EndDeviceQRCodeGenerator"
]
}
},
"/qr-codes/end-devices/formats/{format_id}": {
"get": {
"summary": "Return the QR code format.",
"operationId": "EndDeviceQRCodeGenerator_GetFormat",
"/qr-codes/end-devices/{format_id}/parse": {
"post": {
"summary": "Parse QR Codes of known formats and return the information contained within.",
"operationId": "EndDeviceQRCodeGenerator_Parse2",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/v3QRCodeFormat"
"$ref": "#/definitions/v3ParseEndDeviceQRCodeResponse"
}
},
"default": {
Expand All @@ -14003,10 +13988,25 @@
"parameters": [
{
"name": "format_id",
"description": "QR code format identifier. Enumerate available formats with rpc ListFormats in the EndDeviceQRCodeGenerator service.",
"description": "QR code format identifier.\nEnumerate available formats with the rpc `ListFormats`.\nIf this field is not specified, the server will attempt to parse the data with each known format.",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"type": "object",
"properties": {
"qr_code": {
"type": "string",
"format": "byte",
"description": "Raw QR code contents."
}
}
}
}
],
"tags": [
Expand Down
4 changes: 2 additions & 2 deletions api/qrcodegenerator.proto
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ service EndDeviceQRCodeGenerator {
// Parse QR Codes of known formats and return the information contained within.
rpc Parse(ParseEndDeviceQRCodeRequest) returns (ParseEndDeviceQRCodeResponse){
option (google.api.http) = {
post: "/qr-code/end-devices/parse",
post: "/qr-codes/end-devices/parse",
body: "*"
additional_bindings {
post: "/qr-code/end-devices/{format_id}/parse"
post: "/qr-codes/end-devices/{format_id}/parse"
body: "*"
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('Device onboarding with QR scan', () => {
interceptDeviceRepo(appId)
cy.intercept(
'POST',
'/api/v3/qr-code/end-devices/parse',
'/api/v3/qr-codes/end-devices/parse',
composeQRGeneratorParseResponse({ ...device, vendorId: 428 }),
).as('qr-code-parse-request')
cy.loginConsole({ user_id: user.ids.user_id, password: user.password })
Expand Down
2 changes: 1 addition & 1 deletion pkg/deviceclaimingserver/grpc_end_devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (edcs *endDeviceClaimingServer) Claim(
return nil, errClaimingNotSupported.WithAttributes("eui", joinEUI)
}

err := claimer.Claim(ctx, devEUI, joinEUI, claimAuthenticationCode)
err := claimer.Claim(ctx, joinEUI, devEUI, claimAuthenticationCode)
if err != nil {
return nil, err
}
Expand Down
13 changes: 11 additions & 2 deletions pkg/deviceclaimingserver/grpc_end_devices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ var (
registeredJoinEUI = types.EUI64{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C}
unRegisteredJoinEUI = types.EUI64{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D}
registeredDevEUI = types.EUI64{0x00, 0x04, 0xA3, 0x0B, 0x00, 0x1C, 0x05, 0x30}
authenticationCode = "BEEF1234"
)

func mustHavePeer(ctx context.Context, c *component.Component, role ttnpb.ClusterRole) {
Expand Down Expand Up @@ -88,6 +89,14 @@ func TestEndDeviceClaimingServer(t *testing.T) {
enddevices.Config{},
enddevices.WithClaimer("test", &MockClaimer{
JoinEUI: registeredJoinEUI,
ClaimFunc: func(
ctx context.Context, joinEUI, devEUI types.EUI64, claimAuthenticationCode string,
) error {
a.So(joinEUI, should.Equal, registeredJoinEUI)
a.So(devEUI, should.Resemble, registeredDevEUI)
a.So(claimAuthenticationCode, should.Equal, authenticationCode)
return nil
},
}),
)
a.So(err, should.BeNil)
Expand Down Expand Up @@ -205,7 +214,7 @@ func TestEndDeviceClaimingServer(t *testing.T) {
AuthenticatedIdentifiers: &ttnpb.ClaimEndDeviceRequest_AuthenticatedIdentifiers{
JoinEui: registeredJoinEUI.Bytes(),
DevEui: registeredDevEUI.Bytes(),
AuthenticationCode: "TEST1234",
AuthenticationCode: authenticationCode,
},
},
TargetApplicationIds: registeredApplicationIDs,
Expand All @@ -223,7 +232,7 @@ func TestEndDeviceClaimingServer(t *testing.T) {
AuthenticatedIdentifiers: &ttnpb.ClaimEndDeviceRequest_AuthenticatedIdentifiers{
JoinEui: registeredJoinEUI.Bytes(),
DevEui: registeredDevEUI.Bytes(),
AuthenticationCode: "TEST1234",
AuthenticationCode: authenticationCode,
},
},
TargetApplicationIds: registeredApplicationIDs,
Expand Down
7 changes: 5 additions & 2 deletions pkg/deviceclaimingserver/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
// MockClaimer is a mock Claimer.
type MockClaimer struct {
JoinEUI types.EUI64

ClaimFunc func(context.Context, types.EUI64, types.EUI64, string) error
}

// SupportsJoinEUI returns whether the Join Server supports this JoinEUI.
Expand All @@ -32,9 +34,10 @@ func (m MockClaimer) SupportsJoinEUI(joinEUI types.EUI64) bool {
}

// Claim claims an End Device.
func (MockClaimer) Claim(_ context.Context, _, _ types.EUI64, _ string,
func (m MockClaimer) Claim(
ctx context.Context, joinEUI, devEUI types.EUI64, claimAuthenticationCode string,
) error {
return nil
return m.ClaimFunc(ctx, joinEUI, devEUI, claimAuthenticationCode)
}

// GetClaimStatus returns the claim status an End Device.
Expand Down
24 changes: 12 additions & 12 deletions pkg/ttnpb/qrcodegenerator.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b501fd4

Please sign in to comment.