def test_MarketProfile_update_success(self):
     u = objects.Profile()
     u.about = "updated world"
     p = Profile(self.db)
     p.update(u)
     updated_user = p.get()
     self.assertEqual("updated world", updated_user.about)
Exemple #2
0
    def send_message(self, receiving_node, public_key, message_type, message, subject=None):
        """
        Sends a message to another node. If the node isn't online it
        will be placed in the dht for the node to pick up later.
        """
        pro = Profile().get()
        if len(message) > 1500:
            return
        p = objects.Plaintext_Message()
        p.sender_guid = self.kserver.node.id
        p.signed_pubkey = self.kserver.node.signed_pubkey
        p.encryption_pubkey = PrivateKey(self.signing_key.encode()).public_key.encode()
        p.type = message_type
        p.message = message
        if subject is not None:
            p.subject = subject
        if pro.handle:
            p.handle = pro.handle
        if pro.avatar_hash:
            p.avatar_hash = pro.avatar_hash
        p.timestamp = int(time.time())
        signature = self.signing_key.sign(p.SerializeToString())[:64]
        p.signature = signature

        skephem = PrivateKey.generate()
        pkephem = skephem.public_key.encode(nacl.encoding.RawEncoder)
        box = Box(skephem, PublicKey(public_key, nacl.encoding.HexEncoder))
        nonce = nacl.utils.random(Box.NONCE_SIZE)
        ciphertext = box.encrypt(p.SerializeToString(), nonce)

        def get_response(response):
            if not response[0]:
                self.kserver.set(receiving_node.id, pkephem, ciphertext)
        self.protocol.callMessage(receiving_node, pkephem, ciphertext).addCallback(get_response)
Exemple #3
0
 def rpc_follow(self, sender, proto, signature):
     self.log.info("Follow request from %s" % sender.id.encode("hex"))
     self.router.addContact(sender)
     try:
         verify_key = nacl.signing.VerifyKey(sender.signed_pubkey[64:])
         verify_key.verify(proto, signature)
         f = Followers.Follower()
         f.ParseFromString(proto)
         if f.guid != sender.id:
             raise Exception('GUID does not match sending node')
         if f.following != self.proto.guid:
             raise Exception('Following wrong node')
         f.signature = signature
         FollowData().set_follower(f)
         proto = Profile().get(False)
         m = Metadata()
         m.name = proto.name
         m.handle = proto.handle
         m.avatar_hash = proto.avatar_hash
         m.nsfw = proto.nsfw
         return [
             "True",
             m.SerializeToString(),
             self.signing_key.sign(m.SerializeToString())[:64]
         ]
     except Exception:
         self.log.warning("Failed to validate follower")
         return ["False"]
 def test_MarketProfile_replace_social_no_proof(self):
     p = Profile(self.db)
     p.add_social_account("FACEBOOK", "test_updated_username")
     u = p.get()
     self.assertEqual(1, len(u.social))
     self.assertEqual(0, u.social[0].type)
     self.assertEqual('test_updated_username', u.social[0].username)
 def test_MarketProfile_add_social_invalid(self):
     p = Profile(self.db)
     p.add_social_account("TEST", "test_twitter_username")
     u = p.get()
     self.assertEqual(1, len(u.social))
     self.assertEqual(0, u.social[0].type)
     self.assertEqual('test_fb_username', u.social[0].username)
 def rpc_follow(self, sender, proto, signature):
     self.log.info("received follow request from %s" % sender)
     self.router.addContact(sender)
     try:
         verify_key = nacl.signing.VerifyKey(sender.pubkey)
         verify_key.verify(proto, signature)
         f = Followers.Follower()
         f.ParseFromString(proto)
         if f.guid != sender.id:
             raise Exception('GUID does not match sending node')
         if f.following != self.node.id:
             raise Exception('Following wrong node')
         f.signature = signature
         self.db.follow.set_follower(f)
         proto = Profile(self.db).get(False)
         m = Metadata()
         m.name = proto.name
         m.handle = proto.handle
         m.avatar_hash = proto.avatar_hash
         m.short_description = proto.short_description
         m.nsfw = proto.nsfw
         for listener in self.listeners:
             try:
                 verifyObject(NotificationListener, listener)
                 listener.notify(sender.id, f.metadata.handle, "follow", "", "", f.metadata.avatar_hash)
             except DoesNotImplement:
                 pass
         return ["True", m.SerializeToString(), self.signing_key.sign(m.SerializeToString())[:64]]
     except Exception:
         self.log.warning("failed to validate follower")
         return ["False"]
 def test_MarketProfile_add_pgp_key_success(self):
     p = Profile(self.db)
     self.assertTrue(
         p.add_pgp_key(self.PUBLIC_KEY, self.SIGNATURE, self.VALID_GUID))
     u = p.get()
     self.assertEqual(self.SIGNATURE, u.pgp_key.signature)
     self.assertEqual(self.PUBLIC_KEY, u.pgp_key.public_key)
 def test_MarketProfile_get_success(self):
     p = Profile(self.db).get()
     self.assertEqual('test_name', p.name)
     self.assertEqual(2, p.location)
     self.assertEqual('hello world', p.about)
     self.assertEqual(1, len(p.social))
     self.assertEqual(0, p.social[0].type)
     self.assertEqual('test_fb_username', p.social[0].username)
    def get_profile(self, request):
        def parse_profile(profile):
            if profile is not None:
                profile_json = {
                    "profile": {
                        "name": profile.name,
                        "location": str(CountryCode.Name(profile.location)),
                        "enryption_key": profile.encryption_key.encode("hex"),
                        "nsfw": profile.nsfw,
                        "vendor": profile.vendor,
                        "moderator": profile.moderator,
                        "handle": profile.handle,
                        "about": profile.about,
                        "website": profile.website,
                        "email": profile.email,
                        "primary_color": profile.primary_color,
                        "secondary_color": profile.secondary_color,
                        "background_color": profile.background_color,
                        "text_color": profile.text_color,
                        "pgp_key": profile.pgp_key.publicKey,
                        "avatar_hash": profile.avatar_hash.encode("hex"),
                        "header_hash": profile.header_hash.encode("hex"),
                        "social_accounts": {}
                    }
                }
                if "guid" in request.args:
                    profile_json["profile"]["guid"] = request.args["guid"][0]
                else:
                    profile_json["profile"]["guid"] = KeyChain().guid.encode(
                        "hex")
                for account in profile.social:
                    profile_json["profile"]["social_accounts"][str(
                        objects.Profile.SocialAccount.SocialType.Name(
                            account.type)).lower()] = {
                                "username": account.username,
                                "proof_url": account.proof_url
                            }
                request.setHeader('content-type', "application/json")
                request.write(json.dumps(profile_json, indent=4))
                request.finish()
            else:
                request.write(NoResource().render(request))
                request.finish()

        if "guid" in request.args:

            def get_node(node):
                if node is not None:
                    self.mserver.get_profile(node).addCallback(parse_profile)
                else:
                    request.write(NoResource().render(request))
                    request.finish()

            self.kserver.resolve(unhexlify(
                request.args["guid"][0])).addCallback(get_node)
        else:
            parse_profile(Profile().get())
        return server.NOT_DONE_YET
 def test_MarketProfile_add_social_no_proof(self):
     p = Profile(self.db)
     p.add_social_account("TWITTER", "test_twitter_username")
     u = p.get()
     self.assertEqual(2, len(u.social))
     self.assertEqual(0, u.social[0].type)
     self.assertEqual('test_fb_username', u.social[0].username)
     self.assertEqual(1, u.social[1].type)
     self.assertEqual('test_twitter_username', u.social[1].username)
Exemple #11
0
    def unmake_moderator(self):
        """
        Deletes our moderator entry from the network.
        """

        key = digest(self.kserver.node.getProto().SerializeToString())
        signature = self.signing_key.sign(key)[:64]
        self.kserver.delete("moderators", key, signature)
        Profile(self.db).remove_field("moderator")
Exemple #12
0
 def rpc_get_profile(self, sender):
     self.log.info("Fetching profile")
     self.router.addContact(sender)
     try:
         proto = Profile().get(True)
         return [proto, self.signing_key.sign(proto)[:64]]
     except Exception:
         self.log.error("Unable to load the profile")
         return ["None"]
Exemple #13
0
 def rpc_get_profile(self, sender):
     self.log.info("serving profile to %s" % sender)
     self.router.addContact(sender)
     try:
         proto = Profile(self.db).get(True)
         return [proto, self.signing_key.sign(proto)[:64]]
     except Exception:
         self.log.error("unable to load the profile")
         return None
 def rpc_get_profile(self, sender):
     self.log.info("serving profile to %s" % sender)
     self.audit.record(sender.id.encode("hex"), "GET_PROFILE")
     self.router.addContact(sender)
     try:
         proto = Profile(self.db).get(True)
         return [proto, self.signing_key.sign(proto)[:64]]
     except Exception:
         self.log.error("unable to load the profile")
         return None
Exemple #15
0
 def addsocialaccount():
     parser = argparse.ArgumentParser(
         description="Add a social media account to the profile.",
         usage='''usage:
 networkcli.py addsocialaccout -t TYPE, -u USERNAME, -p PROOF''')
     parser.add_argument('-t', '--type', help="the type of account")
     parser.add_argument('-u', '--username', help="the username")
     parser.add_argument('-p', '--proof', help="the proof url")
     args = parser.parse_args(sys.argv[2:])
     p = Profile()
     p.add_social_account(args.type, args.username, args.proof)
Exemple #16
0
        def parse_response(moderators):
            if moderators is not None:
                m.clear_all()

                def parse_profile(profile, node):
                    if profile is not None:
                        # TODO: should check signatures here before entering in database
                        m.save_moderator(node.id.encode("hex"), node.pubkey,
                                         profile.bitcoin_key.public_key,
                                         profile.bitcoin_key.signature,
                                         profile.name, profile.avatar_hash,
                                         profile.moderation_fee,
                                         profile.handle,
                                         profile.short_description)
                        moderator = {
                            "id": message_id,
                            "moderator": {
                                "guid": node.id.encode("hex"),
                                "name": profile.name,
                                "handle": profile.handle,
                                "short_description": profile.short_description,
                                "avatar_hash":
                                profile.avatar_hash.encode("hex"),
                                "about": profile.about,
                                "fee": profile.moderation_fee
                            }
                        }
                        self.transport.write(
                            str(
                                bleach.clean(json.dumps(moderator, indent=4),
                                             tags=ALLOWED_TAGS)))
                    else:
                        m.delete_moderator(node.id)

                for mod in moderators:
                    try:
                        val = objects.Value()
                        val.ParseFromString(mod)
                        n = objects.Node()
                        n.ParseFromString(val.serializedData)
                        node_to_ask = Node(
                            n.guid, n.nodeAddress.ip, n.nodeAddress.port,
                            n.publicKey,
                            None if not n.HasField("relayAddress") else
                            (n.relayAddress.ip, n.relayAddress.port),
                            n.natType, n.vendor)
                        if n.guid == KeyChain(self.factory.db).guid:
                            parse_profile(
                                Profile(self.factory.db).get(), node_to_ask)
                        else:
                            self.factory.mserver.get_profile(node_to_ask)\
                                .addCallback(parse_profile, node_to_ask)
                    except Exception:
                        pass
Exemple #17
0
 def delete_social_account(self, request):
     try:
         p = Profile(self.db)
         if "account_type" in request.args:
             p.remove_social_account(request.args["account_type"][0])
         request.write(json.dumps({"success": True}))
         request.finish()
         return server.NOT_DONE_YET
     except Exception, e:
         request.write(json.dumps({"success": False, "reason": e.message}, indent=4))
         request.finish()
         return server.NOT_DONE_YET
Exemple #18
0
 def rpc_get_listings(self, sender):
     self.log.info("serving store listings to %s" % sender)
     self.router.addContact(sender)
     try:
         p = Profile(self.db).get()
         l = Listings()
         l.ParseFromString(self.db.ListingsStore().get_proto())
         l.handle = p.handle
         l.avatar_hash = p.avatar_hash
         return [l.SerializeToString(), self.signing_key.sign(l.SerializeToString())[:64]]
     except Exception:
         self.log.warning("could not find any listings in the database")
         return None
Exemple #19
0
    def make_moderator(self):
        """
        Set self as a moderator in the DHT.
        """

        u = objects.Profile()
        k = u.PublicKey()
        k.public_key = bitcoin.bip32_deserialize(KeyChain(self.db).bitcoin_master_pubkey)[5]
        k.signature = self.signing_key.sign(k.public_key)[:64]
        u.bitcoin_key.MergeFrom(k)
        u.moderator = True
        Profile(self.db).update(u)
        proto = self.kserver.node.getProto().SerializeToString()
        self.kserver.set(digest("moderators"), digest(proto), proto)
Exemple #20
0
 def rpc_get_user_metadata(self, sender):
     self.log.info("serving user metadata to %s" % sender)
     self.router.addContact(sender)
     try:
         proto = Profile(self.db).get(False)
         m = Metadata()
         m.name = proto.name
         m.handle = proto.handle
         m.short_description = proto.short_description
         m.avatar_hash = proto.avatar_hash
         m.nsfw = proto.nsfw
         return [m.SerializeToString(), self.signing_key.sign(m.SerializeToString())[:64]]
     except Exception:
         self.log.error("unable to load profile metadata")
         return None
Exemple #21
0
 def add_social_account(self, request):
     try:
         p = Profile(self.db)
         if "account_type" in request.args and "username" in request.args and "proof" in request.args:
             p.add_social_account(request.args["account_type"][0], request.args["username"][0],
                                  request.args["proof"][0] if "proof" in request.args else None)
         else:
             raise Exception("Missing required fields")
         request.write(json.dumps({"success": True}))
         request.finish()
         return server.NOT_DONE_YET
     except Exception, e:
         request.write(json.dumps({"success": False, "reason": e.message}, indent=4))
         request.finish()
         return server.NOT_DONE_YET
    def make_moderator(self):
        """
        Set self as a moderator in the DHT.
        """

        u = objects.Profile()
        k = u.PublicKey()
        k.public_key = unhexlify(bitcointools.bip32_extract_key(KeyChain(self.db).bitcoin_master_pubkey))
        k.signature = self.signing_key.sign(k.public_key)[:64]
        u.bitcoin_key.MergeFrom(k)
        u.moderator = True
        Profile(self.db).update(u)
        proto = self.kserver.node.getProto().SerializeToString()
        self.kserver.set(digest("moderators"), digest(proto), proto)
        self.log.info("setting self as moderator on the network")
Exemple #23
0
        def parse_response(moderators):
            if moderators is not None:
                m.clear_all()

                def parse_profile(profile, node):
                    if profile is not None:
                        m.save_moderator(
                            node.id.encode("hex"), node.signed_pubkey,
                            profile.encryption_key.public_key,
                            profile.encryption_key.signature,
                            profile.bitcoin_key.public_key,
                            profile.bitcoin_key.signature, profile.name,
                            profile.avatar_hash, profile.moderation_fee,
                            profile.handle, profile.short_description)
                        moderator = {
                            "id": message_id,
                            "moderator": {
                                "guid": node.id.encode("hex"),
                                "name": profile.name,
                                "handle": profile.handle,
                                "short_description": profile.short_description,
                                "avatar_hash":
                                profile.avatar_hash.encode("hex"),
                                "about": profile.about,
                                "fee": profile.moderation_fee
                            }
                        }
                        self.sendMessage(json.dumps(moderator, indent=4),
                                         False)
                    else:
                        m.delete_moderator(node.id)

                for mod in moderators:
                    try:
                        val = objects.Value()
                        val.ParseFromString(mod)
                        n = objects.Node()
                        n.ParseFromString(val.serializedData)
                        node_to_ask = Node(n.guid, n.ip, n.port,
                                           n.signedPublicKey)
                        if n.guid == KeyChain(self.factory.db).guid:
                            parse_profile(
                                Profile(self.factory.db).get(), node_to_ask)
                        else:
                            self.factory.mserver.get_profile(node_to_ask)\
                                .addCallback(parse_profile, node_to_ask)
                    except Exception:
                        pass
Exemple #24
0
 def addpgpkey():
     parser = argparse.ArgumentParser(
         description="Add a pgp key to the profile.",
         usage='''usage:
 networkcli.py addpgpkey -k KEY, -s SIGNATURE''')
     parser.add_argument('-k', '--key', help="path to the key file")
     parser.add_argument('-s',
                         '--signature',
                         help="path to the signature file")
     args = parser.parse_args(sys.argv[2:])
     with open(args.key, "r") as filename:
         key = filename.read()
     with open(args.signature, "r") as filename:
         sig = filename.read()
     p = Profile()
     print p.add_pgp_key(key, sig, KeyChain().guid.encode("hex"))
Exemple #25
0
 def rpc_get_user_metadata(self, sender):
     self.log.info("Fetching metadata")
     self.router.addContact(sender)
     try:
         proto = Profile().get(False)
         m = Metadata()
         m.name = proto.name
         m.handle = proto.handle
         m.avatar_hash = proto.avatar_hash
         m.nsfw = proto.nsfw
         return [
             m.SerializeToString(),
             self.signing_key.sign(m.SerializeToString())[:64]
         ]
     except Exception:
         self.log.error("Unable to get the profile metadata")
         return ["None"]
 def rpc_get_contract_metadata(self, sender, contract_hash):
     self.log.info("serving metadata for contract %s to %s" % (contract_hash.encode("hex"), sender))
     self.router.addContact(sender)
     try:
         proto = self.db.listings.get_proto()
         p = Profile(self.db).get()
         l = Listings()
         l.ParseFromString(proto)
         for listing in l.listing:
             if listing.contract_hash == contract_hash:
                 listing.avatar_hash = p.avatar_hash
                 listing.handle = p.handle
                 ser = listing.SerializeToString()
         return [ser, self.signing_key.sign(ser)[:64]]
     except Exception:
         self.log.warning("could not find metadata for contract %s" % contract_hash.encode("hex"))
         return None
    def follow(self, node_to_follow):
        """
        Sends a follow message to another node in the network. The node must be online
        to receive the message. The message contains a signed, serialized `Follower`
        protobuf object which the recipient will store and can send to other nodes,
        proving you are following them. The response is a signed `Metadata` protobuf
        that will store in the db.
        """
        def save_to_db(result):
            if result[0] and result[1][0] == "True":
                try:
                    u = objects.Following.User()
                    u.guid = node_to_follow.id
                    u.signed_pubkey = node_to_follow.signed_pubkey
                    m = objects.Metadata()
                    m.ParseFromString(result[1][1])
                    u.metadata.MergeFrom(m)
                    u.signature = result[1][2]
                    pubkey = node_to_follow.signed_pubkey[64:]
                    verify_key = nacl.signing.VerifyKey(pubkey)
                    verify_key.verify(result[1][1], result[1][2])
                    self.db.FollowData().follow(u)
                    return True
                except Exception:
                    return False
            else:
                return False

        proto = Profile(self.db).get(False)
        m = objects.Metadata()
        m.name = proto.name
        m.handle = proto.handle
        m.avatar_hash = proto.avatar_hash
        m.short_description = proto.short_description
        m.nsfw = proto.nsfw
        f = objects.Followers.Follower()
        f.guid = self.kserver.node.id
        f.following = node_to_follow.id
        f.signed_pubkey = self.kserver.node.signed_pubkey
        f.metadata.MergeFrom(m)
        signature = self.signing_key.sign(f.SerializeToString())[:64]
        d = self.protocol.callFollow(node_to_follow, f.SerializeToString(),
                                     signature)
        self.log.info("sending follow request to %s" % node_to_follow)
        return d.addCallback(save_to_db)
    def rpc_follow(self, sender, proto, signature):
        self.log.info("received follow request from %s" % sender)
        self.router.addContact(sender)
        try:
            verify_key = nacl.signing.VerifyKey(sender.pubkey)
            verify_key.verify(proto, signature)
            f = Followers.Follower()
            f.ParseFromString(proto)
            if f.guid != sender.id:
                raise Exception('GUID does not match sending node')
            if f.following != self.node.id:
                raise Exception('Following wrong node')
            f.signature = signature
            self.db.follow.set_follower(f.SerializeToString())
            proto = Profile(self.db).get(False)
            m = Metadata()
            m.name = proto.name
            m.handle = proto.handle
            m.avatar_hash = proto.avatar_hash
            m.short_description = proto.short_description
            m.nsfw = proto.nsfw
            for listener in self.listeners:
                try:
                    verifyObject(NotificationListener, listener)
                    listener.notify(sender.id, f.metadata.handle, "follow", "",
                                    "", f.metadata.avatar_hash)
                except DoesNotImplement:
                    pass

            # Send SMTP notification
            notification = SMTPNotification(self.db)
            notification.send(
                "[OpenBazaar] %s is now following you!" % f.metadata.name,
                "You have a new follower:<br><br>Name: %s<br>GUID: <a href=\"ob://%s\">%s</a><br>"
                "Handle: %s" % (f.metadata.name, f.guid.encode('hex'),
                                f.guid.encode('hex'), f.metadata.handle))

            return [
                "True",
                m.SerializeToString(),
                self.signing_key.sign(m.SerializeToString())[:64]
            ]
        except Exception:
            self.log.warning("failed to validate follower")
            return ["False"]
Exemple #29
0
 def rpc_get_contract_metadata(self, sender, contract_hash):
     self.log.info("Fetching metadata for contract %s" %
                   hexlify(contract_hash))
     self.router.addContact(sender)
     try:
         proto = ListingsStore().get_proto()
         l = Listings()
         l.ParseFromString(proto)
         for listing in l.listing:
             if listing.contract_hash == contract_hash:
                 country_code = Profile().get().country_code
                 listing.country_code = country_code
                 ser = listing.SerializeToString()
         return [ser, self.signing_key.sign(ser)[:64]]
     except Exception:
         self.log.warning("Could not find metadata for contract %s" %
                          hexlify(contract_hash))
         return ["None"]
 def update_profile(self, request):
     p = Profile()
     if not p.get().encryption_key \
             and "name" not in request.args \
             and "location" not in request.args:
         return "False"
     u = objects.Profile()
     if "name" in request.args:
         u.name = request.args["name"][0]
     if "location" in request.args:
         # This needs to be formatted. Either here or from the UI.
         u.location = CountryCode.Value(request.args["location"][0].upper())
     if "handle" in request.args:
         u.handle = request.args["handle"][0]
     if "about" in request.args:
         u.about = request.args["about"][0]
     if "nsfw" in request.args:
         u.nsfw = True
     if "vendor" in request.args:
         u.vendor = True
     if "moderator" in request.args:
         u.moderator = True
     if "website" in request.args:
         u.website = request.args["website"][0]
     if "email" in request.args:
         u.email = request.args["email"][0]
     if "avatar" in request.args:
         with open(DATA_FOLDER + "store/avatar", 'wb') as outfile:
             outfile.write(request.args["avatar"][0])
         avatar_hash = digest(request.args["avatar"][0])
         HashMap().insert(avatar_hash, DATA_FOLDER + "store/avatar")
         u.avatar_hash = avatar_hash
     if "header" in request.args:
         with open(DATA_FOLDER + "store/header", 'wb') as outfile:
             outfile.write(request.args["header"][0])
         header_hash = digest(request.args["header"][0])
         HashMap().insert(header_hash, DATA_FOLDER + "store/header")
         u.header_hash = header_hash
     if "pgp_key" in request.args and "signature" in request.args:
         p.add_pgp_key(request.args["pgp_key"][0],
                       request.args["signature"][0],
                       KeyChain().guid.encode("hex"))
     u.encryption_key = KeyChain().encryption_pubkey
     p.update(u)