예제 #1
0
    def onInterest(self, prefix, interest, *k):
        print >> sys.stderr, "<< PyNDN %s" % interest.name

        intrestUri = interest.name.toUri()
        prefixUri = prefix.toUri()

        parameters = ''
        if intrestUri != prefixUri:
            parameters = intrestUri[len(prefixUri) + 1:]
            print
            prefixUri += "/%3Cdata%3E"

        d = self.a[prefixUri]
        if self.methods[prefixUri] == "POST":
            content = json.dumps(
                d(interest.getContent().toRawStr().decode('string_escape')))
        else:
            if parameters:
                content = json.dumps(d(parameters))
            else:
                content = json.dumps(d())

        self.counter += 1
        data = ndn.Data(interest.getName())

        meta = ndn.MetaInfo()
        meta.setFreshnessPeriod(5000)
        data.setMetaInfo(meta)

        data.setContent(content)
        self.keyChain.sign(data, self.keyChain.getDefaultCertificateName())

        self.face.putData(data)
예제 #2
0
def send_find_coordinator_data(interest, face, entity):
    logger.debug('Sending FindCoordinatorData for entity %s', entity)

    final_object = entity.serialize(entity)

    find_coordinator_data = pyndn.Data(interest.getName())
    find_coordinator_data.setContent(final_object)
    face.putData(find_coordinator_data)
예제 #3
0
def send_chunk_entities_data(interest, face, chunk):
    logger.debug('Sending ChunkEntitiesData for chunk %d (%d, %d)',
                 chunk.uid, chunk.map.x, chunk.map.y)
    chunk = entities.Chunk.serialize(chunk)

    chunk_data = pyndn.Data(interest.getName())
    chunk_data.setContent(chunk)
    face.putData(chunk_data)
예제 #4
0
    def install_public_params(self, publicParams):
        self.db.save('publicParams', publicParams)
        self.publicParams = pyndn.Data()
        self.publicParams.wireDecode(base64.b64decode(publicParams))

        # TODO: verify validity of public parameters

        encodedPk = self.publicParams.getContent().toBytes()
        self._install_pk(encodedPk)
예제 #5
0
    def test_ndn_sign(self):
        data = pyndn.Data()
        data.setName(pyndn.Name("/foo/bar"))
        data.setContent("Hello, world!")

        self.signer.sign(data, [b'Monday', b'Tuesday'])
        self.assertEqual(data.getSignature().getTypeCode(), 42)
        self.assertEqual(data.getSignature().getKeyLocator().getKeyName().toUri(),
                         pyndn.Name("/test/authority/ABS/%FD%5C%CC%C8%C3/Monday%26Tuesday").toUri())
예제 #6
0
def send_deleted_entity_data(interest, face):
    logger.debug('Sending DeletedEntityData for interest %s',
                 interest.getName().toUri())

    result = entities.Result(
        status=const.status_code.DELETED_ENTITY, value=None)
    name = interest.getName().appendVersion(utils.get_timestamp())
    deleted_entity_data = pyndn.Data(name)
    deleted_entity_data.setContent(entities.Result.serialize(result))

    face.putData(deleted_entity_data)
예제 #7
0
 def handleCompletion(self):
     # print(self.segments)
     content = bytearray()
     for i in sorted(self.segments):
         segment = self.segments[i]
         content.extend(segment.getContent().buf())
     blob = pyndn.Blob(content)
     data = pyndn.Data(self.interest.getName())
     data.setContent(blob)
     self.data = data
     self.onData(self)
예제 #8
0
    def sign(self, args):
        data = pyndn.Data()
        data.setName(pyndn.Name(args.name))
        data.setContent(sys.stdin.buffer.read())

        signer = Signer(self.db)

        attributes = [i.encode('utf-8') for i in args.attribute]
        signer.sign(data, attributes)
        print(str(base64.b64encode(data.wireEncode().toBytes()), 'utf-8'))
        return 0
예제 #9
0
 def __init__(self, db):
     self.db = db
     self.abs = ABS()
     try:
         self.pk = utils.deserialize(self.db.load('pk'), self.abs.group)
         self.publicParams = pyndn.Data()
         self.publicParams.wireDecode(
             base64.b64decode(self.db.load('publicParams')))
     except:
         # print("PK not available")
         pass
예제 #10
0
    def verify(self, wire):
        data = pyndn.Data()
        data.wireDecode(wire)
        signature = Sha256WithAbsSignature(data.getSignature())
        name = signature.getKeyLocator().getKeyName()
        attributes = name[-1].getValue().toBytes().split(b'&')

        # print ("Data name: %s; KeyLocator: %s" % (data.getName().toUri(), signature.getKeyLocator().getKeyName().toUri()))
        # print ("Verifying using: %s" % str(b' & '.join(attributes), 'utf-8'))

        return self._verify(signature.getSignature().toBytes(),
                            data.wireEncode().toSignedBytes(), attributes)
예제 #11
0
def send_chunk_update_data(chunk_x, chunk_y, update):
    logger.debug('Sending ChunkUpdateData for chunk (%d, %d): %s', chunk_x,
                 chunk_y, update)
    name = pyndn.Name(mngt.context.local_name) \
        .append('chunk') \
        .append(str(chunk_x)) \
        .append(str(chunk_y)) \
        .append('updates') \
        .append('touch')

    chunk_update_data = pyndn.Data(name)
    chunk_update_data.setContent(entities.Result.serialize(update))
    mngt.context.face.putData(chunk_update_data)
예제 #12
0
def send_entity_update_data(uid, version, update):
    logger.trace('Sending EntityUpdateData for entity %d %s', uid, update)

    name = pyndn.Name(mngt.context.local_name) \
        .append('entity') \
        .append(str(uid)) \
        .append('updates') \
        .append(str(version)) \
        .append('touch')

    entity_update_data = pyndn.Data(name)
    entity_update_data.setContent(entities.Update.serialize(update))
    mngt.context.face.putData(entity_update_data)
예제 #13
0
    def _onInterest(self, prefix, interest, *k):
        print >> sys.stderr, "<< PyNDN %s" % interest.name

        content = "PyNDN LINE #%d\n" % self.counter
        self.counter += 1

        data = ndn.Data(interest.getName())

        meta = ndn.MetaInfo()
        meta.setFreshnessPeriod(5000)
        data.setMetaInfo(meta)

        data.setContent(content)

        self.keyChain.sign(data, self.keyChain.getDefaultCertificateName())

        self.face.putData(data)
예제 #14
0
def send_fetch_entity_data(interest, face, entity_or_uid):
    if isinstance(entity_or_uid, int):
        entity = mngt.context.object_store.get(entity_or_uid)
    else:
        entity = entity_or_uid

    logger.debug('Sending FetchEntityData for entity %d', entity.uid)

    result = entities.Result(
        status=const.status_code.OK, value=entity)
    name = interest.getName()

    if hasattr(entity, 'version'):
        name.appendVersion(entity.version)

    fetch_entity_data = pyndn.Data(interest.getName())
    fetch_entity_data.setContent(entities.Result.serialize(result))
    face.putData(fetch_entity_data)
예제 #15
0
    def sign(self, args):
        data = pyndn.Data()
        data.setName(pyndn.Name(args.name))
        data.setContent(sys.stdin.buffer.read())

        attributes = [args.attribute]
        producer = Signer(self.db)

        csvData = []

        for i in range(100):
            attributes.append('%s' % i)
            attr = [i.encode('utf-8') for i in attributes]
            p = time.process_time()
            producer.sign(data, attr)
            csvData.append(str(time.process_time() - p))
        with open('signingtime.csv', 'w') as csvFile:
            writer = csv.writer(csvFile)
            writer.writerows([csvData])
        return 0
예제 #16
0
    def onInterest(self, prefix, interest, *k):
        print >> sys.stderr, "<< PyNDN %s" % interest.name
        print prefix
        d = self.a[prefix]
        if self.methods[prefix] == "POST":
            content = json.dumps(
                d(interest.getContent().toRawStr().decode('string_escape')))
        else:
            content = json.dumps(d())
        self.counter += 1
        #print interest.getContent().toRawStr().decode('string_escape')
        data = ndn.Data(interest.getName())

        meta = ndn.MetaInfo()
        meta.setFreshnessPeriod(5000)
        data.setMetaInfo(meta)

        data.setContent(content)
        self.keyChain.sign(data, self.keyChain.getDefaultCertificateName())

        self.face.putData(data)
예제 #17
0
    def setup(self, name):
        self.apk, self.ask = self.abs.authSetup()
        self.self_attributes = [b'self', name.toUri().encode('utf-8')]

        self.db.save('apk', utils.serialize(self.apk, self.abs.group))
        self.db.save('ask', utils.serialize(self.ask, self.abs.group))

        data = pyndn.Data(
            pyndn.Name(name).append("ABS").appendVersion(
                datetime.timestamp(datetime.now())))
        meta = pyndn.MetaInfo()
        meta.setType(pyndn.ContentType.KEY)
        meta.setFreshnessPeriod(86400 * 1000.0)  # 1 day
        data.setMetaInfo(meta)
        data.setContent(self.db.load('apk'))

        signer = Signer(self.db)
        signer._install_pk(self.db.load('apk'))
        signer.install_secret(self.gen_attr_keys(self.self_attributes))
        signer.sign(data, self.self_attributes, selfSign=True)

        signer.install_public_params(
            base64.b64encode(data.wireEncode().toBytes()))
예제 #18
0
def submit_certificate():
    data = ndn.Data()
    # data.wireDecode(ndn.Blob(buffer(base64.b64decode(request.form['data']))))
    data.wireDecode(
        ndn.Blob(memoryview(base64.b64decode(request.form['data']))))

    cert_request = mongo.db.requests.find_one(
        {'_id': ObjectId(str(request.form['id']))})
    if cert_request == None:
        abort(403)

    operator = mongo.db.operators.find_one(
        {"_id": ObjectId(cert_request['operator_id'])})
    if operator == None:
        mongo.db.requests.remove(cert_request)  # remove invalid request
        abort(403)

    # # @todo verify data packet
    # # @todo verify timestamp

    if len(data.getContent()) == 0:
        # (no deny reason for now)
        # eventually, need to check data.type: if NACK, then content contains reason for denial
        #                                      if KEY, then content is the certificate

        msg = Message("[NDN Certification] Rejected certification",
                      sender=app.config['MAIL_FROM'],
                      recipients=[cert_request['email']],
                      body=render_template('cert-rejected-email.txt',
                                           URL=app.config['URL'],
                                           **cert_request),
                      html=render_template('cert-rejected-email.html',
                                           URL=app.config['URL'],
                                           **cert_request))
        mail.send(msg)

        mongo.db.requests.remove(cert_request)

        return "OK. Certificate has been denied"
    else:
        cert = {
            'name': data.getName().toUri(),
            'cert': request.form['data'],
            'operator': operator,
            'created_on': datetime.datetime.utcnow(
            ),  # to periodically remove unverified tokens
        }
        mongo.db.certs.insert(cert)

        msg = Message("[NDN Certification] NDN certificate issued",
                      sender=app.config['MAIL_FROM'],
                      recipients=[cert_request['email']],
                      body=render_template('cert-issued-email.txt',
                                           URL=app.config['URL'],
                                           quoted_cert_name=urllib.parse.quote(
                                               cert['name'], ''),
                                           cert_id=str(data.getName()[-3]),
                                           **cert_request),
                      html=render_template('cert-issued-email.html',
                                           URL=app.config['URL'],
                                           quoted_cert_name=urllib.parse.quote(
                                               cert['name'], ''),
                                           cert_id=str(data.getName()[-3]),
                                           **cert_request))
        mail.send(msg)

        mongo.db.requests.remove(cert_request)

        return "OK. Certificate has been approved and notification sent to the requester"
예제 #19
0
def submit_request():
    if request.method == 'GET':
        # Email and token (to authorize the request==validate email)
        user_email = request.args.get('email')
        user_token = request.args.get('token')

        token = mongo.db.tokens.find_one({
            'email': user_email,
            'token': user_token
        })
        if (token == None):
            abort(403)

        site_prefix = token['site_prefix']
        if site_prefix != "":
            try:
                params = get_operator_for_guest_site(user_email, site_prefix)
            except:
                abort(403)
        else:
            # infer parameters from email
            try:
                # pre-validation
                params = get_operator_for_email(user_email)
            except:
                abort(403)

        # don't delete token for now, just give user a form to input stuff
        return render_template('request-form.html',
                               URL=app.config['URL'],
                               email=user_email,
                               token=user_token,
                               **params)

    else:  # 'POST'
        # Email and token (to authorize the request==validate email)
        user_email = request.form['email']
        user_token = request.form['token']

        token = mongo.db.tokens.find_one({
            'email': user_email,
            'token': user_token
        })
        if (token == None):
            abort(403)

        # Now, do basic validation of correctness of user input, save request in the database
        # and notify the operator
        #optional parameters

        user_fullname = request.form[
            'fullname'] if 'fullname' in request.form else ""
        user_homeurl = request.form[
            'homeurl'] if 'homeurl' in request.form else ""
        user_group = request.form['group'] if 'group' in request.form else ""
        user_advisor = request.form[
            'advisor'] if 'advisor' in request.form else ""

        site_prefix = token['site_prefix']
        if site_prefix != "":
            try:
                params = get_operator_for_guest_site(user_email, site_prefix)
            except:
                abort(403)
        else:
            # infer parameters from email
            try:
                # pre-validation
                params = get_operator_for_email(user_email)
            except:
                abort(403)

        if site_prefix == "" and user_fullname == "":
            return render_template('request-form.html',
                                   error="Full Name field cannot be empty",
                                   URL=app.config['URL'],
                                   email=user_email,
                                   token=user_token,
                                   **params)

        try:
            user_cert_request = base64.b64decode(request.form['cert-request'])
            user_cert_data = ndn.Data()
            # user_cert_data.wireDecode(ndn.Blob(buffer(user_cert_request)))
            user_cert_data.wireDecode(ndn.Blob(memoryview(user_cert_request)))
        except:
            return render_template(
                'request-form.html',
                error="Incorrectly generated NDN certificate request, "
                "please try again",
                URL=app.config['URL'],
                email=user_email,
                token=user_token,
                **params)

        # check if the user supplied correct name for the certificate request
        if not params['assigned_namespace'].isPrefixOf(
                user_cert_data.getName()):
            return render_template(
                'request-form.html',
                error="Incorrectly generated NDN certificate request, "
                "please try again",
                URL=app.config['URL'],
                email=user_email,
                token=user_token,
                **params)

        # cert_name = extract_cert_name(user_cert_data.getName()).toUri()
        # # remove any previous requests for the same certificate name
        # mongo.db.requests.remove({'cert_name': cert_name})

        cert_request = {
            'operator_id': str(params['operator']['_id']),
            'site_prefix': token['site_prefix'],
            'assigned_namespace': str(params['assigned_namespace']),
            'fullname': user_fullname,
            'organization': params['operator']['site_name'],
            'email': user_email,
            'homeurl': user_homeurl,
            'group': user_group,
            'advisor': user_advisor,
            'cert_request': base64.b64encode(user_cert_request),
            'created_on': datetime.datetime.utcnow(
            ),  # to periodically remove unverified tokens
        }
        mongo.db.requests.insert(cert_request)

        # OK. authorized, proceed to the next step
        mongo.db.tokens.remove(token)

        if (token['site_prefix'] != "" and not params['operator']['doNotSendOpRequestsForGuests']) or \
           (token['site_prefix'] == "" and not params['operator']['doNotSendOpRequests']):
            msg = Message(
                "[NDN Certification] User certification request",
                sender=app.config['MAIL_FROM'],
                recipients=[params['operator']['email']],
                body=render_template('operator-notify-email.txt',
                                     URL=app.config['URL'],
                                     operator_name=params['operator']['name'],
                                     **cert_request),
                html=render_template('operator-notify-email.html',
                                     URL=app.config['URL'],
                                     operator_name=params['operator']['name'],
                                     **cert_request))
            mail.send(msg)

        return render_template('request-thankyou.html')
예제 #20
0
def process_submitted_cert(cert_data, email, user_fullname):
    data = ndn.Data()
    data.wireDecode(ndn.Blob(buffer(base64.b64decode(cert_data))))

    # @todo verify data packet
    # Additional operator verification needed? Operator key should be verified
    operator_prefix = extract_cert_name(
        data.getSignature().getKeyLocator().getKeyName())
    operator = mongo.db.operators.find_one(
        {'site_prefix': operator_prefix.toUri()})
    if operator == None:
        return json.dumps({
            "status":
            500,
            "message":
            "operator not found [%s]" % operator_prefix
        })

    # @todo verify timestamp

    if (not app.config['AUTO_APPROVE']):
        cert_name = extract_cert_name(data.getName())
        cert_request = mongo.db.requests.find_one(
            {'cert_name': cert_name.toUri()})

        if cert_request == None:
            return json.dumps({
                "status": 403,
                "message": "No cert request entry"
            })

    if len(data.getContent()) == 0:
        # (no deny reason for now)
        # eventually, need to check data.type: if NACK, then content contains reason for denial
        #                                      if KEY, then content is the certificate

        msg = Message(
            "[NDN Open mHealth Certification] Rejected certification",
            sender=app.config['MAIL_FROM'],
            recipients=[email],
            body=render_template('cert-rejected-email.txt',
                                 URL=app.config['URL'],
                                 fullname=user_fullname),
            html=render_template('cert-rejected-email.html',
                                 URL=app.config['URL'],
                                 fullname=user_fullname))
        mail.send(msg)

        if (not app.config['AUTO_APPROVE']):
            mongo.db.requests.remove(cert_request)

        return json.dumps({
            "status": 200,
            "message": "Certificate request denied"
        })
    else:
        # may want to store assigned_namespace here as well
        cert = {
            'name': data.getName().toUri(),
            'cert': cert_data,
            'operator': operator,
            'created_on': datetime.datetime.utcnow(),
        }
        mongo.db.certs.insert(cert)

        msg = Message("[NDN Open mHealth Certification] Certificate issued",
                      sender=app.config['MAIL_FROM'],
                      recipients=[email],
                      body=render_template('cert-issued-email.txt',
                                           URL=app.config['URL'],
                                           quoted_cert_name=urllib.quote(
                                               cert['name'], ),
                                           cert_id=str(data.getName()[-3]),
                                           fullname=user_fullname),
                      html=render_template('cert-issued-email.html',
                                           URL=app.config['URL'],
                                           quoted_cert_name=urllib.quote(
                                               cert['name'], ''),
                                           cert_id=str(data.getName()[-3]),
                                           fullname=user_fullname))
        mail.send(msg)

        if (not app.config['AUTO_APPROVE']):
            mongo.db.requests.remove(cert_request)

        return json.dumps({
            "status":
            200,
            "message":
            "OK. Certificate has been approved and notification sent to the requester"
        })
예제 #21
0
def submit_request():
    if request.method == 'GET':
        # print 'GET'
        # Email and token (to authorize the request==validate email)
        user_email = request.args.get('email')
        user_token = request.args.get('token')

        token = mongo.db.tokens.find_one({
            'email': user_email,
            'token': user_token
        })
        if (token == None):
            abort(403, "No such token for this email address")

        # if getting operator fails, don't process this get request
        try:
            operator = get_operator()
        except Exception as e:
            print(e)
            abort(500, str(e))

        # don't delete token for now, just give user a form to input stuff

        return render_template('request-form.html',
                               URL=app.config['URL'],
                               email=user_email,
                               token=user_token,
                               assigned_namespace=token['assigned_namespace'])

    else:  # 'POST'
        # print "POST"
        # Email and token (to authorize the request==validate email)
        if ('email' in request.form):
            user_email = request.form['email']
        else:
            print('Expected email in request')
            abort(400, 'Expected email in request')
        if ('token' in request.form):
            user_token = request.form['token']
        else:
            print('Expected token in request')
            abort(400, 'Expected token in request')

        if ('full_name' in request.form):
            user_fullname = request.form['full_name']
        else:
            print('Expected full_name in request')
            abort(400, 'Expected full_name in request')

        token = mongo.db.tokens.find_one({
            'email': user_email,
            'token': user_token
        })
        if (token == None):
            print("No such token for this email address")
            abort(403, "No such token for this email address")

        # Now, do basic validation of correctness of user input, save request in the database
        # and notify the operator

        # if getting operator fails, don't process this post request
        try:
            operator = get_operator()
        except Exception as e:
            print(e)
            abort(500, str(e))

        if user_fullname == "":
            print("User full name should not be empty")
            abort(400, "User full name should not be empty")
        try:
            user_cert_request = base64.b64decode(request.form['cert_request'])
            user_cert_data = ndn.Data()
            user_cert_data.wireDecode(ndn.Blob(buffer(user_cert_request)))
        except:
            print("Malformed cert request")
            abort(400, "Malformed cert request")

        # check if the user supplied correct name for the certificate request
        if not ndn.Name(token['assigned_namespace']).match(
                user_cert_data.getName()):
            print("cert name does not match with assigned namespace")
            abort(400, "cert name does not match with assigned namespace")

        cert_name = extract_cert_name(user_cert_data.getName()).toUri()

        if (not app.config['AUTO_APPROVE']):
            # manual approval of request needed

            # remove any previous requests for the same certificate name
            mongo.db.requests.remove({'cert_name': cert_name})

            cert_request = {
                'operator_id': str(operator['_id']),
                'full_name': user_fullname,
                'organization': operator['site_name'],
                'email': user_email,
                'cert_name': cert_name,
                'cert_request': base64.b64encode(user_cert_request),
                'created_on': datetime.datetime.utcnow(
                ),  # to periodically remove unverified tokens
            }
            mongo.db.requests.insert(cert_request)

            # OK. authorized, proceed to the next step
            mongo.db.tokens.remove(token)

            msg = Message(
                "[NDN Open mHealth Certification] User certification request",
                sender=app.config['MAIL_FROM'],
                recipients=[operator['email']],
                body=render_template('operator-notify-email.txt',
                                     URL=app.config['URL'],
                                     operator_name=operator['name'],
                                     **cert_request),
                html=render_template('operator-notify-email.html',
                                     URL=app.config['URL'],
                                     operator_name=operator['name'],
                                     **cert_request))
            mail.send(msg)

            return json.dumps({"status": 200})
        else:
            # automatically approve any cert request
            # print request
            try:
                mongo.db.tokens.remove(token)
                cert = issue_certificate(request.form)
                ret = process_submitted_cert(cert, user_email, user_fullname)
                ret_obj = json.loads(ret)
                if (ret_obj['status'] != 200):
                    abort(ret_obj['status'], ret_obj['message'])
                else:
                    return json.dumps({"status": 200})
            except Exception as e:
                print(e)
                abort(500)
예제 #22
0
    def send_peer_info_list_data(self, interest, face):
        peer_list_info_data = pyndn.Data(interest.getName())
        peer_list_info_data.setContent(
            entities.PeerArray.serialize(self.context.peer_store.values()))

        face.putData(peer_list_info_data)
예제 #23
0
def submit_certificate():
    data = ndn.Data()
    # data.wireDecode(ndn.Blob(buffer(base64.b64decode(request.form['data']))))
    data.wireDecode(
        ndn.Blob(memoryview(base64.b64decode(request.form['data']))))

    cert_request = mongo.db.requests.find_one(
        {'_id': ObjectId(str(request.form['id']))})
    if cert_request == None:
        abort(403)

    # TODO: haitao remove this hack after test
    # operator = mongo.db.operators.find_one({"_id": ObjectId(cert_request['operator_id'])})
    operator = {
        '_id': 1,
        'site_name': 'UCLA',
        'email': '*****@*****.**',
        'doNotSendOpRequests': False,
        'name': 'haitao'
    }
    if operator == None:
        mongo.db.requests.remove(cert_request)  # remove invalid request
        abort(403)

    # # @todo verify data packet
    # # @todo verify timestamp

    if len(data.getContent()) == 0:
        # (no deny reason for now)
        # eventually, need to check data.type: if NACK, then content contains reason for denial
        #                                      if KEY, then content is the certificate

        msg = Message("[NDN Certification] Rejected certification",
                      sender=app.config['MAIL_FROM'],
                      recipients=[cert_request['email']],
                      body=render_template('cert-rejected-email.txt',
                                           URL=app.config['URL'],
                                           **cert_request),
                      html=render_template('cert-rejected-email.html',
                                           URL=app.config['URL'],
                                           **cert_request))
        mail.send(msg)

        mongo.db.requests.remove(cert_request)

        return "OK. Certificate has been denied"
    else:
        cert = {
            'name': data.getName().toUri(),
            'cert': request.form['data'],
            'operator': operator,
            'created_on': datetime.datetime.utcnow(
            ),  # to periodically remove unverified tokens, 
            'token': cert_request['token'] if 'token' in cert_request else ''
        }
        mongo.db.certs.insert(cert)

        # for nfd-android applicatin, use a token to fetch the certificate but not install it
        # using command line
        if 'token' in cert and len(cert['token']) != 0:
            msg = Message(
                "[NDN Certification] NDN certificate issued",
                sender=app.config['MAIL_FROM'],
                recipients=[cert_request['email']],
                body=render_template('nfd-android-cert-issued-email.txt',
                                     URL=app.config['URL'],
                                     quoted_cert_name=urllib.parse.quote(
                                         cert['name'], ''),
                                     cert_id=str(data.getName()[-3]),
                                     **cert_request),
                html=render_template('nfd-android-cert-issued-email.html',
                                     URL=app.config['URL'],
                                     quoted_cert_name=urllib.parse.quote(
                                         cert['name'], ''),
                                     cert_id=str(data.getName()[-3]),
                                     **cert_request))
        else:
            msg = Message(
                "[NDN Certification] NDN certificate issued",
                sender=app.config['MAIL_FROM'],
                recipients=[cert_request['email']],
                body=render_template('web-cert-issued-email.txt',
                                     URL=app.config['URL'],
                                     quoted_cert_name=urllib.parse.quote(
                                         cert['name'], ''),
                                     cert_id=str(data.getName()[-3]),
                                     **cert_request),
                html=render_template('web-cert-issued-email.html',
                                     URL=app.config['URL'],
                                     quoted_cert_name=urllib.parse.quote(
                                         cert['name'], ''),
                                     cert_id=str(data.getName()[-3]),
                                     **cert_request))
        mail.send(msg)

        mongo.db.requests.remove(cert_request)

        return "OK. Certificate has been approved and notification sent to the requester"