io.jenkins.blueocean.service.embedded.rest.UserImplPermissionTest.java Source code

Java tutorial

Introduction

Here is the source code for io.jenkins.blueocean.service.embedded.rest.UserImplPermissionTest.java

Source

/*
 * The MIT License
 *
 * Copyright (c) 2017, CloudBees, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package io.jenkins.blueocean.service.embedded.rest;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.servlet.ServletException;

import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.apache.commons.lang.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.WebMethod;
import org.kohsuke.stapler.verb.DELETE;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.cloudbees.plugins.credentials.CredentialsProvider;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.Node;
import hudson.model.TopLevelItem;
import hudson.model.TopLevelItemDescriptor;
import hudson.model.User;
import hudson.security.ACL;
import hudson.security.AccessControlled;
import hudson.security.Permission;
import io.jenkins.blueocean.commons.ServiceException;
import io.jenkins.blueocean.rest.ApiHead;
import io.jenkins.blueocean.rest.factory.organization.AbstractOrganization;
import io.jenkins.blueocean.rest.hal.Link;
import io.jenkins.blueocean.rest.model.BluePipeline;
import io.jenkins.blueocean.rest.model.BluePipelineContainer;
import io.jenkins.blueocean.rest.model.BlueUser;
import io.jenkins.blueocean.rest.model.BlueUserContainer;
import io.jenkins.blueocean.rest.model.BlueUserPermission;
import jenkins.model.Jenkins;
import jenkins.model.ModifiableTopLevelItemGroup;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Jenkins.class, User.class })
public class UserImplPermissionTest {
    private TestOrganization testOrganization;
    private User user;
    private Authentication authentication;
    private Jenkins jenkins;

    @Before
    public void setup() throws IOException {
        testOrganization = new TestOrganization("org", "orgDisplayName");

        user = mock(User.class);
        when(user.getId()).thenReturn("some_user");
        authentication = new Authentication() {
            public String getName() {
                return "some_user";
            }

            public GrantedAuthority[] getAuthorities() {
                return null;
            }

            public Object getCredentials() {
                return null;
            }

            public Object getDetails() {
                return null;
            }

            public Object getPrincipal() {
                return null;
            }

            public boolean isAuthenticated() {
                return false;
            }

            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
            }
        };

        jenkins = mock(Jenkins.class);
        when(jenkins.getACL()).thenReturn(new ACL() {
            public boolean hasPermission(Authentication a, Permission permission) {
                return false;
            }
        });

        mockStatic(Jenkins.class);
        when(Jenkins.getAuthentication()).thenReturn(authentication);
        when(Jenkins.getInstance()).thenReturn(jenkins);

        try {
            // After Jenkins 2.77 hasPermission is no longer in Node.class and is not final so we need to mock it
            // prior to it is called as being final and mocking it will fail for the same reason.
            // TODO remove after core base line is >= 2.77
            Node.class.getDeclaredMethod("hasPermission", Permission.class);
        } catch (NoSuchMethodException e) {
            when(jenkins.hasPermission(Mockito.any())).thenAnswer(new Answer<Boolean>() {
                public Boolean answer(InvocationOnMock invocation) {
                    Permission permission = invocation.getArgumentAt(0, Permission.class);
                    Jenkins j = (Jenkins) invocation.getMock();
                    return j.getACL().hasPermission(permission);
                }
            });
        }

        mockStatic(User.class);
        when(User.get("some_user", false, Collections.EMPTY_MAP)).thenReturn(user);
    }

    /**
     * Tests that the permissions are checked against the organization base and not the Jenkins instance. In this case
     * Jenkins instance will always return false to permission request and the organization base true.
     */
    @Test
    public void useTestAgainstOrgBaseOnFolder() {
        UserImpl userImpl = new UserImpl(testOrganization, user, testOrganization);
        checkPermissions(userImpl.getPermission(), false, true);
    }

    /**
     * Tests against jenkins
     */
    @Test
    public void useTestAgainstJenkinsRoot() {
        OrganizationImpl baseOrg = new OrganizationImpl("jenkins", jenkins);
        UserImpl userImpl = new UserImpl(baseOrg, user, baseOrg);
        checkPermissions(userImpl.getPermission(), false, false);

        when(jenkins.getACL()).thenReturn(new ACL() {
            public boolean hasPermission(Authentication a, Permission permission) {
                return true;
            }
        });

        checkPermissions(userImpl.getPermission(), true, true);
    }

    private void checkPermissions(BlueUserPermission permission, boolean shouldBeAdmin,
            boolean shouldHaveOtherPermissions) {

        assertEquals("User permission does not match", permission.isAdministration(), shouldBeAdmin);

        Map<String, Boolean> permissions = permission.getPipelinePermission();
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(BluePipeline.CREATE_PERMISSION));
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(BluePipeline.READ_PERMISSION));
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(BluePipeline.START_PERMISSION));
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(BluePipeline.STOP_PERMISSION));
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(BluePipeline.CONFIGURE_PERMISSION));

        permissions = permission.getCredentialPermission();
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(CredentialsProvider.CREATE.name.toLowerCase()));
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(CredentialsProvider.VIEW.name.toLowerCase()));
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(CredentialsProvider.DELETE.name.toLowerCase()));
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(CredentialsProvider.UPDATE.name.toLowerCase()));
        assertEquals("User permission does not match", shouldHaveOtherPermissions,
                permissions.get(StringUtils.uncapitalize(CredentialsProvider.MANAGE_DOMAINS.name)));
    }

    public static class TestOrganization extends AbstractOrganization
            implements ModifiableTopLevelItemGroup, AccessControlled {
        private final String name;
        private final String displayName;

        private final UserContainerImpl users = new UserContainerImpl(this, this);

        public TestOrganization(@NonNull String name, @CheckForNull String displayName) {
            this.name = name;
            this.displayName = displayName != null ? displayName : name;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getDisplayName() {
            return displayName;
        }

        @Nonnull
        @Override
        public ModifiableTopLevelItemGroup getGroup() {
            return this;
        }

        @Override
        public BluePipelineContainer getPipelines() {
            return new PipelineContainerImpl(this, this, this);
        }

        @WebMethod(name = "")
        @DELETE
        public void delete() {
            throw new ServiceException.NotImplementedException("Not implemented yet");
        }

        @Override
        public BlueUserContainer getUsers() {
            return users;
        }

        @Override
        public BlueUser getUser() {
            User user = User.current();
            if (user == null) {
                throw new ServiceException.NotFoundException("No authenticated user found");
            }
            return new UserImpl(this, user, new UserContainerImpl(this, this));
        }

        @Override
        public Link getLink() {
            return ApiHead.INSTANCE().getLink().rel("organizations/" + getName());
        }

        @Override
        public TopLevelItem doCreateItem(StaplerRequest req, StaplerResponse rsp)
                throws IOException, ServletException {
            return null;
        }

        @Override
        public String getFullName() {
            return name;
        }

        @Override
        public String getFullDisplayName() {
            return name;
        }

        @Override
        public Collection<TopLevelItem> getItems() {
            return null;
        }

        @Override
        public String getUrl() {
            return null;
        }

        @Override
        public String getUrlChildPrefix() {
            return null;
        }

        @Override
        public TopLevelItem getItem(String name) throws AccessDeniedException {
            return null;
        }

        @Override
        public File getRootDirFor(TopLevelItem child) {
            return null;
        }

        @Override
        public void onRenamed(TopLevelItem item, String oldName, String newName) throws IOException {
        }

        @Override
        public void onDeleted(TopLevelItem item) throws IOException {
        }

        @Override
        public File getRootDir() {
            return null;
        }

        @Override
        public void save() throws IOException {
        }

        @Override
        public <T extends TopLevelItem> T copy(T src, String name) throws IOException {
            return null;
        }

        @Override
        public TopLevelItem createProjectFromXML(String name, InputStream xml) throws IOException {
            return null;
        }

        @Override
        public TopLevelItem createProject(TopLevelItemDescriptor type, String name, boolean notify)
                throws IOException {
            return null;
        }

        @Override
        public ACL getACL() {
            return null;
        }

        @Override
        public void checkPermission(Permission permission) throws AccessDeniedException {
        }

        @Override
        public boolean hasPermission(Permission permission) {
            return true;
        }
    }
}