Skip to content

Commit

Permalink
fix: listing duplicate fe (bloom-housing#4309) (#797)
Browse files Browse the repository at this point in the history
* fix: copy paste relevant code

* fix: design alignment

* fix: base functionality

* fix: connect with be + testing

* fix: linting resolution

* fix: alphabetize new strings

* fix: juris table approach

* fix: null check

* fix: default admin access

* fix: avoid redundant admin call

* fix: new flag approach

* fix: unused var

* fix: testing updates

* fix: testing attempt 2

* fix: null checks

* fix: not a doubt

* fix: cover partner listing mismatch

* fix: handle partners access

* fix: remove unused var

* fix: refactor ListingFormActions file (bloom-housing#4403)

* fix: partners logic

* fix: admin and jadmin logic

* fix: readability tweaks

* fix: shift to direct env reference

* fix: lottery results logic

* fix: add enum name field

* fix: migration feedback
  • Loading branch information
ColinBuyck authored Nov 19, 2024
1 parent 740fe3a commit ad62a5b
Show file tree
Hide file tree
Showing 19 changed files with 879 additions and 176 deletions.
2 changes: 0 additions & 2 deletions api/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ LOTTERY_PUBLISH_PROCESSING_CRON_STRING=58 23 * * *
LOTTERY_PROCESSING_CRON_STRING=0 * * * *
# how many days till lottery data expires
LOTTERY_DAYS_TILL_EXPIRY=45
# allow partners and jadmins to create duplicate listings
ALLOW_PARTNERS_TO_DUPLICATE_LISTINGS=FALSE
# the list of allowed urls that can make requests to the api (strings must be exact matches)
CORS_ORIGINS=["http://localhost:3000", "http://localhost:3001"]
# spill over list of allowed urls that can make requests to the api (strings are turned into regex)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "jurisdictions" ADD COLUMN "duplicate_listing_permissions" "user_role_enum"[];
1 change: 1 addition & 0 deletions api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ model Jurisdictions {
translations Translations[]
user_accounts UserAccounts[]
listingApprovalPermissions UserRoleEnum[] @map("listing_approval_permission")
duplicateListingPermissions UserRoleEnum[] @map("duplicate_listing_permissions")
@@map("jurisdictions")
}
Expand Down
5 changes: 5 additions & 0 deletions api/prisma/seed-helpers/jurisdiction-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { randomName } from './word-generator';
export const jurisdictionFactory = (
jurisdictionName = randomName(),
listingApprovalPermissions?: UserRoleEnum[],
duplicateListingPermissions?: UserRoleEnum[],
): Prisma.JurisdictionsCreateInput => ({
name: jurisdictionName,
notificationsSignUpUrl: 'https://www.exygy.com',
Expand All @@ -19,4 +20,8 @@ export const jurisdictionFactory = (
enableGeocodingPreferences: true,
enableGeocodingRadiusMethod: false,
listingApprovalPermissions: listingApprovalPermissions || [],
duplicateListingPermissions: duplicateListingPermissions || [
UserRoleEnum.admin,
UserRoleEnum.jurisdictionAdmin,
],
});
16 changes: 16 additions & 0 deletions api/src/dtos/jurisdictions/jurisdiction.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,24 @@ export class Jurisdiction extends AbstractDTO {
@IsDefined({ groups: [ValidationsGroupsEnum.default] })
@ApiProperty({
enum: UserRoleEnum,
enumName: 'UserRoleEnum',
example: [UserRoleEnum.admin],
isArray: true,
})
listingApprovalPermissions: UserRoleEnum[];

@Expose()
@IsArray({ groups: [ValidationsGroupsEnum.default] })
@IsEnum(UserRoleEnum, {
groups: [ValidationsGroupsEnum.default],
each: true,
})
@IsDefined({ groups: [ValidationsGroupsEnum.default] })
@ApiProperty({
enum: UserRoleEnum,
enumName: 'UserRoleEnum',
example: [UserRoleEnum.admin],
isArray: true,
})
duplicateListingPermissions: UserRoleEnum[];
}
43 changes: 37 additions & 6 deletions api/src/services/listing.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
BadRequestException,
ForbiddenException,
HttpException,
Inject,
Injectable,
Expand Down Expand Up @@ -936,15 +937,30 @@ export class ListingService implements OnModuleInit {
throw new BadRequestException('New listing name must be unique');
}

const duplicateListingPermissions = (
requestingUser?.jurisdictions?.length === 1
? requestingUser?.jurisdictions[0]
: requestingUser?.jurisdictions?.find(
(juris) => juris.id === storedListing?.jurisdictions?.id,
)
)?.duplicateListingPermissions;

const userRoles =
process.env.ALLOW_PARTNERS_TO_DUPLICATE_LISTINGS === 'TRUE' &&
(requestingUser?.userRoles?.isJurisdictionalAdmin ||
requestingUser?.userRoles?.isPartner)
requestingUser?.userRoles?.isAdmin ||
(requestingUser?.userRoles?.isJurisdictionalAdmin &&
duplicateListingPermissions?.includes(
UserRoleEnum.jurisdictionAdmin,
)) ||
(requestingUser?.userRoles?.isPartner &&
duplicateListingPermissions?.includes(UserRoleEnum.partner))
? {
...requestingUser.userRoles,
isAdmin: true,
}
: requestingUser?.userRoles;
: {
...requestingUser?.userRoles,
isAdmin: false,
};

await this.permissionService.canOrThrow(
{ ...requestingUser, userRoles: userRoles },
Expand All @@ -955,6 +971,20 @@ export class ListingService implements OnModuleInit {
},
);

//manually check for juris/listing mismatch since logic above is forcing admin permissioning
if (
(requestingUser?.userRoles?.isJurisdictionalAdmin &&
!requestingUser?.jurisdictions?.some(
(juris) => juris.id === storedListing.jurisdictionId,
)) ||
(requestingUser?.userRoles?.isPartner &&
!requestingUser?.listings?.some(
(listing) => listing.id === storedListing.id,
))
) {
throw new ForbiddenException();
}

const mappedListing = mapTo(ListingCreate, storedListing);

const listingEvents = mappedListing.listingEvents?.filter(
Expand All @@ -976,6 +1006,7 @@ export class ListingService implements OnModuleInit {
const newListingData: ListingCreate = {
...mappedListing,
name: dto.name,
assets: [],
status: ListingsStatusEnum.pending,
listingEvents: listingEvents,
listingMultiselectQuestions:
Expand All @@ -999,8 +1030,8 @@ export class ListingService implements OnModuleInit {
);

if (
process.env.ALLOW_PARTNERS_TO_DUPLICATE_LISTINGS === 'TRUE' &&
requestingUser.userRoles?.isPartner
requestingUser?.userRoles?.isPartner &&
duplicateListingPermissions?.includes(UserRoleEnum.partner)
) {
await this.prisma.userAccounts.update({
data: {
Expand Down
3 changes: 3 additions & 0 deletions api/test/integration/jurisdiction.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ describe('Jurisdiction Controller Tests', () => {
enableUtilitiesIncluded: true,
allowSingleUseCodeLogin: true,
listingApprovalPermissions: [],
duplicateListingPermissions: [],
};
const res = await request(app.getHttpServer())
.post('/jurisdictions')
Expand Down Expand Up @@ -159,6 +160,7 @@ describe('Jurisdiction Controller Tests', () => {
enableUtilitiesIncluded: true,
allowSingleUseCodeLogin: true,
listingApprovalPermissions: [],
duplicateListingPermissions: [],
};
const res = await request(app.getHttpServer())
.put(`/jurisdictions/${id}`)
Expand Down Expand Up @@ -190,6 +192,7 @@ describe('Jurisdiction Controller Tests', () => {
enableUtilitiesIncluded: true,
allowSingleUseCodeLogin: true,
listingApprovalPermissions: [],
duplicateListingPermissions: [],
};

const res = await request(app.getHttpServer())
Expand Down
2 changes: 2 additions & 0 deletions api/test/integration/permission-tests/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export const buildJurisdictionCreateMock = (
enableUtilitiesIncluded: true,
allowSingleUseCodeLogin: true,
listingApprovalPermissions: [],
duplicateListingPermissions: [],
};
};

Expand All @@ -132,6 +133,7 @@ export const buildJurisdictionUpdateMock = (
enableUtilitiesIncluded: true,
allowSingleUseCodeLogin: true,
listingApprovalPermissions: [],
duplicateListingPermissions: [],
};
};

Expand Down
1 change: 1 addition & 0 deletions shared-helpers/__tests__/testHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ export const jurisdiction: Jurisdiction = {
createdAt: new Date("2023-02-06T22:32:30.397Z"),
updatedAt: new Date("2023-02-21T21:57:58.346Z"),
listingApprovalPermissions: [],
duplicateListingPermissions: [],
multiselectQuestions: [
{
id: "d2553d08-6095-40b9-a1e2-c95349effe72",
Expand Down
29 changes: 13 additions & 16 deletions shared-helpers/src/types/backend-swagger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4911,7 +4911,10 @@ export interface JurisdictionCreate {
allowSingleUseCodeLogin: boolean

/** */
listingApprovalPermissions: EnumJurisdictionCreateListingApprovalPermissions[]
listingApprovalPermissions: UserRoleEnum[]

/** */
duplicateListingPermissions: UserRoleEnum[]
}

export interface JurisdictionUpdate {
Expand Down Expand Up @@ -4961,7 +4964,10 @@ export interface JurisdictionUpdate {
allowSingleUseCodeLogin: boolean

/** */
listingApprovalPermissions: EnumJurisdictionUpdateListingApprovalPermissions[]
listingApprovalPermissions: UserRoleEnum[]

/** */
duplicateListingPermissions: UserRoleEnum[]
}

export interface Jurisdiction {
Expand Down Expand Up @@ -5020,7 +5026,10 @@ export interface Jurisdiction {
allowSingleUseCodeLogin: boolean

/** */
listingApprovalPermissions: EnumJurisdictionListingApprovalPermissions[]
listingApprovalPermissions: UserRoleEnum[]

/** */
duplicateListingPermissions: UserRoleEnum[]
}

export interface MultiselectQuestionCreate {
Expand Down Expand Up @@ -6218,19 +6227,7 @@ export enum HouseholdMemberRelationship {
"other" = "other",
}
export type AllExtraDataTypes = BooleanInput | TextInput | AddressInput
export enum EnumJurisdictionCreateListingApprovalPermissions {
"user" = "user",
"partner" = "partner",
"admin" = "admin",
"jurisdictionAdmin" = "jurisdictionAdmin",
}
export enum EnumJurisdictionUpdateListingApprovalPermissions {
"user" = "user",
"partner" = "partner",
"admin" = "admin",
"jurisdictionAdmin" = "jurisdictionAdmin",
}
export enum EnumJurisdictionListingApprovalPermissions {
export enum UserRoleEnum {
"user" = "user",
"partner" = "partner",
"admin" = "admin",
Expand Down
2 changes: 2 additions & 0 deletions sites/partners/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ API_PASS_KEY="some-key-here"
SHOW_LOTTERY=FALSE
# controls whethere the application export is a spreadsheet (TRUE) or a csv (FALSE)
APPLICATION_EXPORT_AS_SPREADSHEET=FALSE
# controls use of edit, republish, and reopen functionality when listing is closed
LIMIT_CLOSED_LISTING_ACTIONS=FALSE
Loading

0 comments on commit ad62a5b

Please sign in to comment.