public void modify()

in interceptors/authz/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java [827:975]


    public void modify( ModifyOperationContext modifyContext ) throws LdapException
    {
        Dn dn = modifyContext.getDn();

        // Access the principal requesting the operation, and bypass checks if it is the admin
        Entry entry = modifyContext.getEntry();

        LdapPrincipal principal = modifyContext.getSession().getEffectivePrincipal();
        Dn principalDn = principal.getDn();

        // bypass authz code if we are disabled
        if ( !directoryService.isAccessControlEnabled() )
        {
            next( modifyContext );
            return;
        }

        List<Modification> mods = modifyContext.getModItems();

        // bypass authz code but manage caches if operation is performed by the admin
        if ( isPrincipalAnAdministrator( principalDn ) )
        {
            next( modifyContext );

            Entry modifiedEntry = modifyContext.getAlteredEntry();
            tupleCache.subentryModified( dn, mods, modifiedEntry );
            groupCache.groupModified( dn, mods, entry, schemaManager );

            return;
        }

        Set<String> userGroups = groupCache.getGroups( principalDn.getNormName() );
        Collection<ACITuple> tuples = new HashSet<>();
        addPerscriptiveAciTuples( modifyContext, tuples, dn, entry );
        addEntryAciTuples( tuples, entry );
        addSubentryAciTuples( modifyContext, tuples, dn, entry );

        AciContext entryAciContext = new AciContext( schemaManager, modifyContext );
        entryAciContext.setUserGroupNames( userGroups );
        entryAciContext.setUserDn( principalDn );
        entryAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
        entryAciContext.setEntryDn( dn );
        entryAciContext.setMicroOperations( Collections.singleton( MicroOperation.MODIFY ) );
        entryAciContext.setAciTuples( tuples );
        entryAciContext.setEntry( entry );

        engine.checkPermission( entryAciContext );

        Collection<MicroOperation> perms;
        Entry entryView = entry.clone();

        for ( Modification mod : mods )
        {
            Attribute attr = mod.getAttribute();

            switch ( mod.getOperation() )
            {
                case ADD_ATTRIBUTE:
                    perms = ADD_PERMS;

                    // If the attribute is being created with an initial value ...
                    if ( entry.get( attr.getId() ) == null )
                    {
                        AciContext attrAciContext = new AciContext( schemaManager, modifyContext );
                        attrAciContext.setUserGroupNames( userGroups );
                        attrAciContext.setUserDn( principalDn );
                        attrAciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                        attrAciContext.setEntryDn( dn );
                        attrAciContext.setAttributeType( attr.getAttributeType() );
                        attrAciContext.setMicroOperations( perms );
                        attrAciContext.setAciTuples( tuples );
                        attrAciContext.setEntry( entry );

                        // ... we also need to check if adding the attribute is permitted
                        engine.checkPermission( attrAciContext );
                    }

                    break;

                case REMOVE_ATTRIBUTE:
                    perms = REMOVE_PERMS;
                    Attribute entryAttr = entry.get( attr.getId() );

                    if ( ( entryAttr != null ) && ( entryAttr.size() == 1 ) )
                    {
                        // If there is only one value remaining in the attribute ...
                        // ... we also need to check if removing the attribute at all is permitted
                        AciContext aciContext = new AciContext( schemaManager, modifyContext );
                        aciContext.setUserGroupNames( userGroups );
                        aciContext.setUserDn( principalDn );
                        aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                        aciContext.setEntryDn( dn );
                        aciContext.setAttributeType( attr.getAttributeType() );
                        aciContext.setMicroOperations( perms );
                        aciContext.setAciTuples( tuples );
                        aciContext.setEntry( entry );

                        engine.checkPermission( aciContext );
                    }

                    break;

                case REPLACE_ATTRIBUTE:
                    perms = REPLACE_PERMS;
                    break;

                default:
                    throw new IllegalArgumentException( "Unexpected modify operation " + mod.getOperation() );
            }

            /**
             * Update the entry view as the current modification is applied to the original entry.
             * This is especially required for handling the MaxValueCount protected item. Number of
             * values for an attribute after a modification should be known in advance in order to
             * check permissions for MaxValueCount protected item. So during addition of the first
             * value of an attribute it can be rejected if the permission denied due the the
             * MaxValueCount protected item. This is not the perfect implementation as required by
             * the specification because the system should reject the addition exactly on the right
             * value of the attribute. However as we do not have that much granularity in our
             * implementation (we consider an Attribute Addition itself a Micro Operation,
             * not the individual Value Additions) we just handle this when the first value of an
             * attribute is being checked for relevant permissions below.
             */
            entryView = ServerEntryUtils.getTargetEntry( mod, entryView, schemaManager );

            for ( Value value : attr )
            {
                AciContext aciContext = new AciContext( schemaManager, modifyContext );
                aciContext.setUserGroupNames( userGroups );
                aciContext.setUserDn( principalDn );
                aciContext.setAuthenticationLevel( principal.getAuthenticationLevel() );
                aciContext.setEntryDn( dn );
                aciContext.setAttributeType( attr.getAttributeType() );
                aciContext.setAttrValue( value );
                aciContext.setMicroOperations( perms );
                aciContext.setAciTuples( tuples );
                aciContext.setEntry( entry );
                aciContext.setEntryView( entryView );

                engine.checkPermission( aciContext );
            }
        }

        next( modifyContext );

        Entry modifiedEntry = modifyContext.getAlteredEntry();
        tupleCache.subentryModified( dn, mods, modifiedEntry );
        groupCache.groupModified( dn, mods, entry, schemaManager );
    }