diff --git a/api/src/affiliation/mutations/invite-user-to-org.js b/api/src/affiliation/mutations/invite-user-to-org.js index 407cb7e521..dd8f881d7c 100644 --- a/api/src/affiliation/mutations/invite-user-to-org.js +++ b/api/src/affiliation/mutations/invite-user-to-org.js @@ -155,6 +155,9 @@ able to sign-up and be assigned to that organization in one mutation.`, name: org.name, }, // name of resource being acted upon resourceType: 'user', // user, org, domain + updatedProperties: [ + { name: 'role', oldValue: '', newValue: requestedRole }, + ], }, }) diff --git a/api/src/affiliation/mutations/remove-user-from-org.js b/api/src/affiliation/mutations/remove-user-from-org.js index cd8bb89add..e40303c737 100644 --- a/api/src/affiliation/mutations/remove-user-from-org.js +++ b/api/src/affiliation/mutations/remove-user-from-org.js @@ -203,7 +203,7 @@ export const removeUserFromOrg = new mutationWithClientMutationId({ userName: user.userName, role: permission, }, - action: 'update', + action: 'remove', target: { resource: requestedUser.userName, organization: { diff --git a/api/src/audit-logs/objects/target-resource.js b/api/src/audit-logs/objects/target-resource.js index 8e8b176215..9d08b38504 100644 --- a/api/src/audit-logs/objects/target-resource.js +++ b/api/src/audit-logs/objects/target-resource.js @@ -56,7 +56,8 @@ export const targetResourceType = new GraphQLObjectType({ resolve: ({ oldValue }) => { if (Array.isArray(oldValue)) { return JSON.stringify(oldValue) - } else return oldValue + } + return oldValue }, }, newValue: { diff --git a/api/src/domain/mutations/create-domain.js b/api/src/domain/mutations/create-domain.js index aa5f90366e..d8a11b63af 100644 --- a/api/src/domain/mutations/create-domain.js +++ b/api/src/domain/mutations/create-domain.js @@ -299,6 +299,27 @@ export const createDomain = new mutationWithClientMutationId({ console.info( `User: ${userKey} successfully created ${returnDomain.domain} in org: ${org.slug}.`, ) + + const updatedProperties = [] + if ( + typeof insertDomain.selectors !== 'undefined' && + insertDomain.selectors.length > 0 + ) { + updatedProperties.push({ + name: 'selectors', + oldValue: [], + newValue: insertDomain.selectors, + }) + } + + if (typeof tags !== 'undefined' && tags.length > 0) { + updatedProperties.push({ + name: 'tags', + oldValue: [], + newValue: tags, + }) + } + await logActivity({ transaction, collections, diff --git a/api/src/domain/mutations/update-domain.js b/api/src/domain/mutations/update-domain.js index f613ca8b2c..abf0544908 100644 --- a/api/src/domain/mutations/update-domain.js +++ b/api/src/domain/mutations/update-domain.js @@ -185,7 +185,29 @@ export const updateDomain = new mutationWithClientMutationId({ throw new Error(i18n._(t`Unable to update domain. Please try again.`)) } + let claimCursor + let currentTags = '' if (tags) { + try { + claimCursor = await query` + WITH claims + FOR claim IN claims + FILTER claim._from == ${org._id} && claim._to == ${domain._id} + RETURN MERGE({ id: claim._key, _type: "claim" }, claim) + ` + } catch (err) { + console.error( + `Database error occurred when user: ${userKey} running loadDomainByKey: ${err}`, + ) + } + try { + currentTags = await claimCursor.next() + } catch (err) { + console.error( + `Cursor error occurred when user: ${userKey} running loadDomainByKey: ${err}`, + ) + } + try { await trx.step( async () => @@ -222,6 +244,7 @@ export const updateDomain = new mutationWithClientMutationId({ const returnDomain = await loadDomainByKey.load(domain._key) console.info(`User: ${userKey} successfully updated domain: ${domainId}.`) + const updatedProperties = [] if (domainToInsert.domain.toLowerCase() !== domain.domain.toLowerCase()) { updatedProperties.push({ @@ -230,37 +253,51 @@ export const updateDomain = new mutationWithClientMutationId({ newValue: domainToInsert.domain, }) } - if (typeof selectors !== 'undefined') { - if ( - JSON.stringify(domainToInsert.selectors) !== + if ( + typeof selectors !== 'undefined' && + JSON.stringify(domainToInsert.selectors) !== JSON.stringify(domain.selectors) - ) - updatedProperties.push({ - name: 'selectors', - oldValue: domain.selectors, - newValue: domainToInsert.selectors, - }) + ) { + updatedProperties.push({ + name: 'selectors', + oldValue: domain.selectors, + newValue: domainToInsert.selectors, + }) + } + + if ( + typeof tags !== 'undefined' && + JSON.stringify(currentTags.tags) !== JSON.stringify(tags) + ) { + updatedProperties.push({ + name: 'tags', + oldValue: currentTags.tags, + newValue: tags, + }) + } + + if (updatedProperties.length > 0) { + await logActivity({ + transaction, + collections, + query, + initiatedBy: { + id: user._key, + userName: user.userName, + role: permission, + }, + action: 'update', + target: { + resource: domain.domain, + organization: { + id: org._key, + name: org.name, + }, // name of resource being acted upon + resourceType: 'domain', // user, org, domain + updatedProperties, + }, + }) } - await logActivity({ - transaction, - collections, - query, - initiatedBy: { - id: user._key, - userName: user.userName, - role: permission, - }, - action: 'update', - target: { - resource: domain.domain, - organization: { - id: org._key, - name: org.name, - }, // name of resource being acted upon - resourceType: 'domain', // user, org, domain - updatedProperties, - }, - }) returnDomain.id = returnDomain._key diff --git a/api/src/organization/mutations/remove-organization.js b/api/src/organization/mutations/remove-organization.js index 58654f6784..7bcc7b61a3 100644 --- a/api/src/organization/mutations/remove-organization.js +++ b/api/src/organization/mutations/remove-organization.js @@ -470,7 +470,7 @@ export const removeOrganization = new mutationWithClientMutationId({ }, action: 'delete', target: { - resource: organization.orgDetails.en.name, // name of resource being acted upon + resource: organization.name, // name of resource being acted upon resourceType: 'organization', // user, org, domain }, }) diff --git a/frontend/src/admin/AuditLogTable.js b/frontend/src/admin/AuditLogTable.js index 6a7aa1647b..9a2cbe0850 100644 --- a/frontend/src/admin/AuditLogTable.js +++ b/frontend/src/admin/AuditLogTable.js @@ -1,13 +1,10 @@ import React, { useCallback, useState } from 'react' import { Box, - Grid, - GridItem, Button, Divider, Tag, Text, - SimpleGrid, Table, Thead, Tbody, @@ -29,18 +26,17 @@ import { SearchBox } from '../components/SearchBox' import { RelayPaginationControls } from '../components/RelayPaginationControls' export function AuditLogTable({ orgId = null }) { - const [orderDirection, setOrderDirection] = useState('ASC') + const [orderDirection, setOrderDirection] = useState('DESC') const [orderField, setOrderField] = useState('TIMESTAMP') const [searchTerm, setSearchTerm] = useState('') const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('') - const [logsPerPage, setLogsPerPage] = useState(10) + const [logsPerPage, setLogsPerPage] = useState(20) const [activeResourceFilters, setActiveResourceFilters] = useState([]) const [activeActionFilters, setActiveActionFilters] = useState([]) const memoizedSetDebouncedSearchTermCallback = useCallback(() => { setDebouncedSearchTerm(searchTerm) }, [searchTerm]) useDebouncedFunction(memoizedSetDebouncedSearchTermCallback, 500) - const { loading, isLoadingMore, @@ -104,12 +100,12 @@ export function AuditLogTable({ orgId = null }) { ) } else { logTable = ( - +
- Time Generated + Time Generated (UTC) Initiated By @@ -144,9 +140,9 @@ export function AuditLogTable({ orgId = null }) { ({ value }) => action.toUpperCase() === value, ) if (typeof reason !== 'undefined') { - if (reason === 'nonexistent') { + if (reason === 'NONEXISTENT') { reason = This domain no longer exists - } else if (reason === 'wrong_org') { + } else if (reason === 'WRONG_ORG') { reason = ( This domain does not belong to this organization @@ -213,123 +209,115 @@ export function AuditLogTable({ orgId = null }) { orderByOptions={orderByOptions} placeholder={t`Search by initiated by, resource name`} /> - - {logTable} - - - - Filters + + + + + Resource: - - - - Resource: - - - {resourceFilters.map(({ value, text }, idx) => { - return ( - { - let optionIdx = activeResourceFilters.indexOf(value) - if (optionIdx < 0) { - setActiveResourceFilters([ - ...activeResourceFilters, - value, - ]) - } else { - setActiveResourceFilters( - activeResourceFilters.filter( - (tag) => tag !== value, - ), - ) - } - }} - > - {text} - - ) - })} - - - Action: - - - {actionFilters.map(({ value, text }, idx) => { - return ( - { - let optionIdx = activeActionFilters.indexOf(value) - if (optionIdx < 0) { - setActiveActionFilters([ - ...activeActionFilters, - value, - ]) - } else { - setActiveActionFilters( - activeActionFilters.filter((tag) => tag !== value), - ) - } - }} - > - {text} - - ) - })} - - - - - - + {resourceFilters.map(({ value, text }, idx) => { + return ( + { + let optionIdx = activeResourceFilters.indexOf(value) + if (optionIdx < 0) { + setActiveResourceFilters([ + ...activeResourceFilters, + value, + ]) + } else { + setActiveResourceFilters( + activeResourceFilters.filter((tag) => tag !== value), + ) + } + }} + > + {text} + + ) + })} + + + + + Action: + + {actionFilters.map(({ value, text }, idx) => { + return ( + { + let optionIdx = activeActionFilters.indexOf(value) + if (optionIdx < 0) { + setActiveActionFilters([...activeActionFilters, value]) + } else { + setActiveActionFilters( + activeActionFilters.filter((tag) => tag !== value), + ) + } + }} + > + {text} + + ) + })} + + + + + {logTable}