def test_dymo_no_write_when_read_disabled(self):  # pylint: disable=no-self-use
        model = QuestionnaireState(USER_ID, STATE_DATA, VERSION)
        with mock.patch('app.storage.data_access.is_dynamodb_read_enabled', mock.Mock(return_value=False)), \
                mock.patch('app.storage.data_access.models.db.session.add') as merge:
            data_access.put(model, overwrite=False)

        merge.assert_called()
    def _save_session(self, session_id, user_id, data, legacy=False):
        raw_data = json.dumps(vars(data))
        protected_header = {
            'alg': 'dir',
            'enc': 'A256GCM',
            'kid': '1,1',
        }

        if legacy:
            plaintext = base64url_encode(raw_data)
        else:
            plaintext = raw_data

        jwe_token = jwe.JWE(
            plaintext=plaintext,
            protected=protected_header,
            recipient=self.key
        )

        session_model = EQSession(
            session_id,
            user_id,
            jwe_token.serialize(compact=True)
        )
        data_access.put(session_model)
Beispiel #3
0
def use_jti_claim(jti_claim, expires):
    """
    Use a jti claim
    :param jti_claim: jti claim to mark as used.
    :param expires: when the jti claim expires.
    :raises ValueError: when jti_claim is None.
    :raises TypeError: when jti_claim is not a valid uuid4.
    :raises JtiTokenUsed: when jti_claim has already been used.
    """
    if jti_claim is None:
        raise ValueError
    if not _is_valid(jti_claim):
        logger.info('jti claim is invalid', jti_claim=jti_claim)
        raise TypeError

    try:
        used_at = datetime.now(tz=tzutc())
        # Make claim expire a little later than exp to avoid race conditions with out of sync clocks.
        expires += timedelta(seconds=60)

        jti = UsedJtiClaim(jti_claim, used_at, expires)

        data_access.put(jti, overwrite=False)
    except ItemAlreadyExistsError as e:
        logger.error('jti claim has already been used', jti_claim=jti_claim)
        raise JtiTokenUsed(jti_claim) from e
    def test_put(self):
        model = QuestionnaireState(USER_ID, STATE_DATA, VERSION)

        with mock.patch('app.storage.dynamodb_api.put') as put:
            data_access.put(model)

        self.assertEqual(put.call_args[0][0], model)
        self.assertTrue(put.call_args[0][1])
    def test_put_rds_no_overwrite(self):
        model = QuestionnaireState(USER_ID, STATE_DATA, VERSION)
        setattr(model, '_use_dynamo', False)

        with mock.patch('app.data_model.models.db.session.add', side_effect=IntegrityError('', '', '')) as add, \
            self.assertRaises(ItemAlreadyExistsError):
            data_access.put(model, overwrite=False)

        self.assertTrue(add.called)
    def test_put_propogate_dynamo_exception(self):
        model = QuestionnaireState(USER_ID, STATE_DATA, VERSION)

        side_effect = ClientError({'Error': {
            'Code': 'RandomError'
        }}, 'PutItem')
        with mock.patch('app.storage.dynamo_api.put_item', side_effect=side_effect) as put_item, \
            self.assertRaises(ClientError):
            data_access.put(model, overwrite=False)

        self.assertFalse(put_item.call_args[1]['overwrite'])
    def save(self):
        """
        save session
        """
        if self._eq_session:
            self._eq_session.session_data = \
                StorageEncryption(self.user_id, self.user_ik, self.pepper).encrypt_data(vars(self.session_data))

            data_access.put(self._eq_session)

        return self
    def test_put_no_overwrite(self):
        model = QuestionnaireState(USER_ID, STATE_DATA, VERSION)

        side_effect = ClientError(
            {'Error': {
                'Code': 'ConditionalCheckFailedException'
            }}, 'PutItem')
        with mock.patch('app.storage.dynamo_api.put_item', side_effect=side_effect) as put_item, \
            self.assertRaises(ItemAlreadyExistsError):
            data_access.put(model, overwrite=False)

        self.assertFalse(put_item.call_args[1]['overwrite'])
    def test_put_rds(self):
        model = QuestionnaireState(USER_ID, STATE_DATA, VERSION)
        setattr(model, '_use_dynamo', False)

        with mock.patch('app.data_model.models.db.session.merge') as merge:
            data_access.put(model)

        self.assertTrue(merge.called)

        rds_model = merge.call_args[0][0]
        self.assertEqual(rds_model.user_id, USER_ID)
        self.assertEqual(rds_model.state, STATE_DATA)
        self.assertEqual(rds_model.version, VERSION)
    def test_put(self):
        model = QuestionnaireState(USER_ID, STATE_DATA, VERSION)

        with mock.patch('app.storage.dynamo_api.put_item') as put_item:
            data_access.put(model)

        self.assertEqual(put_item.call_args[0][1], 'user_id')

        dynamo_item = put_item.call_args[0][2]
        self.assertEqual(dynamo_item['user_id'], USER_ID)
        self.assertEqual(dynamo_item['state_data'], STATE_DATA)
        self.assertEqual(dynamo_item['version'], VERSION)

        self.assertTrue(put_item.call_args[1]['overwrite'])
    def add_or_update(self, data, version):
        compressed_data = snappy.compress(data)
        encrypted_data = self.encrypter.encrypt_data(compressed_data)
        questionnaire_state = self._find_questionnaire_state()
        if questionnaire_state:
            logger.debug('updating questionnaire data', user_id=self._user_id)
            questionnaire_state.state_data = encrypted_data
            questionnaire_state.version = version
        else:
            logger.debug('creating questionnaire data', user_id=self._user_id)
            questionnaire_state = QuestionnaireState(self._user_id,
                                                     encrypted_data, version)

        data_access.put(questionnaire_state)
    def add_or_update(self, data, version):
        encrypted_data = self.encrypter.encrypt_data(data)
        encrypted_data_json = json.dumps({'data': encrypted_data})
        questionnaire_state = self._find_questionnaire_state()
        if questionnaire_state:
            logger.debug('updating questionnaire data', user_id=self._user_id)
            questionnaire_state.state_data = encrypted_data_json
            questionnaire_state.version = version
        else:
            logger.debug('creating questionnaire data', user_id=self._user_id)
            questionnaire_state = QuestionnaireState(self._user_id,
                                                     encrypted_data_json,
                                                     version)

        data_access.put(questionnaire_state)
Beispiel #13
0
def _store_viewable_submission(answers, metadata, submitted_time):
    pepper = current_app.eq['secret_store'].get_secret_by_name(
        'EQ_SERVER_SIDE_STORAGE_ENCRYPTION_USER_PEPPER')
    encrypter = StorageEncryption(current_user.user_id, current_user.user_ik,
                                  pepper)
    encrypted_data = encrypter.encrypt_data(
        {
            'answers': answers,
            'metadata': metadata.copy(),
        }, )

    valid_until = submitted_time + timedelta(
        seconds=g.schema.json['view_submitted_response']['duration'])

    item = SubmittedResponse(
        tx_id=metadata['tx_id'],
        data=encrypted_data,
        valid_until=valid_until.replace(tzinfo=tzutc()),
    )

    data_access.put(item)
Beispiel #14
0
    def _save_legacy_state_data(self, user_id, data):
        protected_header = {
            'alg': 'dir',
            'enc': 'A256GCM',
            'kid': '1,1',
        }

        jwe_token = jwe.JWE(
            plaintext=base64url_encode(data),
            protected=protected_header,
            recipient=self.storage.encrypter.key
        )

        legacy_state_data = json.dumps({'data': jwe_token.serialize(compact=True)})

        questionnaire_state = QuestionnaireState(
            user_id,
            legacy_state_data,
            QuestionnaireStore.LATEST_VERSION
        )
        data_access.put(questionnaire_state)