package org.rundeck.core.auth.access;

import com.dtolabs.rundeck.core.authorization.AuthContextProcessor;
import com.dtolabs.rundeck.core.authorization.AuthResource;
import com.dtolabs.rundeck.core.authorization.UserAndRolesAuthContext;
import lombok.Getter;
import org.rundeck.core.auth.app.RundeckAccess;

import javax.security.auth.Subject;

/**
 * Provides base implementation for authorized resource of specific type and ID
 *
 * @param <T>  resource type
 * @param <ID> ID type
 */
public abstract class BaseAuthorizingIdResource<T, ID>
        extends BaseAuthorizingResource<T>
        implements AuthorizingIdResource<T, ID>
{
    @Getter private final ID identifier;

    public BaseAuthorizingIdResource(
            final AuthContextProcessor rundeckAuthContextProcessor,
            final Subject subject,
            final NamedAuthProvider namedAuthActions,
            final ID identifier
    )
    {
        super(rundeckAuthContextProcessor, subject, namedAuthActions);
        this.identifier = identifier;
    }


    /**
     * @return project name for resource, or from ID, or null
     */
    protected abstract String getProject();


    @Override
    public UserAndRolesAuthContext getAuthContext() {
        return getAuthContext(getProject());
    }

    private UserAndRolesAuthContext projectAuthContext = null;

    public UserAndRolesAuthContext getAuthContext(String project) {
        if (null == projectAuthContext) {
            projectAuthContext =
                    getRundeckAuthContextProcessor().getAuthContextForSubjectAndProject(getSubject(), project);
        }
        return projectAuthContext;
    }

    @Override
    public boolean isAuthorized(final AuthActions actions) throws NotFound {
        T res = retrieve();
        if (res == null) {
            throw new NotFound(getResourceTypeName(), getResourceIdent());
        }

        String projectLevel = getProject();
        AuthResource authResource = getAuthResource(res);

        if (projectLevel == null || authResource.getContext() == AuthResource.Context.System) {
            return super.isAuthorized(actions);
        }


        UserAndRolesAuthContext authContext = getAuthContext(projectLevel);

        return getRundeckAuthContextProcessor().authorizeProjectResourceAny(
                authContext,
                authResource.getResourceMap(),
                actions.getActions(),
                projectLevel
        );
    }


    public T getDelete() throws UnauthorizedAccess, NotFound {
        return access(RundeckAccess.General.APP_DELETE);
    }

}

@@ -1151,16 +1151,177 @@
 ect();%0A%0A
+    /**%0A     * @return true if project value must be set, false otherwise%0A     */%0A    protected boolean isAuthContextWithProject() %7B%0A        return true;%0A    %7D%0A%0A
 %0A    @Ov
@@ -1469,23 +1469,22 @@
 Context 
-project
+loaded
 AuthCont
@@ -1584,23 +1584,22 @@
 null == 
-project
+loaded
 AuthCont
@@ -1617,23 +1617,72 @@
         
-project
+if (isAuthContextWithProject()) %7B%0A                loaded
 AuthCont
@@ -1687,16 +1687,20 @@
 ntext =%0A
+    
         
@@ -1815,32 +1815,175 @@
     
-%7D%0A        return project
+    %7D else %7B%0A                loadedAuthContext = getRundeckAuthContextProcessor().getAuthContextForSubject(getSubject());%0A            %7D%0A        %7D%0A        return loaded
 Auth

Allow subclass to use non-project auth context