示例#1
0
    def test_replication_link(self, _input, expected, mock_circlecore):
        schema = Schema.create(display_name='Schema',
                               properties='x:int,y:float')
        module = Module.create(display_name='Module')

        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema_uuid=schema.uuid,
                         module_uuid=module.uuid,
                         display_name='Box')

        with MetaDataSession.begin():
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(box)

        replication_link = ReplicationLink.create(message_box_uuids=[box.uuid],
                                                  **_input)

        with MetaDataSession.begin():
            MetaDataSession.add(replication_link)

        replication_link = ReplicationLink.query.get(replication_link.uuid)
        assert isinstance(replication_link, ReplicationLink)
        assert replication_link.display_name == expected['display_name']
        assert replication_link.memo == expected['memo']
示例#2
0
    def make_own_cc_info(self, config_uuid: 'UUIDLike') -> CcInfo:
        """自身のCircleCore Infoを作成する.

        Args:
            config_uuid (str): uuid, autoの場合は生成する

        Returns:
            circle_core.models.CcInfo: 自身のCircleCore Info
        """
        with MetaDataSession.begin():
            try:
                my_cc_info = CcInfo.query.filter_by(myself=True).one()
            except NoResultFound:
                logger.info('My CCInfo not found. Create new one')
                my_cc_info = CcInfo(display_name='My CircleCore',
                                    myself=True,
                                    work='')
                if config_uuid == 'auto':
                    my_cc_info.uuid = generate_uuid(model=CcInfo)
                else:
                    my_cc_info.uuid = config_uuid

                MetaDataSession.add(my_cc_info)

        return my_cc_info
示例#3
0
    async def on_slave_hello(self, json_msg):
        """hello コマンドが送られてきた"""
        assert self.state == ReplicationState.HANDSHAKING
        self.state = ReplicationState.MIGRATING

        # slave's cc info
        slave_info = json_msg['ccInfo']
        slave_uuid = uuid.UUID(slave_info['uuid'])

        with MetaDataSession.begin():
            # store slave's information
            if slave_uuid not in [
                    slave.slave_uuid for slave in self.replication_link.slaves
            ]:
                self.replication_link.slaves.append(
                    ReplicationSlave(link_uuid=self.replication_link.uuid,
                                     slave_uuid=slave_uuid))

            cc_info = CcInfo.query.get(slave_uuid)
            if not cc_info:
                cc_info = CcInfo(uuid=slave_uuid, myself=False)
            cc_info.update_from_json(slave_info)
            MetaDataSession.add(cc_info)

        await self.send_migrate()
示例#4
0
    def test_user(self, _input, expected, mock_circlecore):
        user = User.create(**_input)

        with MetaDataSession.begin():
            MetaDataSession.add(user)

        user = User.query.get(user.uuid)
        assert isinstance(user, User)
        assert user.account == expected['account']
        assert user.is_password_matched(expected['password']) is True
        assert user.is_password_matched(expected['password_no_match']) is False
        assert len(user.permissions) == len(expected['permissions'])
        for permission, exp_permission in zip(user.permissions, expected['permissions']):
            assert isinstance(permission, str)
            assert permission == exp_permission
        assert user.work == expected['work']
        assert user.mail_address == expected['mail_address']
        assert user.telephone == expected['telephone']

        assert user.is_admin() == ('admin' in expected['permissions'])

        jsonobj = user.to_json(full=True)
        assert str(user.uuid) == jsonobj['uuid']
        assert user.account == jsonobj['account']
        assert user.work == jsonobj['work']
        assert user.mail_address == jsonobj['mailAddress']
        assert user.telephone == jsonobj['telephone']
        assert len(user.permissions) == len(jsonobj['permissions'])
        for permission, exp_permission in zip(user.permissions, jsonobj['permissions']):
            assert permission == exp_permission
示例#5
0
    def test_moge(self):
        """API認証"""
        with MetaDataSession.begin():
            user = User.create(account='tester', password='******')
            user.renew_token()
            schema = Schema.create(display_name='Schema',
                                   properties='x:int,y:float,data:blob')
            module = Module.create(display_name='Module')
            mbox = MessageBox(uuid='4ffab839-cf56-478a-8614-6003a5980857',
                              schema_uuid=schema.uuid,
                              module_uuid=module.uuid)
            MetaDataSession.add(user)
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(mbox)

        data_api_endpoint = self.get_url('/api/modules/{}/{}/data'.format(
            module.uuid, mbox.uuid))

        # 認証がいるよ
        response = self.fetch(data_api_endpoint)
        assert response.code == 403

        # 認証がいるよ
        response = self.fetch(
            data_api_endpoint,
            headers={'Authorization': 'Bearer {}'.format(user.encoded_token)})
        assert response.code == 200
示例#6
0
    def test_rest(self):
        """登録されているModuleからのPOSTは404"""
        # make dummy environ
        with MetaDataSession.begin():
            user = User.create(account='tester', password='******')
            user.renew_token()
            schema = Schema.create(display_name='Schema', properties='x:int,y:float')
            module = Module.create(display_name='Module')
            mbox = MessageBox(
                uuid='4ffab839-cf56-478a-8614-6003a5980856', schema_uuid=schema.uuid, module_uuid=module.uuid
            )
            MetaDataSession.add(user)
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(mbox)

        response = self.fetch(
            self.get_url('/modules/{}/{}'.format(module.uuid, mbox.uuid)),
            method='POST',
            body=json.dumps({
                'x': 1,
                'y': 2.5
            }),
            headers={
                'Content-Type': 'application/json',
                'Authorization': 'Bearer {token}'.format(token=user.encoded_token),
            }
        )
        self.assertEqual(response.code, 200)
        self.datareceiver.receive_new_message.assert_called_once_with(str(mbox.uuid), {'x': 1, 'y': 2.5})
示例#7
0
    def test_check_match(self, _input, data, expected, mock_circlecore):
        jsonobj = dict(displayName='Schema', memo='memo', properties=_input)
        schema = Schema.create()
        schema.update_from_json(jsonobj)

        with MetaDataSession.begin():
            MetaDataSession.add(schema)

        schema = Schema.query.get(schema.uuid)
        ok, msg = schema.check_match(data)
        assert ok is expected
示例#8
0
def _delete_invitation(invitation):
    """Invitationを削除する.

    :param Invitation invitation: 削除するInvitation
    :return: Invitationの情報
    :rtype: Response
    """
    with MetaDataSession.begin():
        MetaDataSession.delete(invitation)

    return respond_success(invitation={'uuid': invitation.uuid})
示例#9
0
def _delete_replication_master(replication_master):
    """ReplicationMasterを削除する.

    :param ReplicationMaster replication_master: 削除するReplicationMaster
    :return: ReplicationMasterの情報
    :rtype: Response
    """
    with MetaDataSession.begin():
        MetaDataSession.delete(replication_master)

    return respond_success(replicationMaster=replication_master.to_json())
示例#10
0
def _delete_replica(replication_link):
    """ReplicationLinkを削除する.

    :param ReplicationLink replication_link: 削除するReplicationLink
    :return: ReplicationLinkの情報
    :rtype: Response
    """
    with MetaDataSession.begin():
        MetaDataSession.delete(replication_link)

    return respond_success(replicationLink=replication_link.to_json())
示例#11
0
def _put_core(cc_info):
    """CircleCoreを更新する.

    :param CcInfo cc_info: 更新するCircleCore
    :return: CircleCoreの情報
    :rtype: Response
    """
    with MetaDataSession.begin():
        cc_info.update_from_json(request.json)
        MetaDataSession.add(cc_info)

    return respond_success(ccInfo=cc_info.to_json())
示例#12
0
def _post_schemas():
    """Schemaを作成する.

    :return: 作成したSchemaの情報
    :rtype: Response
    """
    with MetaDataSession.begin():
        schema = Schema.create()
        schema.update_from_json(request.json)
        MetaDataSession.add(schema)

    return respond_success(schema=schema.to_json(with_modules=True))
示例#13
0
    async def on_master_migrate(self, message):
        assert self.state == ReplicationState.MIGRATING

        with MetaDataSession.begin():
            # save master info
            data = message['masterInfo']
            try:
                obj = CcInfo.query.filter_by(uuid=data['uuid']).one()
            except NoResultFound:
                obj = CcInfo(uuid=data['uuid'], myself=False)
            obj.update_from_json(data)
            obj.replication_master_id = self.master.id
            MetaDataSession.add(obj)

            master_info = obj

            self.master.master_uuid = master_info.uuid

            # migrate schemas
            for schema_uuid, data in message['schemas'].items():
                try:
                    obj = Schema.query.filter_by(uuid=data['uuid']).one()
                except NoResultFound:
                    obj = Schema(uuid=data['uuid'])
                obj.update_from_json(data)
                obj.cc_uuid = master_info.uuid
                MetaDataSession.add(obj)

            # migrate modules
            for module_uuid, data in message['modules'].items():
                try:
                    obj = Module.query.filter_by(uuid=data['uuid']).one()
                except NoResultFound:
                    obj = Module(uuid=data['uuid'])
                obj.update_from_json(data)
                obj.cc_uuid = master_info.uuid
                obj.replication_master_id = self.master.id
                MetaDataSession.add(obj)

            # migrate boxes
            self.target_boxes = {}
            for box_uuid, data in message['messageBoxes'].items():
                try:
                    obj = MessageBox.query.filter_by(uuid=data['uuid']).one()
                    if obj.schema_uuid != uuid.UUID(data['schemaUuid']):
                        raise DataConfilictedError('schemaUuid not match')
                    if obj.module_uuid != uuid.UUID(data['moduleUuid']):
                        raise DataConfilictedError('moduleUuid not match')
                except NoResultFound:
                    obj = MessageBox(
                        uuid=data['uuid'],
                        schema_uuid=data['schemaUuid'],
                        module_uuid=data['moduleUuid'],
                    )
                obj.update_from_json(data)
                MetaDataSession.add(obj)

                self.target_boxes[obj.uuid] = obj
示例#14
0
def check_login():
    """ログイン確認."""
    user = get_user_from_request()
    if not user:
        raise abort(403)

    # update user's last access
    from circle_core.models import MetaDataSession

    with MetaDataSession.begin():
        user.last_access_at = datetime.utcnow()
        MetaDataSession.add(user)
示例#15
0
def _delete_module(module):
    """Moduleを削除する.

    :param Module module: 削除するModule
    :return: Moduleの情報
    :rtype: Response
    """
    with MetaDataSession.begin():
        if module.replication_master is not None:
            MetaDataSession.delete(module.replication_master)
        else:
            MetaDataSession.delete(module)

    return respond_success(module={'uuid': module.uuid})
示例#16
0
def _post_invitation():
    """Invitationを作成する.

    :return: 作成したInvitationの情報
    :rtype: Response
    """
    # maxInvites項目しか許可しない
    with MetaDataSession.begin():
        obj = Invitation(uuid=generate_uuid(model=Invitation),
                         max_invites=request.json['maxInvites'],
                         created_at=datetime.datetime.utcnow())
        MetaDataSession.add(obj)

    return respond_success(invitation=obj.to_json())
示例#17
0
def _delete_user(user):
    """Userを削除する.

    :param User user: 削除するUser
    :return: Userの情報
    :rtype: Response
    """
    # 自分は削除できない
    if user.uuid == request.oauth.user.uuid:
        return respond_failure('Cannot delete yourself.')

    with MetaDataSession.begin():
        MetaDataSession.delete(user)

    return respond_success(user={'uuid': user.uuid})
示例#18
0
def _post_replicas():
    """ReplicationLinkを作成する.

    :return: 作成したReplicationLinkの情報
    :rtype: Response
    """
    data = request.json
    with MetaDataSession.begin():
        replication_link = ReplicationLink.create(
            data['displayName'],
            data['memo'],
            data['messageBoxes'],
        )
        MetaDataSession.add(replication_link)

    return respond_success(replicationLink=replication_link.to_json())
示例#19
0
    def test_invitation(self, _input, expected, mock_circlecore):
        invitation = Invitation(uuid=generate_uuid(model=Invitation), **_input)

        with MetaDataSession.begin():
            MetaDataSession.add(invitation)

        invitation = Invitation.query.get(invitation.uuid)
        assert isinstance(invitation, Invitation)
        assert invitation.max_invites == expected['max_invites']
        assert invitation.current_invites == expected['current_invites']

        for i in range(_input['max_invites']):
            assert invitation.can_invite() is True
            invitation.inc_invites()
        else:
            assert invitation.can_invite() is False
示例#20
0
def _post_replication_masters():
    """ReplicationMasterを作成する.

    :return: 作成したReplicationMasterの情報
    :rtype: Response
    """
    data = request.json
    try:
        with MetaDataSession.begin():
            replication_master = ReplicationMaster(
                endpoint_url=data['endpointUrl'], )

            MetaDataSession.add(replication_master)
    except sqlalchemy.exc.IntegrityError:
        return respond_failure('このURLは既に登録されています')

    return respond_success(replicationMaster=replication_master.to_json())
示例#21
0
def _put_module(module):
    """Moduleを更新する.

    :param Module module: 更新するModule
    :return: Moduleの情報
    :rtype: Response
    """
    try:
        with MetaDataSession.begin():
            module.update_from_json(request.json, with_boxes=True)
            MetaDataSession.add(module)
    except KeyError:
        return respond_failure('key error')
    except ValueError as e:
        return respond_failure(str(e))

    return respond_success(module=module.to_json(with_boxes=True, with_schema=True))
示例#22
0
    def test_message_box(self, _input, expected, mock_circlecore):
        schema = Schema.create(display_name='Schema',
                               properties='x:int,y:float')
        module = Module.create(display_name='Module')

        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema_uuid=schema.uuid,
                         module_uuid=module.uuid,
                         **_input)

        with MetaDataSession.begin():
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(box)

        box = MessageBox.query.get(box.uuid)
        assert isinstance(box, MessageBox)
        assert box.display_name == expected['display_name']
        assert box.memo == expected['memo']

        assert isinstance(hash(box), int)
        assert isinstance(box.cc_uuid, uuid.UUID)

        jsonobj = box.to_json(with_schema=True, with_module=True)
        assert str(box.uuid) == jsonobj['uuid']
        assert box.display_name == jsonobj['displayName']
        assert box.memo == jsonobj['memo']
        assert str(box.module_uuid) == jsonobj['moduleUuid']
        assert str(box.schema_uuid) == jsonobj['schemaUuid']
        assert schema.display_name == jsonobj['schema']['displayName']
        assert module.display_name == jsonobj['module']['displayName']
示例#23
0
async def test_post_date(mysql, mock_circlecore):
    mbox_id = uuid.uuid4()
    with MetaDataSession.begin():
        schema = Schema.create(display_name='Schema',
                               properties='date:datetime,id1:float')
        module = Module.create(display_name='Module')
        mbox = MessageBox(uuid=mbox_id,
                          schema_uuid=schema.uuid,
                          module_uuid=module.uuid)
        MetaDataSession.add(schema)
        MetaDataSession.add(module)
        MetaDataSession.add(mbox)

    envdir = mock_circlecore[1]
    database = Database(mysql.url, time_db_dir=envdir, log_dir=envdir)
    journal_writer = database.make_writer()
    queued_writer = journal_writer.child_writer
    run_loop = asyncio.ensure_future(journal_writer.run())

    # post
    message = ModuleMessage(mbox.uuid, 123456.789, 0, {
        'date': '2017-09-01T24:00:00Z',
        'id1': 3.14
    })
    await queued_writer.store(mbox, message)
    await queued_writer.flush()

    # close database
    await journal_writer.close()
    await run_loop

    with database._engine.begin() as connection:
        table = database.find_table_for_message_box(mbox)
        rows = connection.execute(select([table])).fetchall()
        assert len(rows) == 0
示例#24
0
def _post_modules() -> 'Response':
    """Moduleを作成する.

    :return: 作成したModuleの情報
    :rtype: Response
    """
    try:
        with MetaDataSession.begin():
            module = Module.create()
            module.update_from_json(request.json, with_boxes=True)

            MetaDataSession.add(module)

    except KeyError:
        raise
        return respond_failure('key error', _status=400)

    return respond_success(module=module.to_json(with_boxes=True, with_schema=True))
示例#25
0
    def test_cc_info(self, _input, expected, mock_circlecore):
        other_cc_info = CcInfo(**_input)
        with MetaDataSession.begin():
            MetaDataSession.add(other_cc_info)

        own_cc_info = CcInfo.query.filter_by(myself=True).all()
        assert len(own_cc_info) == 1

        other_cc_info = CcInfo.query.get(_input['uuid'])
        assert isinstance(other_cc_info, CcInfo)
        assert other_cc_info.display_name == expected['display_name']
        assert str(other_cc_info.uuid).lower() == expected['uuid'].lower()
        assert other_cc_info.myself == expected['myself']
        assert other_cc_info.work == expected['work']

        jsonobj = other_cc_info.to_json()
        assert str(other_cc_info.uuid) == jsonobj['uuid']
        assert other_cc_info.display_name == jsonobj['displayName']
        assert other_cc_info.work == jsonobj['work']
        assert other_cc_info.myself == jsonobj['myself']
示例#26
0
def _delete_schema(schema_uuid):
    """Schemaを削除する.

    :param str schema_uuid: 削除するSchemaのUUID
    :return: Schemaの情報
    :rtype: Response
    """
    schema = Schema.query.get(schema_uuid)
    if not schema:
        return respond_failure('not found', _status=404)

    if len(schema.message_boxes) > 0:
        reason = 'message box {uuids} {verb} attached'.format(
            uuids=', '.join([str(box.uuid) for box in schema.message_boxes]),
            verb='is' if len(schema.message_boxes) == 1 else 'are')
        return respond_failure(reason, _status=400)

    with MetaDataSession.begin():
        MetaDataSession.delete(schema)

    return respond_success(schema={'uuid': schema_uuid})
示例#27
0
    def test_rest_not_found(self):
        """登録されていないModuleからのPOSTは404"""
        with MetaDataSession.begin():
            user = User.create(account='tester', password='******')
            user.renew_token()

            MetaDataSession.add(user)

        response = self.fetch(
            self.get_url('/modules/4ffab839-cf56-478a-8614-6003a5980855/00000000-0000-0000-0000-000000000000'),
            method='POST',
            body=json.dumps({
                'x': 1,
                'y': 2
            }),
            headers={
                'Content-Type': 'application/json',
                'Authorization': 'Bearer {token}'.format(token=user.encoded_token),
            }
        )
        self.assertEqual(response.code, 404)
示例#28
0
    def test_update_from_json(self, _input, expected, mock_circlecore):
        schema = Schema.create(display_name='Schema',
                               properties='x:int,y:float')
        module = Module.create(display_name='Module')
        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema_uuid=schema.uuid,
                         module_uuid=module.uuid,
                         display_name='MessageBoxOldName')
        with MetaDataSession.begin():
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(box)

        box = MessageBox.query.get(box.uuid)
        box.update_from_json(_input)
        with MetaDataSession.begin():
            MetaDataSession.add(box)

        box = MessageBox.query.get(box.uuid)
        assert isinstance(box, MessageBox)
        assert box.display_name == expected['display_name']
        assert box.memo == expected['memo']
示例#29
0
def invitation_endpoint(link_uuid: 'uuid.UUID'):
    """User招待リンク.

    Args:
        link_uuid: User招待リンクのUUID
    """
    invitation = Invitation.query.get(link_uuid)
    if not invitation or not invitation.can_invite():
        raise abort(404)

    error = None
    user = None
    is_completed = False
    if request.method == 'POST':
        form = request.form

        try:
            with MetaDataSession.begin():
                user = User.create(
                    account=form['account'],
                    work=form['work'],
                    telephone=form['telephone'],
                    mail_address=form['mailAddress'],
                )
                user.set_password(form['password'])
                invitation.inc_invites()

                MetaDataSession.add(user)
                MetaDataSession.add(invitation)
        except sqlalchemy.exc.IntegrityError:
            error = 'このアカウントはすでに使われています。'
        except ValueError as exc:
            error = str(exc)
        else:
            is_completed = True

    return render_template(
        'invitation.html', error=error, user=user.to_json() if user else None, is_completed=is_completed
    )
示例#30
0
def _put_user(user):
    """Userを更新する.

    :param User user: 更新するUser
    :return: Userの情報
    :rtype: Response
    """
    has_write, req = oauth.verify_request([CRScope.USER_RW.value])

    # TODO: viewでやるな
    # validation
    errors = {}

    if not has_write:
        # Read権限のみでは、自分の情報しか変更できない、currentPasswordが必要、permissionの変更はできない
        if user.uuid != request.oauth.user.uuid:
            return respond_failure('no permission.', _status=400)

        if 'currentPassword' in request.json:
            if not user.is_password_matched(request.json['currentPassword']):
                errors['currentPassword'] = u'現在のパスワードが間違っています'
        else:
            if 'newPassword' in request.json:
                return respond_failure(
                    'user+r scope cannot change password without current.',
                    _status=400)

        if 'permissions' in request.json:
            return respond_failure(
                'user+r scope cannot change mine permission.', _status=400)

    if 'newPassword' in request.json:
        if not request.json['newPassword']:
            errors['newPassword'] = u'新しいパスワードが空欄です'
        if len(request.json['newPassword']) < 6:
            errors['newPassword'] = u'パスワードは6文字以上にしてください'

    if not request.json['account']:
        errors['account'] = u'アカウントは空には出来ません'

    if errors:
        return respond_failure('パラメータにエラーがあります', _status=400, errors=errors)

    # update
    with MetaDataSession.begin():
        user.update_from_json(request.json)

    respond_full = request.oauth.user.is_admin(
    ) or user.uuid == request.oauth.user.uuid
    return respond_success(user=user.to_json(respond_full))