diff --git a/client/react-native/common/components/Library/PublicKeyWithActions.js b/client/react-native/common/components/Library/PublicKeyWithActions.js index 50ffe75cbb..00478041ae 100644 --- a/client/react-native/common/components/Library/PublicKeyWithActions.js +++ b/client/react-native/common/components/Library/PublicKeyWithActions.js @@ -2,7 +2,7 @@ import { ScrollView, TextInput, Platform, Clipboard } from 'react-native' import { btoa } from 'b64-lite' import React, { PureComponent } from 'react' -import { Button, Flex, TextInputMultilineFix } from './index' +import { Button, Flex, TextInputMultilineFix, Text } from './index' import { RelayContext } from '../../relay' import { colors } from '../../constants' import { @@ -67,6 +67,7 @@ export default class PublicKeyWithActions extends PureComponent { : [props.initialKey, props.initialName] const missingInitialData = props.initialKey === undefined this.state = { + err: null, contact: { id: initialKey || '', displayName: initialName || '', @@ -102,7 +103,6 @@ export default class PublicKeyWithActions extends PureComponent { this.props.navigation.goBack(null) } catch (err) { this.setState({ err }) - console.error(err) } } @@ -119,6 +119,13 @@ export default class PublicKeyWithActions extends PureComponent { contact: { id, displayName }, } = this.state + let errors = [] + try { + errors = this.state.err.res.errors + } catch (e) { + // noop + } + return ( @@ -178,6 +185,7 @@ export default class PublicKeyWithActions extends PureComponent { onPress={this.onSubmit} /> ) : null} + {errors.map((err, i) => {err.message})} ) diff --git a/core/entity/contact.go b/core/entity/contact.go index 015da9a9b5..c5e76f0242 100644 --- a/core/entity/contact.go +++ b/core/entity/contact.go @@ -1,9 +1,26 @@ package entity +import ( + "crypto/x509" + "encoding/base64" + + "github.com/pkg/errors" +) + func (c Contact) Validate() error { if c.ID == "" { return ErrInvalidEntity } + + pubKeyBytes, err := base64.StdEncoding.DecodeString(c.ID) + if err != nil { + return err + } + + if _, err := x509.ParsePKIXPublicKey(pubKeyBytes); err != nil { + return errors.Wrap(ErrInvalidEntity, "invalid public key") + } + return nil } diff --git a/core/node/errors.go b/core/node/errors.go index 56a6e8ccca..d4a0717384 100644 --- a/core/node/errors.go +++ b/core/node/errors.go @@ -3,6 +3,7 @@ package node import "errors" var ( + ErrContactIsMyself = errors.New("contact is myself") ErrEntityAlreadyExists = errors.New("entity already exists") ErrInvalidEventSender = errors.New("invalid event sender") ErrInvalidInput = errors.New("invalid input") diff --git a/core/node/nodeapi.go b/core/node/nodeapi.go index 32325cbbd5..6682bd054e 100644 --- a/core/node/nodeapi.go +++ b/core/node/nodeapi.go @@ -4,6 +4,8 @@ import ( "context" "time" + "github.com/jinzhu/gorm" + "berty.tech/core/api/node" "berty.tech/core/api/p2p" "berty.tech/core/entity" @@ -162,19 +164,35 @@ func (n *Node) ContactRequest(ctx context.Context, req *node.ContactRequestInput // input validation if err := req.Contact.Validate(); err != nil { - return nil, errors.Wrap(err, ErrInvalidInput.Error()) + return nil, ErrInvalidInput } // check for duplicate sql := n.sql(ctx) contact, err := bsql.FindContact(sql, req.Contact) - if err != nil { + + if errors.Cause(err) == gorm.ErrRecordNotFound { // save contact in database contact = req.Contact contact.Status = entity.Contact_IsRequested if err = sql.Set("gorm:association_autoupdate", true).Save(contact).Error; err != nil { return nil, errors.Wrap(err, "failed to save contact") } + } else if err != nil { + return nil, err + + } else if contact.Status == entity.Contact_RequestedMe { + logger().Info("this contact has already asked us, accepting the request") + return n.ContactAcceptRequest(ctx, contact) + + } else if contact.Status == entity.Contact_IsRequested { + logger().Info("contact has already been requested, sending event again") + + } else if contact.Status == entity.Contact_Myself { + return nil, ErrContactIsMyself + + } else { + return nil, ErrEntityAlreadyExists } // send request to peer