started working on JSON-RPC integration

* still WIP
This commit is contained in:
Bernhard B
2021-09-11 22:28:55 +02:00
parent eb312c97c3
commit ae857c7a69
7 changed files with 469 additions and 90 deletions

View File

@@ -18,5 +18,10 @@ EOF
cap_prefix="-cap_" cap_prefix="-cap_"
caps="$cap_prefix$(seq -s ",$cap_prefix" 0 $(cat /proc/sys/kernel/cap_last_cap))" caps="$cap_prefix$(seq -s ",$cap_prefix" 0 $(cat /proc/sys/kernel/cap_last_cap))"
# TODO: check mode
/usr/bin/jsonrpc2-helper
service supervisor start
supervisorctl start all
# Start API as signal-api user # Start API as signal-api user
exec setpriv --reuid=1000 --regid=1000 --init-groups --inh-caps=$caps signal-cli-rest-api -signal-cli-config=${SIGNAL_CLI_CONFIG_DIR} exec setpriv --reuid=1000 --regid=1000 --init-groups --inh-caps=$caps signal-cli-rest-api -signal-cli-config=${SIGNAL_CLI_CONFIG_DIR}

View File

@@ -17,6 +17,7 @@ import (
"github.com/cyphar/filepath-securejoin" "github.com/cyphar/filepath-securejoin"
"github.com/gabriel-vasile/mimetype" "github.com/gabriel-vasile/mimetype"
"github.com/h2non/filetype" "github.com/h2non/filetype"
//"github.com/sourcegraph/jsonrpc2"//"net/rpc/jsonrpc"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
uuid "github.com/gofrs/uuid" uuid "github.com/gofrs/uuid"
@@ -30,26 +31,36 @@ const groupPrefix = "group."
const signalCliV2GroupError = "Cannot create a V2 group as self does not have a versioned profile" const signalCliV2GroupError = "Cannot create a V2 group as self does not have a versioned profile"
type GroupPermission int type GroupPermission int
const ( const (
DefaultGroupPermission GroupPermission = iota + 1 DefaultGroupPermission GroupPermission = iota + 1
EveryMember EveryMember
OnlyAdmins OnlyAdmins
) )
type GroupLinkState int type SignalCliMode int
const ( const (
DefaultGroupLinkState GroupLinkState = iota + 1 Normal SignalCliMode = iota + 1
Native
JsonRpc
)
type GroupLinkState int
const (
DefaultGroupLinkState GroupLinkState = iota + 1
Enabled Enabled
EnabledWithApproval EnabledWithApproval
Disabled Disabled
) )
func (g GroupPermission) String() string { func (g GroupPermission) String() string {
return []string{"", "default", "every-member", "only-admins"}[g] return []string{"", "default", "every-member", "only-admins"}[g]
} }
func (g GroupLinkState) String() string { func (g GroupLinkState) String() string {
return []string{"", "enabled", "enabled-with-approval", "disabled"}[g] return []string{"", "enabled", "enabled-with-approval", "disabled"}[g]
} }
type GroupEntry struct { type GroupEntry struct {
@@ -71,15 +82,30 @@ type IdentityEntry struct {
SafetyNumber string `json:"safety_number"` SafetyNumber string `json:"safety_number"`
} }
type SignalCliGroupMember struct {
Number string `json:"number"`
Uuid string `json:"uuid"`
}
type SignalCliGroupEntry struct { type SignalCliGroupEntry struct {
Name string `json:"name"` Name string `json:"name"`
Id string `json:"id"` Id string `json:"id"`
IsMember bool `json:"isMember"` IsMember bool `json:"isMember"`
IsBlocked bool `json:"isBlocked"` IsBlocked bool `json:"isBlocked"`
Members []string `json:"members"` Members []SignalCliGroupMember `json:"members"`
PendingMembers []string `json:"pendingMembers"` PendingMembers []string `json:"pendingMembers"`
RequestingMembers []string `json:"requestingMembers"` RequestingMembers []string `json:"requestingMembers"`
GroupInviteLink string `json:"groupInviteLink"` GroupInviteLink string `json:"groupInviteLink"`
}
type SignalCliIdentityEntry struct {
Number string `json:"number"`
Uuid string `json:"uuid"`
Fingerprint string `json:"fingerprint"`
SafetyNumber string `json:"safetyNumber"`
ScannableSafetyNumber string `json:"scannableSafetyNumber"`
TrustLevel string `json:"trustLevel"`
AddedTimestamp int64 `json:"addedTimestamp"`
} }
type About struct { type About struct {
@@ -252,7 +278,7 @@ func runSignalCli(wait bool, args []string, stdin string) (string, error) {
} }
fullCmd := "" fullCmd := ""
if(stdin != "") { if stdin != "" {
fullCmd += "echo '" + stdin + "' | " fullCmd += "echo '" + stdin + "' | "
} }
fullCmd += signalCliBinary + " " + strings.Join(args, " ") fullCmd += signalCliBinary + " " + strings.Join(args, " ")
@@ -323,19 +349,47 @@ func ConvertGroupIdToInternalGroupId(id string) (string, error) {
} }
type SignalClient struct { type SignalClient struct {
signalCliConfig string signalCliConfig string
attachmentTmpDir string attachmentTmpDir string
avatarTmpDir string avatarTmpDir string
signalCliMode SignalCliMode
jsonRpc2ClientConfig *utils.JsonRpc2ClientConfig
jsonRpc2ClientConfigPath string
jsonRpc2Clients map[string]*JsonRpc2Client
} }
func NewSignalClient(signalCliConfig string, attachmentTmpDir string, avatarTmpDir string) *SignalClient { func NewSignalClient(signalCliConfig string, attachmentTmpDir string, avatarTmpDir string, signalCliMode SignalCliMode,
jsonRpc2ClientConfigPath string) *SignalClient {
return &SignalClient{ return &SignalClient{
signalCliConfig: signalCliConfig, signalCliConfig: signalCliConfig,
attachmentTmpDir: attachmentTmpDir, attachmentTmpDir: attachmentTmpDir,
avatarTmpDir: avatarTmpDir, avatarTmpDir: avatarTmpDir,
signalCliMode: signalCliMode,
jsonRpc2ClientConfigPath: jsonRpc2ClientConfigPath,
jsonRpc2Clients: make(map[string]*JsonRpc2Client),
} }
} }
func (s *SignalClient) Init() error {
if s.signalCliMode == JsonRpc {
s.jsonRpc2ClientConfig = utils.NewJsonRpc2ClientConfig()
err := s.jsonRpc2ClientConfig.Load(s.jsonRpc2ClientConfigPath)
if err != nil {
return err
}
tcpPortsNumberMapping := s.jsonRpc2ClientConfig.GetTcpPortsForNumbers()
for number, tcpPort := range tcpPortsNumberMapping {
s.jsonRpc2Clients[number] = NewJsonRpc2Client()
err := s.jsonRpc2Clients[number].Dial("127.0.0.1:" + strconv.FormatInt(tcpPort, 10))
if err != nil {
return err
}
}
}
return nil
}
func (s *SignalClient) About() About { func (s *SignalClient) About() About {
about := About{SupportedApiVersions: []string{"v1", "v2"}, BuildNr: 2} about := About{SupportedApiVersions: []string{"v1", "v2"}, BuildNr: 2}
return about return about
@@ -372,6 +426,13 @@ func (s *SignalClient) SendV1(number string, message string, recipients []string
return timestamp, err return timestamp, err
} }
func (s *SignalClient) getJsonRpc2Client(number string) (*JsonRpc2Client, error) {
if val, ok := s.jsonRpc2Clients[number]; ok {
return val, nil
}
return nil, errors.New("Number not registered with JSON-RPC")
}
func (s *SignalClient) SendV2(number string, message string, recps []string, base64Attachments []string) ([]string, error) { func (s *SignalClient) SendV2(number string, message string, recps []string, base64Attachments []string) ([]string, error) {
if len(recps) == 0 { if len(recps) == 0 {
return []string{}, errors.New("Please provide at least one recipient") return []string{}, errors.New("Please provide at least one recipient")
@@ -444,49 +505,81 @@ func (s *SignalClient) Receive(number string, timeout int64) (string, error) {
} }
func (s *SignalClient) CreateGroup(number string, name string, members []string, description string, editGroupPermission GroupPermission, addMembersPermission GroupPermission, groupLinkState GroupLinkState) (string, error) { func (s *SignalClient) CreateGroup(number string, name string, members []string, description string, editGroupPermission GroupPermission, addMembersPermission GroupPermission, groupLinkState GroupLinkState) (string, error) {
cmd := []string{"--config", s.signalCliConfig, "-u", number, "updateGroup", "-n", name, "-m"} var err error
cmd = append(cmd, members...) var rawData string
if s.signalCliMode == JsonRpc {
if addMembersPermission != DefaultGroupPermission { type Request struct {
cmd = append(cmd, []string{"--set-permission-add-member", addMembersPermission.String()}...) Name string `json:"name"`
} Members []string `json:"members"`
if editGroupPermission != DefaultGroupPermission {
cmd = append(cmd, []string{"--set-permission-edit-details", editGroupPermission.String()}...)
}
if groupLinkState != DefaultGroupLinkState {
cmd = append(cmd, []string{"--link", groupLinkState.String()}...)
}
if description != "" {
cmd = append(cmd, []string{"--description", description}...)
}
out, err := runSignalCli(true, cmd, "")
if err != nil {
if strings.Contains(err.Error(), signalCliV2GroupError) {
return "", errors.New("Cannot create group - please first update your profile.")
} }
return "", err request := Request{Name: name, Members: members}
}
internalGroupId := getStringInBetween(out, `"`, `"`) jsonRpc2Client, err := s.getJsonRpc2Client(number)
if err != nil {
return "", err
}
rawData, err = jsonRpc2Client.getRaw("updateGroup", request)
if err != nil {
return "", err
}
} else {
cmd := []string{"--config", s.signalCliConfig, "-u", number, "updateGroup", "-n", name, "-m"}
cmd = append(cmd, members...)
if addMembersPermission != DefaultGroupPermission {
cmd = append(cmd, []string{"--set-permission-add-member", addMembersPermission.String()}...)
}
if editGroupPermission != DefaultGroupPermission {
cmd = append(cmd, []string{"--set-permission-edit-details", editGroupPermission.String()}...)
}
if groupLinkState != DefaultGroupLinkState {
cmd = append(cmd, []string{"--link", groupLinkState.String()}...)
}
if description != "" {
cmd = append(cmd, []string{"--description", description}...)
}
rawData, err = runSignalCli(true, cmd, "")
if err != nil {
if strings.Contains(err.Error(), signalCliV2GroupError) {
return "", errors.New("Cannot create group - please first update your profile.")
}
return "", err
}
}
internalGroupId := getStringInBetween(rawData, `"`, `"`)
groupId := convertInternalGroupIdToGroupId(internalGroupId) groupId := convertInternalGroupIdToGroupId(internalGroupId)
return groupId, nil return groupId, nil
} }
func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) { func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) {
groupEntries := []GroupEntry{} groupEntries := []GroupEntry{}
out, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "--output", "json", "-u", number, "listGroups", "-d"}, "") var signalCliGroupEntries []SignalCliGroupEntry
if err != nil { var err error
return groupEntries, err var rawData string
if s.signalCliMode == JsonRpc {
jsonRpc2Client, err := s.getJsonRpc2Client(number)
if err != nil {
return groupEntries, err
}
rawData, err = jsonRpc2Client.getRaw("listGroups", nil)
if err != nil {
return groupEntries, err
}
} else {
rawData, err = runSignalCli(true, []string{"--config", s.signalCliConfig, "--output", "json", "-u", number, "listGroups", "-d"}, "")
if err != nil {
return groupEntries, err
}
} }
var signalCliGroupEntries []SignalCliGroupEntry err = json.Unmarshal([]byte(rawData), &signalCliGroupEntries)
err = json.Unmarshal([]byte(out), &signalCliGroupEntries)
if err != nil { if err != nil {
return groupEntries, err return groupEntries, err
} }
@@ -497,7 +590,13 @@ func (s *SignalClient) GetGroups(number string) ([]GroupEntry, error) {
groupEntry.Name = signalCliGroupEntry.Name groupEntry.Name = signalCliGroupEntry.Name
groupEntry.Id = convertInternalGroupIdToGroupId(signalCliGroupEntry.Id) groupEntry.Id = convertInternalGroupIdToGroupId(signalCliGroupEntry.Id)
groupEntry.Blocked = signalCliGroupEntry.IsBlocked groupEntry.Blocked = signalCliGroupEntry.IsBlocked
groupEntry.Members = signalCliGroupEntry.Members
members := []string{}
for _, val := range signalCliGroupEntry.Members {
members = append(members, val.Number)
}
groupEntry.Members = members
groupEntry.PendingRequests = signalCliGroupEntry.PendingMembers groupEntry.PendingRequests = signalCliGroupEntry.PendingMembers
groupEntry.PendingInvites = signalCliGroupEntry.RequestingMembers groupEntry.PendingInvites = signalCliGroupEntry.RequestingMembers
groupEntry.InviteLink = signalCliGroupEntry.GroupInviteLink groupEntry.InviteLink = signalCliGroupEntry.GroupInviteLink
@@ -602,12 +701,9 @@ func (s *SignalClient) GetAttachment(attachment string) ([]byte, error) {
} }
func (s *SignalClient) UpdateProfile(number string, profileName string, base64Avatar string) error { func (s *SignalClient) UpdateProfile(number string, profileName string, base64Avatar string) error {
cmd := []string{"--config", s.signalCliConfig, "-u", number, "updateProfile", "--name", profileName} var err error
var avatarTmpPath string
avatarTmpPaths := []string{} if base64Avatar != "" {
if base64Avatar == "" {
cmd = append(cmd, "--remove-avatar")
} else {
u, err := uuid.NewV4() u, err := uuid.NewV4()
if err != nil { if err != nil {
return err return err
@@ -615,7 +711,7 @@ func (s *SignalClient) UpdateProfile(number string, profileName string, base64Av
avatarBytes, err := base64.StdEncoding.DecodeString(base64Avatar) avatarBytes, err := base64.StdEncoding.DecodeString(base64Avatar)
if err != nil { if err != nil {
return errors.New("Couldn't decode base64 encoded avatar: " +err.Error()) return errors.New("Couldn't decode base64 encoded avatar: " + err.Error())
} }
fType, err := filetype.Get(avatarBytes) fType, err := filetype.Get(avatarBytes)
@@ -632,51 +728,113 @@ func (s *SignalClient) UpdateProfile(number string, profileName string, base64Av
defer f.Close() defer f.Close()
if _, err := f.Write(avatarBytes); err != nil { if _, err := f.Write(avatarBytes); err != nil {
cleanupTmpFiles(avatarTmpPaths) cleanupTmpFiles([]string{avatarTmpPath})
return err return err
} }
if err := f.Sync(); err != nil { if err := f.Sync(); err != nil {
cleanupTmpFiles(avatarTmpPaths) cleanupTmpFiles([]string{avatarTmpPath})
return err return err
} }
f.Close() f.Close()
cmd = append(cmd, []string{"--avatar", avatarTmpPath}...)
avatarTmpPaths = append(avatarTmpPaths, avatarTmpPath)
} }
_, err := runSignalCli(true, cmd, "") if s.signalCliMode == JsonRpc {
cleanupTmpFiles(avatarTmpPaths) type Request struct {
Name string `json:"name"`
Avatar string `json:"avatar,omitempty"`
RemoveAvatar bool `json:"remove-avatar"`
}
request := Request{Name: profileName}
if base64Avatar == "" {
request.RemoveAvatar = true
} else {
request.Avatar = avatarTmpPath
request.RemoveAvatar = false
}
jsonRpc2Client, err := s.getJsonRpc2Client(number)
if err != nil {
return err
}
_, err = jsonRpc2Client.getRaw("updateProfile", request)
} else {
cmd := []string{"--config", s.signalCliConfig, "-u", number, "updateProfile", "--name", profileName}
if base64Avatar == "" {
cmd = append(cmd, "--remove-avatar")
} else {
cmd = append(cmd, []string{"--avatar", avatarTmpPath}...)
}
_, err = runSignalCli(true, cmd, "")
}
cleanupTmpFiles([]string{avatarTmpPath})
return err return err
} }
func (s *SignalClient) ListIdentities(number string) (*[]IdentityEntry, error) { func (s *SignalClient) ListIdentities(number string) (*[]IdentityEntry, error) {
out, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "listIdentities"}, "")
if err != nil {
return nil, err
}
identityEntries := []IdentityEntry{} identityEntries := []IdentityEntry{}
keyValuePairs := parseWhitespaceDelimitedKeyValueStringList(out, []string{"NumberAndTrustStatus", "Added", "Fingerprint", "Safety Number"}) if s.signalCliMode == JsonRpc {
for _, keyValuePair := range keyValuePairs { jsonRpc2Client, err := s.getJsonRpc2Client(number)
numberAndTrustStatus := keyValuePair["NumberAndTrustStatus"] if err != nil {
numberAndTrustStatusSplitted := strings.Split(numberAndTrustStatus, ":") return nil, err
}
identityEntry := IdentityEntry{Number: strings.Trim(numberAndTrustStatusSplitted[0], " "), rawData, err := jsonRpc2Client.getRaw("listIdentities", nil)
Status: strings.Trim(numberAndTrustStatusSplitted[1], " "), signalCliIdentityEntries := []SignalCliIdentityEntry{}
Added: keyValuePair["Added"], err = json.Unmarshal([]byte(rawData), &signalCliIdentityEntries)
Fingerprint: strings.Trim(keyValuePair["Fingerprint"], " "), if err != nil {
SafetyNumber: strings.Trim(keyValuePair["Safety Number"], " "), return nil, err
}
for _, signalCliIdentityEntry := range signalCliIdentityEntries {
identityEntry := IdentityEntry{
Number: signalCliIdentityEntry.Number,
Status: signalCliIdentityEntry.TrustLevel,
Added: strconv.FormatInt(signalCliIdentityEntry.AddedTimestamp, 10),
Fingerprint: signalCliIdentityEntry.Fingerprint,
SafetyNumber: signalCliIdentityEntry.SafetyNumber,
}
identityEntries = append(identityEntries, identityEntry)
}
} else {
rawData, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "listIdentities"}, "")
if err != nil {
return nil, err
}
keyValuePairs := parseWhitespaceDelimitedKeyValueStringList(rawData, []string{"NumberAndTrustStatus", "Added", "Fingerprint", "Safety Number"})
for _, keyValuePair := range keyValuePairs {
numberAndTrustStatus := keyValuePair["NumberAndTrustStatus"]
numberAndTrustStatusSplitted := strings.Split(numberAndTrustStatus, ":")
identityEntry := IdentityEntry{Number: strings.Trim(numberAndTrustStatusSplitted[0], " "),
Status: strings.Trim(numberAndTrustStatusSplitted[1], " "),
Added: keyValuePair["Added"],
Fingerprint: strings.Trim(keyValuePair["Fingerprint"], " "),
SafetyNumber: strings.Trim(keyValuePair["Safety Number"], " "),
}
identityEntries = append(identityEntries, identityEntry)
} }
identityEntries = append(identityEntries, identityEntry)
} }
return &identityEntries, nil return &identityEntries, nil
} }
func (s *SignalClient) TrustIdentity(number string, numberToTrust string, verifiedSafetyNumber string) error { func (s *SignalClient) TrustIdentity(number string, numberToTrust string, verifiedSafetyNumber string) error {
cmd := []string{"--config", s.signalCliConfig, "-u", number, "trust", numberToTrust, "--verified-safety-number", verifiedSafetyNumber} var err error
_, err := runSignalCli(true, cmd, "") if s.signalCliMode == JsonRpc {
type Request struct {
VerifiedSafetyNumber string `json:"verified-safety-number"`
Recipient string `json:"recipient"`
}
request := Request{VerifiedSafetyNumber: verifiedSafetyNumber, Recipient: numberToTrust}
jsonRpc2Client, err := s.getJsonRpc2Client(number)
if err != nil {
return err
}
_, err = jsonRpc2Client.getRaw("trust", request)
} else {
cmd := []string{"--config", s.signalCliConfig, "-u", number, "trust", numberToTrust, "--verified-safety-number", verifiedSafetyNumber}
_, err = runSignalCli(true, cmd, "")
}
return err return err
} }
@@ -686,11 +844,37 @@ func (s *SignalClient) BlockGroup(number string, groupId string) error {
} }
func (s *SignalClient) JoinGroup(number string, groupId string) error { func (s *SignalClient) JoinGroup(number string, groupId string) error {
_, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "updateGroup", "-g", groupId}, "") var err error
if s.signalCliMode == JsonRpc {
type Request struct {
GroupId string `json:"groupId"`
}
request := Request{GroupId: groupId}
jsonRpc2Client, err := s.getJsonRpc2Client(number)
if err != nil {
return err
}
_, err = jsonRpc2Client.getRaw("updateGroup", request)
} else {
_, err = runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "updateGroup", "-g", groupId}, "")
}
return err return err
} }
func (s *SignalClient) QuitGroup(number string, groupId string) error { func (s *SignalClient) QuitGroup(number string, groupId string) error {
_, err := runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "quitGroup", "-g", groupId}, "") var err error
if s.signalCliMode == JsonRpc {
type Request struct {
GroupId string `json:"groupId"`
}
request := Request{GroupId: groupId}
jsonRpc2Client, err := s.getJsonRpc2Client(number)
if err != nil {
return err
}
_, err = jsonRpc2Client.getRaw("quitGroup", request)
} else {
_, err = runSignalCli(true, []string{"--config", s.signalCliConfig, "-u", number, "quitGroup", "-g", groupId}, "")
}
return err return err
} }

95
src/client/jsonrpc2.go Normal file
View File

@@ -0,0 +1,95 @@
package client
import (
"encoding/json"
"errors"
"net"
"bufio"
uuid "github.com/gofrs/uuid"
log "github.com/sirupsen/logrus"
)
type JsonRpc2Client struct {
conn net.Conn
}
func NewJsonRpc2Client() *JsonRpc2Client {
return &JsonRpc2Client{
}
}
func (r *JsonRpc2Client) Dial(address string) error {
var err error
r.conn, err = net.Dial("tcp", address)
if err != nil {
return err
}
return nil
}
func (r *JsonRpc2Client) getRaw(command string, args interface{}) (string, error) {
type Request struct {
JsonRpc string `json:"jsonrpc"`
Method string `json:"method"`
Id string `json:"id"`
Params interface{} `json:"params,omitempty"`
}
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
}
type Response struct {
Id string `json:"id"`
Result json.RawMessage `json:"result"`
Err Error `json:"error"`
}
u, err := uuid.NewV4()
if err != nil {
return "", err
}
fullCommand := Request{JsonRpc: "2.0", Method: command, Id: u.String()}
if args != nil {
fullCommand.Params = args
}
fullCommandBytes, err := json.Marshal(fullCommand)
if err != nil {
return "", err
}
log.Info("request = ", string(fullCommandBytes))
_, err = r.conn.Write([]byte(string(fullCommandBytes) + "\n"))
if err != nil {
return "", err
}
connbuf := bufio.NewReader(r.conn)
for {
str, err := connbuf.ReadString('\n')
if err != nil {
return "", err
}
var resp Response
err = json.Unmarshal([]byte(str), &resp)
if err == nil {
if resp.Id == u.String() {
log.Info("Response1 = ", string(resp.Result))
if resp.Err.Code != 0 {
return "", errors.New(resp.Err.Message)
}
return string(resp.Result), nil
}
} else {
log.Info("Response = ", str)
}
}
return "", errors.New("no data")
}

View File

@@ -23,5 +23,5 @@ require (
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
golang.org/x/text v0.3.3 // indirect golang.org/x/text v0.3.3 // indirect
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v2 v2.3.0
) )

View File

@@ -16,6 +16,7 @@ github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrP
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU= github.com/gabriel-vasile/mimetype v1.1.2 h1:gaPnPcNor5aZSVCJVSGipcpbgMWiAAj9z182ocSGbHU=
github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To= github.com/gabriel-vasile/mimetype v1.1.2/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
@@ -70,6 +71,7 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/h2non/filetype v1.1.0 h1:Or/gjocJrJRNK/Cri/TDEKFjAR+cfG6eK65NGYB6gBA= github.com/h2non/filetype v1.1.0 h1:Or/gjocJrJRNK/Cri/TDEKFjAR+cfG6eK65NGYB6gBA=
github.com/h2non/filetype v1.1.0/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/h2non/filetype v1.1.0/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -95,6 +97,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -143,6 +147,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -156,9 +161,11 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -188,8 +195,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -73,7 +73,13 @@ func main() {
log.Fatal("Couldn't set env variable: ", err.Error()) log.Fatal("Couldn't set env variable: ", err.Error())
} }
signalClient := client.NewSignalClient(*signalCliConfig, *attachmentTmpDir, *avatarTmpDir) jsonRpc2ClientConfigPathPath := *signalCliConfig + "/jsonrpc2.yml"
signalClient := client.NewSignalClient(*signalCliConfig, *attachmentTmpDir, *avatarTmpDir, client.JsonRpc, jsonRpc2ClientConfigPathPath)
err = signalClient.Init()
if err != nil {
log.Fatal("Couldn't init Signal Client: ", err.Error())
}
api := api.NewApi(signalClient) api := api.NewApi(signalClient)
v1 := router.Group("/v1") v1 := router.Group("/v1")
{ {

80
src/utils/config.go Normal file
View File

@@ -0,0 +1,80 @@
package utils
import (
"io/ioutil"
"errors"
"gopkg.in/yaml.v2"
)
type ConfigEntry struct {
TcpPort int64 `yaml:"tcp_port"`
FifoPathname string `yaml:"fifo_pathname"`
}
type Config struct {
Entries map[string]ConfigEntry `yaml:"config,omitempty"`
}
type JsonRpc2ClientConfig struct {
config Config
}
func NewJsonRpc2ClientConfig() *JsonRpc2ClientConfig {
return &JsonRpc2ClientConfig{
}
}
func (c *JsonRpc2ClientConfig) Load(path string) error {
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
err = yaml.Unmarshal(data, &c.config)
if err != nil {
return err
}
return nil
}
func (c *JsonRpc2ClientConfig) GetTcpPortForNumber(number string) (int64, error) {
if val, ok := c.config.Entries[number]; ok {
return val.TcpPort, nil
}
return 0, errors.New("No number found")
}
func (c *JsonRpc2ClientConfig) GetFifoPathnameForNumber(number string) (string, error) {
if val, ok := c.config.Entries[number]; ok {
return val.FifoPathname, nil
}
return "", errors.New("No number found")
}
func (c *JsonRpc2ClientConfig) GetTcpPortsForNumbers() map[string]int64 {
mapping := make(map[string]int64)
for number, val := range c.config.Entries {
mapping[number] = val.TcpPort
}
return mapping
}
func (c *JsonRpc2ClientConfig) AddEntry(number string, configEntry ConfigEntry) {
if c.config.Entries == nil {
c.config.Entries = make(map[string]ConfigEntry)
}
c.config.Entries[number] = configEntry
}
func (c *JsonRpc2ClientConfig) Persist(path string) error {
out, err := yaml.Marshal(&c.config)
if err != nil {
return err
}
return ioutil.WriteFile(path, out, 0644)
}