Skip to content
This repository was archived by the owner on Nov 1, 2024. It is now read-only.

Commit

Permalink
feat: access request
Browse files Browse the repository at this point in the history
Co-authored-by: Erik Vattekar <[email protected]>
  • Loading branch information
Kyrremann and erikvatt committed May 2, 2022
1 parent 6414228 commit 15c13cd
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 76 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ yarn-error.log*
spec-v1.0.yaml
data.sql

# local graphql
.graphqlconfig
schema.graphql

# asdf
.tool-versions
4 changes: 2 additions & 2 deletions components/dataproducts/access/owner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import LoaderSpinner from '../../lib/spinner'
import * as React from 'react'
import { useState } from 'react'
import { Button } from '@navikt/ds-react'
import AccessList from './accessList'
import OwnerAccessList from './ownerAccessList'
import ExpiredAccessList from './expiredAccessList'
import { AddCircle } from '@navikt/ds-icons'
import NewAccessForm from "./newAccessForm";
Expand Down Expand Up @@ -33,7 +33,7 @@ const Owner = ({ accessQuery }: OwnerProps) => {
</Button>
<br />
<SubHeader>Aktive tilganger</SubHeader>
<AccessList id={dataproduct.id} access={dataproduct.access} requesters={dataproduct.requesters} />
<OwnerAccessList id={dataproduct.id} access={dataproduct.access} requesters={dataproduct.requesters} />
<SubHeader onClick={() => setShowExpired(!showExpired)}>Utløpte tilganger {showExpired ? <Collapse /> : <Expand />}</SubHeader>
{showExpired && <ExpiredAccessList access={dataproduct.access} />}
<NewAccessForm open={open} setOpen={setOpen} id={dataproduct.id} pii={dataproduct.pii} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ interface AccessListProps {
requesters: string[],
}

const AccessList = ({ id, access, requesters }: AccessListProps) => {
const OwnerAccessList = ({ id, access, requesters }: AccessListProps) => {
const [revokeAccess] = useRevokeAccessMutation()
const [removeRequester] = useRemoveRequesterMutation()
const removeAccess = async (id: string, a: AccessEntry) => {
Expand Down Expand Up @@ -95,7 +95,7 @@ const AccessList = ({ id, access, requesters }: AccessListProps) => {
<TableHead>
<TableRow>
<TableCell align='left'>Bruker / gruppe</TableCell>
<TableCell align='center'>Kan be om tilgang</TableCell>
<TableCell align='center'>Kan gi seg selv tilgang</TableCell>
<TableCell align='center'>Har tilgang</TableCell>
<TableCell align='center'>Fjern tilgang</TableCell>
</TableRow>
Expand All @@ -118,4 +118,4 @@ const AccessList = ({ id, access, requesters }: AccessListProps) => {
</div>
)
}
export default AccessList
export default OwnerAccessList
65 changes: 21 additions & 44 deletions components/dataproducts/access/user.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { QueryResult } from '@apollo/client'
import { DataproductAccessQuery, Exact, useRevokeAccessMutation } from '../../../lib/schema/graphql'
import { DataproductAccessQuery, Exact, useRevokeAccessMutation, } from '../../../lib/schema/graphql'
import ErrorMessage from '../../lib/error'
import LoaderSpinner from '../../lib/spinner'
import * as React from 'react'
import { useState } from 'react'
import { isAfter, parseISO } from 'date-fns'
import humanizeDate from '../../../lib/humanizeDate'
import { Alert, Button } from '@navikt/ds-react'
import { Delete } from '@navikt/ds-icons'
import {AddCircle, Delete} from '@navikt/ds-icons'
import AddAccess from './addAccess'
import SubHeader from "../../lib/subHeader";
import UserAccessList from "./userAccessList";

interface UserProps {
accessQuery: QueryResult<DataproductAccessQuery, Exact<{ id: string }>>
Expand Down Expand Up @@ -42,48 +44,23 @@ const User = ({ accessQuery, currentUser, groups }: UserProps) => {
}

// Has access
if (activeAccess) return (<>
{formError && <Alert variant='error'>{formError}</Alert>}
Du har tilgang til dette produktet{' '}
{activeAccess.expires && <>til {humanizeDate(activeAccess.expires)}</>}
{' '}{group && `via gruppen ${group}`}
<br />
{personalAccess &&
<Button onClick={() => removeAccess(activeAccess.id)} variant='danger' style={{ marginTop: '10px' }}><Delete />Fjern
tilgang </Button>}
</>)
// Can request access
if (dataproduct.requesters.length > 0) {
if (dataproduct.requesters.includes(currentUser) || groups.some(g => dataproduct.requesters.includes(g))){
return (
<>
Du kan gi deg selv tidsbegrenset tilgang.
<br />
<Button onClick={() => setOpen(true)} variant='primary' style={{ marginTop: '20px' }}>Gi meg tilgang </Button>
<AddAccess
open={open}
setOpen={setOpen}
dataproductID={dataproduct.id}
dataproductName={dataproduct.name}
subject={currentUser}
/>
</>)}}

return (
<>
Du har visst ikke tilgang til disse dataene.
<br /> <br />
Ta kontakt med eieren av produktet (team {dataproduct.owner.group.split('@')[0]}), så finner dere en løsning.
<br /> <br />
{dataproduct.owner?.teamkatalogenURL && (
<a
href={dataproduct.owner.teamkatalogenURL}
target='_blank'
rel='noreferrer'
>
Team {dataproduct.owner.group.split('@')[0]} i Teamkatalogen
</a>
)}
</>)
<>
<Button key='ny_tilgang' style={{ marginLeft: '15px', marginBottom: '10px' }} variant='primary' size='small' onClick={() => setOpen(true)}>
<AddCircle /> Søk om ny tilgang
</Button>
<br />
{false && <>
<SubHeader>Søknader</SubHeader>
<UserAccessList id={dataproduct.id} access={[]} requests={[]} />
</>
}
{dataproduct.access.length != 0 && <>
<SubHeader>Aktive tilganger</SubHeader>
<UserAccessList id={dataproduct.id} access={dataproduct.access} requests={[]}/>
</>
}
</>
)
}
export default User
95 changes: 95 additions & 0 deletions components/dataproducts/access/userAccessList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import {Table, TableBody, TableCell, TableHead, TableRow} from '@mui/material'
import * as React from 'react'
import {useState} from 'react'
import {Delete, Error, Success} from '@navikt/ds-icons'
import {navGronn, navRod} from '../../../styles/constants'
import humanizeDate from '../../../lib/humanizeDate'
import {isAfter, parseISO} from 'date-fns'
import {useRemoveRequesterMutation, useRevokeAccessMutation} from '../../../lib/schema/graphql'
import {Alert} from '@navikt/ds-react'
import {Accessibility} from "@mui/icons-material";

interface AccessEntry {
subject: string,
access?: access,
}

const productAccess = (access: access[]): AccessEntry[] => {
// Valid access entries are unrevoked and either eternal or expires in the future
const valid = (a: access) => !a.revoked && (!a.expires || isAfter(parseISO(a.expires), Date.now()))
return access.filter(valid).map(a => {
return {
access: a,
subject: a.subject.split(":")[1],
};
})
}

interface access {
id: string;
subject: string;
granter: string;
expires?: any;
created: any;
revoked?: any;
}

interface request {

}

interface AccessListProps {
id: string,
access: access[],
requests: request[]
}

const UserAccessList = ({ id, access, requests}: AccessListProps) => {
const [revokeAccess] = useRevokeAccessMutation()
const removeAccess = async (id: string, a: AccessEntry) => {
if (a.access) {
try {
await revokeAccess({
variables: { id: a.access.id },
refetchQueries: ['DataproductAccess'],
},
)
} catch (e: any) {
setFormError(e.message)
}
}

}

const [formError, setFormError] = useState('')
const accesses = productAccess(access)

return (
<div>
{formError && <Alert variant={'error'}>{formError}</Alert>}
<Table sx={{ minWidth: 650 }} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell align='left'>Bruker / gruppe</TableCell>
{accesses.length != 0 && <TableCell align='left'>Har tilgang til</TableCell>}
<TableCell align='center'>Din søknad</TableCell>
<TableCell align='center'>Fjern tilgang</TableCell>
</TableRow>
</TableHead>
<TableBody>
{accesses.map((a, i) => <TableRow key={i}>
<TableCell>{a.subject}</TableCell>
{accesses.length != 0 && <TableCell align='left'>{a.access ? <>{a.access.expires ? humanizeDate(a.access.expires) : 'evig'}</> :
<Error style={{ color: navRod }}/>}
</TableCell>}
<TableCell align='center'>show</TableCell>
<TableCell align='center'><Delete style={{ cursor: 'pointer', color: navRod }}
onClick={() => removeAccess(id, a)}/></TableCell>
</TableRow>)}

</TableBody>
</Table>
</div>
)
}
export default UserAccessList
18 changes: 18 additions & 0 deletions lib/queries/accessRequest/accessRequestsForOwner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { gql } from 'graphql-tag'

export const ACCESS_REQUESTS_FOR_OWNER = gql`
query AccessRequestsForOwner {
accessRequestsForOwner {
id
dataproductID
subject
subjectType
polly {
id
externalID
name
url
}
}
}
`
Loading

0 comments on commit 15c13cd

Please sign in to comment.