I have a small plugin that I developed to freeze pull requests into repos. It is not used often, but when it is the company wanted a banner displayed on that repo, so there was no confusion. So I added a message here:
<web-panel name="Frozen Panel" key="repo-frozen-banner-panel" location="bitbucket.web.repository.banner" weight="2000">
The problem is it only shows up for Admins of Bitbucket or the Repo, which are the very people that normally apply the freeze repo in the first place, so they are not the intended audience, but rather anyone that can read or write to it is. What am I missing to show this banner to everyone?
atlassian-plugin.xml for this plugin:
<atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2">
<plugin-info>
<description>${project.description}</description>
<version>${project.version}</version>
<vendor name="${project.organization.name}" url="${project.organization.url}" />
<param name="plugin-icon">images/pluginIcon.png</param>
<param name="plugin-logo">images/pluginLogo.png</param>
</plugin-info>
<web-panel name="Frozen Panel" key="repo-frozen-banner-panel" location="bitbucket.web.repository.banner" weight="2000">
<condition class="com.tesi.bitbucket.freeze.repo.IsMergeCheckEnabledCondition">
<param name="mergeCheck">${atlassian.plugin.key}:freezeRepo</param>
</condition>
<resource name="view" type="static"><![CDATA[<div class="aui-message">
<p class="title">
<strong>REPO FROZEN</strong>
</p>
<p>An Administrator has currently FROZEN this repository.</p>
</div>]]>
</resource>
</web-panel>
<!-- add our i18n resource -->
<resource type="i18n" name="i18n" location="FreezeRepo"/>
<repository-merge-check key="freezeRepo" class="bean:FreezeRepo" name="Freeze Repo"/>
</atlassian-plugin>
If you need more of the code to figure it out, I can try to attach it, but I am not sure you will find it helpful.
We’d have to see what is in ${atlassian.plugin.key}:freezeRepo
.
This is the class being referred to if it helps.
public class IsMergeCheckEnabledCondition implements Condition {
public static final String MERGE_CHECK = "mergeCheck";
public static final String REPOSITORY = "repository";
RepositoryHookService repositoryHookService;
private String mergeCheckName;
@Autowired
public IsMergeCheckEnabledCondition(@ComponentImport RepositoryHookService repositoryHookService)
{
this.repositoryHookService = repositoryHookService;
}
@Override
public void init(Map<String, String> params)
{
mergeCheckName = params.get(MERGE_CHECK);
}
@Nonnull
@Override
public boolean shouldDisplay(Map<String, Object> context)
{
Repository repository = (Repository) context.get(REPOSITORY);
RepositoryScope repositoryScope = new RepositoryScope(repository);
RepositoryHook repositoryHook = repositoryHookService.getByKey(repositoryScope, mergeCheckName);
return repositoryHook.isEnabled();
}
}
Know that if the the mergecheck is Enabled that it always returns “True” So it is either on or off, and never has in-between states.
Also snippets from pom.xml
<modelVersion>4.0.0</modelVersion>
<groupId>com.tesi.bitbucket</groupId>
<artifactId>freeze-repo</artifactId>
<version>1.0.2</version>
…
<properties>
<bitbucket.data.version>5.16.2</bitbucket.data.version>
<bitbucket.version>5.16.2</bitbucket.version>
<amps.version>8.0.0</amps.version>
<!-- This key is used to keep the consistency between the key in atlassian-plugin.xml and the key to generate bundle. -->
<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
<atlassian.spring.scanner.version>2.1.3</atlassian.spring.scanner.version>
<commons.lang3.version>3.5</commons.lang3.version>
<gson.version>2.8.0</gson.version>
<javax.inject.version>1</javax.inject.version>
<jsr311.version>1.1.1</jsr311.version>
<junit.libversion>4.12</junit.libversion>
<plugin.testrunner.version>1.2.3</plugin.testrunner.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@MichaelSmith1,
RepositoryHookService.getByKey
can only be called by users with REPO_ADMIN
permission. Based on that, I suspect your shouldDisplay
will throw an AuthorisationException
when called for a normal user. (I’d expect that exception to be visible in the logs, but perhaps it’s not?) That exception probably prevents your banner from being rendered.
If you wrapped your getByKey
call in a SecurityService.withPermission(Permission.REPO_ADMIN, "Checking if frozen")
escalation to assert REPO_ADMIN
, then the call would succeed even when running for normal users. That may allow your banner to render as you’d expect.
Best regards,
Bryan Turner
Atlassian Bitbucket
2 Likes
This pointed me in the right direction, but still required me understanding quite a bit. After about 6 hours of fooling around I came up with this working code which is hard to do because understanding how to log is ridiculously hard.
public boolean shouldDisplay(Map<String, Object> context) {
Repository repository = (Repository) context.get(REPOSITORY);
RepositoryScope repositoryScope = new RepositoryScope(repository);
EscalatedSecurityContext escalatedSecurityContext = securityService.withPermission(Permission.REPO_ADMIN, "Checking if frozen");
boolean hookEnabled = false;
try {
RepositoryHook repositoryHook = escalatedSecurityContext.call(() -> {
RepositoryHook repositoryInternalHook = repositoryHookService.getByKey(repositoryScope, mergeCheckName);
return repositoryInternalHook;
});
hookEnabled = repositoryHook.isEnabled();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return hookEnabled;
}
I also had to add this to my pom.xml in properties area …
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
...
</properties>
As a side comment for logging this is my feelings on it …
Some good examples of Logback and how you can place it in a plugin without touching the server to get decent debug logs would be great. I spend 2 hours trying to just get logging to work. I even start with log4j because that is what I think JIRA or a different plugin uses but I guess not Bitbucket … Why can’t Atlassian use common things? Why are there not some simple code snippets that Atlassian can provide to start plugins.