Skip to content

Commit

Permalink
Merge pull request #975 from criske/issue943
Browse files Browse the repository at this point in the history
#943 Started Implementing BitBucket.
  • Loading branch information
amihaiemil authored Feb 6, 2021
2 parents 6a339f1 + 747783b commit 3ed3f65
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 0 deletions.
5 changes: 5 additions & 0 deletions self-api/src/main/java/com/selfxdsd/api/Provider.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,10 @@ private Names(){ }
* Gitlab provider.
*/
public static final String GITLAB = "gitlab";

/**
* Bitbucket provider.
*/
public static final String BITBUCKET = "bitbucket";
}
}
31 changes: 31 additions & 0 deletions self-core-impl/src/main/java/com/selfxdsd/core/AccessToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,35 @@ public String value() {
return "Bearer " + this.value;
}
}

/**
* A Bitbucket <a href="https://developer.atlassian.com/bitbucket/api/2/reference/meta/authentication#make-requests">access token</a>.
*
*/
class Bitbucket implements AccessToken {

/**
* Header value.
*/
private final String value;

/**
* Ctor.
*
* @param value Header value.
*/
public Bitbucket(final String value) {
this.value = value;
}

@Override
public String header() {
return "Authorization";
}

@Override
public String value() {
return "Bearer " + this.value;
}
}
}
148 changes: 148 additions & 0 deletions self-core-impl/src/main/java/com/selfxdsd/core/Bitbucket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/**
* Copyright (c) 2020-2021, Self XDSD Contributors
* All rights reserved.
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"),
* to read the Software only. Permission is hereby NOT GRANTED to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software.
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.selfxdsd.core;

import com.selfxdsd.api.*;
import com.selfxdsd.api.storage.Storage;

import java.net.URI;

/**
* Bitbucket as a Provider.
* @author criske
* @version $Id$
* @since 0.0.62
* @todo #943:60min Start scaffolding BitbucketRepo using the other providers
* as model.
* Documentation reference:
* https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories
* @todo #943:60min Start scaffolding BitbucketInvitations using the other
* providers as model.
* Warning: 2.0 API doesn't support yet invitations.Until then we will use 1.0,
* so make sure you're using https://api.bitbucket.org/1.0/invitations
* when you're constructing the URI.
* Documentation reference:
* https://support.atlassian.com/bitbucket-cloud/docs/invitations-resource/
* @todo #943:60min Start scaffolding BitbucketOrganizations using the other
* providers as model.
* Documentation reference:
* https://developer.atlassian.com/bitbucket/api/2/reference/resource/teams
*/
public final class Bitbucket implements Provider {

/**
* User.
*/
private final User user;

/**
* Bitbucket's URI.
*/
private final URI uri = URI.create("https://bitbucket.org/api/2.0");

/**
* Bitbucket's JSON Resources.
*/
private final JsonResources resources;

/**
* Storage where we might save some stuff.
*/
private final Storage storage;

/**
* Constructor.
* @param user Authenticated user.
* @param storage Storage where we might save some stuff.
*/
public Bitbucket(final User user, final Storage storage) {
this(user, storage, new JsonResources.JdkHttp());
}

/**
* Constructor.
* @param user Authenticated user.
* @param storage Storage where we might save some stuff.
* @param resources Bitbucket's JSON resources.
*/
public Bitbucket(
final User user, final Storage storage,
final JsonResources resources
) {
this(user, storage, resources, "");
}

/**
* Private ctor, it can only be used by the withToken(...) method
* to return an instance which has a token.
* @param user User.
* @param storage Self Storage
* @param resources Bitbucket's JSON Resources.
* @param accessToken Access token.
*/
private Bitbucket(
final User user,
final Storage storage,
final JsonResources resources,
final String accessToken
) {
this.user = user;
this.storage = storage;
if (accessToken == null || accessToken.isBlank()) {
this.resources = resources;
} else {
this.resources = resources
.authenticated(new AccessToken.Bitbucket(accessToken));
}
}

@Override
public String name() {
return Names.BITBUCKET;
}

@Override
public Repo repo(final String owner, final String name) {
throw new UnsupportedOperationException("Not implemented yet");
}

@Override
public Invitations invitations() {
throw new UnsupportedOperationException("Not implemented yet");
}

@Override
public Organizations organizations() {
throw new UnsupportedOperationException("Not implemented yet");
}

@Override
public Provider withToken(final String accessToken) {
return new Bitbucket(
new BaseSelf.Authenticated(this.user, accessToken),
this.storage,
this.resources,
accessToken
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,17 @@ public void representsGitlabAccessToken(){
MatcherAssert.assertThat(token.value(),
Matchers.equalTo("Bearer gitlab123"));
}

/**
* Bitbucket token representation.
*/
@Test
public void representsBitbucketAccessToken(){
final AccessToken token = new AccessToken
.Bitbucket("bitbucket123");
MatcherAssert.assertThat(token.header(),
Matchers.equalTo("Authorization"));
MatcherAssert.assertThat(token.value(),
Matchers.equalTo("Bearer bitbucket123"));
}
}
138 changes: 138 additions & 0 deletions self-core-impl/src/test/java/com/selfxdsd/core/BitbucketTestCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/**
* Copyright (c) 2020-2021, Self XDSD Contributors
* All rights reserved.
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"),
* to read the Software only. Permission is hereby NOT GRANTED to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software.
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.selfxdsd.core;

import com.selfxdsd.api.Provider;
import com.selfxdsd.api.User;
import com.selfxdsd.api.storage.Storage;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.mockito.Mockito;

/**
* Unit tests for {@link Bitbucket}.
*
* @author criske
* @version $Id$
* @since 0.0.62
*/
public final class BitbucketTestCase {

/**
* Bitbucket provider has a name.
*/
@Test
public void hasName() {
final Provider bitbucket = new Bitbucket(
Mockito.mock(User.class),
Mockito.mock(Storage.class),
Mockito.mock(JsonResources.class)
);
MatcherAssert.assertThat(
bitbucket.name(),
Matchers.is(Provider.Names.BITBUCKET)
);
}

/**
* Bitbucket provider returns one of its repositories.
*/
@Test(expected = UnsupportedOperationException.class)
public void returnsRepository() {
final Provider bitbucket = new Bitbucket(
Mockito.mock(User.class),
Mockito.mock(Storage.class)
);
bitbucket.repo("john", "test");
}

/**
* Bitbucket provider returns its invitations.
*/
@Test(expected = UnsupportedOperationException.class)
public void returnsInvitations() {
final Provider bitbucket = new Bitbucket(
Mockito.mock(User.class),
Mockito.mock(Storage.class)
);
bitbucket.invitations();
}

/**
* Bitbucket provider returns its organizations.
*/
@Test(expected = UnsupportedOperationException.class)
public void organizations() {
final Provider bitbucket = new Bitbucket(
Mockito.mock(User.class),
Mockito.mock(Storage.class)
);
bitbucket.organizations();
}

/**
* Bitbucket provider can be created with access token.
*/
@Test
public void createsProviderWithToken() {
final JsonResources resources = Mockito.mock(JsonResources.class);
new Bitbucket(
Mockito.mock(User.class),
Mockito.mock(Storage.class),
resources
).withToken("bitbucket123");
Mockito.verify(resources, Mockito.times(1))
.authenticated(Mockito.any(AccessToken.Bitbucket.class));
}

/**
* Bitbucket provider is created without access token when token is null.
*/
@Test
public void createsProviderWithoutTokenWhenTokenNull() {
final JsonResources resources = Mockito.mock(JsonResources.class);
new Bitbucket(
Mockito.mock(User.class),
Mockito.mock(Storage.class),
resources
).withToken(null);
Mockito.verify(resources, Mockito.never())
.authenticated(Mockito.any(AccessToken.Bitbucket.class));
}

/**
* Bitbucket provider is created without access token when token is blank.
*/
@Test
public void createsProviderWithoutTokenWhenTokenBlank() {
final JsonResources resources = Mockito.mock(JsonResources.class);
new Bitbucket(
Mockito.mock(User.class),
Mockito.mock(Storage.class),
resources
).withToken(" ");
Mockito.verify(resources, Mockito.never())
.authenticated(Mockito.any(AccessToken.Bitbucket.class));
}
}

0 comments on commit 3ed3f65

Please sign in to comment.