Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat cerfa dates #3600

Merged
merged 1 commit into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ async function createTables(queryRunner: QueryRunner) {
"timeZone" text NULL,
telephone jsonb DEFAULT '{"numero": "", "countryCode": "fr"}'::jsonb NOT NULL,
"acceptTerms" timestamptz NULL,
"filesUpdated" bool DEFAULT false NOT NULL,
latitude float8 NULL,
longitude float8 NULL,
"organismeType" text NULL,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
import { Structure } from "@domifa/common";

export const CurrentStructure = createParamDecorator(
(_data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.structure as Structure;
}
);
1 change: 1 addition & 0 deletions packages/backend/src/auth/decorators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from "./AllowUserStructureRoles.decorator";
export * from "./current-chosen-user-structure.decorator";
export * from "./current-interaction.decorator";
export * from "./current-structure-information.decorator";
export * from "./current-structure.decorator";
export * from "./current-usager-doc.decorator";
export * from "./current-usager-note.decorator";
export * from "./current-usager.decorator";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function IsSocialGouvEmail(validationOptions?: ValidationOptions) {
registerDecorator({
name: "isValidPassword",
target: object.constructor,
propertyName: propertyName,
propertyName,
options: validationOptions,
constraints: [propertyName],
validator: {
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/auth/guards/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
export * from "./AppUserGuard.guard";
export * from "./CanGetUserStructure.guard";
export * from "./interactions.guard";
export * from "./structure-access.guard";
export * from "./structure-information-access.guard";
export * from "./usager-access.guard";
export * from "./usager-doc-access.guard";
Expand Down
56 changes: 56 additions & 0 deletions packages/backend/src/auth/guards/structure-access.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
CanActivate,
ExecutionContext,
HttpException,
HttpStatus,
Injectable,
} from "@nestjs/common";

import { appLogger } from "../../util";
import { structureRepository } from "../../database";

@Injectable()
export class StructureAccessGuard implements CanActivate {
public async canActivate(context: ExecutionContext) {
const r = context.switchToHttp().getRequest();

console.log(r?.params?.structureId);

Check warning

Code scanning / CodeQL

Log injection Medium

Log entry depends on a
user-provided value
.

Copilot Autofix AI 28 days ago

To fix the problem, we need to sanitize the user input before logging it. Specifically, we should remove any newline characters from the structureId parameter to prevent log injection attacks. This can be done using the String.prototype.replace method to strip out newline characters.

We will modify the code to sanitize r?.params?.structureId before logging it. This involves creating a sanitized version of structureId and then logging the sanitized value.

Suggested changeset 1
packages/backend/src/auth/guards/structure-access.guard.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/backend/src/auth/guards/structure-access.guard.ts b/packages/backend/src/auth/guards/structure-access.guard.ts
--- a/packages/backend/src/auth/guards/structure-access.guard.ts
+++ b/packages/backend/src/auth/guards/structure-access.guard.ts
@@ -16,3 +16,4 @@
 
-    console.log(r?.params?.structureId);
+    const sanitizedStructureId = r?.params?.structureId?.replace(/\n|\r/g, "");
+    console.log(sanitizedStructureId);
     console.log(r?.user?.isSuperAdminDomifa);
EOF
@@ -16,3 +16,4 @@

console.log(r?.params?.structureId);
const sanitizedStructureId = r?.params?.structureId?.replace(/\n|\r/g, "");
console.log(sanitizedStructureId);
console.log(r?.user?.isSuperAdminDomifa);
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
console.log(r?.user?.isSuperAdminDomifa);
if (!r?.params?.structureId || !r?.user?.isSuperAdminDomifa) {
appLogger.error("[StructureAccessGuard] invalid structureId for admin", {
sentry: true,
context: {
usagerRef: r?.params?.uui,
structureId: r?.user?.structureId,
user: r?.user?._id,
},
});
throw new HttpException(
"STRUCTURE_INFORMATION_NOT_FOUND",
HttpStatus.BAD_REQUEST
);
}

const structureId = parseInt(r.params.structureId, 10);

try {
const structure = await structureRepository.findOneOrFail({
where: {
id: structureId,
},
});
r.structure = structure;
return r;
} catch (e) {
appLogger.error("[UsagerAccessGuard] Structure not found", {
sentry: true,
context: {
structureId,
user: r?.user?._id,
role: r?.user?.role,
},
});
throw new HttpException("USAGER_NOT_FOUND", HttpStatus.BAD_REQUEST);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ export class StructureTable
@Column({ type: "bool", default: false })
import: boolean;

@Column({ type: "bool", default: false })
filesUpdated: boolean;

@Column({ type: "timestamptz", nullable: false })
registrationDate: Date;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const structureRepository = myDataSource
}): Promise<Pick<Structure, "hardReset" | "id" | "uuid">> {
const select = ["hardReset", "id", "uuid"];

return this.createQueryBuilder()
return await this.createQueryBuilder()
.select(joinSelectFields(select))
.where(`"hardReset" @> :hardReset`, {
hardReset: JSON.stringify({ token, userId }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,20 @@ import {
Res,
UseGuards,
Param,
ParseIntPipe,
} from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";

import { AllowUserProfiles } from "../../../../auth/decorators";
import { AppUserGuard } from "../../../../auth/guards";
import {
AllowUserProfiles,
CurrentStructure,
} from "../../../../auth/decorators";
import { AppUserGuard, StructureAccessGuard } from "../../../../auth/guards";
import {
userStructureRepository,
structureRepository,
userStructureSecurityRepository,
} from "../../../../database";
import { statsDeploiementExporter } from "../../../../excel/export-stats-deploiement";

Expand Down Expand Up @@ -111,39 +116,48 @@ export class AdminStructuresController {
}

@Get("structure/:structureId")
@UseGuards(StructureAccessGuard)
@AllowUserProfiles("super-admin-domifa")
public async getStructure(
@CurrentUser() _user: UserAdminAuthenticated,
@Param("structureId") structureId: number
@CurrentStructure() structure: Structure,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@Param("structureId") _structureId: number
): Promise<Structure> {
return await structureRepository.findOneOrFail({
where: { id: structureId },
where: { id: structure.id },
});
}

@Get("structure/:structureId/users")
@UseGuards(StructureAccessGuard)
@AllowUserProfiles("super-admin-domifa")
public async getUsers(
@CurrentUser() _user: UserAdminAuthenticated,
@Param("structureId") structureId: number
@CurrentStructure() structure: Structure,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@Param("structureId", new ParseIntPipe()) _structureId: number
): Promise<Array<UserStructureWithSecurity>> {
return (await userStructureRepository
.createQueryBuilder("u")
.leftJoinAndSelect("user_structure_security", "uss", "u.id = uss.user_id")
.select([
"u.nom",
"u.prenom",
"u.mail",
"u.role",
"u.lastLogin",
"u.id",
"u.uuid",
"u.createdAt",
"uss.temporaryTokens",
"uss.eventsHistory",
])
.where({ structureId })
.getMany()) as unknown as UserStructureWithSecurity[];
return (await userStructureSecurityRepository.query(
`
SELECT
user_structure.nom,
user_structure.id,
user_structure.prenom,
user_structure.email,
user_structure.role,
user_structure."lastLogin",
user_structure."createdAt",
user_structure.uuid,
uss."temporaryTokens",
uss."eventsHistory"
FROM user_structure_security uss
INNER JOIN user_structure
ON user_structure.id = uss."userId"
WHERE uss."structureId" = $1
`,
[structure.id]
)) as unknown as UserStructureWithSecurity[];
}

@AllowUserProfiles("super-admin-domifa")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ export interface Structure extends AppEntity {
verified: boolean;

timeZone: TimeZone;
filesUpdated: boolean;

sms: StructureSmsParams;
portailUsager: StructurePortailUsagerParams;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,6 @@ <h1 class="title">Questions / Réponses sur DomiFa</h1>
Les fonctionnalités
</a>
</li>
<li>
<a
class="btn btn-outline-primary"
routerLink="/faq"
fragment="faq-videos"
>
Les tutoriels vidéo
</a>
</li>
</ol>
</nav>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class ManageUsagersPageComponent
placeholder: "Recherche par ID, nom, prénom, ayant-droit ou mandataire",
},
DATE_NAISSANCE: {
label: "Date de naissance",
label: "Date de naissance (format attendu: JJ/MM/AAAA)",
placeholder: "Recherche par date de naissance JJ/MM/AAAA",
},
};
Expand Down
Loading
Loading