diff --git a/scm-ui/src/createReduxStore.js b/scm-ui/src/createReduxStore.js index 55e0d3f514..8956da22ae 100644 --- a/scm-ui/src/createReduxStore.js +++ b/scm-ui/src/createReduxStore.js @@ -11,6 +11,7 @@ import groups from "./groups/modules/groups"; import auth from "./modules/auth"; import pending from "./modules/pending"; import failure from "./modules/failure"; +import permissions from "./permissions/modules/permissions"; import type { BrowserHistory } from "history/createBrowserHistory"; @@ -25,6 +26,7 @@ function createReduxStore(history: BrowserHistory) { users, repos, repositoryTypes, + permissions, groups, auth }); diff --git a/scm-ui/src/permissions/containers/Permissions.js b/scm-ui/src/permissions/containers/Permissions.js index 8e2ffe7d04..48b7aa5990 100644 --- a/scm-ui/src/permissions/containers/Permissions.js +++ b/scm-ui/src/permissions/containers/Permissions.js @@ -1,13 +1,46 @@ //@flow import React from "react"; -import type { History } from "history"; +import connect from "react-redux/es/connect/connect"; +import { translate } from "react-i18next"; +import { fetchPermissions } from "../modules/permissions"; -type Props = {}; +type Props = { + namespace: string, + name: string, + + //dispatch functions + fetchPermissions: (namespace: string, name: string) => void +}; class Permissions extends React.Component { + componentDidMount() { + const { fetchPermissions, namespace, name } = this.props; + + fetchPermissions(namespace, name); + } + render() { return
Permissions will be shown here!
; } } -export default Permissions; +const mapStateToProps = (state, ownProps) => { + // const { namespace, name } = ownProps.match.params; + return { + //namespace, + //name + }; +}; + +const mapDispatchToProps = dispatch => { + return { + fetchPermissions: (namespace: string, name: string) => { + dispatch(fetchPermissions(namespace, name)); + } + }; +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(translate("repos")(Permissions)); diff --git a/scm-ui/src/permissions/modules/permissions.js b/scm-ui/src/permissions/modules/permissions.js index 2dec35b075..84de9df95c 100644 --- a/scm-ui/src/permissions/modules/permissions.js +++ b/scm-ui/src/permissions/modules/permissions.js @@ -2,7 +2,9 @@ import { apiClient } from "../../apiclient"; import * as types from "../../modules/types"; import type { Action } from "../../types/Action"; -import type { Permission, Permissions } from "../types/Permissions"; +import type { Permissions } from "../types/Permissions"; +import { isPending } from "../../modules/pending"; +import { getFailure } from "../../modules/failure"; export const FETCH_PERMISSIONS = "scm/repos/FETCH_PERMISSIONS"; export const FETCH_PERMISSIONS_PENDING = `${FETCH_PERMISSIONS}_${ @@ -88,8 +90,32 @@ export default function reducer( switch (action.type) { case FETCH_PERMISSIONS_SUCCESS: - return state; + return { + ...state, + [action.itemId]: action.payload + }; default: return state; } } + +// selectors + +export function getPermissionsOfRepo( + state: Object, + namespace: string, + name: string +) { + if (state.permissions && state.permissions[namespace + "/" + name]) { + const permissions = state.permissions[namespace + "/" + name]; + return permissions; + } +} + +export function isFetchPermissionsPending(state: Object) { + return isPending(state, FETCH_PERMISSIONS); +} + +export function getFetchPermissionsFailure(state: Object) { + return getFailure(state, FETCH_PERMISSIONS); +} diff --git a/scm-ui/src/permissions/modules/permissions.test.js b/scm-ui/src/permissions/modules/permissions.test.js index 1221837995..22a2a43249 100644 --- a/scm-ui/src/permissions/modules/permissions.test.js +++ b/scm-ui/src/permissions/modules/permissions.test.js @@ -5,33 +5,60 @@ import fetchMock from "fetch-mock"; import reducer, { fetchPermissions, fetchPermissionsSuccess, + getPermissionsOfRepo, + isFetchPermissionsPending, + getFetchPermissionsFailure, + FETCH_PERMISSIONS, FETCH_PERMISSIONS_PENDING, FETCH_PERMISSIONS_SUCCESS, FETCH_PERMISSIONS_FAILURE } from "./permissions"; import type { Permission, Permissions } from "../types/Permissions"; -const s_bPermission_user_eins: Permission = { +const hitchhiker_puzzle42Permission_user_eins: Permission = { name: "user_eins", type: "READ", groupPermission: true, _links: { self: { href: - "http://localhost:8081/scm/api/rest/v2/repositories/s/b/permissions/user_eins" + "http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_eins" }, delete: { href: - "http://localhost:8081/scm/api/rest/v2/repositories/s/b/permissions/user_eins" + "http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_eins" }, update: { href: - "http://localhost:8081/scm/api/rest/v2/repositories/s/b/permissions/user_eins" + "http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_eins" } } }; -const s_bPermissions: Permissions = [s_bPermission_user_eins]; +const hitchhiker_puzzle42Permission_user_zwei: Permission = { + name: "user_zwei", + type: "WRITE", + groupPermission: true, + _links: { + self: { + href: + "http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_zwei" + }, + delete: { + href: + "http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_zwei" + }, + update: { + href: + "http://localhost:8081/scm/api/rest/v2/repositories/hitchhiker/puzzle42/permissions/user_zwei" + } + } +}; + +const hitchhiker_puzzle42Permissions: Permissions = [ + hitchhiker_puzzle42Permission_user_eins, + hitchhiker_puzzle42Permission_user_zwei +]; describe("permission fetch", () => { const REPOS_URL = "/scm/api/rest/v2/repositories"; @@ -42,47 +69,54 @@ describe("permission fetch", () => { fetchMock.restore(); }); - it("should successfully fetch permissions to repo s/b", () => { - fetchMock.getOnce(REPOS_URL + "/s/b/permissions", s_bPermissions); + it("should successfully fetch permissions to repo hitchhiker/puzzle42", () => { + fetchMock.getOnce( + REPOS_URL + "/hitchhiker/puzzle42/permissions", + hitchhiker_puzzle42Permissions + ); const expectedActions = [ { type: FETCH_PERMISSIONS_PENDING, payload: { - namespace: "s", - name: "b" + namespace: "hitchhiker", + name: "puzzle42" }, - itemId: "s/b" + itemId: "hitchhiker/puzzle42" }, { type: FETCH_PERMISSIONS_SUCCESS, - payload: s_bPermissions, - itemId: "s/b" + payload: hitchhiker_puzzle42Permissions, + itemId: "hitchhiker/puzzle42" } ]; const store = mockStore({}); - return store.dispatch(fetchPermissions("s", "b")).then(() => { - expect(store.getActions()).toEqual(expectedActions); - }); + return store + .dispatch(fetchPermissions("hitchhiker", "puzzle42")) + .then(() => { + expect(store.getActions()).toEqual(expectedActions); + }); }); it("should dispatch FETCH_PERMISSIONS_FAILURE, it the request fails", () => { - fetchMock.getOnce(REPOS_URL + "/s/b/permissions", { + fetchMock.getOnce(REPOS_URL + "/hitchhiker/puzzle42/permissions", { status: 500 }); const store = mockStore({}); - return store.dispatch(fetchPermissions("s", "b")).then(() => { - const actions = store.getActions(); - expect(actions[0].type).toEqual(FETCH_PERMISSIONS_PENDING); - expect(actions[1].type).toEqual(FETCH_PERMISSIONS_FAILURE); - expect(actions[1].payload).toBeDefined(); - }); + return store + .dispatch(fetchPermissions("hitchhiker", "puzzle42")) + .then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(FETCH_PERMISSIONS_PENDING); + expect(actions[1].type).toEqual(FETCH_PERMISSIONS_FAILURE); + expect(actions[1].payload).toBeDefined(); + }); }); }); -describe("repos reducer", () => { +describe("permissions reducer", () => { it("should return empty object, if state and action is undefined", () => { expect(reducer()).toEqual({}); }); @@ -100,7 +134,60 @@ describe("repos reducer", () => { it("should store the permissions on FETCH_PERMISSION_SUCCESS", () => { const newState = reducer( {}, - fetchPermissionsSuccess(s_bPermissions, "s", "b") + fetchPermissionsSuccess( + hitchhiker_puzzle42Permissions, + "hitchhiker", + "puzzle42" + ) + ); + + expect(newState["hitchhiker/puzzle42"]).toBe( + hitchhiker_puzzle42Permissions ); }); }); + +describe("permissions selectors", () => { + const error = new Error("something goes wrong"); + + it("should return the permissions of one repository", () => { + const state = { + permissions: { + "hitchhiker/puzzle42": hitchhiker_puzzle42Permissions + } + }; + + const repoPermissions = getPermissionsOfRepo( + state, + "hitchhiker", + "puzzle42" + ); + expect(repoPermissions).toEqual(hitchhiker_puzzle42Permissions); + }); + + it("should return true, when fetch permissions is pending", () => { + const state = { + pending: { + [FETCH_PERMISSIONS]: true + } + }; + expect(isFetchPermissionsPending(state)).toEqual(true); + }); + + it("should return false, when fetch permissions is not pending", () => { + expect(isFetchPermissionsPending({})).toEqual(false); + }); + + it("should return error when fetch permissions did fail", () => { + const state = { + failure: { + [FETCH_PERMISSIONS]: error + } + }; + expect(getFetchPermissionsFailure(state)).toEqual(error); + }); + + it("should return undefined when fetch permissions did not fail", () => { + expect(getFetchPermissionsFailure({})).toBe(undefined); + }); +}); diff --git a/scm-ui/src/repos/containers/RepositoryRoot.js b/scm-ui/src/repos/containers/RepositoryRoot.js index 05678794d9..bff19c2405 100644 --- a/scm-ui/src/repos/containers/RepositoryRoot.js +++ b/scm-ui/src/repos/containers/RepositoryRoot.js @@ -101,7 +101,7 @@ class RepositoryRoot extends React.Component { /> } + component={() => } />