added API endpoints to set/remove a pin

see #660
This commit is contained in:
Bernhard B
2025-02-26 22:26:13 +01:00
parent 46bd47fc04
commit 4404929c90
6 changed files with 295 additions and 2 deletions

View File

@@ -202,6 +202,10 @@ type AddStickerPackRequest struct {
PackKey string `json:"pack_key" example:"19546e18eba0ff69dea78eb591465289d39e16f35e58389ae779d4f9455aff3a"` PackKey string `json:"pack_key" example:"19546e18eba0ff69dea78eb591465289d39e16f35e58389ae779d4f9455aff3a"`
} }
type SetPinRequest struct {
Pin string `json:"pin"`
}
type Api struct { type Api struct {
signalClient *client.SignalClient signalClient *client.SignalClient
wsMutex sync.Mutex wsMutex sync.Mutex
@@ -2166,3 +2170,68 @@ func (a *Api) ListContacts(c *gin.Context) {
c.JSON(200, contacts) c.JSON(200, contacts)
} }
// @Summary Set Pin
// @Tags Accounts
// @Description Sets a new Signal Pin
// @Produce json
// @Success 201
// @Failure 400 {object} Error
// @Param number path string true "Registered Phone Number"
// @Router /v1/accounts/{number}/pin [get]
func (a *Api) SetPin(c *gin.Context) {
number, err := url.PathUnescape(c.Param("number"))
if err != nil {
c.JSON(400, Error{Msg: "Couldn't process request - malformed number"})
return
}
if number == "" {
c.JSON(400, Error{Msg: "Couldn't process request - number missing"})
return
}
var req SetPinRequest
err = c.BindJSON(&req)
if err != nil {
c.JSON(400, Error{Msg: "Couldn't process request - invalid request"})
return
}
err = a.signalClient.SetPin(number, req.Pin)
if err != nil {
c.JSON(400, Error{Msg: err.Error()})
return
}
c.Status(201)
}
// @Summary Remove Pin
// @Tags Accounts
// @Description Removes a Signal Pin
// @Produce json
// @Success 204
// @Failure 400 {object} Error
// @Param number path string true "Registered Phone Number"
// @Router /v1/accounts/{number}/pin [delete]
func (a *Api) RemovePin(c *gin.Context) {
number, err := url.PathUnescape(c.Param("number"))
if err != nil {
c.JSON(400, Error{Msg: "Couldn't process request - malformed number"})
return
}
if number == "" {
c.JSON(400, Error{Msg: "Couldn't process request - number missing"})
return
}
err = a.signalClient.RemovePin(number)
if err != nil {
c.JSON(400, Error{Msg: err.Error()})
return
}
c.Status(204)
}

View File

@@ -2239,3 +2239,49 @@ func (s *SignalClient) ListContacts(number string) ([]ListContactsResponse, erro
return resp, nil return resp, nil
} }
func (s *SignalClient) SetPin(number string, registrationLockPin string) (error) {
if s.signalCliMode == JsonRpc {
type Request struct {
RegistrationLockPin string `json:"pin"`
}
req := Request{RegistrationLockPin: registrationLockPin}
jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil {
return err
}
_, err = jsonRpc2Client.getRaw("setPin", &number, req)
if err != nil {
return err
}
} else {
cmd := []string{"--config", s.signalCliConfig, "-o", "json", "-a", number, "setPin", registrationLockPin}
rawData, err := s.cliClient.Execute(true, cmd, "")
if err != nil {
return err
}
log.Info(string(rawData))
}
return nil
}
func (s *SignalClient) RemovePin(number string) (error) {
if s.signalCliMode == JsonRpc {
jsonRpc2Client, err := s.getJsonRpc2Client()
if err != nil {
return err
}
_, err = jsonRpc2Client.getRaw("removePin", &number, nil)
if err != nil {
return err
}
} else {
cmd := []string{"--config", s.signalCliConfig, "-o", "json", "-a", number, "removePin"}
_, err := s.cliClient.Execute(true, cmd, "")
if err != nil {
return err
}
}
return nil
}

View File

@@ -64,6 +64,68 @@ const docTemplate = `{
} }
} }
}, },
"/v1/accounts/{number}/pin": {
"get": {
"description": "Sets a new Signal Pin",
"produces": [
"application/json"
],
"tags": [
"Accounts"
],
"summary": "Set Pin",
"parameters": [
{
"type": "string",
"description": "Registered Phone Number",
"name": "number",
"in": "path",
"required": true
}
],
"responses": {
"201": {
"description": "Created"
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/api.Error"
}
}
}
},
"delete": {
"description": "Removes a Signal Pin",
"produces": [
"application/json"
],
"tags": [
"Accounts"
],
"summary": "Remove Pin",
"parameters": [
{
"type": "string",
"description": "Registered Phone Number",
"name": "number",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/api.Error"
}
}
}
}
},
"/v1/accounts/{number}/rate-limit-challenge": { "/v1/accounts/{number}/rate-limit-challenge": {
"post": { "post": {
"description": "When running into rate limits, sometimes the limit can be lifted, by solving a CAPTCHA. To get the captcha token, go to https://signalcaptchas.org/challenge/generate.html For the staging environment, use: https://signalcaptchas.org/staging/registration/generate.html. The \"challenge_token\" is the token from the failed send attempt. The \"captcha\" is the captcha result, starting with signalcaptcha://", "description": "When running into rate limits, sometimes the limit can be lifted, by solving a CAPTCHA. To get the captcha token, go to https://signalcaptchas.org/challenge/generate.html For the staging environment, use: https://signalcaptchas.org/staging/registration/generate.html. The \"challenge_token\" is the token from the failed send attempt. The \"captcha\" is the captcha result, starting with signalcaptcha://",
@@ -1717,7 +1779,8 @@ const docTemplate = `{
"type": "string", "type": "string",
"description": "Registered Phone Number", "description": "Registered Phone Number",
"name": "number", "name": "number",
"in": "path" "in": "path",
"required": true
}, },
{ {
"type": "array", "type": "array",
@@ -2526,6 +2589,9 @@ const docTemplate = `{
"blocked": { "blocked": {
"type": "boolean" "type": "boolean"
}, },
"description": {
"type": "string"
},
"id": { "id": {
"type": "string" "type": "string"
}, },

View File

@@ -61,6 +61,68 @@
} }
} }
}, },
"/v1/accounts/{number}/pin": {
"get": {
"description": "Sets a new Signal Pin",
"produces": [
"application/json"
],
"tags": [
"Accounts"
],
"summary": "Set Pin",
"parameters": [
{
"type": "string",
"description": "Registered Phone Number",
"name": "number",
"in": "path",
"required": true
}
],
"responses": {
"201": {
"description": "Created"
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/api.Error"
}
}
}
},
"delete": {
"description": "Removes a Signal Pin",
"produces": [
"application/json"
],
"tags": [
"Accounts"
],
"summary": "Remove Pin",
"parameters": [
{
"type": "string",
"description": "Registered Phone Number",
"name": "number",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/api.Error"
}
}
}
}
},
"/v1/accounts/{number}/rate-limit-challenge": { "/v1/accounts/{number}/rate-limit-challenge": {
"post": { "post": {
"description": "When running into rate limits, sometimes the limit can be lifted, by solving a CAPTCHA. To get the captcha token, go to https://signalcaptchas.org/challenge/generate.html For the staging environment, use: https://signalcaptchas.org/staging/registration/generate.html. The \"challenge_token\" is the token from the failed send attempt. The \"captcha\" is the captcha result, starting with signalcaptcha://", "description": "When running into rate limits, sometimes the limit can be lifted, by solving a CAPTCHA. To get the captcha token, go to https://signalcaptchas.org/challenge/generate.html For the staging environment, use: https://signalcaptchas.org/staging/registration/generate.html. The \"challenge_token\" is the token from the failed send attempt. The \"captcha\" is the captcha result, starting with signalcaptcha://",
@@ -1714,7 +1776,8 @@
"type": "string", "type": "string",
"description": "Registered Phone Number", "description": "Registered Phone Number",
"name": "number", "name": "number",
"in": "path" "in": "path",
"required": true
}, },
{ {
"type": "array", "type": "array",
@@ -2523,6 +2586,9 @@
"blocked": { "blocked": {
"type": "boolean" "type": "boolean"
}, },
"description": {
"type": "string"
},
"id": { "id": {
"type": "string" "type": "string"
}, },

View File

@@ -312,6 +312,8 @@ definitions:
type: array type: array
blocked: blocked:
type: boolean type: boolean
description:
type: string
id: id:
type: string type: string
internal_id: internal_id:
@@ -433,6 +435,47 @@ paths:
summary: List all accounts summary: List all accounts
tags: tags:
- Accounts - Accounts
/v1/accounts/{number}/pin:
delete:
description: Removes a Signal Pin
parameters:
- description: Registered Phone Number
in: path
name: number
required: true
type: string
produces:
- application/json
responses:
"204":
description: No Content
"400":
description: Bad Request
schema:
$ref: '#/definitions/api.Error'
summary: Remove Pin
tags:
- Accounts
get:
description: Sets a new Signal Pin
parameters:
- description: Registered Phone Number
in: path
name: number
required: true
type: string
produces:
- application/json
responses:
"201":
description: Created
"400":
description: Bad Request
schema:
$ref: '#/definitions/api.Error'
summary: Set Pin
tags:
- Accounts
/v1/accounts/{number}/rate-limit-challenge: /v1/accounts/{number}/rate-limit-challenge:
post: post:
consumes: consumes:
@@ -1544,6 +1587,7 @@ paths:
- description: Registered Phone Number - description: Registered Phone Number
in: path in: path
name: number name: number
required: true
type: string type: string
- collectionFormat: multi - collectionFormat: multi
description: Numbers to check description: Numbers to check

View File

@@ -223,6 +223,8 @@ func main() {
accounts.PUT(":number/settings", api.UpdateAccountSettings) accounts.PUT(":number/settings", api.UpdateAccountSettings)
accounts.POST(":number/username", api.SetUsername) accounts.POST(":number/username", api.SetUsername)
accounts.DELETE(":number/username", api.RemoveUsername) accounts.DELETE(":number/username", api.RemoveUsername)
accounts.POST(":number/pin", api.SetPin)
accounts.DELETE(":number/pin", api.RemovePin)
} }
devices := v1.Group("devices") devices := v1.Group("devices")