Skip to content

Commit 81ed831

Browse files
committed
feat: support username on POST mapping
1 parent 4659632 commit 81ed831

File tree

6 files changed

+75
-16
lines changed

6 files changed

+75
-16
lines changed

README.md

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,7 @@ For debugging mapping and API issues, set `LOGLEVEL=DEBUG` to see detailed trace
4949

5050
You can pre-load SMS-to-Matrix mappings at startup by providing a `MAPPING_FILE` environment variable pointing to a JSON file. This is useful for initializing the proxy with a set of known mappings.
5151

52-
The JSON file should be an array of mapping objects:
53-
54-
```json
55-
[
56-
{
57-
"sms_number": "91201",
58-
"matrix_id": "@giacomo:synapse.gs.nethserver.net",
59-
"room_id": "!giacomo-room:synapse.gs.nethserver.net"
60-
},
61-
{
62-
"sms_number": "91202",
63-
"matrix_id": "@mario:synapse.gs.nethserver.net",
64-
"room_id": "!mario-room:synapse.gs.nethserver.net"
65-
}
66-
]
67-
```
52+
See `docs/example-mappings.json` for an example format.
6853

6954
Usage:
7055

docs/openapi.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ components:
229229
room_id:
230230
type: string
231231
description: Matrix room ID where the mapped identifier should route messages.
232+
user_name:
233+
type: string
234+
description: Optional human-friendly name to expose for this mapping (e.g., contact name).
232235
MappingResponse:
233236
type: object
234237
properties:
@@ -238,6 +241,9 @@ components:
238241
type: string
239242
room_id:
240243
type: string
244+
user_name:
245+
type: string
246+
description: Optional human-friendly name associated with the mapping.
241247
updated_at:
242248
type: string
243249
format: date-time

main_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,68 @@ func TestIntegration_MappingAPI(t *testing.T) {
494494
}
495495
})
496496

497+
t.Run("CreateAndGetMappingWithUserName", func(t *testing.T) {
498+
headers := map[string]string{
499+
"X-Super-Admin-Token": cfg.adminToken,
500+
}
501+
502+
mappingReq := models.MappingRequest{
503+
SMSNumber: "+1234509876",
504+
MatrixID: fmt.Sprintf("@userwithname:%s", serverName),
505+
RoomID: fmt.Sprintf("!roomwithname:%s", serverName),
506+
UserName: "Mario Rossi",
507+
}
508+
509+
// Create mapping with user_name
510+
resp, body, err := doRequest("POST", baseURL+"/api/internal/map_sms_to_matrix", mappingReq, headers)
511+
if err != nil {
512+
t.Fatalf("request failed: %v", err)
513+
}
514+
if resp.StatusCode != http.StatusOK {
515+
// Try variants if creation failed due to environment
516+
if resp.StatusCode == http.StatusBadRequest {
517+
if v, err := ensureMappingVariants(t, baseURL, cfg.adminToken, mappingReq.SMSNumber, mappingReq.MatrixID, mappingReq.RoomID); err == nil {
518+
t.Logf("created mapping variant %s for sms_number %s", v, mappingReq.SMSNumber)
519+
} else {
520+
t.Skip("mapping creation failed in this environment; skipping assertion")
521+
}
522+
}
523+
if resp.StatusCode != http.StatusOK {
524+
t.Fatalf("unexpected status code %d: %s", resp.StatusCode, string(body))
525+
}
526+
}
527+
528+
// Retrieve mapping and check user_name
529+
resp, body, err = doRequest("GET", baseURL+"/api/internal/map_sms_to_matrix?sms_number=%2B1234509876", nil, headers)
530+
if err != nil {
531+
t.Fatalf("request failed: %v", err)
532+
}
533+
if resp.StatusCode != http.StatusOK {
534+
if resp.StatusCode == http.StatusBadRequest {
535+
if _, err := ensureMappingVariants(t, baseURL, cfg.adminToken, mappingReq.SMSNumber, mappingReq.MatrixID, mappingReq.RoomID); err == nil {
536+
// retry GET
537+
resp, body, err = doRequest("GET", baseURL+"/api/internal/map_sms_to_matrix?sms_number=%2B1234509876", nil, headers)
538+
if err != nil {
539+
t.Fatalf("request failed: %v", err)
540+
}
541+
} else {
542+
t.Skip("mapping not found and creation attempts failed; skipping assertion")
543+
}
544+
}
545+
if resp.StatusCode != http.StatusOK {
546+
t.Fatalf("unexpected status code %d: %s", resp.StatusCode, string(body))
547+
}
548+
}
549+
550+
var mappingResp models.MappingResponse
551+
if err := json.Unmarshal(body, &mappingResp); err != nil {
552+
t.Fatalf("failed to parse response: %v", err)
553+
}
554+
if mappingResp.UserName != "Mario Rossi" {
555+
t.Errorf("expected user_name='Mario Rossi', got '%s'", mappingResp.UserName)
556+
}
557+
})
558+
497559
t.Run("UnauthorizedAccess", func(t *testing.T) {
498560
mappingReq := models.MappingRequest{
499561
SMSNumber: "+1111111111",

models/mapping.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ type MappingResponse struct {
1313
SMSNumber string `json:"sms_number"`
1414
MatrixID string `json:"matrix_id"`
1515
RoomID string `json:"room_id"`
16+
UserName string `json:"user_name,omitempty"`
1617
UpdatedAt string `json:"updated_at"`
1718
}

models/models_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func TestMappingRequest_Marshal(t *testing.T) {
5454
SMSNumber: "+1234567890",
5555
MatrixID: "@user:example.com",
5656
RoomID: "!room:example.com",
57+
UserName: "Test User",
5758
}
5859

5960
data, err := json.Marshal(req)
@@ -66,6 +67,7 @@ func TestMappingRequest_Marshal(t *testing.T) {
6667
assert.Equal(t, req.SMSNumber, req2.SMSNumber)
6768
assert.Equal(t, req.MatrixID, req2.MatrixID)
6869
assert.Equal(t, req.RoomID, req2.RoomID)
70+
assert.Equal(t, req.UserName, req2.UserName)
6971
}
7072

7173
func TestMessage_Marshal(t *testing.T) {
@@ -138,6 +140,7 @@ func TestMappingResponse_Marshal(t *testing.T) {
138140
SMSNumber: "+1234567890",
139141
MatrixID: "@user:example.com",
140142
RoomID: "!room:example.com",
143+
UserName: "Test User",
141144
UpdatedAt: "2025-01-01T00:00:00Z",
142145
}
143146

service/messages.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ func (s *MessageService) SaveMapping(req *models.MappingRequest) (*models.Mappin
350350
SMSNumber: smsNumber,
351351
MatrixID: strings.TrimSpace(req.MatrixID),
352352
RoomID: id.RoomID(roomID),
353+
UserName: strings.TrimSpace(req.UserName),
353354
UpdatedAt: s.now(),
354355
}
355356
entry = s.setMapping(entry)
@@ -399,6 +400,7 @@ func (s *MessageService) buildMappingResponse(entry mappingEntry) *models.Mappin
399400
SMSNumber: entry.SMSNumber,
400401
MatrixID: entry.MatrixID,
401402
RoomID: string(entry.RoomID),
403+
UserName: entry.UserName,
402404
UpdatedAt: entry.UpdatedAt.UTC().Format(time.RFC3339),
403405
}
404406
}

0 commit comments

Comments
 (0)