Skip to content

Commit

Permalink
Merge pull request #682 from housingbayarea/hba-release-03-25-2024
Browse files Browse the repository at this point in the history
Release: 03-25-2024
  • Loading branch information
YazeedLoonat authored Mar 26, 2024
2 parents 2647aa1 + 737721b commit 4edb185
Show file tree
Hide file tree
Showing 66 changed files with 2,306 additions and 783 deletions.
4 changes: 4 additions & 0 deletions api/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ CORS_ORIGINS=["http://localhost:3000", "http://localhost:3001"]
CORS_REGEX=["test1", "test2"]
# controls the repetition of the temp file clearing cron job
TEMP_FILE_CLEAR_CRON_STRING=0 * * *
# how long we maintain our request time outs (60 * 60 * 1000 ms)
THROTTLE_TTL=3600000
# how many requests before we throttle
THROTTLE_LIMIT=100
3 changes: 2 additions & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@
"@nestjs/platform-express": "^10.3.2",
"@nestjs/schedule": "^4.0.1",
"@nestjs/swagger": "~7.1.12",
"@nestjs/throttler": "^5.1.2",
"@prisma/client": "^5.0.0",
"@sendgrid/mail": "7.7.0",
"@turf/boolean-point-in-polygon": "6.5.0",
"@turf/buffer": "6.5.0",
"@turf/helpers": "6.5.0",
"@turf/boolean-point-in-polygon": "6.5.0",
"@turf/points-within-polygon": "6.5.0",
"@types/archiver": "^6.0.2",
"archiver": "^6.0.1",
Expand Down
5 changes: 4 additions & 1 deletion api/prisma/seed-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ export const devSeeding = async (
jurisdictionName?: string,
) => {
const jurisdiction = await prismaClient.jurisdictions.create({
data: jurisdictionFactory(jurisdictionName),
data: {
...jurisdictionFactory(jurisdictionName),
allowSingleUseCodeLogin: false,
},
});
await prismaClient.userAccounts.create({
data: await userFactory({
Expand Down
26 changes: 12 additions & 14 deletions api/prisma/seed-helpers/map-layer-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,18 @@ export const simplifiedDCMap = {
geometry: {
coordinates: [
[
[
[-77.0392589333301, 38.79186072967565],
[-76.90981025809415, 38.89293952026222],
[-77.04122027689426, 38.996161202682146],
[-77.12000091005532, 38.93465307055658],
[-77.10561772391833, 38.91990351952725],
[-77.09123453778136, 38.90565966392609],
[-77.06802530560486, 38.9015894658674],
[-77.06181438431805, 38.889377471720564],
[-77.03697069917165, 38.870801038935525],
[-77.03043288729134, 38.850437727576235],
[-77.03435557441966, 38.80816525459605],
[-77.0392589333301, 38.79186072967565],
],
[-77.0392589333301, 38.79186072967565],
[-76.90981025809415, 38.89293952026222],
[-77.04122027689426, 38.996161202682146],
[-77.12000091005532, 38.93465307055658],
[-77.10561772391833, 38.91990351952725],
[-77.09123453778136, 38.90565966392609],
[-77.06802530560486, 38.9015894658674],
[-77.06181438431805, 38.889377471720564],
[-77.03697069917165, 38.870801038935525],
[-77.03043288729134, 38.850437727576235],
[-77.03435557441966, 38.80816525459605],
[-77.0392589333301, 38.79186072967565],
],
],
type: 'Polygon',
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/ami-chart.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ import { SuccessDTO } from '../dtos/shared/success.dto';
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { JwtAuthGuard } from '../guards/jwt.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('/amiCharts')
@ApiTags('amiCharts')
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
@PermissionTypeDecorator('amiChart')
@UseGuards(JwtAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, JwtAuthGuard, PermissionGuard)
@ApiExtraModels(AmiChartQueryParams)
export class AmiChartController {
constructor(private readonly AmiChartService: AmiChartService) {}
Expand Down
2 changes: 2 additions & 0 deletions api/src/controllers/app.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import { PermissionAction } from '../decorators/permission-action.decorator';
import { permissionActions } from '../enums/permissions/permission-actions-enum';
import { AdminOrJurisdictionalAdminGuard } from '../guards/admin-or-jurisdiction-admin.guard';
import { AppService } from '../services/app.service';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller()
@UseGuards(ThrottleGuard)
@ApiExtraModels(SuccessDTO)
@ApiTags('root')
export class AppController {
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/application-flagged-set.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ import { mapTo } from '../utilities/mapTo';
import { OptionalAuthGuard } from '../guards/optional.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('/applicationFlaggedSets')
@ApiExtraModels(SuccessDTO)
@ApiTags('applicationFlaggedSets')
@UseGuards(OptionalAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, OptionalAuthGuard, PermissionGuard)
@PermissionTypeDecorator('applicationFlaggedSet')
@UsePipes(
new ValidationPipe({
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/application.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { ApplicationCsvExporterService } from '../services/application-csv-expor
import { ApplicationCsvQueryParams } from '../dtos/applications/application-csv-query-params.dto';
import { MostRecentApplicationQueryParams } from '../dtos/applications/most-recent-application-query-params.dto';
import { ExportLogInterceptor } from '../interceptors/export-log.interceptor';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('applications')
@ApiTags('applications')
Expand All @@ -59,7 +60,7 @@ import { ExportLogInterceptor } from '../interceptors/export-log.interceptor';
}),
)
@ApiExtraModels(IdDTO, AddressInput, BooleanInput, TextInput)
@UseGuards(OptionalAuthGuard)
@UseGuards(ThrottleGuard, OptionalAuthGuard)
@PermissionTypeDecorator('application')
@UseInterceptors(ActivityLogInterceptor)
export class ApplicationController {
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/asset.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { CreatePresignedUploadMetadataResponse } from '../dtos/assets/create-pre
import { CreatePresignedUploadMetadata } from '../dtos/assets/create-presigned-upload-meta.dto';
import { AssetService } from '../services/asset.service';
import { defaultValidationPipeOptions } from '../utilities/default-validation-pipe-options';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('assets')
@ApiTags('assets')
Expand All @@ -28,7 +29,7 @@ import { defaultValidationPipeOptions } from '../utilities/default-validation-pi
CreatePresignedUploadMetadataResponse,
)
@PermissionTypeDecorator('asset')
@UseGuards(JwtAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, JwtAuthGuard, PermissionGuard)
export class AssetController {
constructor(private readonly assetService: AssetService) {}

Expand Down
8 changes: 6 additions & 2 deletions api/src/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { User } from '../dtos/users/user.dto';
import { RequestSingleUseCode } from '../dtos/single-use-code/request-single-use-code.dto';
import { LoginViaSingleUseCode } from '../dtos/auth/login-single-use-code.dto';
import { SingleUseCodeAuthGuard } from '../guards/single-use-code.guard';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('auth')
@ApiTags('auth')
Expand All @@ -43,7 +44,7 @@ export class AuthController {
@ApiOperation({ summary: 'Login', operationId: 'login' })
@ApiOkResponse({ type: SuccessDTO })
@ApiBody({ type: Login })
@UseGuards(MfaAuthGuard)
@UseGuards(ThrottleGuard, MfaAuthGuard)
async login(
@Request() req: ExpressRequest,
@Response({ passthrough: true }) res: ExpressResponse,
Expand All @@ -63,7 +64,10 @@ export class AuthController {
@Request() req: ExpressRequest,
@Response({ passthrough: true }) res: ExpressResponse,
): Promise<SuccessDTO> {
return await this.authService.setCredentials(res, mapTo(User, req['user']));
return await this.authService.confirmAndSetCredentials(
mapTo(User, req['user']),
res,
);
}

@Get('logout')
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/jurisdiction.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ import { SuccessDTO } from '../dtos/shared/success.dto';
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { OptionalAuthGuard } from '../guards/optional.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('jurisdictions')
@ApiTags('jurisdictions')
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
@ApiExtraModels(JurisdictionCreate, JurisdictionUpdate, IdDTO)
@PermissionTypeDecorator('jurisdiction')
@UseGuards(OptionalAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, OptionalAuthGuard, PermissionGuard)
export class JurisdictionController {
constructor(private readonly jurisdictionService: JurisdictionService) {}

Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/listing.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import { ListingCsvExporterService } from '../services/listing-csv-export.servic
import { ListingCsvQueryParams } from '../dtos/listings/listing-csv-query-params.dto';
import { PermissionGuard } from '../guards/permission.guard';
import { ExportLogInterceptor } from '../interceptors/export-log.interceptor';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('listings')
@ApiTags('listings')
Expand All @@ -63,7 +64,7 @@ import { ExportLogInterceptor } from '../interceptors/export-log.interceptor';
PaginationAllowsAllQueryParams,
IdDTO,
)
@UseGuards(OptionalAuthGuard)
@UseGuards(ThrottleGuard, OptionalAuthGuard)
@PermissionTypeDecorator('listing')
@ActivityLogMetadata([{ targetPropertyName: 'status', propertyPath: 'status' }])
@UseInterceptors(ActivityLogInterceptor)
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/map-layer.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import { defaultValidationPipeOptions } from '../utilities/default-validation-pi
import { OptionalAuthGuard } from '../guards/optional.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('/mapLayers')
@ApiTags('mapLayers')
@UseGuards(OptionalAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, OptionalAuthGuard, PermissionGuard)
@PermissionTypeDecorator('mapLayers')
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
export class MapLayersController {
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/multiselect-question.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { OptionalAuthGuard } from '../guards/optional.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { AdminOrJurisdictionalAdminGuard } from '../guards/admin-or-jurisdiction-admin.guard';
import { ActivityLogInterceptor } from '../interceptors/activity-log.interceptor';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('multiselectQuestions')
@ApiTags('multiselectQuestions')
Expand All @@ -46,7 +47,7 @@ import { ActivityLogInterceptor } from '../interceptors/activity-log.interceptor
IdDTO,
)
@PermissionTypeDecorator('multiselectQuestion')
@UseGuards(OptionalAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, OptionalAuthGuard, PermissionGuard)
export class MultiselectQuestionController {
constructor(
private readonly multiselectQuestionService: MultiselectQuestionService,
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/reserved-community-type.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ import { SuccessDTO } from '../dtos/shared/success.dto';
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { JwtAuthGuard } from '../guards/jwt.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('reservedCommunityTypes')
@ApiTags('reservedCommunityTypes')
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
@ApiExtraModels(ReservedCommunityTypeQueryParams)
@PermissionTypeDecorator('reservedCommunityType')
@UseGuards(JwtAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, JwtAuthGuard, PermissionGuard)
export class ReservedCommunityTypeController {
constructor(
private readonly ReservedCommunityTypeService: ReservedCommunityTypeService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ import { SuccessDTO } from '../dtos/shared/success.dto';
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { JwtAuthGuard } from '../guards/jwt.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('unitAccessibilityPriorityTypes')
@ApiTags('unitAccessibilityPriorityTypes')
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
@ApiExtraModels(IdDTO)
@PermissionTypeDecorator('unitAccessibilityPriorityType')
@UseGuards(JwtAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, JwtAuthGuard, PermissionGuard)
export class UnitAccessibilityPriorityTypeController {
constructor(
private readonly unitAccessibilityPriorityTypeService: UnitAccessibilityPriorityTypeService,
Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/unit-rent-type.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ import { SuccessDTO } from '../dtos/shared/success.dto';
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { JwtAuthGuard } from '../guards/jwt.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('unitRentTypes')
@ApiTags('unitRentTypes')
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
@ApiExtraModels(UnitRentTypeCreate, UnitRentTypeUpdate, IdDTO)
@PermissionTypeDecorator('unitRentType')
@UseGuards(JwtAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, JwtAuthGuard, PermissionGuard)
export class UnitRentTypeController {
constructor(private readonly unitRentTypeService: UnitRentTypeService) {}

Expand Down
3 changes: 2 additions & 1 deletion api/src/controllers/unit-type.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import { SuccessDTO } from '../dtos/shared/success.dto';
import { PermissionTypeDecorator } from '../decorators/permission-type.decorator';
import { JwtAuthGuard } from '../guards/jwt.guard';
import { PermissionGuard } from '../guards/permission.guard';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('unitTypes')
@ApiTags('unitTypes')
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
@PermissionTypeDecorator('unitType')
@UseGuards(JwtAuthGuard, PermissionGuard)
@UseGuards(ThrottleGuard, JwtAuthGuard, PermissionGuard)
export class UnitTypeController {
constructor(private readonly unitTypeService: UnitTypeService) {}

Expand Down
27 changes: 18 additions & 9 deletions api/src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ import { PermissionTypeDecorator } from '../decorators/permission-type.decorator
import { UserFilterParams } from '../dtos/users/user-filter-params.dto';
import { UserCsvExporterService } from '../services/user-csv-export.service';
import { ExportLogInterceptor } from '../interceptors/export-log.interceptor';
import { RequestSingleUseCode } from '../dtos/single-use-code/request-single-use-code.dto';
import { ThrottleGuard } from '../guards/throttler.guard';

@Controller('user')
@UseGuards(ThrottleGuard)
@ApiTags('user')
@PermissionTypeDecorator('user')
@UsePipes(new ValidationPipe(defaultValidationPipeOptions))
Expand Down Expand Up @@ -168,13 +171,11 @@ export class UserController {
@Body() dto: UserCreate,
@Query() queryParams: UserCreateParams,
): Promise<User> {
const jurisdictionName = req.headers['jurisdictionname'] || '';
return await this.userService.create(
dto,
false,
queryParams.noWelcomeEmail !== true,
mapTo(User, req['user']),
jurisdictionName as string,
req,
);
}

Expand All @@ -187,12 +188,20 @@ export class UserController {
@Body() dto: UserInvite,
@Request() req: ExpressRequest,
): Promise<User> {
return await this.userService.create(
dto,
true,
undefined,
mapTo(User, req['user']),
);
return await this.userService.create(dto, true, undefined, req);
}

@Post('request-single-use-code')
@ApiOperation({
summary: 'Request single use code',
operationId: 'requestSingleUseCode',
})
@ApiOkResponse({ type: SuccessDTO })
async requestSingleUseCode(
@Request() req: ExpressRequest,
@Body() dto: RequestSingleUseCode,
): Promise<SuccessDTO> {
return await this.userService.requestSingleUseCode(dto, req);
}

@Post('resend-confirmation')
Expand Down
22 changes: 22 additions & 0 deletions api/src/guards/throttler.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ThrottlerGuard } from '@nestjs/throttler';
import { ExecutionContext, Injectable } from '@nestjs/common';
import { ThrottlerLimitDetail } from '@nestjs/throttler/dist/throttler.guard.interface';

@Injectable()
export class ThrottleGuard extends ThrottlerGuard {
protected async getTracker(req: Record<string, any>): Promise<string> {
if (req?.headers && req.headers['x-forwarded-for']) {
// if we are passing through the proxy use forwarded for
return req.headers['x-forwarded-for'].split(',')[0];
}
return req.ips.length ? req.ips[0] : req.ip;
}

protected async throwThrottlingException(
context: ExecutionContext,
throttlerLimitDetail: ThrottlerLimitDetail,
): Promise<void> {
console.error(`IP Address: ${throttlerLimitDetail.tracker} was throttled`);
await super.throwThrottlingException(context, throttlerLimitDetail);
}
}
Loading

0 comments on commit 4edb185

Please sign in to comment.