Skip to content

Commit

Permalink
feat: merge develop
Browse files Browse the repository at this point in the history
Signed-off-by: Jeroen Branje <[email protected]>
  • Loading branch information
jeroenbranje committed Jan 31, 2024
2 parents f53799e + 427f562 commit fec000b
Show file tree
Hide file tree
Showing 19 changed files with 1,650 additions and 5 deletions.
2 changes: 2 additions & 0 deletions apps/envited.ascs.digital/app/dashboard/users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export default async function Index() {

return <Users users={users} />
}

export const dynamic = 'force-dynamic'
3 changes: 2 additions & 1 deletion apps/envited.ascs.digital/common/database/queries/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { connectDb } from '../database'
import * as schema from '../schema'
import { fetchTables } from './common'
import { maybeUpdatePublishedState, update as updateProfile } from './profiles'
import { getUserById, getUserWithProfileById, getUsersByIssuerId, insertUserTx } from './users'
import { deleteUserById, getUserById, getUserWithProfileById, getUsersByIssuerId, insertUserTx } from './users'

const queries = {
deleteUserById,
fetchTables,
getUserById,
getUserWithProfileById,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ describe('common/database/users', () => {
streetAddress: 'Teststraße 1',
updatedAt: new Date(),
vatId: 'vatId',
isActive: true,
})
expect(transaction).toEqual({
id: 'USER_ID',
Expand Down
8 changes: 8 additions & 0 deletions apps/envited.ascs.digital/common/database/queries/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ import {
} from '../schema'
import { Credential, DatabaseConnection, Issuer, User } from '../types'

export const deleteUserById = (db: DatabaseConnection) => async (id: string) =>
db
.update(user)
.set({ isActive: false, updatedAt: new Date() })
.where(eq(user.id, id))
.returning({ updatedId: user.id })

export const getUserById = (db: DatabaseConnection) => async (id: string) =>
db.select().from(user).where(eq(user.id, id))

Expand Down Expand Up @@ -162,6 +169,7 @@ export const _txn =
issuerId: id,
issuanceDate: new Date(issuanceDate),
expirationDate: new Date(expirationDate),
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
})
Expand Down
1 change: 1 addition & 0 deletions apps/envited.ascs.digital/common/database/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const user = pgTable('user', {
addressTypeId: uuid('address_type_id').references(() => addressType.id),
issuanceDate: timestamp('issuance_date'),
expirationDate: timestamp('expiration_date'),
isActive: boolean('is_active').default(true),
createdAt: timestamp('created_at'),
updatedAt: timestamp('updated_at'),
})
Expand Down
1 change: 1 addition & 0 deletions apps/envited.ascs.digital/common/database/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface User {
issuerId: StringChange
issuanceDate: string
expirationDate: string
isActive: boolean
createdAt: string
updatedAt: string
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import * as SUT from './deleteUserById'

describe('common/serverActions/users/deleteUserById', () => {
it('should return a deleted user as expected', async () => {
// when ... we request a user by id
// then ... it returns a user as expected
const getServerSessionStub = jest.fn().mockResolvedValue({
user: {
pkh: 'ISSUER_PKH',
},
})
const user = {
id: 'USER_PKH',
issuerId: 'ISSUER_PKH',
}

const expected = {
updatedId: 'USER_PKH',
}
const dbStub = jest.fn().mockResolvedValue({
getUserById: jest.fn().mockResolvedValue([user]),
deleteUserById: jest.fn().mockResolvedValue([{ updatedId: 'USER_PKH' }]),
})

const result = await SUT._deleteUserById({ db: dbStub, getServerSession: getServerSessionStub })('USER_ID')
expect(result).toEqual(expected)
})

it('should throw because of missing session', async () => {
// when ... we request a user by id without a session
// then ... it throws as expected
const getServerSessionStub = jest.fn().mockResolvedValue(null)
const user = {
id: 'USER_PKH',
issuerId: 'ISSUER_PKH',
}
const dbStub = jest.fn().mockResolvedValue({
getUserById: jest.fn().mockResolvedValue([user]),
deleteUserById: jest.fn().mockResolvedValue([{ updatedId: 'USER_PKH' }]),
})

await expect(
SUT._deleteUserById({ db: dbStub, getServerSession: getServerSessionStub })('USER_ID'),
).rejects.toThrow('Something went wrong')
})

it('should throw because requester is not allowed to get this resource', async () => {
// when ... we request a user by id, but the requested user is not issued by the requester OR is not their own user
// then ... it throws as expected
const getServerSessionStub = jest.fn().mockResolvedValue({
user: {
pkh: 'ISSUER_PKH',
},
})
const user = {
id: 'USER_PKH',
issuerId: 'FEDERATOR_PKH',
}
const dbStub = jest.fn().mockResolvedValue({
getUserById: jest.fn().mockResolvedValue([user]),
deleteUserById: jest.fn().mockResolvedValue([{ updatedId: 'USER_PKH' }]),
})

await expect(
SUT._deleteUserById({ db: dbStub, getServerSession: getServerSessionStub })('USER_ID'),
).rejects.toThrow('Something went wrong')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { isNil } from 'ramda'
import { cache } from 'react'

import { getServerSession } from '../../auth'
import { db } from '../../database/queries'
import { Database } from '../../database/types'
import { userIsIssuedByLoggedInUser } from '../../guards'
import { User } from '../../types'
import { Session } from '../../types/types'
import { badRequestError, error, unauthorizedError } from '../../utils'

export const _deleteUserById =
({ db, getServerSession }: { db: Database; getServerSession: () => Promise<Session | null> }) =>
async (id: string): Promise<User> => {
try {
const session = await getServerSession()

if (isNil(session)) {
throw unauthorizedError()
}

const connection = await db()
const [user] = await connection.getUserById(id)

if (!userIsIssuedByLoggedInUser(user)(session)) {
throw badRequestError('Incorrect permissions')
}

const [deletedUser] = await connection.deleteUserById(user.id)

return deletedUser
} catch (e) {
console.log('error', e)
throw error()
}
}

export const deleteUserById = cache(_deleteUserById({ db, getServerSession }))
1 change: 1 addition & 0 deletions apps/envited.ascs.digital/common/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export interface User {
streetAddress: string
updatedAt: string
vatId?: string
isActive: boolean
}

export interface Profile {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE "user" ADD COLUMN "is_active" boolean DEFAULT true;
Loading

0 comments on commit fec000b

Please sign in to comment.