def find_user_info_by_subject(self, subject=''):
     # Find UserCredentials
     objects, matches = self.clients.resource_registry.find_resources(
         RT.UserCredentials, None, subject, id_only=False)
     if not objects:
         raise NotFound("UserCredentials with subject %s does not exist" %
                        subject)
     if len(objects) > 1:
         raise Inconsistent(
             "Multiple UserCredentials with subject %s exist" % subject)
     user_credentials_id = objects[0]._id
     subjects, assocs = self.clients.resource_registry.find_subjects(
         RT.ActorIdentity, PRED.hasCredentials, user_credentials_id)
     if not subjects or len(subjects) == 0:
         raise NotFound(
             "ActorIdentity to UserCredentials association for subject %s does not exist"
             % subject)
     if len(subjects) > 1:
         raise Inconsistent(
             "Multiple ActorIdentity to UserCredentials associations for subject %s exist"
             % subject)
     actor_identity_id = subjects[0]._id
     # Look up UserInfo via association with ActorIdentity
     objects, assocs = self.clients.resource_registry.find_objects(
         actor_identity_id, PRED.hasInfo, RT.UserInfo)
     if not objects:
         raise NotFound("UserInfo for subject %s does not exist" % subject)
     if len(objects) > 1:
         raise Inconsistent("Multiple UserInfos for subject %s exist" %
                            subject)
     user_info = objects[0]
     return user_info
    def delete_user_info(self, user_info_id='', actor_identity_id=''):
        # Read UserInfo
        user_info = self.clients.resource_registry.read(user_info_id)
        if not user_info:
            raise NotFound("UserInfo %s does not exist" % user_info_id)
        # Find and break association with ActorIdentity
        if not actor_identity_id:
            subjects, assocs = self.clients.resource_registry.find_subjects(
                RT.ActorIdentity, PRED.hasInfo, user_info_id)
            if not assocs:
                raise NotFound(
                    "ActorIdentity to UserInfo association for user info id %s does not exist"
                    % user_info_id)
            actor_identity_id = subjects[0]._id

        assocs = self.clients.resource_registry.find_associations(
            actor_identity_id, PRED.hasInfo, user_info_id)
        if not assocs:
            raise NotFound(
                "ActorIdentity to UserInfo association for user info id %s does not exist"
                % user_info_id)
        association_id = assocs[0]._id

        self.clients.resource_registry.delete_association(association_id)
        # Delete the UserInfo
        self.clients.resource_registry.delete(user_info_id)
예제 #3
0
    def get_service_spec(self, service_name=None, spec_name=None):
        try:
            if not self._swagger_gen:
                raise NotFound("Spec not available")
            if spec_name != "swagger.json":
                raise NotFound("Unknown spec format")

            swagger_json = self._swagger_gen.get_spec(service_name)

            resp = flask.make_response(flask.jsonify(swagger_json))
            self._add_cors_headers(resp)
            return resp

        except Exception as ex:
            return self.gateway_error_response(ex)
    def undeclare_exchange_name(self, canonical_name='', exchange_space_id=''):
        """Remove an exhange name resource
        """
        exchange_space_obj = self._validate_resource_id("exchange_space_id", exchange_space_id, RT.ExchangeSpace,
                                                        optional=True)
        # TODO: currently we are using the exchange_name's id as the canonical name and exchange_space_id is unused?
        exchange_name = self.rr.read(canonical_name)
        if not exchange_name:
            raise NotFound("ExchangeName with id %s does not exist" % canonical_name)

        exchange_name_id = exchange_name._id        # yes, this should be same, but let's make it look cleaner

        # Get associated XS first
        exchange_space_list, assocs = self.rr.find_subjects(RT.ExchangeSpace, PRED.hasExchangeName, exchange_name_id)
        if len(exchange_space_list) != 1:
            log.warn("ExchangeName %s has no associated Exchange Space" % exchange_name_id)

        exchange_space = exchange_space_list[0] if exchange_space_list else None

        # Remove association between itself and XS
        for assoc in assocs:
            self.rr.delete_association(assoc._id)

        # Remove XN
        self.rr.delete(exchange_name_id)

        # Call container API
        if exchange_space:
            xs = self.container.ex_manager.create_xs(exchange_space.name, declare=False)
            xn = self.container.ex_manager._create_xn(exchange_name.xn_type, exchange_name.name, xs, declare=False)
            self.container.ex_manager.delete_xn(xn)
    def initiate_account_merge(self, merge_user_email=''):
        '''
        Initiate merging two accounts

        @throws BadRequest: A parameter is missing
        @throws NotFound: Merge user email address is not found
        @retval token_string: Token string that will be email to the user for verification
        '''
        if not merge_user_email:
            raise BadRequest(
                "initiate_account_merge: merge_user_email must be set")

        # Find UserInfo of the account that needs to be merged into
        merge_user_info = self.find_user_info_by_email(merge_user_email)
        if not merge_user_info:
            raise NotFound("initiate_account_merge: email address not found")
        # Validate current user and the merger user are two different accounts
        if self.find_user_info_by_id(
                self._get_current_user_id())._id == merge_user_info._id:
            raise BadRequest(
                "initiate_account_merge: current and merge accounts are the same"
            )
        token_str = self._generate_token()
        expire_time = calendar.timegm(
            (datetime.utcnow() +
             timedelta(days=2)).timetuple())  # Set token expire time
        token = SecurityToken(token_string=token_str,
                              expires=expire_time,
                              status="OPEN",
                              merge_email=merge_user_email)
        self._update_user_info_token(token)

        return token_str
예제 #6
0
    def cancel_member_enrollment(self, org_id="", actor_id=""):
        """Cancels the membership of a specific actor actor within the specified Org.
        Once canceled, the actor will no longer have access to the resource of that Org.
        """
        org_obj = self._validate_resource_id("org_id", org_id, RT.Org)
        actor_obj = self._validate_resource_id("actor_id", actor_id,
                                               RT.ActorIdentity)

        if org_obj.name == self._get_root_org_name():
            raise BadRequest(
                "A request to cancel enrollment in the root ION Org is not allowed"
            )

        # First remove all associations to any roles
        role_list = self.list_actor_roles(actor_id, org_id)
        for user_role in role_list:
            self._delete_role_association(org_obj, actor_obj, user_role)

        # Finally remove the association to the Org
        aid = self.rr.get_association(org_obj, PRED.hasMember, actor_obj)
        if not aid:
            raise NotFound(
                "The membership association between the specified actor and Org is not found"
            )

        self.rr.delete_association(aid)

        self.event_pub.publish_event(
            event_type=OT.OrgMembershipCancelledEvent,
            origin=org_id,
            origin_type="Org",
            description="The member has cancelled enrollment in the Org",
            actor_id=actor_id,
            org_name=org_obj.name)
    def test_read_user_info_not_found(self):
        self.mock_read.side_effect = NotFound("bad")

        # TEST: Execute the service operation call
        with self.assertRaises(NotFound) as cm:
            self.identity_management_service.read_user_info('bad')

        self.mock_read.assert_called_once_with('bad', '')
 def find_user_info_by_id(self, actor_id=''):
     # Look up UserInfo via association with ActorIdentity
     objects, assocs = self.clients.resource_registry.find_objects(
         actor_id, PRED.hasInfo, RT.UserInfo)
     if not objects:
         raise NotFound("UserInfo for user id %s does not exist" % actor_id)
     user_info = objects[0]
     return user_info
 def find_user_info_by_name(self, name=''):
     objects, matches = self.clients.resource_registry.find_resources(
         RT.UserInfo, None, name, id_only=False)
     if not objects:
         raise NotFound("UserInfo with name %s does not exist" % name)
     if len(objects) > 1:
         raise Inconsistent("Multiple UserInfo objects with name %s exist" %
                            name)
     return objects[0]
 def find_actor_identity_by_username(self, username=''):
     if not username:
         raise BadRequest("Invalid username")
     res_ids, _ = self.rr.find_resources_ext(alt_id_ns="UNAME",
                                             alt_id=username,
                                             id_only=True)
     if not res_ids:
         raise NotFound("No actor found with username")
     return res_ids[0]
예제 #11
0
    def query_view(self, view_id='', view_name='', ext_query=None, id_only=True, search_args=None):
        """Execute an existing query as defined within a View resource, providing additional arguments for
        parameterized values.
        If ext_query is provided, it will be combined with the query defined by the View.
        Search_args may contain parameterized values.
        Returns a list of resource or event objects or their IDs only.
        """
        if not view_id and not view_name:
            raise BadRequest("Must provide argument view_id or view_name")
        if view_id and view_name:
            raise BadRequest("Cannot provide both arguments view_id and view_name")
        if view_id:
            view_obj = self.clients.resource_registry.read(view_id)
        else:
            view_obj = self.ds_discovery.get_builtin_view(view_name)
            if not view_obj:
                view_objs, _ = self.clients.resource_registry.find_resources(restype=RT.View, name=view_name)
                if not view_objs:
                    raise NotFound("View with name '%s' not found" % view_name)
                view_obj = view_objs[0]

        if view_obj.type_ != RT.View:
            raise BadRequest("Argument view_id is not a View resource")
        view_query = view_obj.view_definition
        if not QUERY_EXP_KEY in view_query:
            raise BadRequest("Unknown View query format")

        # Get default query params and override them with provided args
        param_defaults = {param.name: param.default for param in view_obj.view_parameters}
        query_params = param_defaults
        if view_obj.param_values:
            query_params.update(view_obj.param_values)
        if search_args:
            query_params.update(search_args)

        # Merge ext_query into query
        if ext_query:
            if ext_query["where"] and view_query["where"]:
                view_query["where"] = [DQ.EXP_AND, [view_query["where"], ext_query["where"]]]
            else:
                view_query["where"] = view_query["where"] or ext_query["where"]
            if ext_query["order_by"]:
                # Override ordering if present
                view_query["where"] = ext_query["order_by"]

            # Other query settings
            view_qargs = view_query["query_args"]
            ext_qargs = ext_query["query_args"]
            view_qargs["id_only"] = ext_qargs.get("id_only", view_qargs["id_only"])
            view_qargs["limit"] = ext_qargs.get("limit", view_qargs["limit"])
            view_qargs["skip"] = ext_qargs.get("skip", view_qargs["skip"])

        return self._discovery_request(view_query, id_only=id_only,
                                       search_args=search_args, query_params=query_params)
 def delete_user_credential_association(self, user_credential_id,
                                        actor_identity_id):
     association_id = self.clients.resource_registry.find_associations(
         actor_identity_id,
         PRED.hasCredentials,
         user_credential_id,
         id_only=True)
     if not association_id:
         raise NotFound(
             "complete_account_merge: Association between UserCredentials and ActorIdentity not found. ActorIdentity ID %s, UserCredentials ID: %s "
             % actor_identity_id % user_credential_id)
     self.clients.resource_registry.delete_association(association_id[0])
    def check_actor_credentials(self, username='', password=''):
        if not username:
            raise BadRequest("Invalid argument username")
        if not password:
            raise BadRequest("Invalid argument password")

        actor_id = self.find_actor_identity_by_username(username)
        actor_obj = self.read_actor_identity(actor_id)
        try:
            if actor_obj.auth_status != AuthStatusEnum.ENABLED:
                raise NotFound("identity not enabled")

            cred_obj = None
            for cred in actor_obj.credentials:
                if cred.username == username:
                    cred_obj = cred
                    break

            if bcrypt.hashpw(password,
                             cred_obj.password_salt) != cred_obj.password_hash:
                # Failed login
                if password:  # Only record fail if password is non-empty and wrong
                    actor_obj.auth_fail_count += 1
                    actor_obj.auth_ts_last_fail = get_ion_ts()
                    max_fail_cnt = IdentityUtils.get_auth_fail_lock_count()
                    if actor_obj.auth_fail_count > max_fail_cnt:
                        actor_obj.auth_status = AuthStatusEnum.LOCKED

                raise NotFound("Invalid password")

            # Success
            actor_obj.auth_count += 1
            actor_obj.auth_fail_count = 0
            actor_obj.auth_ts_last = get_ion_ts()

            return actor_obj._id

        finally:
            # Lower level RR call to avoid credentials clearing
            self.rr.update(actor_obj)
예제 #14
0
    def _find_org_role(self, org_id="", role_name=""):
        if not org_id:
            raise BadRequest("The org_id argument is missing")
        if not role_name:
            raise BadRequest("The role_name argument is missing")

        # Iterating (vs. query) is just fine, because the number of org roles is sufficiently small
        org_roles = self._list_org_roles(org_id)
        for role in org_roles:
            if role.governance_name == role_name:
                return role

        raise NotFound("Role %s not found in Org id=%s" % (role_name, org_id))
 def find_actor_identity_by_name(self, name=''):
     """Return the ActorIdentity object whose name attribute matches the passed value.
     """
     objects, _ = self.rr.find_resources(RT.ActorIdentity,
                                         None,
                                         name,
                                         id_only=False)
     if not objects:
         raise NotFound("ActorIdentity with name %s does not exist" % name)
     if len(objects) > 1:
         raise Inconsistent(
             "Multiple ActorIdentity objects with name %s exist" % name)
     return objects[0]
 def unregister_user_credentials(self, actor_id='', credentials_name=''):
     # Read UserCredentials
     objects, matches = self.clients.resource_registry.find_resources(
         RT.UserCredentials, None, credentials_name, id_only=False)
     if not objects or len(objects) == 0:
         raise NotFound("UserCredentials %s does not exist" %
                        credentials_name)
     if len(objects) > 1:
         raise Conflict(
             "Multiple UserCredentials objects found for subject %s" %
             credentials_name)
     user_credentials_id = objects[0]._id
     # Find and break association with ActorIdentity
     assocs = self.clients.resource_registry.find_associations(
         actor_id, PRED.hasCredentials, user_credentials_id)
     if not assocs or len(assocs) == 0:
         raise NotFound(
             "ActorIdentity to UserCredentials association for user id %s to credential %s does not exist"
             % (actor_id, credentials_name))
     association_id = assocs[0]._id
     self.clients.resource_registry.delete_association(association_id)
     # Delete the UserCredentials
     self.clients.resource_registry.delete(user_credentials_id)
예제 #17
0
    def find_org(self, name=""):
        """Finds an Org object with the specified name. Defaults to the
        root ION object. Throws a NotFound exception if the object does not exist.
        """

        # Default to the root ION Org if not specified
        if not name:
            name = self._get_root_org_name()

        res_list, _ = self.rr.find_resources(restype=RT.Org,
                                             name=name,
                                             id_only=False)
        if not res_list:
            raise NotFound("The Org with name %s does not exist" % name)
        return res_list[0]
    def find_actor_identity_by_name(self, name=''):
        """Return the ActorIdentity object whose name attribute matches the passed value.

        @param name    str
        @retval user_info    ActorIdentity
        @throws NotFound    failed to find ActorIdentity
        @throws Inconsistent    Multiple ActorIdentity objects matched name
        """
        objects, matches = self.clients.resource_registry.find_resources(
            RT.ActorIdentity, None, name, id_only=False)
        if not objects:
            raise NotFound("ActorIdentity with name %s does not exist" % name)
        if len(objects) > 1:
            raise Inconsistent(
                "Multiple ActorIdentity objects with name %s exist" % name)
        return objects[0]
예제 #19
0
    def unaffiliate_org(self, org_id="", affiliate_org_id=""):
        """Removes an association between multiple Orgs as an affiliation.
        Throws a NotFound exception if neither id is found.
        """
        org_obj = self._validate_resource_id("org_id", org_id, RT.Org)
        affiliate_org_obj = self._validate_resource_id("affiliate_org_id",
                                                       affiliate_org_id,
                                                       RT.Org)

        aid = self.rr.get_association(org_obj, PRED.hasAffiliation,
                                      affiliate_org_obj)
        if not aid:
            raise NotFound(
                "The affiliation association between the specified Orgs is not found"
            )

        self.rr.delete_association(aid)
 def _validate_token_string(self, token_string, user_info):
     # Find the token from the  UserInfo
     token_obj = [
         token for token in user_info.tokens
         if token.token_string == token_string
     ]
     if not token_obj or not token_obj[0].merge_email or not token_obj[
             0].expires:
         raise NotFound("_validate_token: Token data not found")
     token_obj = token_obj[0]
     # Validate the expiration time and token status
     current_time = calendar.timegm((datetime.utcnow()).timetuple())
     if current_time > token_obj.expires or "OPEN" != token_obj.status:
         raise BadRequest(
             "_validate_token: access token expired or token status is invalid"
         )
     return token_obj
예제 #21
0
    def _delete_role_association(self, org, actor, user_role):
        aid = self.rr.get_association(actor, PRED.hasRole, user_role)
        if not aid:
            raise NotFound(
                "ActorIdentity %s to UserRole %s association not found" %
                (actor._id, user_role._id))

        self.rr.delete_association(aid)

        self.event_pub.publish_event(event_type=OT.UserRoleRevokedEvent,
                                     origin=org._id,
                                     origin_type="Org",
                                     sub_type=user_role.governance_name,
                                     description="Revoked the %s role" %
                                     user_role.name,
                                     actor_id=actor._id,
                                     role_name=user_role.governance_name,
                                     org_name=org.name)
예제 #22
0
    def __init__(self, resource_id, *args, **kwargs):
        """
        Resource agent client constructor.
        @param resource_id The ID this service represents.
        @param name Use this kwarg to set the target exchange name (= agent process id or service name)
        (service or process).
        """

        # Assert and set the resource ID.
        if not resource_id:
            raise BadRequest("resource_id must be set for an agent")
        self.resource_id = resource_id
        self.agent_process_id = None
        self.agent_dir_entry = None

        # Set the name, retrieve as proc ID if not set by user.
        if 'name' not in kwargs:
            self.agent_process_id = self._get_agent_process_id(
                self.resource_id, client_instance=self)
            if self.agent_process_id:
                log.debug("Use agent process %s for resource_id=%s" %
                          (self.agent_process_id, self.resource_id))
            else:
                log.debug("No agent process found for resource_id %s" %
                          self.resource_id)
                raise NotFound("No agent process found for resource_id %s" %
                               self.resource_id)
        else:
            self.agent_process_id = kwargs.pop("name")

        # transpose name -> to_name to make underlying layer happy
        #kwargs["to_name"] = self.agent_process_id
        kwargs["to_name"] = resource_id

        # HACK to allow use of this client without process
        if "process" not in kwargs:
            log.warn(
                "Using FakeProcess to allow agent client without process arg")
            kwargs["process"] = StreamingAgentClient.FakeAgentProcess()

        kwargs["declare_name"] = False

        # Superclass constructor.
        StreamingAgentProcessClient.__init__(self, *args, **kwargs)
    def unregister_credentials(self, actor_id='', credentials_name=''):
        actor_obj = self._validate_resource_id("actor_id", actor_id,
                                               RT.ActorIdentity)
        if not credentials_name:
            raise BadRequest("Invalid credentials_name")
        found_cred = -1
        for i, cred in enumerate(actor_obj.credentials):
            if cred.username == credentials_name:
                found_cred = i
                break
        if found_cred != -1:
            del actor_obj.credentials[found_cred]
        else:
            raise NotFound("Credentials not found")

        actor_obj.alt_ids.remove("UNAME:" + credentials_name)

        # Lower level RR call to avoid credentials clearing
        self.rr.update(actor_obj)
예제 #24
0
    def unshare_resource(self, org_id="", resource_id=""):
        """Unshare a resource with the specified Org. Once unshared, the resource will be
        removed from the directory of available resources within the Org.
        """
        org_obj = self._validate_resource_id("org_id", org_id, RT.Org)
        resource_obj = self._validate_resource_id("resource_id", resource_id)

        aid = self.rr.get_association(org_obj, PRED.hasResource, resource_obj)
        if not aid:
            raise NotFound("Association between Resource and Org not found")

        self.rr.delete_association(aid)

        self.event_pub.publish_event(
            event_type=OT.ResourceUnsharedEvent,
            origin=org_obj._id,
            origin_type="Org",
            sub_type=resource_obj.type_,
            description="The resource has been unshared in the Org",
            resource_id=resource_id,
            org_name=org_obj.name)
    def get_user_info_extension(self, user_info_id='', org_id=''):
        """Returns an UserInfoExtension object containing additional related information

        @param user_info_id    str
        @param org_id    str  - An optional org id that the user is interested in filtering against.
        @retval user_info    UserInfoExtension
        @throws BadRequest    A parameter is missing
        @throws NotFound    An object with the specified actor_id does not exist
        """
        if not user_info_id:
            raise BadRequest("The user_info_id parameter is empty")

        #THis is a hack to get the UI going. It would be preferable to get the actor id from the extended resource
        #container below, but their would need to be a guarantee of order of field processing in order
        #to ensure that the actor identity has been found BEFORE the negotiation methods are called - and probably
        #some elegant way to indicate the field and sub field; ie actor_identity._id
        actors, _ = self.clients.resource_registry.find_subjects(
            subject_type=RT.ActorIdentity,
            predicate=PRED.hasInfo,
            object=user_info_id,
            id_only=True)
        actor_id = actors[0] if len(actors) > 0 else ''

        extended_resource_handler = ExtendedResourceContainer(self)
        extended_user = extended_resource_handler.create_extended_resource_container(
            extended_resource_type=OT.UserInfoExtension,
            resource_id=user_info_id,
            computed_resource_type=OT.ComputedAttributes,
            user_id=user_info_id,
            org_id=org_id,
            actor_id=actor_id)

        #If the org_id is not provided then skip looking for Org related roles.
        if extended_user:
            #Did not setup a dependency to org_management service to avoid a potential circular bootstrap issue
            # since this method should never be called until the system is fully running
            try:
                org_client = OrgManagementServiceProcessClient(process=self)
                roles = org_client.find_all_roles_by_user(
                    extended_user.actor_identity._id)
                extended_user.roles = list()
                for org_name in roles:
                    for role in roles[org_name]:
                        flattened_role = copy.copy(role.__dict__)
                        del flattened_role[
                            'type_']  #Have to do this to appease the message validators for ION objects
                        flattened_role[
                            'org_name'] = org_name  #Nothing like forcing a value into the dict to appease the UI code
                        extended_user.roles.append(flattened_role)

            except Exception, e:
                raise NotFound(
                    'Could not retrieve UserRoles for User Info id: %s - %s' %
                    (user_info_id, e.message))

            #filter notification requests that are retired
            extended_user.subscriptions = [
                nr for nr in extended_user.subscriptions
                if nr.temporal_bounds.end_datetime == ''
            ]

            #filter owned resources that are retired
            nr_removed = []
            for rsrc in extended_user.owned_resources:
                #remove all the Notifications
                if rsrc.type_ != OT.NotificationRequest:
                    nr_removed.append(rsrc)
            extended_user.owned_resources = [
                rsrc for rsrc in nr_removed if rsrc.lcstate != 'DELETED'
            ]
            #now append the active NotificationRequests
            extended_user.owned_resources.extend(extended_user.subscriptions)
    def test_delete_actor_identity_not_found(self):
        self.mock_delete.side_effect = NotFound("bad")

        # TEST: Execute the service operation call
        with self.assertRaises(NotFound) as cm:
            self.identity_management_service.delete_actor_identity('bad')
    def complete_account_merge(self, token_string=""):
        '''
        Completes merging the two accounts after verifying the token string
        @throws BadRequest  A parameter is missing
        @throws NotFound  Merge data not found
        '''
        log.debug("complete_account_merge with token string: %s" %
                  token_string)
        if not token_string:
            raise BadRequest("complete_account_merge: token_str must be set")

        # Get current UserInfo
        current_user_id = self._get_current_user_id()
        current_user_info = self.find_user_info_by_id(current_user_id)

        # Find all the necessary data of the merge account
        token_obj = self._validate_token_string(token_string,
                                                current_user_info)
        merge_user_info_obj = self.find_user_info_by_email(
            token_obj.merge_email)  # Find UserInfo of the merge account
        merge_user_info_id = merge_user_info_obj._id
        subjects, associations = self.clients.resource_registry.find_subjects(
            RT.ActorIdentity, PRED.hasInfo,
            merge_user_info_id)  # Find ActorIdentity of the merge account
        if not associations:
            raise NotFound(
                "complete_account_merge: ActorIdentity and UserInfo association does not exist. UserInfo ID: %s"
                % merge_user_info_id)
        merge_actor_identity_id = subjects[0]._id

        # Find  UserCredentials of the merge account
        merge_user_credential_id, matches = self.clients.resource_registry.find_objects(
            merge_actor_identity_id,
            PRED.hasCredentials,
            RT.UserCredentials,
            id_only=True)
        if not merge_user_credential_id:
            raise NotFound(
                "complete_account_merge: UserCredentials and ActorIdentity association does not exist.ActorIdentity ID: %s"
                % merge_actor_identity_id)
        merge_user_credential_id = merge_user_credential_id[0]

        # Remove association bewteeen ActorIdentity and UserCreentials
        log.debug(
            "complete_account_merge: merge account data: merge_user_info_id: %s merge_user_credential_id:%s merge_actor_identity_id:%s"
            % (merge_user_info_id, merge_user_credential_id,
               merge_actor_identity_id))
        self.delete_user_credential_association(merge_user_credential_id,
                                                merge_actor_identity_id)

        # Remove the merge account ActorIdentity and merge UserInfo.
        self.delete_user_info(merge_user_info_id, merge_actor_identity_id)
        self.delete_actor_identity(merge_actor_identity_id)

        # Create association between the current user ActorIdentity and the merge user UserCredentials
        self.clients.resource_registry.create_association(
            current_user_id, PRED.hasCredentials, merge_user_credential_id)

        # Update the token status
        token_obj.status = "VERIFIED"
        self.update_user_info(current_user_info)
        log.debug(
            "complete_account_merge: account merge completed from %s to %s" %
            (merge_actor_identity_id, current_user_id))
        return True