Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ charset = utf-8
[*.properties]
charset = latin1

[*.{yaml, yml}]
[*.{ts, tsx, js, jsx, json, yaml, yml, babelrc}]
indent_size = 2
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,13 @@ com_crashlytics_export_strings.xml

# JMH benchmark reports
jmh-report.json

# Node.js modules
node_modules

# Webpack build output
src/main/webapp/js
npm-debug.log

# node binaries from frontend-maven-plugin
node/
Empty file added .mvn_exec_node
Empty file.
5,651 changes: 5,651 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "folder-auth-plugin",
"version": "1.0.0",
"description": "Jenkins Folder Auth plugin",
"private": true,
"main": "index.js",
"directories": {
"doc": "docs"
},
"scripts": {
"mvnbuild": "npm run build",
"build": "webpack --mode production",
"build:dev": "webpack --mode development --watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jenkinsci/folder-auth-plugin.git"
},
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/jenkinsci/folder-auth-plugin/issues"
},
"homepage": "https://github.com/jenkinsci/folder-auth-plugin#readme",
"dependencies": {
"bootstrap": "^4.5.0",
"react": "^16.13.1",
"react-bootstrap": "^1.0.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"@babel/core": "^7.9.6",
"@babel/preset-env": "^7.9.6",
"@babel/preset-react": "^7.9.4",
"@types/react": "^16.9.35",
"@types/react-bootstrap": "^1.0.1",
"@types/react-dom": "^16.9.8",
"babel-loader": "^8.1.0",
"css-loader": "^3.5.3",
"source-map-loader": "^0.2.4",
"style-loader": "^1.2.1",
"ts-loader": "^7.0.5",
"typescript": "^3.9.3",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
16 changes: 14 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>3.55</version>
<version>4.2</version>
<relativePath/>
</parent>

Expand All @@ -27,9 +27,11 @@
<properties>
<revision>1.3</revision>
<changelist>-SNAPSHOT</changelist>
<jenkins.version>2.164.1</jenkins.version>
<jenkins.version>2.235</jenkins.version>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also needs a version bump to at least 2.235

<java.level>8</java.level>
<configuration-as-code.version>1.35</configuration-as-code.version>
<node.version>12.16.3</node.version>
<npm.version>6.14.5</npm.version>
</properties>

<repositories>
Expand Down Expand Up @@ -82,4 +84,14 @@
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.10.0</version>
</plugin>
</plugins>
</build>
</project>
50 changes: 50 additions & 0 deletions src/main/frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from 'react';
import {FunctionComponent, useEffect, useState} from 'react';
import Tab from 'react-bootstrap/Tab';
import Tabs from 'react-bootstrap/Tabs';

import RoleType from './model/RoleType';

import './css/App.css';
import 'bootstrap/dist/css/bootstrap.min.css';

// @ts-ignore
const rootUrl = rootURL;
// @ts-ignore
const csrfCrumb = crumb.value;


const App: FunctionComponent = () => {
const [authorizationStrategy, setAuthorizationStrategy] = useState(null);

useEffect(() => {
(async () => {
const request = await fetch(`${rootUrl}/folder-auth/authorizationStrategy`, {
headers: {
'Jenkins-Crumb': csrfCrumb,
},
});
const data = await request.json();
setAuthorizationStrategy(data);
})().catch(err => {
throw new Error(`Unable to load authorization strategy: ${err}`);
});
});

return (
<Tabs defaultActiveKey={RoleType.GLOBAL} id='role-type-tabs' variant='tabs'>
<Tab eventKey={RoleType.GLOBAL} title='Global Roles' tabClassName='tab'>
Hello world - Global Roles
</Tab>
<Tab eventKey={RoleType.FOLDER} title='Folder Roles' tabClassName='tab'>
Hello world - Folder Roles <br/>
{authorizationStrategy && JSON.stringify(authorizationStrategy)}
</Tab>
<Tab eventKey={RoleType.AGENT} title='Agent Roles' tabClassName='tab'>
Hello world - Agent Roles
</Tab>
</Tabs>
);
}

export default App;
5 changes: 5 additions & 0 deletions src/main/frontend/src/css/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
a.tab:link,
a.tab:visited {
color: #007bff;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hack to unset global a:link and a:visited.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's a known PITA, I want to fix that

text-decoration: none !important;
}
9 changes: 9 additions & 0 deletions src/main/frontend/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';

import App from './App';
import { resetEnvironment } from './resetEnvironment';

resetEnvironment();
const root = document.getElementById('root');
ReactDOM.render(<App/>, root);
7 changes: 7 additions & 0 deletions src/main/frontend/src/model/RoleType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
enum RoleType {
GLOBAL,
FOLDER,
AGENT,
}

export default RoleType;
1 change: 1 addition & 0 deletions src/main/frontend/src/resetEnvironment.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function resetEnvironment(): void;
14 changes: 14 additions & 0 deletions src/main/frontend/src/resetEnvironment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Reset JS environment set up by prototype.js to not interfere with
* our react components.
*
* @see https://github.com/jenkinsci/jenkins/blob/75468da366c1d257a51655dcbe952d55b8aeeb9c/war/src/main/js/util/jenkins.js#L22
*/
export function resetEnvironment() {
if (Array.prototype.toJSON) {
delete Array.prototype.toJSON;
delete Object.prototype.toJSON;
delete Hash.prototype.toJSON;
delete String.prototype.toJSON;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import hudson.security.Permission;
import hudson.security.PermissionGroup;
import io.jenkins.plugins.folderauth.misc.AgentRoleCreationRequest;
import io.jenkins.plugins.folderauth.misc.FolderBasedAuthorizationStrategyWrapper;
import io.jenkins.plugins.folderauth.misc.FolderRoleCreationRequest;
import io.jenkins.plugins.folderauth.misc.GlobalRoleCreationRequest;
import io.jenkins.plugins.folderauth.misc.PermissionWrapper;
Expand All @@ -25,6 +26,7 @@
import io.jenkins.plugins.folderauth.roles.GlobalRole;
import jenkins.model.Jenkins;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.QueryParameter;
Expand Down Expand Up @@ -430,4 +432,19 @@ public void doRemoveSidFromAgentRole(@QueryParameter(required = true) String rol
FolderAuthorizationStrategyAPI.removeSidFromAgentRole(sid, roleName);
redirect();
}

@GET
@Nonnull
@Restricted(NoExternalUse.class)
public JSONObject doAuthorizationStrategy() throws IllegalStateException {
Jenkins jenkins = Jenkins.get();
jenkins.checkPermission(Jenkins.ADMINISTER);
AuthorizationStrategy strategy = jenkins.getAuthorizationStrategy();
if (!(strategy instanceof FolderBasedAuthorizationStrategy)) {
throw new IllegalStateException("Folder Based Authorization Strategy is not active.");
}
FolderBasedAuthorizationStrategy folderStrategy = (FolderBasedAuthorizationStrategy) strategy;
return JSONObject.fromObject(new FolderBasedAuthorizationStrategyWrapper(folderStrategy.getGlobalRoles(),
folderStrategy.getFolderRoles(), folderStrategy.getAgentRoles()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.jenkins.plugins.folderauth.misc;

import io.jenkins.plugins.folderauth.roles.AgentRole;
import io.jenkins.plugins.folderauth.roles.FolderRole;
import io.jenkins.plugins.folderauth.roles.GlobalRole;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Set;

@ParametersAreNonnullByDefault
public class FolderBasedAuthorizationStrategyWrapper {
private final Set<GlobalRole> globalRoles;
private final Set<FolderRole> folderRoles;
private final Set<AgentRole> agentRoles;

public FolderBasedAuthorizationStrategyWrapper(Set<GlobalRole> globalRoles,
Set<FolderRole> folderRoles,
Set<AgentRole> agentRoles) {
this.globalRoles = globalRoles;
this.folderRoles = folderRoles;
this.agentRoles = agentRoles;
}

public Set<GlobalRole> getGlobalRoles() {
return globalRoles;
}

public Set<FolderRole> getFolderRoles() {
return folderRoles;
}

public Set<AgentRole> getAgentRoles() {
return agentRoles;
}
}
Loading