def test_should_signup_new_user(self):
     response = self.rest.post('/api/v1/signup', USER)
     session = json.loads(response.content)
     JsonConverter.from_json(TypeCode.Map, response.content)
     assert session is not None
     assert session['id'] is not None
     assert session['user_name'] == USER['name']
    def test_json_to_map(self):
        # Handling simple objects
        value = '{ "value1":123, "value2":234 }'
        result = JsonConverter.to_nullable_map(value)
        assert 123 == result["value1"]
        assert 234 == result["value2"]

        # Recursive conversion
        value = '{ "value1":123, "value2": { "value1": 111, "value2": 222 } }'
        result = JsonConverter.to_nullable_map(value)
        assert result != None
        assert 123 == result["value1"]
        assert result["value2"] != None
        assert isinstance(result["value2"], dict)

        # Handling arrays
        value = '{ "value1": [{ "value1": 111, "value2": 222 }] }'
        result = JsonConverter.to_nullable_map(value)
        assert result != None
        assert type(result["value1"]) == list
        resultElements = result["value1"]
        resultElement0 = resultElements[0]
        assert resultElement0 != None
        assert 111 == resultElement0["value1"]
        assert 222 == resultElement0["value2"]
    def test_should_perform_invitation_operations(self):
        invitation1: InvitationV1 = None
        invitation2: InvitationV1 = None

        # Send one invitation
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/' + INVITATION1.site_id + '/invitations',
            JsonConverter.to_json(INVITATION1))
        invitation = JsonConverter.from_json(TypeCode.Map, response.content)

        assert invitation['site_id'] == INVITATION1.site_id
        assert invitation['creator_id'] == INVITATION1.creator_id
        assert invitation['invitee_email'] == INVITATION1.invitee_email

        invitation1 = InvitationV1(**invitation)

        # Send another invitation
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/' + INVITATION2.site_id + '/invitations',
            JsonConverter.to_json(INVITATION2),
        )

        invitation = JsonConverter.from_json(TypeCode.Map, response.content)

        assert invitation['site_id'] == INVITATION2.site_id
        assert invitation['creator_id'] == INVITATION2.creator_id
        assert invitation['invitee_email'] == INVITATION2.invitee_email

        invitation2 = InvitationV1(**invitation)

        # Get all invitations
        response = self.rest.get_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/' + INVITATION1.site_id + '/invitations')

        page = JsonConverter.from_json(TypeCode.Map, response.content)

        assert response.status_code == 200
        assert page is not None and page != {}
        # assert len(page['data']) == 2

        # Delete invitation
        response = self.rest.delete_as_user(
            TestUsers.AdminUserSessionId, '/api/v1/sites/' +
            invitation1.site_id + '/invitations/' + invitation1.id)

        assert response.status_code < 300

        # Try to get delete invitation
        response = self.rest.get_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/' + invitation1.site_id + '/invitations/' +
            invitation1.id,
        )

        assert response.status_code < 300
        assert response.content == b''
Пример #4
0
    def test_from_json(self):
        assert 123 == JsonConverter.from_json(TypeCode.Integer, '123')
        assert 'ABC' == JsonConverter.from_json(TypeCode.String, '"ABC"')

        filter = JsonConverter.from_json(None,
                                         '{"Key2": "ABC", "Key1": "123"}')
        assert isinstance(filter, dict)

        array = JsonConverter.from_json(TypeCode.Array, "[123,\"ABC\"]")
        assert len(array) == 2

        date = DateTimeConverter.to_datetime("1975-04-08T00:00:00.000Z")
        json_date = JsonConverter.from_json(TypeCode.DateTime,
                                            "\"1975-04-08T00:00Z\"")
        assert date.timestamp() == json_date.timestamp()
    def test_set_properties(self):
        obj = JsonConverter.to_map(
            "{ \"value1\": 123, \"value2\": { \"value21\": 111, \"value22\": 222 }, \"value3\": [ 444, "
            "{ \"value311\": 555 } ] } "
        )

        values = AnyValueMap.from_tuples(
            "value1", "AAA",
            "value2", "BBB",
            "value3.1.value312", "CCC",
            "value3.3", "DDD",
            "value4.1", "EEE"
        )
        RecursiveObjectWriter.set_properties(obj, values)

        values = RecursiveObjectReader.get_properties(obj)
        assert 8 == len(values)
        assert "AAA" == values["value1"]
        assert "BBB", values["value2"]
        assert 444 == values["value3.0"]
        assert 555 == values["value3.1.value311"]
        assert "CCC", values["value3.1.value312"]
        assert None is values["value3.2"]
        assert "DDD" == values["value3.3"]
        assert "EEE" == values["value4.1"]
    def signup(self):
        try:
            signup_data = bottle.request.json if isinstance(
                bottle.request.json, dict) else JsonConverter.from_json(
                    TypeCode.Map, bottle.request.json)
            account: AccountV1 = None
            invited: bool = False
            roles: List[str] = []

            # Validate password first
            # Todo: complete implementation after validate password is added

            # Create account
            new_account = AccountV1(name=signup_data.get('name'),
                                    login=signup_data.get('login')
                                    or signup_data.get('email'),
                                    language=signup_data.get('language'),
                                    theme=signup_data.get('theme'),
                                    time_zone=signup_data.get('time_zone'))

            account = self.__accounts_client.create_account(None, new_account)

            # Create password for the account
            password = signup_data.get('password')

            self.__passwords_client.set_password(None, account.id, password)

            # Activate all pending invitations
            email = signup_data.get('email')

            invitations = self.__invitations_client.activate_invitations(
                None, email, account.id)
            if invitations:
                # Calculate user roles from activated invitations
                for invitation in invitations:
                    # Was user invited with the same email?
                    invited = invited or email == invitation.invitee_email

                    if invitation.site_id:
                        invitation.role = invitation.role or 'user'
                        role = invitation.site_id + ':' + invitation.role
                        roles.append(role)

            # Create email settings for the account
            new_email_settings = EmailSettingsV1(id=account.id,
                                                 name=account.name,
                                                 email=email,
                                                 language=account.language)

            if self.__email_settings_client is not None:
                if invited:
                    self.__email_settings_client.set_verified_settings(
                        None, new_email_settings)
                else:
                    self.__email_settings_client.set_settings(
                        None, new_email_settings)

            return self.open_session(account, roles)
        except Exception as err:
            return self._send_error(err)
Пример #7
0
    def create_site(self):
        try:
            data = bottle.request.json if isinstance(bottle.request.json,
                                                     dict) else JsonConverter.from_json(TypeCode.Map,
                                                                                        bottle.request.json)
            site: SiteV1 = SiteV1(**data)

            # Create a site
            site = self.__sites_client.create_site(None, site)

            # Assign permissions to the owner
            if self.__roles_client is not None and hasattr(bottle.request,
                                                           'user') and bottle.request.user.id is not None:
                self.__roles_client.grant_roles(None, bottle.request.user.id, [site.id + ':admin'])

            # Update current user session
            if hasattr(bottle.request, 'user') and hasattr(bottle.request, 'session_id'):
                user = bottle.request.user
                user.roles = user.roles or []
                user.roles.append(site.id + ':admin')

                user.sites = user.sites or []
                user.sites.append(site)

                self.__sessions_client.update_session_user(None, bottle.request.session_id, user)

            return self._send_result(site)

        except Exception as err:
            return self._send_error(err)
    def create_beacon_x(self, site_id) -> Optional[str]:
        json_data = bottle.request.json if isinstance(
            bottle.request.json, dict) else JsonConverter.from_json(
                TypeCode.Map, bottle.request.json)
        beacon = BeaconV1(**json_data)

        result = self.__beacons_client.create_beacon(None, beacon)
        return self._send_result(result)
    def test_should_notify_invitations(self):
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/' + INVITATION1.site_id + '/invitations/notify',
            JsonConverter.to_json(INVITATION3),
        )

        assert response.status_code < 300
        assert response.content == b''
    def validate_beacon_udi_x(self, site_id) -> Optional[str]:
        params = dict(bottle.request.query.decode())
        udi = params.get('udi')

        beacon = self.__beacons_client.get_beacon_by_udi(None, udi)
        if beacon:
            return JsonConverter.to_json(beacon)
        else:
            return ''
    def update_beacon(self, site_id, beacon_id) -> Optional[str]:
        beacon = bottle.request.json if isinstance(
            bottle.request.json, dict) else JsonConverter.from_json(
                TypeCode.Map, bottle.request.json)
        beacon['id'] = beacon_id

        beacon = BeaconV1(**beacon)

        result = self.__beacons_client.update_beacon(None, beacon)
        return self._send_result(result)
    def calculate_position_x(self, site_id) -> Optional[str]:
        params = bottle.request.json if isinstance(
            bottle.request.json, dict) else JsonConverter.from_json(
                TypeCode.Map, bottle.request.json)
        udis = params.get('udis')

        if isinstance(udis, str):
            udis = udis.split(',')

        result = self.__beacons_client.calculate_position(None, site_id, udis)
        return self._send_result(result)
    def test_get_properties(self):
        obj = JsonConverter.to_map(
            "{ \"value1\": 123, \"value2\": { \"value21\": 111, \"value22\": 222 }, \"value3\": [ 444, "
            "{ \"value311\": 555 } ] } ")

        values = RecursiveObjectReader.get_properties(obj)
        assert 5 == len(values)
        assert 123 == values["value1"]
        assert 111 == values["value2.value21"]
        assert 222 == values["value2.value22"]
        assert 444 == values["value3.0"]
        assert 555 == values["value3.1.value311"]
    def test_get_property_names(self):
        obj = JsonConverter.to_map(
            "{ \"value1\": 123, \"value2\": { \"value21\": 111, \"value22\": 222 }, \"value3\": [ 444, "
            "{ \"value311\": 555 } ] } ")

        names = RecursiveObjectReader.get_property_names(obj)
        assert 5 == len(names)
        assert "value1" in names
        assert "value2.value21" in names
        assert "value2.value22" in names
        assert "value3.0" in names
        assert "value3.1.value311" in names
    def test_should_resend_invitations(self):
        invitation1: InvitationV1 = None

        # Send invitation
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/' + INVITATION1.site_id + '/invitations',
            JsonConverter.to_json(INVITATION1))

        invitation = JsonConverter.from_json(TypeCode.Map, response.content)
        assert invitation['site_id'] == INVITATION1.site_id
        assert invitation['invitee_email'] == INVITATION1.invitee_email

        invitation1 = InvitationV1(**invitation)

        # Send another invitation
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId, '/api/v1/sites/' +
            invitation1.site_id + '/invitations/' + invitation1.id + '/resend',
            {})

        assert response.status_code < 300
    def restore_session(self):
        try:
            session_id = dict(bottle.request.query.decode()).get('session_id')

            session = self.__sessions_client.get_session_by_id(
                None, session_id)

            # If session closed then return null
            if session and not session.active:
                session = None

            if session:
                return JsonConverter.to_json(session)
            else:
                return bottle.HTTPResponse(status=204)
        except Exception as err:
            return self._send_error(err)
    def test_has_property(self):
        obj = JsonConverter.to_map(
            "{ \"value1\": 123, \"value2\": { \"value21\": 111, \"value22\": 222 }, \"value3\": [ 444, "
            "{ \"value311\": 555 } ] } ")

        has = RecursiveObjectReader.has_property(obj, "")
        assert False == has

        has = RecursiveObjectReader.has_property(obj, "value1")
        assert True == has

        has = RecursiveObjectReader.has_property(obj, "value2")
        assert True == has

        has = RecursiveObjectReader.has_property(obj, "value2.value21")
        assert True == has

        has = RecursiveObjectReader.has_property(obj, "value2.value31")
        assert False == has

        has = RecursiveObjectReader.has_property(obj,
                                                 "value2.value21.value211")
        assert False == has

        has = RecursiveObjectReader.has_property(obj, "valueA.valueB.valueC")
        assert False == has

        has = RecursiveObjectReader.has_property(obj, "value3")
        assert True == has

        has = RecursiveObjectReader.has_property(obj, "value3.0")
        assert True == has

        has = RecursiveObjectReader.has_property(obj, "value3.0.value311")
        assert False == has

        has = RecursiveObjectReader.has_property(obj, "value3.1")
        assert True == has

        has = RecursiveObjectReader.has_property(obj, "value3.1.value311")
        assert True == has

        has = RecursiveObjectReader.has_property(obj, "value3.2")
        assert False == has
    def test_get_property(self):
        obj = JsonConverter.to_map(
            "{ \"value1\": 123, \"value2\": { \"value21\": 111, \"value22\": 222 }, \"value3\": [ 444, "
            "{ \"value311\": 555 } ] } ")

        value = RecursiveObjectReader.get_property(obj, "")
        assert None == value

        value = RecursiveObjectReader.get_property(obj, "value1")
        assert 123 == value

        value = RecursiveObjectReader.get_property(obj, "value2")
        assert None != value

        value = RecursiveObjectReader.get_property(obj, "value2.value21")
        assert 111 == value

        value = RecursiveObjectReader.get_property(obj, "value2.value31")
        assert None == value

        value = RecursiveObjectReader.get_property(obj,
                                                   "value2.value21.value211")
        assert None == value

        value = RecursiveObjectReader.get_property(obj, "valueA.valueB.valueC")
        assert None == value

        value = RecursiveObjectReader.get_property(obj, "value3")
        assert None != value

        value = RecursiveObjectReader.get_property(obj, "value3.0")
        assert 444 == value

        value = RecursiveObjectReader.get_property(obj, "value3.0.value311")
        assert None == value

        value = RecursiveObjectReader.get_property(obj, "value3.1")
        assert None != value

        value = RecursiveObjectReader.get_property(obj, "value3.1.value311")
        assert 555 == value

        value = RecursiveObjectReader.get_property(obj, "value3.2")
        assert None == value
    def signin(self):
        json_data = bottle.request.json if isinstance(
            bottle.request.json, dict) else JsonConverter.from_json(
                TypeCode.Map, bottle.request.json)

        login = json_data.get('login')
        password = json_data.get('password')

        account: AccountV1 = None
        roles: List[str] = []

        # Find user account
        try:
            account = self.__accounts_client.get_account_by_id_or_login(
                None, login)

            if account is None:
                raise BadRequestException(
                    None, 'WRONG_LOGIN',
                    'Account ' + login + ' was not found').with_details(
                        'login', login)

            # Authenticate user
            result = self.__passwords_client.authenticate(
                None, account.id, password)
            # wrong password error is UNKNOWN when use http client
            if result is False:
                raise BadRequestException(
                    None, 'WRONG_PASSWORD',
                    'Wrong password for account ' + login).with_details(
                        'login', login)

            # Retrieve user roles
            if self.__roles_client:
                roles = self.__roles_client.get_roles_by_id(
                    None,
                    account.id,
                )
            else:
                roles = []

            return self.open_session(account, roles)
        except Exception as err:
            return self._send_error(err)
Пример #20
0
        def inner():
            user = bottle.request.user
            if user is None:
                raise UnauthorizedException(
                    None, 'NOT_SIGNED',
                    'User must be signed in to perform this operation'
                ).with_status(401)

            else:
                user_id = dict(bottle.request.query.decode()).get(user_id_param) or JsonConverter.to_json(
                    bottle.request.json)
                if user_id is not None and user_id == user.user_id:
                    return
                else:
                    site_id = bottle.request.params.get(site_id_param)
                    authorized = 'admin' in user.roles or site_id + ':admin' in user.roles
                    if not authorized:
                        raise UnauthorizedException(
                            None, 'NOT_IN_SITE_ROLE',
                            'User must be site:admin to perform this operation'
                        ).with_details('roles', ['admin']).with_status(403)
Пример #21
0
    def test_to_json(self):
        assert JsonConverter.to_json(None) is None
        assert '123' == JsonConverter.to_json(123)
        assert "\"ABC\"" == JsonConverter.to_json('ABC')

        filter = {"Key1": 123, "Key2": "ABC"}
        json_filter = JsonConverter.to_json(filter)
        assert '{"Key1": 123, "Key2": "ABC"}' == json_filter

        array = [123, "ABC"]
        json_array = JsonConverter.to_json(array)
        assert '[123, "ABC"]' == json_array

        date = DateTimeConverter.to_datetime("1975-04-08T00:00:00.000Z")
        json_date = JsonConverter.to_json(date)
        assert "\"1975-04-08T00:00:00.000Z\"", json_date
Пример #22
0
    def update_site(self, site_id):
        try:
            data = bottle.request.json if isinstance(bottle.request.json,
                                                     dict) else JsonConverter.from_json(TypeCode.Map,
                                                                                        bottle.request.json)
            data['id'] = site_id
            site: SiteV1 = SiteV1(**data)

            # Update site
            site = self.__sites_client.update_site(None, site)

            # Update current user session
            if hasattr(bottle.request, 'user') is not None and hasattr(bottle.request, 'session_id') is not None:
                user = bottle.request.user

                user.sites = user.sites or []
                user.sites = list(filter(lambda x: x.id == site.id, user.sites))
                user.sites.append(site)

                self.__sessions_client.update_session_user(None, bottle.request.session_id, user)

            return self._send_result(site)
        except Exception as err:
            self._send_error(err)
    def open_session(
        self,
        account: AccountV1,
        roles: List[str],
    ):
        try:
            session: SessionV1 = None
            sites: List[SiteV1] = None
            passwordInfo: UserPasswordInfoV1 = None
            settings: ConfigParams = None

            # Retrieve sites for user

            site_roles = [] if not roles else list(
                filter(lambda x: x.find(':') > 0, roles))
            site_ids = [] if not site_roles else list(
                map(lambda x: x[0:x.find(':')]
                    if x.find(':') >= 0 else x, site_roles))

            if len(site_ids) > 0:
                filter_params = FilterParams.from_tuples('ids', site_ids)
                page = self.__sites_client.get_sites(None, filter_params, None)
                sites = [] if page is None else page.data
            else:
                sites = []

            password_info = self.__passwords_client.get_password_info(
                None, account.id)

            settings = self.__settings_client.get_section_by_id(
                None, account.id)

            # Open a new user session
            user = SessionUserV1(
                id=account.id,
                name=account.name,
                login=account.login,
                create_time=account.create_time,
                time_zone=account.time_zone,
                language=account.language,
                theme=account.theme,
                roles=roles,
                sites=list(map(lambda x: {
                    'id': x.id,
                    'name': x.name
                }, sites)),
                settings=settings,
                change_pwd_time=None
                if password_info is None else password_info.change_time,
                custom_hdr=account.custom_hdr,
                custom_dat=account.custom_dat)

            address = HttpRequestDetector.detect_address(bottle.request)
            client = HttpRequestDetector.detect_browser(bottle.request)
            platform = HttpRequestDetector.detect_platform(bottle.request)

            session = self.__sessions_client.open_session(
                None, account.id, account.name, address, client, user, None)
            return JsonConverter.to_json(session)
        except Exception as err:
            return self._send_error(err)
    def test_should_perform_site_operations(self):
        site1: SiteV1 = SiteV1()
        site2: SiteV1 = SiteV1()

        # Create one site
        response = self.rest.post_as_user(TestUsers.AdminUserSessionId,
                                          '/api/v1/sites',
                                          JsonConverter.to_json(SITE1))
        site = JsonConverter.from_json(TypeCode.Map, response.content)

        assert site['name'] == SITE1.name
        assert site['description'] == SITE1.description

        site1 = SiteV1(**site)

        # Create another site
        response = self.rest.post_as_user(TestUsers.AdminUserSessionId,
                                          '/api/v1/sites',
                                          JsonConverter.to_json(SITE2))

        site = JsonConverter.from_json(TypeCode.Map, response.content)

        assert site['name'] == SITE2.name
        assert site['description'] == SITE2.description

        site2 = SiteV1(**site)

        # Get all sites
        response = self.rest.get_as_user(TestUsers.AdminUserSessionId,
                                         '/api/v1/sites')
        page = JsonConverter.from_json(TypeCode.Map, response.content)

        # Account for 1 test site
        assert len(page['data'])

        # Find site by code
        response = self.rest.get('/api/v1/sites/find_by_code?code=' +
                                 site1.code)
        site = JsonConverter.from_json(TypeCode.Map, response.content)

        assert site['id'] == site1.id

        # Validate site code
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/validate_code?code=' + site1.code,
            {},
        )

        assert response.content.decode('utf-8').replace('"', '') == site1.id

        # Generate code
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/' + site1.id + '/generate_code',
            {},
        )

        assert len(response.content.decode('utf-8')) > 0

        # Update the site
        site1.description = 'Updated Content 1'
        site1.center = {'type': 'Point', 'coordinates': [32, -110]}
        site1.radius = 5

        response = self.rest.put_as_user(TestUsers.AdminUserSessionId,
                                         '/api/v1/sites/' + site1.id,
                                         JsonConverter.to_json(site1))
        site = JsonConverter.from_json(TypeCode.Map, response.content)

        assert site['description'] == 'Updated Content 1'
        assert site['name'] == site1.name
        assert site['radius'] == 5
        assert site['center'] == {'type': 'Point', 'coordinates': [32, -110]}

        # Delete site
        response = self.rest.delete_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v1/sites/' + site1.id,
        )
        site = JsonConverter.from_json(TypeCode.Map, response.content)
        assert site['deleted'] is True

        # Try to get delete site
        response = self.rest.get_as_user(TestUsers.AdminUserSessionId,
                                         '/api/v1/sites/' + site1.id)

        site = JsonConverter.from_json(TypeCode.Map, response.content)

        assert site['deleted'] is True
Пример #25
0
    def notify_invitation(self, site_id):
        json_data = bottle.request.json if isinstance(bottle.request.json, dict) else JsonConverter.from_json(
            TypeCode.Map, bottle.request.json)

        invitation = InvitationV1(**json_data)
        user = {} if not hasattr(bottle.request, 'user') else bottle.request.user

        invitation.create_time = datetime.datetime.now()
        invitation.creator_id = getattr(user, 'id', None)
        invitation.creator_name = getattr(user, 'name', None)

        result = self.__invitations_client.notify_invitation(None, invitation)
        return self._send_empty_result(result)
    def test_beacons_operations(self):
        # Create one beacon
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v2/sites/' + BEACON1.site_id + '/xbeacons',
            JsonConverter.to_json(BEACON1))

        created_beacon = JsonConverter.from_json(TypeCode.Map,
                                                 response.content)
        beacon1 = created_beacon

        assert response.status_code < 300
        assert BEACON1.udi == created_beacon['udi']
        assert BEACON1.id == created_beacon['id']
        assert BEACON1.site_id == created_beacon['site_id']
        assert created_beacon['center'] is not None

        # Create the second beacon
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v2/sites/' + BEACON2.site_id + '/xbeacons',
            JsonConverter.to_json(BEACON2))
        assert response.status_code < 300

        created_beacon = JsonConverter.from_json(TypeCode.Map,
                                                 response.content)
        assert BEACON2.udi == created_beacon['udi']
        assert BEACON2.id == created_beacon['id']
        assert BEACON2.site_id == created_beacon['site_id']
        assert created_beacon['center'] is not None

        # Create yet another beacon
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v2/sites/' + BEACON3.site_id + '/xbeacons',
            JsonConverter.to_json(BEACON3))
        assert response.status_code < 300

        created_beacon = JsonConverter.from_json(TypeCode.Map,
                                                 response.content)
        assert BEACON3.udi == created_beacon['udi']
        assert BEACON3.id == created_beacon['id']
        assert BEACON3.site_id == created_beacon['site_id']
        assert created_beacon['center'] is not None

        # Get all beacons
        response = self.rest.get_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v2/sites/' + BEACON1.site_id + '/xbeacons',
        )
        beacons = JsonConverter.from_json(TypeCode.Map, response.content)
        assert len(beacons['data']) == 2

        # Calculate position for one beacon
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId, '/api/v2/sites/' + BEACON1.site_id +
            '/xbeacons/calculate_position', {
                'site_id': BEACON1.site_id,
                'udis': [BEACON1.udi]
            })

        calc_position = JsonConverter.from_json(TypeCode.Map, response.content)

        assert response.status_code < 300
        assert calc_position['type'] == 'Point'
        assert len(calc_position['coordinates']) == 2

        # Validate beacon udi
        response = self.rest.post_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v2/sites/' + beacon1['site_id'] +
            '/xbeacons/validate_udi?udi=' + beacon1['udi'],
            {},
        )
        assert JsonConverter.from_json(TypeCode.Map,
                                       response.content)['id'] == beacon1['id']

        # Update the beacon
        BEACON1.label = 'ABC'
        response = self.rest.put_as_user(
            TestUsers.AdminUserSessionId, '/api/v2/sites/' +
            beacon1['site_id'] + '/xbeacons/' + beacon1['id'],
            JsonConverter.to_json(BEACON1))

        updated_beacon = JsonConverter.from_json(TypeCode.Map,
                                                 response.content)
        beacon1 = updated_beacon

        assert response.status_code < 300
        assert BEACON1.id == updated_beacon['id']
        assert updated_beacon['label'] == 'ABC'

        # Delete the beacon
        response = self.rest.delete_as_user(
            TestUsers.AdminUserSessionId, '/api/v2/sites/' +
            beacon1['site_id'] + '/xbeacons/' + beacon1['id'])
        deleted_result = JsonConverter.from_json(TypeCode.Map,
                                                 response.content)
        assert deleted_result['id'] == BEACON1.id

        # Try to get deleted beacon
        response = self.rest.get_as_user(
            TestUsers.AdminUserSessionId,
            '/api/v2/sites/' + beacon1['site_id'] + '/xbeacons/' +
            beacon1['id'],
        )
        assert response.status_code == 204