Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 12 additions & 0 deletions rdmo/projects/assets/js/common/utils/permissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// combine permission sets, granting a permission when it is true in any set
export const combinePermissions = (...permissionSets) => {
const effectivePermissions = {}

permissionSets.forEach((permissions) => {
Object.entries(permissions ?? {}).forEach(([key, value]) => {
effectivePermissions[key] = effectivePermissions[key] === true || value === true
})
})

return effectivePermissions
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useDispatch, useSelector } from 'react-redux'
import * as configActions from 'rdmo/core/assets/js/actions/configActions'

import { navigateDashboard, updateProjectTask } from '../../actions/projectActions'
import { usePermissions } from '../../hooks'
import { Tile } from '../helper'

import IssueDate from '../../../common/components/IssueDate'
Expand All @@ -17,7 +18,7 @@ const Dashboard = () => {
const dispatch = useDispatch()
const config = useSelector(state => state.config)
const settings = useSelector(state => state.settings)
const perms = useSelector(state => state.project.project.project.permissions) ?? {}
const perms = usePermissions()

const allIssues = useSelector((state) => state.project.project.tasks) ?? []
/* Show only issues that resolve */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import { useSelector } from 'react-redux'

import { usePermissions } from '../../hooks'

import CopyProject from './information/CopyProject'
import HierarchyTree from './information/HierarchyTree'
import ProjectDelete from './information/ProjectDelete'
Expand All @@ -9,7 +11,7 @@ import ProjectVisibilityForm from './information/ProjectVisibilityForm'

const Information = () => {
const { hierarchy, project } = useSelector((state) => state.project.project) ?? {}
const perms = project?.permissions ?? {}
const perms = usePermissions()

return (
<div className="project-information">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { useSelector } from 'react-redux'

import { useModal } from 'rdmo/core/assets/js/hooks'

import { usePermissions } from '../../hooks'

import IntegrationsDropdown from '../helper/IntegrationsDropdown'

import IntegrationDeleteModal from './integrations/IntegrationDeleteModal'
import IntegrationModal from './integrations/IntegrationModal'

const Integrations = () => {
const perms = useSelector((state) => state.project.project.project.permissions) ?? {}
const perms = usePermissions()
const providers = useSelector((state) => state.project.providers) ?? {}
const integrations = useSelector((state) => state.project.integrations) ?? []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import { isEmpty } from 'lodash'

import { useModal } from 'rdmo/core/assets/js/hooks'

import { usePermissions } from '../../hooks'

import MembershipInviteModal from './memberships/MembershipInviteModal'
import MembershipTable from './memberships/MembershipTable'

const Memberships = () => {
const { show: showInvite, open: openInvite, close: closeInvite } = useModal()

const { memberships, project } = useSelector((state) => state.project.project) ?? {}
const { memberships } = useSelector((state) => state.project.project) ?? {}
const { invites } = useSelector((state) => state.project)
const perms = project?.permissions ?? {}
const perms = usePermissions()

return (
<>
Expand Down
6 changes: 4 additions & 2 deletions rdmo/projects/assets/js/project/components/areas/Snapshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { useSelector } from 'react-redux'

import { useModal } from 'rdmo/core/assets/js/hooks'

import { usePermissions } from '../../hooks'

import SnapshotModal from './snapshots/SnapshotModal'
import SnapshotTable from './snapshots/SnapshotTable'

const Snapshots = () => {
const { show: showSnapshot, open: openSnapshot, close: closeSnapshot } = useModal()

const { snapshots, project } = useSelector((state) => state.project.project) ?? {}
const perms = project?.permissions ?? {}
const { snapshots } = useSelector((state) => state.project.project) ?? {}
const perms = usePermissions()

return (
<div className="project-snapshots">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Html from 'rdmo/core/assets/js/components/Html'

import { copyProject, createProject } from '../../../../projects/actions/projectsActions'
import { updateProject } from '../../../actions/projectActions'
import { useFieldErrors } from '../../../hooks/useFieldErrors'
import { useFieldErrors } from '../../../hooks'

import ProjectApi from '../../../api/ProjectApi'

Expand Down Expand Up @@ -265,7 +265,7 @@ const ProjectForm = ({
}

{
unavailableCatalog && project.permissions.can_change_project &&
unavailableCatalog && !disabled &&
<Html className="form-text mb-2" html={templates.project_view_no_catalog_info} />
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Modal } from 'rdmo/core/assets/js/components'
import Html from 'rdmo/core/assets/js/components/Html'

import { clearProjectErrors, deleteProjectIntegration } from '../../../actions/projectActions'
import { useFieldErrors } from '../../../hooks/useFieldErrors'
import { useFieldErrors } from '../../../hooks'

const IntegrationDeleteModal = ({ show, onClose, integration }) => {
const dispatch = useDispatch()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
createProjectIntegration,
updateProjectIntegration
} from '../../../actions/projectActions'
import { useFieldErrors } from '../../../hooks/useFieldErrors'
import { useFieldErrors } from '../../../hooks'

import IntegrationSecretField from './IntegrationSecretField'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Html from 'rdmo/core/assets/js/components/Html'
import Modal from 'rdmo/core/assets/js/components/Modal'

import { deleteProjectInvite, deleteProjectMember, leaveProject } from '../../../actions/projectActions'
import { useFieldErrors } from '../../../hooks/useFieldErrors'
import { useFieldErrors } from '../../../hooks'

const MembershipDeleteModal = ({
type, show, person, onClose, isAdminOrSiteManager = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ import { Modal, Tooltip } from 'rdmo/core/assets/js/components'
import Html from 'rdmo/core/assets/js/components/Html'

import { clearProjectErrors, createProjectMember, sendProjectInvite } from '../../../actions/projectActions'
import { useFieldErrors } from '../../../hooks/useFieldErrors'
import { useFieldErrors, usePermissions } from '../../../hooks'

const initialForm = { lookup: '', role: 'author' }

const MembershipInviteModal = ({ show, onClose }) => {
const dispatch = useDispatch()
const templates = useSelector((state) => state.templates)
const { project } = useSelector((state) => state.project.project) || {}
const errors = useFieldErrors()
const perms = project?.permissions || {}
const perms = usePermissions()
const roleOptions = useSelector((state) => state.roles?.roles) || []

const [formData, setFormData] = useState(initialForm)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import { useModal } from 'rdmo/core/assets/js/hooks'
import Select from 'rdmo/core/assets/js/components/Select'

import { updateProjectInvite, updateProjectMember } from '../../../actions/projectActions'
import { usePermissions } from '../../../hooks'

import MembershipDeleteModal from './MembershipDeleteModal'

const MembershipTable = ({ persons, type }) => {
const dispatch = useDispatch()
const currentUser = useSelector((state) => state.user.currentUser)
const { project } = useSelector((state) => state.project.project) || {}
const perms = project?.permissions || {}
const perms = usePermissions()
const roleOptions = useSelector((state) => state.roles?.roles) || []
const { show: showConfirm, open: openConfirm, close: closeConfirm } = useModal()
const [modalState, setModalState] = useState(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Html from 'rdmo/core/assets/js/components/Html'
import Modal from 'rdmo/core/assets/js/components/Modal'

import { deleteSnapshot } from '../../../actions/projectActions'
import { useFieldErrors } from '../../../hooks/useFieldErrors'
import { useFieldErrors } from '../../../hooks'

const SnapshotDeleteModal = ({ show, onClose, snapshot }) => {
const dispatch = useDispatch()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Input, Textarea } from 'rdmo/core/assets/js/components/forms'
import Html from 'rdmo/core/assets/js/components/Html'

import { clearProjectErrors, createSnapshot, updateSnapshot } from '../../../actions/projectActions'
import { useFieldErrors } from '../../../hooks/useFieldErrors'
import { useFieldErrors } from '../../../hooks'

const initialForm = { title: '', description: '' }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Html from 'rdmo/core/assets/js/components/Html'
import Modal from 'rdmo/core/assets/js/components/Modal'

import { rollbackSnapshot } from '../../../actions/projectActions'
import { useFieldErrors } from '../../../hooks/useFieldErrors'
import { useFieldErrors } from '../../../hooks'

const SnapshotRollbackModal = ({ show, onClose, snapshot }) => {
const dispatch = useDispatch()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { useDispatch, useSelector } from 'react-redux'
import { useDispatch } from 'react-redux'

import { Link } from 'rdmo/core/assets/js/components'
import { useModal } from 'rdmo/core/assets/js/hooks'
import { formatDateTime } from 'rdmo/core/assets/js/utils/date'

import { navigateDashboard } from '../../../actions/projectActions'
import { usePermissions } from '../../../hooks'
import { buildPath } from '../../../utils/location'

import SnapshotDeleteModal from './SnapshotDeleteModal'
Expand All @@ -15,8 +16,7 @@ import SnapshotRollbackModal from './SnapshotRollbackModal'

const SnapshotTable = ({ snapshots, onCreate}) => {
const dispatch = useDispatch()
const { project } = useSelector((state) => state.project.project) || {}
const perms = project?.permissions || {}
const perms = usePermissions()

const updateModal = useModal()
const rollbackModal = useModal()
Expand Down
2 changes: 2 additions & 0 deletions rdmo/projects/assets/js/project/hooks/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { useFieldErrors } from './useFieldErrors'
export { usePermissions } from './usePermissions'
19 changes: 19 additions & 0 deletions rdmo/projects/assets/js/project/hooks/usePermissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useMemo } from 'react'
import { useSelector } from 'react-redux'

import { combinePermissions } from '../../common/utils/permissions'

// return the combined model-based permissions for the current user and object-based permissions for the current project
export const usePermissions = () => {
const projectPermissions = useSelector(
(state) => state.project.project?.project?.permissions
)
const userPermissions = useSelector(
(state) => state.user.currentUser?.permissions
)

return useMemo(
() => combinePermissions(projectPermissions, userPermissions),
[projectPermissions, userPermissions]
)
}
16 changes: 7 additions & 9 deletions rdmo/projects/assets/js/project/store/configureStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { checkStoreId } from 'rdmo/core/assets/js/utils/store'

import * as rolesActions from '../../common/actions/rolesActions'
import rolesReducer from '../../common/reducers/rolesReducer'
// import { getEffectivePermissions } from '../../common/utils/permissions'
import { combinePermissions } from '../../common/utils/permissions'
import * as projectActions from '../actions/projectActions'
import projectReducer from '../reducers/projectReducer'
import { parseLocation } from '../utils/location'
Expand Down Expand Up @@ -91,22 +91,20 @@ export default function configureStore() {
const project = state.project.project.project
const currentUser = state.user.currentUser

const permissions = project.permissions

// const permissions = getEffectivePermissions(
// project.permissions,
// currentUser.permissions
// )
const permissions = combinePermissions(
project.permissions,
currentUser.permissions
)

if (permissions.can_view_invite) {
store.dispatch(projectActions.fetchProjectInvites(projectId))
}

if (permissions.can_view_visibility) {
if (state.settings.multisite && currentUser.permissions.can_view_site) {
if (state.settings.multisite && permissions.can_view_site) {
store.dispatch(sitesActions.fetchSites())
}
if (state.settings.groups && currentUser.permissions.can_view_group) {
if (state.settings.groups && permissions.can_view_group) {
store.dispatch(groupsActions.fetchGroups())
}
if (!isNil(project.visibility)) {
Expand Down
4 changes: 3 additions & 1 deletion rdmo/projects/assets/js/projects/components/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useModal, useScrollToTop } from 'rdmo/core/assets/js/hooks'
import { formatDateTime } from 'rdmo/core/assets/js/utils/date'
import { baseUrl } from 'rdmo/core/assets/js/utils/meta'

import { combinePermissions } from '../../common/utils/permissions'
import * as projectsActions from '../actions/projectsActions'
import { HEADER_FORMATTERS, SORTABLE_COLUMNS } from '../utils'

Expand Down Expand Up @@ -39,6 +40,7 @@ const Main = () => {
if (!projectsObject.ready) return null
const { allowedTypes, catalogs, importUrls, invites, projects, projectsCount, hasNext } = projectsObject
const { currentUser } = currentUserObject
const userPerms = currentUser.permissions ?? {}
const { myProjects } = config

const invitationsModalProps = {
Expand Down Expand Up @@ -266,7 +268,7 @@ const Main = () => {
created: content => formatDateTime(content, 'long'),
last_changed: content => formatDateTime(content, 'long'),
actions: (_content, row) => {
const perms = row.permissions || {}
const perms = combinePermissions(row.permissions, userPerms)
return (
<div className="d-flex align-items-center gap-1">
<Link
Expand Down
Loading