diff --git a/package-lock.json b/package-lock.json index 40938186..95fd3b41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@nestjs/serve-static": "^3.0.1", "@nestjs/swagger": "^6.2.1", "@nestjs/typeorm": "9.0.1", - "@qualweb/core": "0.7.73", + "@qualweb/core": "0.7.75", "axios": "^1.3.4", "bcrypt": "5.1.0", "body-parser": "^1.20.2", @@ -1910,11 +1910,11 @@ "integrity": "sha512-9Jr9tXU7OAOmXEOPBzd3F0FUpQsPtsAYh7pIyTxk5D3E4O8V3cUBqxwqZlZOQQIcvOrxq2VbszVprVHwHch4Jw==" }, "node_modules/@qualweb/core": { - "version": "0.7.73", - "resolved": "https://registry.npmjs.org/@qualweb/core/-/core-0.7.73.tgz", - "integrity": "sha512-joDSxV7tqP+dTaaG+AzUNbJ1FIjLEifRVxqYmrpFax8jKFWbq9oXguTPwupuzdtERfnmYEMl+zn+YsCjpvZvVw==", + "version": "0.7.75", + "resolved": "https://registry.npmjs.org/@qualweb/core/-/core-0.7.75.tgz", + "integrity": "sha512-SsfNFT3VQoZGWN/dyIrGsy/o/SEQi4YxQikKFlOKcPaP0p+ciOG2uQqUgBSRFqOwAD89QerN3B6fcsAD1Mr+Xw==", "dependencies": { - "@qualweb/crawler": "0.3.18", + "@qualweb/crawler": "0.3.20", "@qualweb/dom": "0.2.10", "@qualweb/earl-reporter": "0.4.6", "@qualweb/evaluation": "0.3.57", @@ -2065,9 +2065,9 @@ "integrity": "sha512-TdO2AwOWixsXT2kf0hVAwowJIS5TuBaZu5Z/0reHY+8fCMkZLulcNwmXZMmg3KBA17oPf4x9Y07X7SRyZuuC/A==" }, "node_modules/@qualweb/crawler": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@qualweb/crawler/-/crawler-0.3.18.tgz", - "integrity": "sha512-LMEnMwYVqbQCFf0EZDCNmY/XsWgwWc8QwB2oT3mRElOOMJI+WLMRWkjdkGebZwMmKmSDJoZT2xOx59VivZYQbQ==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@qualweb/crawler/-/crawler-0.3.20.tgz", + "integrity": "sha512-TSG9TV7V9afzO9ytdgLmEIt8SAMG9Pd+1e2t7SVrub2hqKuI8FrZI/827t2UmktsAoOdlyfnSEB0u/iYpSF2fw==", "dependencies": { "log-update": "4.0.0" }, @@ -13422,11 +13422,11 @@ "integrity": "sha512-9Jr9tXU7OAOmXEOPBzd3F0FUpQsPtsAYh7pIyTxk5D3E4O8V3cUBqxwqZlZOQQIcvOrxq2VbszVprVHwHch4Jw==" }, "@qualweb/core": { - "version": "0.7.73", - "resolved": "https://registry.npmjs.org/@qualweb/core/-/core-0.7.73.tgz", - "integrity": "sha512-joDSxV7tqP+dTaaG+AzUNbJ1FIjLEifRVxqYmrpFax8jKFWbq9oXguTPwupuzdtERfnmYEMl+zn+YsCjpvZvVw==", + "version": "0.7.75", + "resolved": "https://registry.npmjs.org/@qualweb/core/-/core-0.7.75.tgz", + "integrity": "sha512-SsfNFT3VQoZGWN/dyIrGsy/o/SEQi4YxQikKFlOKcPaP0p+ciOG2uQqUgBSRFqOwAD89QerN3B6fcsAD1Mr+Xw==", "requires": { - "@qualweb/crawler": "0.3.18", + "@qualweb/crawler": "0.3.20", "@qualweb/dom": "0.2.10", "@qualweb/earl-reporter": "0.4.6", "@qualweb/evaluation": "0.3.57", @@ -13522,9 +13522,9 @@ "integrity": "sha512-TdO2AwOWixsXT2kf0hVAwowJIS5TuBaZu5Z/0reHY+8fCMkZLulcNwmXZMmg3KBA17oPf4x9Y07X7SRyZuuC/A==" }, "@qualweb/crawler": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@qualweb/crawler/-/crawler-0.3.18.tgz", - "integrity": "sha512-LMEnMwYVqbQCFf0EZDCNmY/XsWgwWc8QwB2oT3mRElOOMJI+WLMRWkjdkGebZwMmKmSDJoZT2xOx59VivZYQbQ==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@qualweb/crawler/-/crawler-0.3.20.tgz", + "integrity": "sha512-TSG9TV7V9afzO9ytdgLmEIt8SAMG9Pd+1e2t7SVrub2hqKuI8FrZI/827t2UmktsAoOdlyfnSEB0u/iYpSF2fw==", "requires": { "log-update": "4.0.0" } diff --git a/package.json b/package.json index d9c03882..e3af98da 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@nestjs/serve-static": "^3.0.1", "@nestjs/swagger": "^6.2.1", "@nestjs/typeorm": "9.0.1", - "@qualweb/core": "0.7.73", + "@qualweb/core": "0.7.76", "axios": "^1.3.4", "bcrypt": "5.1.0", "body-parser": "^1.20.2", diff --git a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.controller.spec.ts b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.controller.spec.ts index 7c9f480c..df7f8c4c 100644 --- a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.controller.spec.ts +++ b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AccessibilityStatementController } from './accessibility-statement.controller'; -import { AccessibilityStatementService } from './accessibility-statement.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AccessibilityStatementController } from "./accessibility-statement.controller"; +import { AccessibilityStatementService } from "./accessibility-statement.service"; -describe('AccessibilityStatementController', () => { +describe("AccessibilityStatementController", () => { let controller: AccessibilityStatementController; beforeEach(async () => { @@ -11,10 +11,12 @@ describe('AccessibilityStatementController', () => { providers: [AccessibilityStatementService], }).compile(); - controller = module.get(AccessibilityStatementController); + controller = module.get( + AccessibilityStatementController + ); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.controller.ts b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.controller.ts index 98cae90f..245895eb 100644 --- a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.controller.ts +++ b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.controller.ts @@ -1,14 +1,26 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; -import { success } from 'src/lib/response'; -import { AccessibilityStatementService } from './accessibility-statement.service'; - -@Controller('accessibility-statement') +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from "@nestjs/common"; +import { success } from "src/lib/response"; +import { AccessibilityStatementService } from "./accessibility-statement.service"; + +@Controller("accessibility-statement") export class AccessibilityStatementController { - constructor(private readonly accessibilityStatementService: AccessibilityStatementService) {} - - @Get('website/:name') - async findOne(@Param('name') name: string) { - return success(await this.accessibilityStatementService.findByWebsiteName(name)); + constructor( + private readonly accessibilityStatementService: AccessibilityStatementService + ) {} + + @Get("website/:name") + async findOne(@Param("name") name: string) { + return success( + await this.accessibilityStatementService.findByWebsiteName(name) + ); } @Get() @@ -16,58 +28,65 @@ export class AccessibilityStatementController { return success(await this.accessibilityStatementService.getASList()); } - @Get('id/:id') - async findOneById(@Param('id') id: number) { + @Get("id/:id") + async findOneById(@Param("id") id: number) { return success(await this.accessibilityStatementService.findById(id)); } - @Get('year') + @Get("year") async findAllByYear() { return success(await this.accessibilityStatementService.getByAge()); } - @Get('conformance') + @Get("conformance") async findAllByConformance() { return success(await this.accessibilityStatementService.getByConformance()); } - @Get('seal') + @Get("seal") async findAllBySeal() { return success(await this.accessibilityStatementService.getBySeal()); } - @Get('state') + @Get("state") async findAllByState() { return success(await this.accessibilityStatementService.getByState()); } - @Get('directory/state') + @Get("directory/state") async findAllByDirectoryState() { - return success(await this.accessibilityStatementService.getByDirectoryState()); + return success( + await this.accessibilityStatementService.getByDirectoryState() + ); } - @Get('directory/seal') + @Get("directory/seal") async findAllByDirectorySeal() { - return success(await this.accessibilityStatementService.getByDirectorySeal()); + return success( + await this.accessibilityStatementService.getByDirectorySeal() + ); } - @Get('directory/conformance') + @Get("directory/conformance") async findAllByDirectoryConformity() { - return success(await this.accessibilityStatementService.getByDirectoryConformity()); + return success( + await this.accessibilityStatementService.getByDirectoryConformity() + ); } - - @Get('directory/OPAW') + @Get("directory/OPAW") async findAllByDirectoryWebsite() { return success(await this.accessibilityStatementService.getOPAWTable()); } - @Get('evaluations') + @Get("evaluations") async findNumberOfEvaluationByType() { - return success(await this.accessibilityStatementService.getNumberOfEvaluationByType()); + return success( + await this.accessibilityStatementService.getNumberOfEvaluationByType() + ); } - /* @Post() + /* @Post() create(@Body() createAccessibilityStatementDto: CreateAccessibilityStatementDto) { return this.accessibilityStatementService.create(createAccessibilityStatementDto); } diff --git a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.module.ts b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.module.ts index f0ee616e..3a13d9d9 100644 --- a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.module.ts +++ b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.module.ts @@ -1,18 +1,23 @@ -import { Module } from '@nestjs/common'; -import { AccessibilityStatementService } from './accessibility-statement.service'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { AccessibilityStatement } from './entities/accessibility-statement.entity'; -import { AutomaticEvaluationModule } from '../automatic-evaluation/automatic-evaluation.module'; -import { ManualEvaluationModule } from '../manual-evaluation/manual-evaluation.module'; -import { UserEvaluationModule } from '../user-evaluation/user-evaluation.module'; -import { ContactModule } from '../contact/contact.module'; -import { AccessibilityStatementController } from './accessibility-statement.controller'; +import { Module } from "@nestjs/common"; +import { AccessibilityStatementService } from "./accessibility-statement.service"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { AccessibilityStatement } from "./entities/accessibility-statement.entity"; +import { AutomaticEvaluationModule } from "../automatic-evaluation/automatic-evaluation.module"; +import { ManualEvaluationModule } from "../manual-evaluation/manual-evaluation.module"; +import { UserEvaluationModule } from "../user-evaluation/user-evaluation.module"; +import { ContactModule } from "../contact/contact.module"; +import { AccessibilityStatementController } from "./accessibility-statement.controller"; @Module({ controllers: [AccessibilityStatementController], imports: [ - TypeOrmModule.forFeature([AccessibilityStatement]), AutomaticEvaluationModule, ManualEvaluationModule, UserEvaluationModule, ContactModule], + TypeOrmModule.forFeature([AccessibilityStatement]), + AutomaticEvaluationModule, + ManualEvaluationModule, + UserEvaluationModule, + ContactModule, + ], providers: [AccessibilityStatementService], - exports: [AccessibilityStatementService] + exports: [AccessibilityStatementService], }) -export class AccessibilityStatementModule { } +export class AccessibilityStatementModule {} diff --git a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.service.spec.ts b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.service.spec.ts index cfdb05a8..2cf237d9 100644 --- a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.service.spec.ts +++ b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AccessibilityStatementService } from './accessibility-statement.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AccessibilityStatementService } from "./accessibility-statement.service"; -describe('AccessibilityStatementService', () => { +describe("AccessibilityStatementService", () => { let service: AccessibilityStatementService; beforeEach(async () => { @@ -9,10 +9,12 @@ describe('AccessibilityStatementService', () => { providers: [AccessibilityStatementService], }).compile(); - service = module.get(AccessibilityStatementService); + service = module.get( + AccessibilityStatementService + ); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.service.ts b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.service.ts index 90caeed5..6321a5b1 100644 --- a/src/accessibility-statement-module/accessibility-statement/accessibility-statement.service.ts +++ b/src/accessibility-statement-module/accessibility-statement/accessibility-statement.service.ts @@ -1,35 +1,40 @@ -import { Injectable } from '@nestjs/common'; -import { Repository } from 'typeorm'; -import { CreateAccessibilityStatementDto } from './dto/create-accessibility-statement.dto'; -import { AccessibilityStatement } from './entities/accessibility-statement.entity'; +import { Injectable } from "@nestjs/common"; +import { Repository } from "typeorm"; +import { CreateAccessibilityStatementDto } from "./dto/create-accessibility-statement.dto"; +import { AccessibilityStatement } from "./entities/accessibility-statement.entity"; import { InjectRepository } from "@nestjs/typeorm"; -import { PageParser } from './page-parser'; -import { AutomaticEvaluationService } from '../automatic-evaluation/automatic-evaluation.service'; -import { ManualEvaluationService } from '../manual-evaluation/manual-evaluation.service'; -import { UserEvaluationService } from '../user-evaluation/user-evaluation.service'; -import { CreateAutomaticEvaluationDto } from '../automatic-evaluation/dto/create-automatic-evaluation.dto'; -import { CreateManualEvaluationDto } from '../manual-evaluation/dto/create-manual-evaluation.dto'; -import { CreateUserEvaluationDto } from '../user-evaluation/dto/create-user-evaluation.dto'; -import { State } from './state'; -import { Website } from 'src/website/website.entity'; -import { CreateContactDto } from '../contact/dto/create-contact.dto'; -import { ContactService } from '../contact/contact.service'; -import { AccessibilityStatementDto } from './dto/accessibility-statement.dto'; -import { BRONZE, NAO_CONFORME, OURO, PARCIALMENTE_CONFORME, PLENAMENTE_CONFORME, PRATA } from './contants'; -var hash = require('object-hash'); +import { PageParser } from "./page-parser"; +import { AutomaticEvaluationService } from "../automatic-evaluation/automatic-evaluation.service"; +import { ManualEvaluationService } from "../manual-evaluation/manual-evaluation.service"; +import { UserEvaluationService } from "../user-evaluation/user-evaluation.service"; +import { CreateAutomaticEvaluationDto } from "../automatic-evaluation/dto/create-automatic-evaluation.dto"; +import { CreateManualEvaluationDto } from "../manual-evaluation/dto/create-manual-evaluation.dto"; +import { CreateUserEvaluationDto } from "../user-evaluation/dto/create-user-evaluation.dto"; +import { State } from "./state"; +import { Website } from "src/website/website.entity"; +import { CreateContactDto } from "../contact/dto/create-contact.dto"; +import { ContactService } from "../contact/contact.service"; +import { AccessibilityStatementDto } from "./dto/accessibility-statement.dto"; +import { + BRONZE, + NAO_CONFORME, + OURO, + PARCIALMENTE_CONFORME, + PLENAMENTE_CONFORME, + PRATA, +} from "./contants"; +var hash = require("object-hash"); @Injectable() export class AccessibilityStatementService { - constructor( @InjectRepository(AccessibilityStatement) private readonly accessibilityStatementRepository: Repository, private automaticEvaluationService: AutomaticEvaluationService, private manualEvaluationService: ManualEvaluationService, private userEvaluationService: UserEvaluationService, - private contactService: ContactService, - ) { - } + private contactService: ContactService + ) {} async createIfExist(html: string, website: Website, url: string) { const currentAS = await this.findLatestByWebsiteID(website.WebsiteId); @@ -39,23 +44,30 @@ export class AccessibilityStatementService { const currentHash = currentAS.hash; const currentDate = currentAS.statementDate; const newhash = hash(aStatementParsed); - const dateDiferent = currentDate.toISOString() !== aStatementParsed.statementDate.toISOString(); - + const dateDiferent = + currentDate.toISOString() !== + aStatementParsed.statementDate.toISOString(); + if (!dateDiferent && currentHash !== newhash) { this.deleteById(currentAS.Id); aStatement = this.createAStatement(aStatementParsed, website); } else if (dateDiferent) { aStatement = this.createAStatement(aStatementParsed, website); } - } - else if (aStatementParsed) + } else if (aStatementParsed) aStatement = this.createAStatement(aStatementParsed, website); - return aStatement + return aStatement; } - async parseAStatement(html: string, website: Website, url: string): Promise { + async parseAStatement( + html: string, + website: Website, + url: string + ): Promise { const pageParser = new PageParser(html); - if (!pageParser.verifyAccessiblityStatement() /*&& !pageParser.verifyAccessiblityPossibleStatement(url)*/) + if ( + !pageParser.verifyAccessiblityStatement() /*&& !pageParser.verifyAccessiblityPossibleStatement(url)*/ + ) return; const aStatementDto = pageParser.getAccessiblityStatementData(url); const autoList = pageParser.getAutomaticEvaluationData(); @@ -63,50 +75,79 @@ export class AccessibilityStatementService { const manualList = pageParser.getManualEvaluationData(); const contacts = pageParser.getContacts(); return { ...aStatementDto, autoList, userList, manualList, contacts }; - } - async createAStatement(aStatementParser: AccessibilityStatementDto, website: Website) { - const { autoList, userList, manualList, contacts, ...aStatementDto } = aStatementParser; + async createAStatement( + aStatementParser: AccessibilityStatementDto, + website: Website + ) { + const { autoList, userList, manualList, contacts, ...aStatementDto } = + aStatementParser; const hashResult = hash(aStatementParser); const state = this.calculateFlag(aStatementParser); let aStatement = await this.createDB({ ...aStatementDto, state }, website); - aStatement = await this.createLists(aStatement, autoList, manualList, userList); + aStatement = await this.createLists( + aStatement, + autoList, + manualList, + userList + ); aStatement = await this.createContacts(aStatement, contacts); this.updateHash(hashResult, aStatement.Id); return aStatement; } - - async createLists(aStatement: AccessibilityStatement, createAutomaticEvaluationList: CreateAutomaticEvaluationDto[], createManualEvaluationDto: CreateManualEvaluationDto[], createUserEvaluationDto: CreateUserEvaluationDto[]) { - aStatement.automaticEvaluationList = await Promise.all(createAutomaticEvaluationList.map(async (evalu) => { - return await this.automaticEvaluationService.create(evalu, aStatement); - })); - aStatement.manualEvaluationList = await Promise.all(createManualEvaluationDto.map(async (evalu) => { - return await this.manualEvaluationService.create(evalu, aStatement); - })); - aStatement.userEvaluationList = await Promise.all(createUserEvaluationDto.map(async (evalu) => { - return await this.userEvaluationService.create(evalu, aStatement); - })); + async createLists( + aStatement: AccessibilityStatement, + createAutomaticEvaluationList: CreateAutomaticEvaluationDto[], + createManualEvaluationDto: CreateManualEvaluationDto[], + createUserEvaluationDto: CreateUserEvaluationDto[] + ) { + aStatement.automaticEvaluationList = await Promise.all( + createAutomaticEvaluationList.map(async (evalu) => { + return await this.automaticEvaluationService.create(evalu, aStatement); + }) + ); + aStatement.manualEvaluationList = await Promise.all( + createManualEvaluationDto.map(async (evalu) => { + return await this.manualEvaluationService.create(evalu, aStatement); + }) + ); + aStatement.userEvaluationList = await Promise.all( + createUserEvaluationDto.map(async (evalu) => { + return await this.userEvaluationService.create(evalu, aStatement); + }) + ); return aStatement; } - async createContacts(aStatement: AccessibilityStatement, createContactList: CreateContactDto[]) { - await Promise.all(createContactList.map(async (contact) => { - return this.contactService.create(contact, aStatement) - })); + async createContacts( + aStatement: AccessibilityStatement, + createContactList: CreateContactDto[] + ) { + await Promise.all( + createContactList.map(async (contact) => { + return this.contactService.create(contact, aStatement); + }) + ); return aStatement; } async updateHash(hash: string, id: number) { - const aStatement = await this.accessibilityStatementRepository.findOne({where:{Id:id}}); + const aStatement = await this.accessibilityStatementRepository.findOne({ + where: { Id: id }, + }); aStatement.hash = hash; return this.accessibilityStatementRepository.save(aStatement); } - createDB(createAccessibilityStatementDto: CreateAccessibilityStatementDto, Website: Website) { + createDB( + createAccessibilityStatementDto: CreateAccessibilityStatementDto, + Website: Website + ) { const aStatement = this.accessibilityStatementRepository.create({ - ...createAccessibilityStatementDto, Website + ...createAccessibilityStatementDto, + Website, }); console.log({ aStatement, createAccessibilityStatementDto }); return this.accessibilityStatementRepository.save(aStatement); @@ -119,7 +160,7 @@ export class AccessibilityStatementService { const hasManualEval = acessibilityStatementDto.manualList.length > 0; let result; if (conformance && date && hasAutoEval && hasManualEval) { - result = State.completeStatement + result = State.completeStatement; } else if (!conformance && !date && !hasAutoEval && !hasManualEval) { result = State.possibleStatement; } else { @@ -129,22 +170,54 @@ export class AccessibilityStatementService { } findLatestByWebsiteID(WebsiteId: number) { - return this.accessibilityStatementRepository.findOne({ where: { Website: { WebsiteId } }, relations: ["manualEvaluationList", "automaticEvaluationList", "userEvaluationList", "Website"], order: { statementDate: "ASC" } }); + return this.accessibilityStatementRepository.findOne({ + where: { Website: { WebsiteId } }, + relations: [ + "manualEvaluationList", + "automaticEvaluationList", + "userEvaluationList", + "Website", + ], + order: { statementDate: "ASC" }, + }); } findByWebsiteName(Name: string) { - return this.accessibilityStatementRepository.findOne({ where: { Website: { Name } }, relations: ["manualEvaluationList", "automaticEvaluationList", "userEvaluationList", "Website"] }); + return this.accessibilityStatementRepository.findOne({ + where: { Website: { Name } }, + relations: [ + "manualEvaluationList", + "automaticEvaluationList", + "userEvaluationList", + "Website", + ], + }); } findById(Id: number): any { - return this.accessibilityStatementRepository.findOne({ where: { Id }, relations: ["manualEvaluationList", "automaticEvaluationList", "userEvaluationList", "Website"] }); + return this.accessibilityStatementRepository.findOne({ + where: { Id }, + relations: [ + "manualEvaluationList", + "automaticEvaluationList", + "userEvaluationList", + "Website", + ], + }); } deleteById(Id: number) { return this.accessibilityStatementRepository.delete({ Id }); } async getASList() { - const list = await this.accessibilityStatementRepository.find({ relations: ["manualEvaluationList", "automaticEvaluationList", "userEvaluationList", "Website"] }); + const list = await this.accessibilityStatementRepository.find({ + relations: [ + "manualEvaluationList", + "automaticEvaluationList", + "userEvaluationList", + "Website", + ], + }); const convertList = list.map((elem: any) => { elem.Website = elem.Website.Name; elem.manualEvaluationList = elem.manualEvaluationList.length; @@ -173,7 +246,7 @@ export class AccessibilityStatementService { const keys = Object.keys(result); const list = []; for (let key of keys) { - list.push({ [atributeName]: key, declarationNumber: result[key] }) + list.push({ [atributeName]: key, declarationNumber: result[key] }); } return list; } @@ -191,10 +264,14 @@ export class AccessibilityStatementService { case when ast.state = ? then 1 else 0 end ) as possibleStatement FROM - Accessibility_Statement as ast`, [State.completeStatement, State.incompleteStatement, State.possibleStatement] + Accessibility_Statement as ast`, + [ + State.completeStatement, + State.incompleteStatement, + State.possibleStatement, + ] ); return this.convertToAngularTable("state", result[0]); - } async getByConformance() { @@ -210,7 +287,8 @@ export class AccessibilityStatementService { case when ast.conformance = ? then 1 else 0 end ) as naoConforme FROM - Accessibility_Statement as ast`, [PLENAMENTE_CONFORME, PARCIALMENTE_CONFORME, NAO_CONFORME] + Accessibility_Statement as ast`, + [PLENAMENTE_CONFORME, PARCIALMENTE_CONFORME, NAO_CONFORME] ); //conversion to Angular table form @@ -230,7 +308,8 @@ export class AccessibilityStatementService { case when ast.seal = ? then 1 else 0 end ) as ouro FROM - Accessibility_Statement as ast`, [BRONZE, PRATA, OURO] + Accessibility_Statement as ast`, + [BRONZE, PRATA, OURO] ); return this.convertToAngularTable("seal", result[0]); @@ -255,7 +334,12 @@ export class AccessibilityStatementService { JOIN DirectoryTag as dt on dt.TagId = tw.TagId JOIN Directory as d on d.DirectoryId = dt.DirectoryId GROUP BY - d.Name`, [State.completeStatement, State.incompleteStatement, State.possibleStatement] + d.Name`, + [ + State.completeStatement, + State.incompleteStatement, + State.possibleStatement, + ] ); } @@ -278,7 +362,8 @@ export class AccessibilityStatementService { JOIN DirectoryTag as dt on dt.TagId = tw.TagId JOIN Directory as d on d.DirectoryId = dt.DirectoryId GROUP BY - d.Name`, [OURO, PRATA, BRONZE] + d.Name`, + [OURO, PRATA, BRONZE] ); } @@ -301,7 +386,8 @@ export class AccessibilityStatementService { JOIN DirectoryTag as dt on dt.TagId = tw.TagId JOIN Directory as d on d.DirectoryId = dt.DirectoryId GROUP BY - d.Name`, [PLENAMENTE_CONFORME, PARCIALMENTE_CONFORME, NAO_CONFORME] + d.Name`, + [PLENAMENTE_CONFORME, PARCIALMENTE_CONFORME, NAO_CONFORME] ); } private async getByDirectoryWebsiteLength() { @@ -333,7 +419,8 @@ export class AccessibilityStatementService { GROUP BY d.Name ORDER BY - d.Name`); + d.Name` + ); } async getOPAWTable() { @@ -347,11 +434,18 @@ export class AccessibilityStatementService { async getNumberOfEvaluationByType() { return [ - { type: "user", numberOfEvaluations: await this.userEvaluationService.getLength() }, - { type: "manual", numberOfEvaluations: await this.manualEvaluationService.getLength() }, - { type: "automatic", numberOfEvaluations: await this.automaticEvaluationService.getLength() } - ] + { + type: "user", + numberOfEvaluations: await this.userEvaluationService.getLength(), + }, + { + type: "manual", + numberOfEvaluations: await this.manualEvaluationService.getLength(), + }, + { + type: "automatic", + numberOfEvaluations: await this.automaticEvaluationService.getLength(), + }, + ]; } - - } diff --git a/src/accessibility-statement-module/accessibility-statement/contants.ts b/src/accessibility-statement-module/accessibility-statement/contants.ts index ee9855d5..75cbd57e 100644 --- a/src/accessibility-statement-module/accessibility-statement/contants.ts +++ b/src/accessibility-statement-module/accessibility-statement/contants.ts @@ -1,51 +1,78 @@ -const SELECTORS = ['.mr-manual-summary', '.mr-date', '.mr', '.mr-conformance-status', '.mr-t-type']; -const CONFORMANCE_OUTPUT = '.conformance-output'; -const DATE = '.mr-date'; -const TARGET_SELECTOR = '.target-type'; -const AUTOMATIC_EVALUATION = '.mr-automatic-summary'; -const MANUAL_EVALUATION = '.mr-manual-summary'; -const USER_EVALUATION = '.mr-users-summary'; -const CONTACTS = '.mr-contacts dl'; -const SEAL = '.mr-seal'; -const EVIDENCE = '#accstmnt_additional_evidence_summary'; +const SELECTORS = [ + ".mr-manual-summary", + ".mr-date", + ".mr", + ".mr-conformance-status", + ".mr-t-type", +]; +const CONFORMANCE_OUTPUT = ".conformance-output"; +const DATE = ".mr-date"; +const TARGET_SELECTOR = ".target-type"; +const AUTOMATIC_EVALUATION = ".mr-automatic-summary"; +const MANUAL_EVALUATION = ".mr-manual-summary"; +const USER_EVALUATION = ".mr-users-summary"; +const CONTACTS = ".mr-contacts dl"; +const SEAL = ".mr-seal"; +const EVIDENCE = "#accstmnt_additional_evidence_summary"; const AUTOMATIC_EVALUATION_ATTRIBUTES = { - //title conteudo a - //url link a - //date inicio entre parenteses - "Ferramenta utilizada": "Tool", - "Amostra": "Sample", - "Principais resultados (sumário)": "Summary" -} + //title conteudo a + //url link a + //date inicio entre parenteses + "Ferramenta utilizada": "Tool", + Amostra: "Sample", + "Principais resultados (sumário)": "Summary", +}; const MANUAL_EVALUATION_ATTRIBUTES = { - //title conteudo a - //url link a - //date inicio entre parenteses - "Ferramenta utilizada": "Tool", - "Amostra": "Sample", - "Principais resultados (heurísticas satisfeitas/total heurísticas aplicadas)": "Heuristics" -} + //title conteudo a + //url link a + //date inicio entre parenteses + "Ferramenta utilizada": "Tool", + Amostra: "Sample", + "Principais resultados (heurísticas satisfeitas/total heurísticas aplicadas)": + "Heuristics", +}; const USER_EVALUATION_ATTRIBUTES = { - //title conteudo a - //url link a - //date inicio entre parenteses - "Caraterização dos participantes": "Participants", - "Tarefas/Processos": "Process", - "Principais resultados (sumário)": "Summary" -} -const AUTOMATIC = 'automatic'; -const MANUAL = 'manual'; -const USER = 'user'; + //title conteudo a + //url link a + //date inicio entre parenteses + "Caraterização dos participantes": "Participants", + "Tarefas/Processos": "Process", + "Principais resultados (sumário)": "Summary", +}; +const AUTOMATIC = "automatic"; +const MANUAL = "manual"; +const USER = "user"; const PROCEDURE = { - automatic: { selector: AUTOMATIC_EVALUATION, data: AUTOMATIC_EVALUATION_ATTRIBUTES}, - manual: { selector: MANUAL_EVALUATION, data: MANUAL_EVALUATION_ATTRIBUTES }, - user: { selector: USER_EVALUATION, data: USER_EVALUATION_ATTRIBUTES } -} -const PLENAMENTE_CONFORME= "plenamente conforme"; + automatic: { + selector: AUTOMATIC_EVALUATION, + data: AUTOMATIC_EVALUATION_ATTRIBUTES, + }, + manual: { selector: MANUAL_EVALUATION, data: MANUAL_EVALUATION_ATTRIBUTES }, + user: { selector: USER_EVALUATION, data: USER_EVALUATION_ATTRIBUTES }, +}; +const PLENAMENTE_CONFORME = "plenamente conforme"; const PARCIALMENTE_CONFORME = "parcialmente conforme"; const NAO_CONFORME = "não conforme"; const OURO = "ouro"; const PRATA = "prata"; const BRONZE = "bronze"; -export { SELECTORS, CONFORMANCE_OUTPUT, DATE, TARGET_SELECTOR, SEAL, EVIDENCE, PROCEDURE, AUTOMATIC, MANUAL, USER, - CONTACTS, PLENAMENTE_CONFORME, PARCIALMENTE_CONFORME, NAO_CONFORME,OURO,PRATA,BRONZE} +export { + SELECTORS, + CONFORMANCE_OUTPUT, + DATE, + TARGET_SELECTOR, + SEAL, + EVIDENCE, + PROCEDURE, + AUTOMATIC, + MANUAL, + USER, + CONTACTS, + PLENAMENTE_CONFORME, + PARCIALMENTE_CONFORME, + NAO_CONFORME, + OURO, + PRATA, + BRONZE, +}; diff --git a/src/accessibility-statement-module/accessibility-statement/contantsTest.ts b/src/accessibility-statement-module/accessibility-statement/contantsTest.ts index dea45bbb..d82bd877 100644 --- a/src/accessibility-statement-module/accessibility-statement/contantsTest.ts +++ b/src/accessibility-statement-module/accessibility-statement/contantsTest.ts @@ -113,4 +113,4 @@ const HTML = ` `; -export { HTML} +export { HTML }; diff --git a/src/accessibility-statement-module/accessibility-statement/dto/accessibility-statement.dto.ts b/src/accessibility-statement-module/accessibility-statement/dto/accessibility-statement.dto.ts index 11147adb..4c40e2c0 100644 --- a/src/accessibility-statement-module/accessibility-statement/dto/accessibility-statement.dto.ts +++ b/src/accessibility-statement-module/accessibility-statement/dto/accessibility-statement.dto.ts @@ -5,13 +5,12 @@ import { CreateUserEvaluationDto } from "src/accessibility-statement-module/user import { State } from "../state"; export class AccessibilityStatementDto { - url: string; - conformance:string; - statementDate: Date; - state?:State; - autoList: Array; - userList: Array; - manualList: Array; - contacts: Array; - + url: string; + conformance: string; + statementDate: Date; + state?: State; + autoList: Array; + userList: Array; + manualList: Array; + contacts: Array; } diff --git a/src/accessibility-statement-module/accessibility-statement/dto/create-accessibility-statement.dto.ts b/src/accessibility-statement-module/accessibility-statement/dto/create-accessibility-statement.dto.ts index 17d1c7ce..f06e9090 100644 --- a/src/accessibility-statement-module/accessibility-statement/dto/create-accessibility-statement.dto.ts +++ b/src/accessibility-statement-module/accessibility-statement/dto/create-accessibility-statement.dto.ts @@ -1,8 +1,8 @@ import { State } from "../state"; export class CreateAccessibilityStatementDto { - url: string; - conformance:string; - statementDate: Date; - state?:State; + url: string; + conformance: string; + statementDate: Date; + state?: State; } diff --git a/src/accessibility-statement-module/accessibility-statement/dto/update-accessibility-statement.dto.ts b/src/accessibility-statement-module/accessibility-statement/dto/update-accessibility-statement.dto.ts index 2026b744..66523158 100644 --- a/src/accessibility-statement-module/accessibility-statement/dto/update-accessibility-statement.dto.ts +++ b/src/accessibility-statement-module/accessibility-statement/dto/update-accessibility-statement.dto.ts @@ -1,4 +1,6 @@ -import { PartialType } from '@nestjs/mapped-types'; -import { CreateAccessibilityStatementDto } from './create-accessibility-statement.dto'; +import { PartialType } from "@nestjs/mapped-types"; +import { CreateAccessibilityStatementDto } from "./create-accessibility-statement.dto"; -export class UpdateAccessibilityStatementDto extends PartialType(CreateAccessibilityStatementDto) {} +export class UpdateAccessibilityStatementDto extends PartialType( + CreateAccessibilityStatementDto +) {} diff --git a/src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity.ts b/src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity.ts index b2c84907..8aae26e7 100644 --- a/src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity.ts +++ b/src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity.ts @@ -2,78 +2,96 @@ import { AutomaticEvaluation } from "src/accessibility-statement-module/automati import { Contact } from "src/accessibility-statement-module/contact/entities/contact.entity"; import { ManualEvaluation } from "src/accessibility-statement-module/manual-evaluation/entities/manual-evaluation.entity"; import { Website } from "src/website/website.entity"; -import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm"; +import { + Column, + CreateDateColumn, + Entity, + JoinColumn, + ManyToOne, + OneToMany, + PrimaryGeneratedColumn, + UpdateDateColumn, +} from "typeorm"; import { Page } from "../../../page/page.entity"; import { UserEvaluation } from "../../user-evaluation/entities/user-evaluation.entity"; import { State } from "../state"; @Entity("Accessibility_Statement") export class AccessibilityStatement { - @PrimaryGeneratedColumn() - Id: number; + @PrimaryGeneratedColumn() + Id: number; - @CreateDateColumn() - CreatedAt: Date; + @CreateDateColumn() + CreatedAt: Date; - @UpdateDateColumn({ - type: "timestamp", - onUpdate: new Date().toString(), - nullable: true - }) - UpdatedAt: Date; + @UpdateDateColumn({ + type: "timestamp", + onUpdate: new Date().toString(), + nullable: true, + }) + UpdatedAt: Date; - @ManyToOne(type => Website, (website) => website.AStatements) - @JoinColumn({ name: "WebsiteId", referencedColumnName: "WebsiteId" }) - Website: Website; + @ManyToOne((type) => Website, (website) => website.AStatements) + @JoinColumn({ name: "WebsiteId", referencedColumnName: "WebsiteId" }) + Website: Website; - @Column({ - type: "varchar", - length: 255, - nullable: false, - }) - url:string; + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + url: string; - @Column({ - type: "varchar", - length: 255, - nullable: false, - }) - conformance: string; + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + conformance: string; - @Column({ - type: "text", - nullable: false, - }) - evidence: string; + @Column({ + type: "text", + nullable: false, + }) + evidence: string; - @Column({ - type: "varchar", - length: 255, - nullable: false, - }) - seal: string; + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + seal: string; - @Column({ - type: 'datetime', - nullable: true, - }) - statementDate: Date; + @Column({ + type: "datetime", + nullable: true, + }) + statementDate: Date; - @Column({ type: 'enum', enum: State }) - state: State; + @Column({ type: "enum", enum: State }) + state: State; - @Column({ type: 'varchar', length: 255}) - hash:string; + @Column({ type: "varchar", length: 255 }) + hash: string; - @OneToMany(type => ManualEvaluation, (evaluation) => evaluation.accessibilityStatement) - manualEvaluationList: ManualEvaluation[]; + @OneToMany( + (type) => ManualEvaluation, + (evaluation) => evaluation.accessibilityStatement + ) + manualEvaluationList: ManualEvaluation[]; - @OneToMany(type => AutomaticEvaluation, (evaluation) => evaluation.accessibilityStatement) - automaticEvaluationList: AutomaticEvaluation[]; + @OneToMany( + (type) => AutomaticEvaluation, + (evaluation) => evaluation.accessibilityStatement + ) + automaticEvaluationList: AutomaticEvaluation[]; - @OneToMany(type => UserEvaluation, (evaluation) => evaluation.accessibilityStatement) - userEvaluationList: UserEvaluation[]; + @OneToMany( + (type) => UserEvaluation, + (evaluation) => evaluation.accessibilityStatement + ) + userEvaluationList: UserEvaluation[]; - @OneToMany(type => Contact, (contact) => contact.acessiblityStatement) - contacts: Contact[]; + @OneToMany((type) => Contact, (contact) => contact.acessiblityStatement) + contacts: Contact[]; } diff --git a/src/accessibility-statement-module/accessibility-statement/page-parser-test.spec.ts b/src/accessibility-statement-module/accessibility-statement/page-parser-test.spec.ts index 602910d2..a7bacc81 100644 --- a/src/accessibility-statement-module/accessibility-statement/page-parser-test.spec.ts +++ b/src/accessibility-statement-module/accessibility-statement/page-parser-test.spec.ts @@ -1,25 +1,26 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { HTML } from './contantsTest'; -import { PageParser } from './page-parser'; -var hash = require('object-hash'); +import { Test, TestingModule } from "@nestjs/testing"; +import { HTML } from "./contantsTest"; +import { PageParser } from "./page-parser"; +var hash = require("object-hash"); -describe('PageParser', () => { +describe("PageParser", () => { let parser: PageParser; beforeEach(async () => { parser = new PageParser(HTML); }); - it('should be defined', () => { + it("should be defined", () => { expect(parser).toBeDefined(); - const result = parser.getAccessiblityStatementData("https://www.acessibilidade.gov.pt/acessibilidade/"); + const result = parser.getAccessiblityStatementData( + "https://www.acessibilidade.gov.pt/acessibilidade/" + ); console.log(result); const automatic = parser.getAutomaticEvaluationData(); const manual = parser.getManualEvaluationData(); const user = parser.getUserEvaluationData(); const contacts = parser.getContacts(); - console.log({automatic, manual, user,contacts}); + console.log({ automatic, manual, user, contacts }); console.log(hash({ automatic, manual, user, contacts })); - }); }); diff --git a/src/accessibility-statement-module/accessibility-statement/page-parser.ts b/src/accessibility-statement-module/accessibility-statement/page-parser.ts index 2d5c9d15..215a5f56 100644 --- a/src/accessibility-statement-module/accessibility-statement/page-parser.ts +++ b/src/accessibility-statement-module/accessibility-statement/page-parser.ts @@ -1,204 +1,203 @@ -import { AUTOMATIC, CONFORMANCE_OUTPUT, CONTACTS, DATE, EVIDENCE, MANUAL, PROCEDURE, SEAL, SELECTORS, USER } from "./contants"; +import { + AUTOMATIC, + CONFORMANCE_OUTPUT, + CONTACTS, + DATE, + EVIDENCE, + MANUAL, + PROCEDURE, + SEAL, + SELECTORS, + USER, +} from "./contants"; const htmlparser2 = require("htmlparser2"); const CSSselect = require("css-select"); export class PageParser { - public urls = new Array(); - private dom: any; - - constructor(html: string) { - this.dom = htmlparser2.parseDocument(html); - } - - public verifyAccessiblityPossibleStatement(url: string): boolean { - return url.includes("/acessibilidade") || this.verifyAccessiblityPossibleStatementTitle() - } - - public verifyAccessiblityPossibleStatementTitle(): boolean { - const title = CSSselect.selectOne('title', this.dom); - const h1 = CSSselect.selectOne('h1', this.dom); - let result = false; - if (h1) { - const text = this.getText(h1).toLowerCase(); - result = text.includes("acessibilidade") && text.includes("declaração"); - } - if (!result && title && title.data) { - const text = this.getText(title).toLowerCase(); - result = text.includes("acessibilidade") && text.includes("declaração"); - } - return result; - } - - - public verifyAccessiblityStatement(): boolean { - return SELECTORS.reduce((result, selector) => { - const list = CSSselect.selectAll(selector, this.dom); - return result && list.length > 0; - }, true); - } - public getConformance(): string { - return this.getDataFromSelector(CONFORMANCE_OUTPUT) - } - - public getSeal(): string { - return this.getDataFromSelector(SEAL) - } - - public getEvidence(): string { - return this.getDataFromSelector(EVIDENCE) - } - - public getDate(): Date { - const dateString = this.getDataFromSelector(DATE); - if (!dateString) - return null; - else { - return new Date(dateString) - } - } - - public getAccessiblityStatementData(url: string) { - return { - statementDate: this.getDate(), - evidence: this.getEvidence(), - seal: this.getSeal(), - conformance: this.getConformance(), - url, - } - } - - public getUserEvaluationData() { - try { - return this.processProcedure(USER); - } - catch (e) { - console.log(e); - return []; - } - } - - public getAutomaticEvaluationData() { - try { - return this.processProcedure(AUTOMATIC); - } - catch (e) { - console.log(e); - return []; - } - } - - public getManualEvaluationData() { - try { - return this.processProcedure(MANUAL); - } - catch (e) { - console.log(e); - return []; - } - } - - public processProcedure(procedure) { - const procedureJson = PROCEDURE[procedure]; - const selector = procedureJson.selector; - const element = CSSselect.selectOne(selector, this.dom); - if (!element) - return []; - const list = CSSselect.selectOne('ol', element); - const listElements = list.children; - const data = procedureJson.data; - return listElements.flatMap((li) => { - if (li.name === 'li') - return this.processProcedureElement(data, li); - else - return []; - }); - } - private processProcedureElement(data, element) { - const Date = this.getDateProcedure(element); - const link = CSSselect.selectOne('a', element); - const Url = link.attribs.href; - const Title = this.getText(link); - const otherData = this.getOtherProcedureData(element, data); - return { Date, Url, Title, ...otherData }; - } - - private getOtherProcedureData(element, data) { - const list = CSSselect.selectOne('ul', element); - const listElements = list.children; - const result = {}; - listElements.flatMap((li) => { - const text = this.getText(li); - if (text && text.trim()) { - const splittedText = text.split(":"); - const attName = splittedText[0]; - let content = splittedText[1]; - if (attName === 'Amostra') - content = content.replace(/[^\d]/g, ''); - result[data[attName]] = content; - } - else - return []; - }); - return result; - } - - - private getDateProcedure(element) { - const text = this.getText(element); - const splittedText = text.split(/[()]/); - return splittedText[1]; - } - - - private getDataFromSelector(select: string) { - const element = CSSselect.selectOne(select, this.dom); - if (!element) - return null; - else { - return this.getText(element); - } - } - - private getText(element: any): string { - const children = element.children; - let text = ""; - if (element.type === 'text') - text = text + element.data; - children?.map((child) => { - text = text + this.getTextRecursion(child) - }); - return text; - } - private getTextAux(element: any): string { - const children = element.children; - let text = ""; - children?.map((child) => { - text = text + this.getTextRecursion(child) + public urls = new Array(); + private dom: any; + + constructor(html: string) { + this.dom = htmlparser2.parseDocument(html); + } + + public verifyAccessiblityPossibleStatement(url: string): boolean { + return ( + url.includes("/acessibilidade") || + this.verifyAccessiblityPossibleStatementTitle() + ); + } + + public verifyAccessiblityPossibleStatementTitle(): boolean { + const title = CSSselect.selectOne("title", this.dom); + const h1 = CSSselect.selectOne("h1", this.dom); + let result = false; + if (h1) { + const text = this.getText(h1).toLowerCase(); + result = text.includes("acessibilidade") && text.includes("declaração"); + } + if (!result && title && title.data) { + const text = this.getText(title).toLowerCase(); + result = text.includes("acessibilidade") && text.includes("declaração"); + } + return result; + } + + public verifyAccessiblityStatement(): boolean { + return SELECTORS.reduce((result, selector) => { + const list = CSSselect.selectAll(selector, this.dom); + return result && list.length > 0; + }, true); + } + public getConformance(): string { + return this.getDataFromSelector(CONFORMANCE_OUTPUT); + } + + public getSeal(): string { + return this.getDataFromSelector(SEAL); + } + + public getEvidence(): string { + return this.getDataFromSelector(EVIDENCE); + } + + public getDate(): Date { + const dateString = this.getDataFromSelector(DATE); + if (!dateString) return null; + else { + return new Date(dateString); + } + } + + public getAccessiblityStatementData(url: string) { + return { + statementDate: this.getDate(), + evidence: this.getEvidence(), + seal: this.getSeal(), + conformance: this.getConformance(), + url, + }; + } + + public getUserEvaluationData() { + try { + return this.processProcedure(USER); + } catch (e) { + console.log(e); + return []; + } + } + + public getAutomaticEvaluationData() { + try { + return this.processProcedure(AUTOMATIC); + } catch (e) { + console.log(e); + return []; + } + } + + public getManualEvaluationData() { + try { + return this.processProcedure(MANUAL); + } catch (e) { + console.log(e); + return []; + } + } + + public processProcedure(procedure) { + const procedureJson = PROCEDURE[procedure]; + const selector = procedureJson.selector; + const element = CSSselect.selectOne(selector, this.dom); + if (!element) return []; + const list = CSSselect.selectOne("ol", element); + const listElements = list.children; + const data = procedureJson.data; + return listElements.flatMap((li) => { + if (li.name === "li") return this.processProcedureElement(data, li); + else return []; + }); + } + private processProcedureElement(data, element) { + const Date = this.getDateProcedure(element); + const link = CSSselect.selectOne("a", element); + const Url = link.attribs.href; + const Title = this.getText(link); + const otherData = this.getOtherProcedureData(element, data); + return { Date, Url, Title, ...otherData }; + } + + private getOtherProcedureData(element, data) { + const list = CSSselect.selectOne("ul", element); + const listElements = list.children; + const result = {}; + listElements.flatMap((li) => { + const text = this.getText(li); + if (text && text.trim()) { + const splittedText = text.split(":"); + const attName = splittedText[0]; + let content = splittedText[1]; + if (attName === "Amostra") content = content.replace(/[^\d]/g, ""); + result[data[attName]] = content; + } else return []; + }); + return result; + } + + private getDateProcedure(element) { + const text = this.getText(element); + const splittedText = text.split(/[()]/); + return splittedText[1]; + } + + private getDataFromSelector(select: string) { + const element = CSSselect.selectOne(select, this.dom); + if (!element) return null; + else { + return this.getText(element); + } + } + + private getText(element: any): string { + const children = element.children; + let text = ""; + if (element.type === "text") text = text + element.data; + children?.map((child) => { + text = text + this.getTextRecursion(child); + }); + return text; + } + private getTextAux(element: any): string { + const children = element.children; + let text = ""; + children?.map((child) => { + text = text + this.getTextRecursion(child); + }); + return text; + } + private getTextRecursion(child) { + let text = ""; + if (child.type === "text") text = text + child.data; + text = text + this.getTextAux(child); + return text; + } + public getContacts() { + const dl = CSSselect.selectOne(CONTACTS, this.dom); + const children = dl?.children; + const contacts = []; + children?.map((element, index) => { + const name = element.name; + if (name === "dd") { + const previousElement = children[index - 1]; + const previousElementText = this.getText(previousElement); + const elementText = this.getText(element); + contacts.push({ + contactType: previousElementText, + contact: elementText, }); - return text; - } - private getTextRecursion(child) { - let text = ""; - if (child.type === 'text') - text = text + child.data; - text = text + this.getTextAux(child); - return text; - } - public getContacts() { - const dl = CSSselect.selectOne(CONTACTS, this.dom); - const children = dl?.children; - const contacts = []; - children?.map((element, index) => { - const name = element.name; - if (name === 'dd') { - const previousElement = children[index - 1]; - const previousElementText = this.getText(previousElement); - const elementText = this.getText(element); - contacts.push({ contactType:previousElementText,contact:elementText}); - } - }) - return contacts; - - - } + } + }); + return contacts; + } } diff --git a/src/accessibility-statement-module/accessibility-statement/state.ts b/src/accessibility-statement-module/accessibility-statement/state.ts index bb0fbe08..e0d40052 100644 --- a/src/accessibility-statement-module/accessibility-statement/state.ts +++ b/src/accessibility-statement-module/accessibility-statement/state.ts @@ -1,5 +1,5 @@ export enum State { - completeStatement = 'completeStatement', - incompleteStatement = 'incompleteStatement', - possibleStatement = 'possibleStatement', + completeStatement = "completeStatement", + incompleteStatement = "incompleteStatement", + possibleStatement = "possibleStatement", } diff --git a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.controller.spec.ts b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.controller.spec.ts index 551b9c82..99a0d414 100644 --- a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.controller.spec.ts +++ b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AutomaticEvaluationController } from './automatic-evaluation.controller'; -import { AutomaticEvaluationService } from './automatic-evaluation.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AutomaticEvaluationController } from "./automatic-evaluation.controller"; +import { AutomaticEvaluationService } from "./automatic-evaluation.service"; -describe('AutomaticEvaluationController', () => { +describe("AutomaticEvaluationController", () => { let controller: AutomaticEvaluationController; beforeEach(async () => { @@ -11,10 +11,12 @@ describe('AutomaticEvaluationController', () => { providers: [AutomaticEvaluationService], }).compile(); - controller = module.get(AutomaticEvaluationController); + controller = module.get( + AutomaticEvaluationController + ); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.controller.ts b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.controller.ts index 81390341..727eeb15 100644 --- a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.controller.ts +++ b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.controller.ts @@ -1,12 +1,22 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; -import { AutomaticEvaluationService } from './automatic-evaluation.service'; -import { CreateAutomaticEvaluationDto } from './dto/create-automatic-evaluation.dto'; -import { UpdateAutomaticEvaluationDto } from './dto/update-automatic-evaluation.dto'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from "@nestjs/common"; +import { AutomaticEvaluationService } from "./automatic-evaluation.service"; +import { CreateAutomaticEvaluationDto } from "./dto/create-automatic-evaluation.dto"; +import { UpdateAutomaticEvaluationDto } from "./dto/update-automatic-evaluation.dto"; -@Controller('automatic-evaluation') +@Controller("automatic-evaluation") export class AutomaticEvaluationController { - constructor(private readonly automaticEvaluationService: AutomaticEvaluationService) {} -/* + constructor( + private readonly automaticEvaluationService: AutomaticEvaluationService + ) {} + /* @Post() create(@Body() createAutomaticEvaluationDto: CreateAutomaticEvaluationDto) { return this.automaticEvaluationService.create(createAutomaticEvaluationDto); diff --git a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.module.ts b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.module.ts index 10226383..7ddf482c 100644 --- a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.module.ts +++ b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.module.ts @@ -1,11 +1,11 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { AutomaticEvaluationService } from './automatic-evaluation.service'; -import { AutomaticEvaluation } from './entities/automatic-evaluation.entity'; +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { AutomaticEvaluationService } from "./automatic-evaluation.service"; +import { AutomaticEvaluation } from "./entities/automatic-evaluation.entity"; @Module({ - imports:[ TypeOrmModule.forFeature([AutomaticEvaluation])], + imports: [TypeOrmModule.forFeature([AutomaticEvaluation])], providers: [AutomaticEvaluationService], - exports: [AutomaticEvaluationService] + exports: [AutomaticEvaluationService], }) export class AutomaticEvaluationModule {} diff --git a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.service.spec.ts b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.service.spec.ts index 78c4f9d1..1e517d96 100644 --- a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.service.spec.ts +++ b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AutomaticEvaluationService } from './automatic-evaluation.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AutomaticEvaluationService } from "./automatic-evaluation.service"; -describe('AutomaticEvaluationService', () => { +describe("AutomaticEvaluationService", () => { let service: AutomaticEvaluationService; beforeEach(async () => { @@ -9,10 +9,12 @@ describe('AutomaticEvaluationService', () => { providers: [AutomaticEvaluationService], }).compile(); - service = module.get(AutomaticEvaluationService); + service = module.get( + AutomaticEvaluationService + ); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.service.ts b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.service.ts index bb10c961..97be9252 100644 --- a/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.service.ts +++ b/src/accessibility-statement-module/automatic-evaluation/automatic-evaluation.service.ts @@ -1,25 +1,32 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { AccessibilityStatement } from '../accessibility-statement/entities/accessibility-statement.entity'; -import { CreateAutomaticEvaluationDto } from './dto/create-automatic-evaluation.dto'; -import { AutomaticEvaluation } from './entities/automatic-evaluation.entity'; +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; +import { AccessibilityStatement } from "../accessibility-statement/entities/accessibility-statement.entity"; +import { CreateAutomaticEvaluationDto } from "./dto/create-automatic-evaluation.dto"; +import { AutomaticEvaluation } from "./entities/automatic-evaluation.entity"; @Injectable() export class AutomaticEvaluationService { constructor( @InjectRepository(AutomaticEvaluation) - private readonly automaticEvaluationRepository: Repository) { - } - create(createAutomaticEvaluationDto: CreateAutomaticEvaluationDto, accessibilityStatement: AccessibilityStatement) { + private readonly automaticEvaluationRepository: Repository + ) {} + create( + createAutomaticEvaluationDto: CreateAutomaticEvaluationDto, + accessibilityStatement: AccessibilityStatement + ) { const evaluation = this.automaticEvaluationRepository.create({ - ...createAutomaticEvaluationDto, accessibilityStatement + ...createAutomaticEvaluationDto, + accessibilityStatement, }); return this.automaticEvaluationRepository.save(evaluation); } - async getLength(){ - return (await this.automaticEvaluationRepository.query(`SELECT COUNT(*) as length FROM Automatic_Evaluation`))[0].length; + async getLength() { + return ( + await this.automaticEvaluationRepository.query( + `SELECT COUNT(*) as length FROM Automatic_Evaluation` + ) + )[0].length; } - } diff --git a/src/accessibility-statement-module/automatic-evaluation/dto/create-automatic-evaluation.dto.ts b/src/accessibility-statement-module/automatic-evaluation/dto/create-automatic-evaluation.dto.ts index 8bf34054..e179fdf1 100644 --- a/src/accessibility-statement-module/automatic-evaluation/dto/create-automatic-evaluation.dto.ts +++ b/src/accessibility-statement-module/automatic-evaluation/dto/create-automatic-evaluation.dto.ts @@ -1,8 +1,8 @@ export class CreateAutomaticEvaluationDto { - Title: string; - Url: string; - Sample: string; - Tool: string; - Summary: string; - Date: Date; + Title: string; + Url: string; + Sample: string; + Tool: string; + Summary: string; + Date: Date; } diff --git a/src/accessibility-statement-module/automatic-evaluation/dto/update-automatic-evaluation.dto.ts b/src/accessibility-statement-module/automatic-evaluation/dto/update-automatic-evaluation.dto.ts index 8ace159c..b54fe406 100644 --- a/src/accessibility-statement-module/automatic-evaluation/dto/update-automatic-evaluation.dto.ts +++ b/src/accessibility-statement-module/automatic-evaluation/dto/update-automatic-evaluation.dto.ts @@ -1,4 +1,6 @@ -import { PartialType } from '@nestjs/mapped-types'; -import { CreateAutomaticEvaluationDto } from './create-automatic-evaluation.dto'; +import { PartialType } from "@nestjs/mapped-types"; +import { CreateAutomaticEvaluationDto } from "./create-automatic-evaluation.dto"; -export class UpdateAutomaticEvaluationDto extends PartialType(CreateAutomaticEvaluationDto) {} +export class UpdateAutomaticEvaluationDto extends PartialType( + CreateAutomaticEvaluationDto +) {} diff --git a/src/accessibility-statement-module/automatic-evaluation/entities/automatic-evaluation.entity.ts b/src/accessibility-statement-module/automatic-evaluation/entities/automatic-evaluation.entity.ts index 90af6104..bc81f339 100644 --- a/src/accessibility-statement-module/automatic-evaluation/entities/automatic-evaluation.entity.ts +++ b/src/accessibility-statement-module/automatic-evaluation/entities/automatic-evaluation.entity.ts @@ -1,53 +1,61 @@ import { AccessibilityStatement } from "src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity"; -import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, PrimaryGeneratedColumn} from "typeorm"; +import { + Column, + Entity, + JoinColumn, + ManyToMany, + ManyToOne, + PrimaryGeneratedColumn, +} from "typeorm"; @Entity("Automatic_Evaluation") export class AutomaticEvaluation { - @PrimaryGeneratedColumn() - Id: number; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Title: string; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Url: string; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Sample: string; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Tool: string; - - @Column({ - type: 'text', - nullable: true - }) - Summary: string; - - @Column({ - type: 'datetime', - nullable: true, - }) - Date: any; - - @ManyToOne((type => AccessibilityStatement), (accessibilityStatement) => accessibilityStatement.automaticEvaluationList) - @JoinColumn({ name: "Accessibility_Statement_Id"}) - accessibilityStatement: AccessibilityStatement; - - + @PrimaryGeneratedColumn() + Id: number; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Title: string; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Url: string; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Sample: string; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Tool: string; + + @Column({ + type: "text", + nullable: true, + }) + Summary: string; + + @Column({ + type: "datetime", + nullable: true, + }) + Date: any; + + @ManyToOne( + (type) => AccessibilityStatement, + (accessibilityStatement) => accessibilityStatement.automaticEvaluationList + ) + @JoinColumn({ name: "Accessibility_Statement_Id" }) + accessibilityStatement: AccessibilityStatement; } diff --git a/src/accessibility-statement-module/collection-date/collection-date.controller.spec.ts b/src/accessibility-statement-module/collection-date/collection-date.controller.spec.ts index a2e03f6f..40332dea 100644 --- a/src/accessibility-statement-module/collection-date/collection-date.controller.spec.ts +++ b/src/accessibility-statement-module/collection-date/collection-date.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { CollectionDateController } from './collection-date.controller'; -import { CollectionDateService } from './collection-date.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { CollectionDateController } from "./collection-date.controller"; +import { CollectionDateService } from "./collection-date.service"; -describe('CollectionDateController', () => { +describe("CollectionDateController", () => { let controller: CollectionDateController; beforeEach(async () => { @@ -14,7 +14,7 @@ describe('CollectionDateController', () => { controller = module.get(CollectionDateController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/collection-date/collection-date.controller.ts b/src/accessibility-statement-module/collection-date/collection-date.controller.ts index 9e6a1ebc..65211c76 100644 --- a/src/accessibility-statement-module/collection-date/collection-date.controller.ts +++ b/src/accessibility-statement-module/collection-date/collection-date.controller.ts @@ -1,9 +1,16 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; -import { CollectionDateService } from './collection-date.service'; -import { success } from 'src/lib/response'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from "@nestjs/common"; +import { CollectionDateService } from "./collection-date.service"; +import { success } from "src/lib/response"; - -@Controller('collection-date') +@Controller("collection-date") export class CollectionDateController { constructor(private readonly collectionDateService: CollectionDateService) {} @@ -11,5 +18,4 @@ export class CollectionDateController { async findLatest() { return success(await this.collectionDateService.findLatest()); } - } diff --git a/src/accessibility-statement-module/collection-date/collection-date.module.ts b/src/accessibility-statement-module/collection-date/collection-date.module.ts index 90f977e0..7db8c8fc 100644 --- a/src/accessibility-statement-module/collection-date/collection-date.module.ts +++ b/src/accessibility-statement-module/collection-date/collection-date.module.ts @@ -1,13 +1,13 @@ -import { Module } from '@nestjs/common'; -import { CollectionDateService } from './collection-date.service'; -import { CollectionDateController } from './collection-date.controller'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { CollectionDate } from './entities/collection-date.entity'; +import { Module } from "@nestjs/common"; +import { CollectionDateService } from "./collection-date.service"; +import { CollectionDateController } from "./collection-date.controller"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { CollectionDate } from "./entities/collection-date.entity"; @Module({ imports: [TypeOrmModule.forFeature([CollectionDate])], controllers: [CollectionDateController], providers: [CollectionDateService], - exports: [CollectionDateService] + exports: [CollectionDateService], }) export class CollectionDateModule {} diff --git a/src/accessibility-statement-module/collection-date/collection-date.service.spec.ts b/src/accessibility-statement-module/collection-date/collection-date.service.spec.ts index 564dc5d1..caab230d 100644 --- a/src/accessibility-statement-module/collection-date/collection-date.service.spec.ts +++ b/src/accessibility-statement-module/collection-date/collection-date.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { CollectionDateService } from './collection-date.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { CollectionDateService } from "./collection-date.service"; -describe('CollectionDateService', () => { +describe("CollectionDateService", () => { let service: CollectionDateService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('CollectionDateService', () => { service = module.get(CollectionDateService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/collection-date/collection-date.service.ts b/src/accessibility-statement-module/collection-date/collection-date.service.ts index 1ed69f24..c568feb3 100644 --- a/src/accessibility-statement-module/collection-date/collection-date.service.ts +++ b/src/accessibility-statement-module/collection-date/collection-date.service.ts @@ -1,23 +1,26 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { CollectionDate } from './entities/collection-date.entity'; +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; +import { CollectionDate } from "./entities/collection-date.entity"; @Injectable() export class CollectionDateService { - constructor( @InjectRepository(CollectionDate) - private readonly collectionDateRepository: Repository) { - } + private readonly collectionDateRepository: Repository + ) {} create() { - const collection = this.collectionDateRepository.create({ createdAt: new Date() }); + const collection = this.collectionDateRepository.create({ + createdAt: new Date(), + }); return this.collectionDateRepository.save(collection); } findLatest() { - return this.collectionDateRepository.findOne({ where: {}, order: { createdAt: 'DESC' } }); + return this.collectionDateRepository.findOne({ + where: {}, + order: { createdAt: "DESC" }, + }); } - } diff --git a/src/accessibility-statement-module/collection-date/entities/collection-date.entity.ts b/src/accessibility-statement-module/collection-date/entities/collection-date.entity.ts index 9a575fb3..a138bbef 100644 --- a/src/accessibility-statement-module/collection-date/entities/collection-date.entity.ts +++ b/src/accessibility-statement-module/collection-date/entities/collection-date.entity.ts @@ -2,9 +2,9 @@ import { Entity, PrimaryGeneratedColumn, CreateDateColumn } from "typeorm"; @Entity("Collection_Date") export class CollectionDate { - @PrimaryGeneratedColumn({name: "Id"}) - id: number; + @PrimaryGeneratedColumn({ name: "Id" }) + id: number; - @CreateDateColumn({name:"CreatedAt"}) - createdAt: Date; -} \ No newline at end of file + @CreateDateColumn({ name: "CreatedAt" }) + createdAt: Date; +} diff --git a/src/accessibility-statement-module/contact/contact.controller.spec.ts b/src/accessibility-statement-module/contact/contact.controller.spec.ts index 7b890b0c..bc4a8d96 100644 --- a/src/accessibility-statement-module/contact/contact.controller.spec.ts +++ b/src/accessibility-statement-module/contact/contact.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ContactController } from './contact.controller'; -import { ContactService } from './contact.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { ContactController } from "./contact.controller"; +import { ContactService } from "./contact.service"; -describe('ContactController', () => { +describe("ContactController", () => { let controller: ContactController; beforeEach(async () => { @@ -14,7 +14,7 @@ describe('ContactController', () => { controller = module.get(ContactController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/contact/contact.controller.ts b/src/accessibility-statement-module/contact/contact.controller.ts index cdb7c205..d6d00e74 100644 --- a/src/accessibility-statement-module/contact/contact.controller.ts +++ b/src/accessibility-statement-module/contact/contact.controller.ts @@ -1,7 +1,15 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; -import { ContactService } from './contact.service'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from "@nestjs/common"; +import { ContactService } from "./contact.service"; -@Controller('contact') +@Controller("contact") export class ContactController { constructor(private readonly contactService: ContactService) {} } diff --git a/src/accessibility-statement-module/contact/contact.module.ts b/src/accessibility-statement-module/contact/contact.module.ts index a07932d0..08825bd1 100644 --- a/src/accessibility-statement-module/contact/contact.module.ts +++ b/src/accessibility-statement-module/contact/contact.module.ts @@ -1,13 +1,13 @@ -import { Module } from '@nestjs/common'; -import { ContactService } from './contact.service'; -import { ContactController } from './contact.controller'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { Contact } from './entities/contact.entity'; +import { Module } from "@nestjs/common"; +import { ContactService } from "./contact.service"; +import { ContactController } from "./contact.controller"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { Contact } from "./entities/contact.entity"; @Module({ imports: [TypeOrmModule.forFeature([Contact])], controllers: [ContactController], providers: [ContactService], - exports:[ContactService] + exports: [ContactService], }) export class ContactModule {} diff --git a/src/accessibility-statement-module/contact/contact.service.spec.ts b/src/accessibility-statement-module/contact/contact.service.spec.ts index 20040c84..b4b2cc13 100644 --- a/src/accessibility-statement-module/contact/contact.service.spec.ts +++ b/src/accessibility-statement-module/contact/contact.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ContactService } from './contact.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { ContactService } from "./contact.service"; -describe('ContactService', () => { +describe("ContactService", () => { let service: ContactService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('ContactService', () => { service = module.get(ContactService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/contact/contact.service.ts b/src/accessibility-statement-module/contact/contact.service.ts index 6683282a..59e34835 100644 --- a/src/accessibility-statement-module/contact/contact.service.ts +++ b/src/accessibility-statement-module/contact/contact.service.ts @@ -1,25 +1,29 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { AccessibilityStatement } from '../accessibility-statement/entities/accessibility-statement.entity'; -import { CreateContactDto } from './dto/create-contact.dto'; -import { Contact } from './entities/contact.entity'; +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; +import { AccessibilityStatement } from "../accessibility-statement/entities/accessibility-statement.entity"; +import { CreateContactDto } from "./dto/create-contact.dto"; +import { Contact } from "./entities/contact.entity"; @Injectable() export class ContactService { constructor( @InjectRepository(Contact) - private readonly contactRepository: Repository) { - } - - create(createContactDto: CreateContactDto,acessiblityStatement: AccessibilityStatement) { + private readonly contactRepository: Repository + ) {} + + create( + createContactDto: CreateContactDto, + acessiblityStatement: AccessibilityStatement + ) { const contact = this.contactRepository.create({ - ...createContactDto, acessiblityStatement - }); + ...createContactDto, + acessiblityStatement, + }); return this.contactRepository.save(contact); } - getContactsByWebsite(){ + getContactsByWebsite() { this.contactRepository.query( `select w.Name, @@ -29,6 +33,7 @@ export class ContactService { join Accessibility_Statement as st on st.Id = c.Accessibility_Statement_Id join Website as w on w.WebsiteId = st.WebsiteId where - c.Contact is not null`); + c.Contact is not null` + ); } } diff --git a/src/accessibility-statement-module/contact/dto/create-contact.dto.ts b/src/accessibility-statement-module/contact/dto/create-contact.dto.ts index 2f379f94..aff818a1 100644 --- a/src/accessibility-statement-module/contact/dto/create-contact.dto.ts +++ b/src/accessibility-statement-module/contact/dto/create-contact.dto.ts @@ -1,4 +1,4 @@ export class CreateContactDto { - contactType: string; - contact: string; + contactType: string; + contact: string; } diff --git a/src/accessibility-statement-module/contact/entities/contact.entity.ts b/src/accessibility-statement-module/contact/entities/contact.entity.ts index 3f0778d0..355becd0 100644 --- a/src/accessibility-statement-module/contact/entities/contact.entity.ts +++ b/src/accessibility-statement-module/contact/entities/contact.entity.ts @@ -1,25 +1,33 @@ import { AccessibilityStatement } from "src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity"; -import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { + Column, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, +} from "typeorm"; @Entity("Contact") export class Contact { + @PrimaryGeneratedColumn() + Id: number; - @PrimaryGeneratedColumn() - Id: number; + @Column({ + type: "varchar", + length: 255, + }) + ContactType: string; - @Column({ - type: "varchar", - length: 255, - }) - ContactType:string; + @Column({ + type: "varchar", + length: 255, + }) + Contact: string; - @Column({ - type: "varchar", - length: 255, - }) - Contact:string; - - @ManyToOne(type => AccessibilityStatement, (statement) => statement.contacts) - @JoinColumn({ name: "Accessibility_Statement_Id" }) - acessiblityStatement:AccessibilityStatement; + @ManyToOne( + (type) => AccessibilityStatement, + (statement) => statement.contacts + ) + @JoinColumn({ name: "Accessibility_Statement_Id" }) + acessiblityStatement: AccessibilityStatement; } diff --git a/src/accessibility-statement-module/manual-evaluation/dto/create-manual-evaluation.dto.ts b/src/accessibility-statement-module/manual-evaluation/dto/create-manual-evaluation.dto.ts index 4b0dd1bf..b443955b 100644 --- a/src/accessibility-statement-module/manual-evaluation/dto/create-manual-evaluation.dto.ts +++ b/src/accessibility-statement-module/manual-evaluation/dto/create-manual-evaluation.dto.ts @@ -1,8 +1,8 @@ -export class CreateManualEvaluationDto { - Title: string; - Url: string; - Sample: string; - Heuristics: string; - Summary: string; - Date: Date; -} +export class CreateManualEvaluationDto { + Title: string; + Url: string; + Sample: string; + Heuristics: string; + Summary: string; + Date: Date; +} diff --git a/src/accessibility-statement-module/manual-evaluation/dto/update-manual-evaluation.dto.ts b/src/accessibility-statement-module/manual-evaluation/dto/update-manual-evaluation.dto.ts index 7ebb95b3..7e61cbb9 100644 --- a/src/accessibility-statement-module/manual-evaluation/dto/update-manual-evaluation.dto.ts +++ b/src/accessibility-statement-module/manual-evaluation/dto/update-manual-evaluation.dto.ts @@ -1,4 +1,6 @@ -import { PartialType } from '@nestjs/mapped-types'; -import { CreateManualEvaluationDto } from './create-manual-evaluation.dto'; - -export class UpdateManualEvaluationDto extends PartialType(CreateManualEvaluationDto) {} +import { PartialType } from "@nestjs/mapped-types"; +import { CreateManualEvaluationDto } from "./create-manual-evaluation.dto"; + +export class UpdateManualEvaluationDto extends PartialType( + CreateManualEvaluationDto +) {} diff --git a/src/accessibility-statement-module/manual-evaluation/entities/manual-evaluation.entity.ts b/src/accessibility-statement-module/manual-evaluation/entities/manual-evaluation.entity.ts index 1b832288..b0017a5c 100644 --- a/src/accessibility-statement-module/manual-evaluation/entities/manual-evaluation.entity.ts +++ b/src/accessibility-statement-module/manual-evaluation/entities/manual-evaluation.entity.ts @@ -1,56 +1,65 @@ -import { AccessibilityStatement } from "src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity"; -import { Column, Entity,JoinColumn,ManyToOne,PrimaryGeneratedColumn } from "typeorm"; -@Entity("Manual_Evaluation") -export class ManualEvaluation { - @PrimaryGeneratedColumn() - Id: number; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Title: string; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Url: string; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Sample: string; - - @Column({ - type: 'int', - nullable: true - }) - HeuristicsPassed: number; - - @Column({ - type: 'int', - nullable: true - }) - HeuristicsTotal: number; - - @Column({ - type: 'text', - nullable: true - }) - Summary: string; - - @Column({ - type: 'datetime', - nullable: true, - }) - Date: any; - - @ManyToOne((type => AccessibilityStatement), (accessibilityStatement) => accessibilityStatement.manualEvaluationList) - @JoinColumn({ name: "Accessibility_Statement_Id" }) - accessibilityStatement: AccessibilityStatement; -} +import { AccessibilityStatement } from "src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity"; +import { + Column, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, +} from "typeorm"; +@Entity("Manual_Evaluation") +export class ManualEvaluation { + @PrimaryGeneratedColumn() + Id: number; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Title: string; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Url: string; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Sample: string; + + @Column({ + type: "int", + nullable: true, + }) + HeuristicsPassed: number; + + @Column({ + type: "int", + nullable: true, + }) + HeuristicsTotal: number; + + @Column({ + type: "text", + nullable: true, + }) + Summary: string; + + @Column({ + type: "datetime", + nullable: true, + }) + Date: any; + + @ManyToOne( + (type) => AccessibilityStatement, + (accessibilityStatement) => accessibilityStatement.manualEvaluationList + ) + @JoinColumn({ name: "Accessibility_Statement_Id" }) + accessibilityStatement: AccessibilityStatement; +} diff --git a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.controller.spec.ts b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.controller.spec.ts index 8202519e..24a8e820 100644 --- a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.controller.spec.ts +++ b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ManualEvaluationController } from './manual-evaluation.controller'; -import { ManualEvaluationService } from './manual-evaluation.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { ManualEvaluationController } from "./manual-evaluation.controller"; +import { ManualEvaluationService } from "./manual-evaluation.service"; -describe('ManualEvaluationController', () => { +describe("ManualEvaluationController", () => { let controller: ManualEvaluationController; beforeEach(async () => { @@ -11,10 +11,12 @@ describe('ManualEvaluationController', () => { providers: [ManualEvaluationService], }).compile(); - controller = module.get(ManualEvaluationController); + controller = module.get( + ManualEvaluationController + ); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.controller.ts b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.controller.ts index ed905286..8fc3e3cf 100644 --- a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.controller.ts +++ b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.controller.ts @@ -1,12 +1,22 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; -import { ManualEvaluationService } from './manual-evaluation.service'; -import { CreateManualEvaluationDto } from './dto/create-manual-evaluation.dto'; -import { UpdateManualEvaluationDto } from './dto/update-manual-evaluation.dto'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from "@nestjs/common"; +import { ManualEvaluationService } from "./manual-evaluation.service"; +import { CreateManualEvaluationDto } from "./dto/create-manual-evaluation.dto"; +import { UpdateManualEvaluationDto } from "./dto/update-manual-evaluation.dto"; -@Controller('manual-evaluation') +@Controller("manual-evaluation") export class ManualEvaluationController { - constructor(private readonly manualEvaluationService: ManualEvaluationService) {} -/* + constructor( + private readonly manualEvaluationService: ManualEvaluationService + ) {} + /* @Post() create(@Body() createManualEvaluationDto: CreateManualEvaluationDto) { return this.manualEvaluationService.create(createManualEvaluationDto); diff --git a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.module.ts b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.module.ts index b1bbfe46..08d97258 100644 --- a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.module.ts +++ b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.module.ts @@ -1,11 +1,11 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { ManualEvaluation } from './entities/manual-evaluation.entity'; -import { ManualEvaluationService } from './manual-evaluation.service'; - -@Module({ - imports: [TypeOrmModule.forFeature([ManualEvaluation])], - providers: [ManualEvaluationService], - exports: [ManualEvaluationService] -}) -export class ManualEvaluationModule {} +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { ManualEvaluation } from "./entities/manual-evaluation.entity"; +import { ManualEvaluationService } from "./manual-evaluation.service"; + +@Module({ + imports: [TypeOrmModule.forFeature([ManualEvaluation])], + providers: [ManualEvaluationService], + exports: [ManualEvaluationService], +}) +export class ManualEvaluationModule {} diff --git a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.service.spec.ts b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.service.spec.ts index 7bfdccc4..8fde4587 100644 --- a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.service.spec.ts +++ b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ManualEvaluationService } from './manual-evaluation.service'; - -describe('ManualEvaluationService', () => { - let service: ManualEvaluationService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ManualEvaluationService], - }).compile(); - - service = module.get(ManualEvaluationService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { ManualEvaluationService } from "./manual-evaluation.service"; + +describe("ManualEvaluationService", () => { + let service: ManualEvaluationService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ManualEvaluationService], + }).compile(); + + service = module.get(ManualEvaluationService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.service.ts b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.service.ts index 20698121..2f5cf358 100644 --- a/src/accessibility-statement-module/manual-evaluation/manual-evaluation.service.ts +++ b/src/accessibility-statement-module/manual-evaluation/manual-evaluation.service.ts @@ -1,31 +1,41 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { AccessibilityStatement } from '../accessibility-statement/entities/accessibility-statement.entity'; -import { CreateManualEvaluationDto } from './dto/create-manual-evaluation.dto'; -import { ManualEvaluation } from './entities/manual-evaluation.entity'; - -@Injectable() -export class ManualEvaluationService { - constructor( - @InjectRepository(ManualEvaluation) - private readonly manualEvaluationRepository: Repository) { } - create(createManualEvaluationDto: CreateManualEvaluationDto, accessibilityStatement: AccessibilityStatement) { - let heuristics = {}; - if (createManualEvaluationDto.Heuristics) { - const heuristicsValue = createManualEvaluationDto.Heuristics; - const splittedText = heuristicsValue.split('/'); - const HeuristicsPassed = parseInt(splittedText[0]); - const HeuristicsTotal = parseInt(splittedText[1]); - heuristics = { HeuristicsPassed, HeuristicsTotal } - } - const evaluation = this.manualEvaluationRepository.create({ - ...createManualEvaluationDto, accessibilityStatement, ...heuristics - }); - return this.manualEvaluationRepository.save(evaluation); - } - - async getLength() { - return (await this.manualEvaluationRepository.query(`SELECT COUNT(*) as length FROM Manual_Evaluation`))[0].length; - } -} +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; +import { AccessibilityStatement } from "../accessibility-statement/entities/accessibility-statement.entity"; +import { CreateManualEvaluationDto } from "./dto/create-manual-evaluation.dto"; +import { ManualEvaluation } from "./entities/manual-evaluation.entity"; + +@Injectable() +export class ManualEvaluationService { + constructor( + @InjectRepository(ManualEvaluation) + private readonly manualEvaluationRepository: Repository + ) {} + create( + createManualEvaluationDto: CreateManualEvaluationDto, + accessibilityStatement: AccessibilityStatement + ) { + let heuristics = {}; + if (createManualEvaluationDto.Heuristics) { + const heuristicsValue = createManualEvaluationDto.Heuristics; + const splittedText = heuristicsValue.split("/"); + const HeuristicsPassed = parseInt(splittedText[0]); + const HeuristicsTotal = parseInt(splittedText[1]); + heuristics = { HeuristicsPassed, HeuristicsTotal }; + } + const evaluation = this.manualEvaluationRepository.create({ + ...createManualEvaluationDto, + accessibilityStatement, + ...heuristics, + }); + return this.manualEvaluationRepository.save(evaluation); + } + + async getLength() { + return ( + await this.manualEvaluationRepository.query( + `SELECT COUNT(*) as length FROM Manual_Evaluation` + ) + )[0].length; + } +} diff --git a/src/accessibility-statement-module/user-evaluation/dto/create-user-evaluation.dto.ts b/src/accessibility-statement-module/user-evaluation/dto/create-user-evaluation.dto.ts index 14d28a73..0482c5f1 100644 --- a/src/accessibility-statement-module/user-evaluation/dto/create-user-evaluation.dto.ts +++ b/src/accessibility-statement-module/user-evaluation/dto/create-user-evaluation.dto.ts @@ -1,8 +1,8 @@ export class CreateUserEvaluationDto { - Title: string; - Url: string; - Participants: string; - Process: string; - Summary: string; - Date: Date; + Title: string; + Url: string; + Participants: string; + Process: string; + Summary: string; + Date: Date; } diff --git a/src/accessibility-statement-module/user-evaluation/dto/update-user-evaluation.dto.ts b/src/accessibility-statement-module/user-evaluation/dto/update-user-evaluation.dto.ts index 2eb7a0ab..dea4000b 100644 --- a/src/accessibility-statement-module/user-evaluation/dto/update-user-evaluation.dto.ts +++ b/src/accessibility-statement-module/user-evaluation/dto/update-user-evaluation.dto.ts @@ -1,4 +1,6 @@ -import { PartialType } from '@nestjs/mapped-types'; -import { CreateUserEvaluationDto } from './create-user-evaluation.dto'; +import { PartialType } from "@nestjs/mapped-types"; +import { CreateUserEvaluationDto } from "./create-user-evaluation.dto"; -export class UpdateUserEvaluationDto extends PartialType(CreateUserEvaluationDto) {} +export class UpdateUserEvaluationDto extends PartialType( + CreateUserEvaluationDto +) {} diff --git a/src/accessibility-statement-module/user-evaluation/entities/user-evaluation.entity.ts b/src/accessibility-statement-module/user-evaluation/entities/user-evaluation.entity.ts index aa8a6d86..32685f42 100644 --- a/src/accessibility-statement-module/user-evaluation/entities/user-evaluation.entity.ts +++ b/src/accessibility-statement-module/user-evaluation/entities/user-evaluation.entity.ts @@ -1,51 +1,60 @@ -import { Column, Entity,JoinColumn,ManyToOne,PrimaryGeneratedColumn } from "typeorm"; +import { + Column, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, +} from "typeorm"; import { AccessibilityStatement } from "../../accessibility-statement/entities/accessibility-statement.entity"; @Entity("User_Evaluation") export class UserEvaluation { - @PrimaryGeneratedColumn() - Id: number; + @PrimaryGeneratedColumn() + Id: number; - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Title: string; + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Title: string; - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Url: string; + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Url: string; - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Participants: string; + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Participants: string; - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Process: string; + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Process: string; - @Column({ - type: 'text', - nullable: true - }) - Summary: string; + @Column({ + type: "text", + nullable: true, + }) + Summary: string; - @Column({ - type: 'datetime', - nullable: true, - }) - Date: any; - - @ManyToOne((type => AccessibilityStatement), (accessibilityStatement) => accessibilityStatement.userEvaluationList) - @JoinColumn({ name: "Accessibility_Statement_Id" }) - accessibilityStatement: AccessibilityStatement; + @Column({ + type: "datetime", + nullable: true, + }) + Date: any; + + @ManyToOne( + (type) => AccessibilityStatement, + (accessibilityStatement) => accessibilityStatement.userEvaluationList + ) + @JoinColumn({ name: "Accessibility_Statement_Id" }) + accessibilityStatement: AccessibilityStatement; } diff --git a/src/accessibility-statement-module/user-evaluation/user-evaluation.controller.spec.ts b/src/accessibility-statement-module/user-evaluation/user-evaluation.controller.spec.ts index 1db9df4f..fe928ddf 100644 --- a/src/accessibility-statement-module/user-evaluation/user-evaluation.controller.spec.ts +++ b/src/accessibility-statement-module/user-evaluation/user-evaluation.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { UserEvaluationController } from './user-evaluation.controller'; -import { UserEvaluationService } from './user-evaluation.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { UserEvaluationController } from "./user-evaluation.controller"; +import { UserEvaluationService } from "./user-evaluation.service"; -describe('UserEvaluationController', () => { +describe("UserEvaluationController", () => { let controller: UserEvaluationController; beforeEach(async () => { @@ -14,7 +14,7 @@ describe('UserEvaluationController', () => { controller = module.get(UserEvaluationController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/user-evaluation/user-evaluation.controller.ts b/src/accessibility-statement-module/user-evaluation/user-evaluation.controller.ts index 0ed6a1f8..88915f9c 100644 --- a/src/accessibility-statement-module/user-evaluation/user-evaluation.controller.ts +++ b/src/accessibility-statement-module/user-evaluation/user-evaluation.controller.ts @@ -1,9 +1,17 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; -import { UserEvaluationService } from './user-evaluation.service'; -import { CreateUserEvaluationDto } from './dto/create-user-evaluation.dto'; -import { UpdateUserEvaluationDto } from './dto/update-user-evaluation.dto'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from "@nestjs/common"; +import { UserEvaluationService } from "./user-evaluation.service"; +import { CreateUserEvaluationDto } from "./dto/create-user-evaluation.dto"; +import { UpdateUserEvaluationDto } from "./dto/update-user-evaluation.dto"; -@Controller('user-evaluation') +@Controller("user-evaluation") export class UserEvaluationController { constructor(private readonly userEvaluationService: UserEvaluationService) {} diff --git a/src/accessibility-statement-module/user-evaluation/user-evaluation.module.ts b/src/accessibility-statement-module/user-evaluation/user-evaluation.module.ts index a1d07314..e4818d1e 100644 --- a/src/accessibility-statement-module/user-evaluation/user-evaluation.module.ts +++ b/src/accessibility-statement-module/user-evaluation/user-evaluation.module.ts @@ -1,11 +1,11 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { UserEvaluation } from './entities/user-evaluation.entity'; -import { UserEvaluationService } from './user-evaluation.service'; +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { UserEvaluation } from "./entities/user-evaluation.entity"; +import { UserEvaluationService } from "./user-evaluation.service"; @Module({ imports: [TypeOrmModule.forFeature([UserEvaluation])], providers: [UserEvaluationService], - exports: [UserEvaluationService] + exports: [UserEvaluationService], }) export class UserEvaluationModule {} diff --git a/src/accessibility-statement-module/user-evaluation/user-evaluation.service.spec.ts b/src/accessibility-statement-module/user-evaluation/user-evaluation.service.spec.ts index 6eb4cfda..efffee93 100644 --- a/src/accessibility-statement-module/user-evaluation/user-evaluation.service.spec.ts +++ b/src/accessibility-statement-module/user-evaluation/user-evaluation.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { UserEvaluationService } from './user-evaluation.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { UserEvaluationService } from "./user-evaluation.service"; -describe('UserEvaluationService', () => { +describe("UserEvaluationService", () => { let service: UserEvaluationService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('UserEvaluationService', () => { service = module.get(UserEvaluationService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/accessibility-statement-module/user-evaluation/user-evaluation.service.ts b/src/accessibility-statement-module/user-evaluation/user-evaluation.service.ts index 7fb2921b..771e91fc 100644 --- a/src/accessibility-statement-module/user-evaluation/user-evaluation.service.ts +++ b/src/accessibility-statement-module/user-evaluation/user-evaluation.service.ts @@ -1,23 +1,32 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { AccessibilityStatement } from '../accessibility-statement/entities/accessibility-statement.entity'; -import { CreateUserEvaluationDto } from './dto/create-user-evaluation.dto'; -import { UserEvaluation } from './entities/user-evaluation.entity'; +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; +import { AccessibilityStatement } from "../accessibility-statement/entities/accessibility-statement.entity"; +import { CreateUserEvaluationDto } from "./dto/create-user-evaluation.dto"; +import { UserEvaluation } from "./entities/user-evaluation.entity"; @Injectable() export class UserEvaluationService { constructor( @InjectRepository(UserEvaluation) - private readonly userEvaluationRepository: Repository) { } - create(createUserEvaluationDto: CreateUserEvaluationDto, accessibilityStatement: AccessibilityStatement) { + private readonly userEvaluationRepository: Repository + ) {} + create( + createUserEvaluationDto: CreateUserEvaluationDto, + accessibilityStatement: AccessibilityStatement + ) { const evaluation = this.userEvaluationRepository.create({ - ...createUserEvaluationDto, accessibilityStatement + ...createUserEvaluationDto, + accessibilityStatement, }); return this.userEvaluationRepository.save(evaluation); } async getLength() { - return (await this.userEvaluationRepository.query(`SELECT COUNT(*) as length FROM User_Evaluation`))[0].length; + return ( + await this.userEvaluationRepository.query( + `SELECT COUNT(*) as length FROM User_Evaluation` + ) + )[0].length; } } diff --git a/src/amp/amp.controller.spec.ts b/src/amp/amp.controller.spec.ts index 92fda239..6bd345a3 100644 --- a/src/amp/amp.controller.spec.ts +++ b/src/amp/amp.controller.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AmpController } from './amp.controller'; +import { Test, TestingModule } from "@nestjs/testing"; +import { AmpController } from "./amp.controller"; -describe('Amp Controller', () => { +describe("Amp Controller", () => { let controller: AmpController; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('Amp Controller', () => { controller = module.get(AmpController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/amp/amp.controller.ts b/src/amp/amp.controller.ts index afe9512c..9df4de47 100644 --- a/src/amp/amp.controller.ts +++ b/src/amp/amp.controller.ts @@ -1,4 +1,11 @@ -import { Controller, Get, Post, Param, Request, UseInterceptors } from "@nestjs/common"; +import { + Controller, + Get, + Post, + Param, + Request, + UseInterceptors, +} from "@nestjs/common"; import { EvaluationService } from "../evaluation/evaluation.service"; import { success, accessDenied } from "../lib/response"; import { readFileSync } from "fs"; @@ -6,23 +13,27 @@ import dns from "dns"; import ipRangeCheck from "ip-range-check"; import { RateLimit } from "nestjs-rate-limiter"; import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; - +import { + ApiBasicAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; const blackList = readFileSync("../black-list.txt").toString().split("\n"); @ApiBasicAuth() -@ApiTags('amp') -@ApiResponse({ status: 403, description: 'Forbidden' }) +@ApiTags("amp") +@ApiResponse({ status: 403, description: "Forbidden" }) @Controller("amp") @UseInterceptors(LoggingInterceptor) export class AmpController { constructor(private readonly evaluationService: EvaluationService) {} - @ApiOperation({ summary: 'Evaluate page via url' }) + @ApiOperation({ summary: "Evaluate page via url" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @RateLimit({ @@ -56,10 +67,10 @@ export class AmpController { ); } - @ApiOperation({ summary: 'Evaluate html code' }) + @ApiOperation({ summary: "Evaluate html code" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @Post("eval/html") diff --git a/src/amp/amp.module.ts b/src/amp/amp.module.ts index 77287710..1a73e831 100644 --- a/src/amp/amp.module.ts +++ b/src/amp/amp.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { AmpController } from './amp.controller'; -import { EvaluationModule } from '../evaluation/evaluation.module'; - -@Module({ - imports: [EvaluationModule], - controllers: [AmpController] -}) -export class AmpModule {} +import { Module } from "@nestjs/common"; +import { AmpController } from "./amp.controller"; +import { EvaluationModule } from "../evaluation/evaluation.module"; + +@Module({ + imports: [EvaluationModule], + controllers: [AmpController], +}) +export class AmpModule {} diff --git a/src/api-selo/api-selo.controller.spec.ts b/src/api-selo/api-selo.controller.spec.ts index 385dee59..41face89 100644 --- a/src/api-selo/api-selo.controller.spec.ts +++ b/src/api-selo/api-selo.controller.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { APISeloController } from './api-selo.controller'; +import { Test, TestingModule } from "@nestjs/testing"; +import { APISeloController } from "./api-selo.controller"; -describe('ApiseloController', () => { +describe("ApiseloController", () => { let controller: APISeloController; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('ApiseloController', () => { controller = module.get(APISeloController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/api-selo/api-selo.controller.ts b/src/api-selo/api-selo.controller.ts index 4c8b01b6..6d5d2da8 100644 --- a/src/api-selo/api-selo.controller.ts +++ b/src/api-selo/api-selo.controller.ts @@ -1,20 +1,22 @@ -import { Controller, Get, UseInterceptors } from '@nestjs/common'; -import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; -import { error, success } from 'src/lib/response'; -import { LoggingInterceptor } from 'src/log/log.interceptor'; -import { ApiSeloService } from './api-selo.service'; +import { Controller, Get, UseInterceptors } from "@nestjs/common"; +import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; +import { error, success } from "src/lib/response"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { ApiSeloService } from "./api-selo.service"; -@ApiTags('apiselo') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller('apiselo') +@ApiTags("apiselo") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("apiselo") @UseInterceptors(LoggingInterceptor) export class APISeloController { constructor(private readonly apiSeloService: ApiSeloService) {} - @ApiOperation({ summary: 'Retrieve digital stamp information for all websites' }) + @ApiOperation({ + summary: "Retrieve digital stamp information for all websites", + }) @ApiResponse({ status: 200, - description: 'The information was retrieved', + description: "The information was retrieved", type: Boolean, }) @Get("all") @@ -22,5 +24,4 @@ export class APISeloController { const response = await this.apiSeloService.getAllStamps(); return response; } - } diff --git a/src/api-selo/api-selo.module.ts b/src/api-selo/api-selo.module.ts index 0446f08a..e7ff9658 100644 --- a/src/api-selo/api-selo.module.ts +++ b/src/api-selo/api-selo.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { APISeloController } from './api-selo.controller'; -import { ApiSeloService } from './api-selo.service'; +import { Module } from "@nestjs/common"; +import { APISeloController } from "./api-selo.controller"; +import { ApiSeloService } from "./api-selo.service"; @Module({ controllers: [APISeloController], - providers: [ApiSeloService] + providers: [ApiSeloService], }) export class ApiSeloModule {} diff --git a/src/api-selo/api-selo.service.spec.ts b/src/api-selo/api-selo.service.spec.ts index 9e7696a8..9f481d97 100644 --- a/src/api-selo/api-selo.service.spec.ts +++ b/src/api-selo/api-selo.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ApiSeloService } from './api-selo.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { ApiSeloService } from "./api-selo.service"; -describe('ApiSeloService', () => { +describe("ApiSeloService", () => { let service: ApiSeloService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('ApiSeloService', () => { service = module.get(ApiSeloService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/api-selo/api-selo.service.ts b/src/api-selo/api-selo.service.ts index 7e361fa9..ac064018 100644 --- a/src/api-selo/api-selo.service.ts +++ b/src/api-selo/api-selo.service.ts @@ -1,27 +1,28 @@ -import { Injectable } from '@nestjs/common'; -import { InjectDataSource } from '@nestjs/typeorm'; +import { Injectable } from "@nestjs/common"; +import { InjectDataSource } from "@nestjs/typeorm"; import { DataSource } from "typeorm"; type WebsiteInfo = { - id: number, - Name: string, - url: string, - entidade: string, - selo: string, - data_selo: string, - declaracao: string, - data_declaracao: string, - url_observatorio: string + id: number; + Name: string; + url: string; + entidade: string; + selo: string; + data_selo: string; + declaracao: string; + data_declaracao: string; + url_observatorio: string; }; @Injectable() export class ApiSeloService { - constructor( - @InjectDataSource() - private readonly connection: DataSource) { } + constructor( + @InjectDataSource() + private readonly connection: DataSource + ) {} - async getAllStamps(): Promise { - const sitesWithStamp = await this.connection.query(` + async getAllStamps(): Promise { + const sitesWithStamp = await this.connection.query(` SELECT DISTINCT w.WebsiteId as 'id', w.Name as 'Name', @@ -46,41 +47,40 @@ export class ApiSeloService { w.Stamp IS NOT NULL `); - const siteList: WebsiteInfo[] = []; + const siteList: WebsiteInfo[] = []; - for (const site of sitesWithStamp) { - const siteInfo: WebsiteInfo = { - id: site.id, - Name: site.Name, - url: site.url, - entidade: site.entidade, - selo: site.selo, - data_selo: site.data_selo, - declaracao: site.declaracao, - data_declaracao: site.data_declaracao, - url_observatorio: `/directories/${site.id_diretorio}/${site.id}` - } - // convert selo according to the mapping 1 -> "Bronze", 2 -> "Prata", 3 -> "Ouro" - if (siteInfo.selo == "1") { - siteInfo.selo = "Bronze"; - } else if (siteInfo.selo == "2") { - siteInfo.selo = "Prata"; - } else if (siteInfo.selo == "3") { - siteInfo.selo = "Ouro"; - } - // convert declaracao according to the mapping 1 -> "Não conforme", 2 -> "Parcialmente conforme", 3 -> "Conforme" - if (siteInfo.declaracao == "1") { - siteInfo.declaracao = "Não conforme"; - } else if (siteInfo.declaracao == "2") { - siteInfo.declaracao = "Parcialmente conforme"; - } else if (siteInfo.declaracao == "3") { - siteInfo.declaracao = "Conforme"; - } + for (const site of sitesWithStamp) { + const siteInfo: WebsiteInfo = { + id: site.id, + Name: site.Name, + url: site.url, + entidade: site.entidade, + selo: site.selo, + data_selo: site.data_selo, + declaracao: site.declaracao, + data_declaracao: site.data_declaracao, + url_observatorio: `/directories/${site.id_diretorio}/${site.id}`, + }; + // convert selo according to the mapping 1 -> "Bronze", 2 -> "Prata", 3 -> "Ouro" + if (siteInfo.selo == "1") { + siteInfo.selo = "Bronze"; + } else if (siteInfo.selo == "2") { + siteInfo.selo = "Prata"; + } else if (siteInfo.selo == "3") { + siteInfo.selo = "Ouro"; + } + // convert declaracao according to the mapping 1 -> "Não conforme", 2 -> "Parcialmente conforme", 3 -> "Conforme" + if (siteInfo.declaracao == "1") { + siteInfo.declaracao = "Não conforme"; + } else if (siteInfo.declaracao == "2") { + siteInfo.declaracao = "Parcialmente conforme"; + } else if (siteInfo.declaracao == "3") { + siteInfo.declaracao = "Conforme"; + } - siteList.push(siteInfo); - } - - return JSON.stringify(siteList); + siteList.push(siteInfo); } + return JSON.stringify(siteList); + } } diff --git a/src/app.controller.spec.ts b/src/app.controller.spec.ts index a3540026..f643a709 100644 --- a/src/app.controller.spec.ts +++ b/src/app.controller.spec.ts @@ -1,22 +1,22 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); - - describe('root', () => { - it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!'); - }); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { AppController } from "./app.controller"; +import { AppService } from "./app.service"; + +describe("AppController", () => { + let appController: AppController; + + beforeEach(async () => { + const app: TestingModule = await Test.createTestingModule({ + controllers: [AppController], + providers: [AppService], + }).compile(); + + appController = app.get(AppController); + }); + + describe("root", () => { + it('should return "Hello World!"', () => { + expect(appController.getHello()).toBe("Hello World!"); + }); + }); +}); diff --git a/src/app.controller.ts b/src/app.controller.ts index a669c251..1e7e6283 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,14 +1,12 @@ -import { Controller, Get } from '@nestjs/common'; -import { AppService } from './app.service'; - -@Controller() -export class AppController { - constructor( - private readonly appService: AppService, - ) {} - - @Get() - getHello(): string { - return this.appService.getHello(); - } -} +import { Controller, Get } from "@nestjs/common"; +import { AppService } from "./app.service"; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getHello(): string { + return this.appService.getHello(); + } +} diff --git a/src/app.module.ts b/src/app.module.ts index 851e6bd5..46ff23e7 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,114 +1,120 @@ -import { Module } from "@nestjs/common"; -import { APP_GUARD } from "@nestjs/core"; -import { TypeOrmModule } from "@nestjs/typeorm"; -import { ScheduleModule } from "@nestjs/schedule"; -import { ServeStaticModule } from "@nestjs/serve-static"; -import { RateLimiterModule, RateLimiterGuard } from "nestjs-rate-limiter"; -import { readFileSync } from "fs"; -import { join } from "path"; - -import { AppController } from "./app.controller"; -import { AppService } from "./app.service"; -import { AuthModule } from "./auth/auth.module"; -import { UserModule } from "./user/user.module"; -import { ObservatoryModule } from "./observatory/observatory.module"; -import { PageModule } from "./page/page.module"; -import { TagModule } from "./tag/tag.module"; -import { WebsiteModule } from "./website/website.module"; -import { EntityModule } from "./entity/entity.module"; -import { EvaluationModule } from "./evaluation/evaluation.module"; -import { AmpModule } from "./amp/amp.module"; -import { StampModule } from "./stamp/stamp.module"; -import { CrawlerModule } from "./crawler/crawler.module"; -import { DirectoryModule } from "./directory/directory.module"; -import { AccessibilityStatementModule } from './accessibility-statement-module/accessibility-statement/accessibility-statement.module'; -import { AutomaticEvaluationModule } from './accessibility-statement-module/automatic-evaluation/automatic-evaluation.module'; -import { ManualEvaluationModule } from './accessibility-statement-module/manual-evaluation/manual-evaluation.module'; -import { UserEvaluationModule } from './accessibility-statement-module/user-evaluation/user-evaluation.module'; -import { GovUserModule } from './gov-user/gov-user.module'; -import winston from "winston"; -import 'winston-daily-rotate-file'; -import { utilities as nestWinstonModuleUtilities, WinstonModule } from 'nest-winston'; -import { LogModule } from './log/log.module'; -import { DumpModule } from './dump/dump.module'; -import { ApiSeloModule } from './api-selo/api-selo.module'; - -const databaseConfig = JSON.parse( - readFileSync("../monitor_db.json").toString() -); - -@Module({ - imports: [ - WinstonModule.forRoot({ - transports: [ - new winston.transports.DailyRotateFile({ - filename: 'error-log/monitor-server-%DATE%.log', - datePattern: 'YYYY-MM-DD', - zippedArchive: true, - maxSize: '1m', - level: "error"}), - new winston.transports.DailyRotateFile({ - filename: 'action-log/monitor-server-%DATE%.log', - datePattern: 'YYYY-MM-DD', - zippedArchive: true, - maxSize: '1m', - level: "http" - }), - new winston.transports.Console({ - format: winston.format.combine( - winston.format.timestamp(), - winston.format.ms(), - nestWinstonModuleUtilities.format.nestLike('monitor-server', { - // options - }) - ), - }), - ], - // options - }), - ScheduleModule.forRoot(), - TypeOrmModule.forRoot({ - type: "mysql", - host: databaseConfig.host, - port: 3306, - username: databaseConfig.user, - password: databaseConfig.password, - database: databaseConfig.database, - entities: [__dirname + "/**/*.entity{.ts,.js}"], - synchronize: false, - }), - ServeStaticModule.forRoot({ - rootPath: join(__dirname, "..", "public"), - }), - RateLimiterModule.register({ - points: 1000, - }), - AuthModule, - UserModule, - ObservatoryModule, - PageModule, - TagModule, - WebsiteModule, - EntityModule, - EvaluationModule, - AmpModule, - StampModule, - CrawlerModule, - DirectoryModule, - AccessibilityStatementModule, - AutomaticEvaluationModule, ManualEvaluationModule, UserEvaluationModule, - GovUserModule, - LogModule, - DumpModule, - ApiSeloModule, - ], - controllers: [AppController], - providers: [ - AppService, - { - provide: APP_GUARD, - useClass: RateLimiterGuard, - }, - ], -}) -export class AppModule { } +import { Module } from "@nestjs/common"; +import { APP_GUARD } from "@nestjs/core"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { ScheduleModule } from "@nestjs/schedule"; +import { ServeStaticModule } from "@nestjs/serve-static"; +import { RateLimiterModule, RateLimiterGuard } from "nestjs-rate-limiter"; +import { readFileSync } from "fs"; +import { join } from "path"; + +import { AppController } from "./app.controller"; +import { AppService } from "./app.service"; +import { AuthModule } from "./auth/auth.module"; +import { UserModule } from "./user/user.module"; +import { ObservatoryModule } from "./observatory/observatory.module"; +import { PageModule } from "./page/page.module"; +import { TagModule } from "./tag/tag.module"; +import { WebsiteModule } from "./website/website.module"; +import { EntityModule } from "./entity/entity.module"; +import { EvaluationModule } from "./evaluation/evaluation.module"; +import { AmpModule } from "./amp/amp.module"; +import { StampModule } from "./stamp/stamp.module"; +import { CrawlerModule } from "./crawler/crawler.module"; +import { DirectoryModule } from "./directory/directory.module"; +import { AccessibilityStatementModule } from "./accessibility-statement-module/accessibility-statement/accessibility-statement.module"; +import { AutomaticEvaluationModule } from "./accessibility-statement-module/automatic-evaluation/automatic-evaluation.module"; +import { ManualEvaluationModule } from "./accessibility-statement-module/manual-evaluation/manual-evaluation.module"; +import { UserEvaluationModule } from "./accessibility-statement-module/user-evaluation/user-evaluation.module"; +import { GovUserModule } from "./gov-user/gov-user.module"; +import winston from "winston"; +import "winston-daily-rotate-file"; +import { + utilities as nestWinstonModuleUtilities, + WinstonModule, +} from "nest-winston"; +import { LogModule } from "./log/log.module"; +import { DumpModule } from "./dump/dump.module"; +import { ApiSeloModule } from "./api-selo/api-selo.module"; + +const databaseConfig = JSON.parse( + readFileSync("../monitor_db.json").toString() +); + +@Module({ + imports: [ + WinstonModule.forRoot({ + transports: [ + new winston.transports.DailyRotateFile({ + filename: "error-log/monitor-server-%DATE%.log", + datePattern: "YYYY-MM-DD", + zippedArchive: true, + maxSize: "1m", + level: "error", + }), + new winston.transports.DailyRotateFile({ + filename: "action-log/monitor-server-%DATE%.log", + datePattern: "YYYY-MM-DD", + zippedArchive: true, + maxSize: "1m", + level: "http", + }), + new winston.transports.Console({ + format: winston.format.combine( + winston.format.timestamp(), + winston.format.ms(), + nestWinstonModuleUtilities.format.nestLike("monitor-server", { + // options + }) + ), + }), + ], + // options + }), + ScheduleModule.forRoot(), + TypeOrmModule.forRoot({ + type: "mysql", + host: databaseConfig.host, + port: 3306, + username: databaseConfig.user, + password: databaseConfig.password, + database: databaseConfig.database, + entities: [__dirname + "/**/*.entity{.ts,.js}"], + synchronize: false, + }), + ServeStaticModule.forRoot({ + rootPath: join(__dirname, "..", "public"), + }), + RateLimiterModule.register({ + points: 1000, + }), + AuthModule, + UserModule, + ObservatoryModule, + PageModule, + TagModule, + WebsiteModule, + EntityModule, + EvaluationModule, + AmpModule, + StampModule, + CrawlerModule, + DirectoryModule, + AccessibilityStatementModule, + AutomaticEvaluationModule, + ManualEvaluationModule, + UserEvaluationModule, + GovUserModule, + LogModule, + DumpModule, + ApiSeloModule, + ], + controllers: [AppController], + providers: [ + AppService, + { + provide: APP_GUARD, + useClass: RateLimiterGuard, + }, + ], +}) +export class AppModule {} diff --git a/src/app.service.ts b/src/app.service.ts index d12de693..b00a6679 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -1,8 +1,8 @@ -import { Injectable } from '@nestjs/common'; - -@Injectable() -export class AppService { - getHello(): string { - return 'Hello World!'; - } -} +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class AppService { + getHello(): string { + return "Hello World!"; + } +} diff --git a/src/auth/auth.controller.spec.ts b/src/auth/auth.controller.spec.ts index 1b7aefba..2391cac9 100644 --- a/src/auth/auth.controller.spec.ts +++ b/src/auth/auth.controller.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AuthController } from './auth.controller'; - -describe('Auth Controller', () => { - let controller: AuthController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [AuthController], - }).compile(); - - controller = module.get(AuthController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { AuthController } from "./auth.controller"; + +describe("Auth Controller", () => { + let controller: AuthController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [AuthController], + }).compile(); + + controller = module.get(AuthController); + }); + + it("should be defined", () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 1b2fc7d0..adee0f08 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -1,110 +1,116 @@ -import { - Controller, - InternalServerErrorException, - UnauthorizedException, - Request, - Post, - UseGuards, - Get, - Param, - Query, - Res, - UseInterceptors, -} from "@nestjs/common"; -import { AuthGuard } from "@nestjs/passport"; -import { AuthService } from "./auth.service"; -import { success } from "../lib/response"; -import { Response } from 'express'; -import { GovAuthGuard } from "./gov-auth.guard"; -import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; - - -@ApiBasicAuth() -@ApiTags('auth') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller("auth") -@UseInterceptors(LoggingInterceptor) -export class AuthController { - constructor(private readonly authService: AuthService) { } - - @ApiOperation({ summary: 'Login in AMS' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("local")) - @Post("login") - async login(@Request() req: any): Promise { - const token = this.authService.login(req.user); - if (req.user.Type !== req.body.type) { - throw new UnauthorizedException(); - } else { - const date = new Date() - .toISOString() - .replace(/T/, " ") - .replace(/\..+/, ""); - const updatedLogin = await this.authService.updateUserLastLogin( - req.user.UserId, - date - ); - if (!updatedLogin) { - throw new InternalServerErrorException(); - } - - return success(token); - } - } - - @ApiOperation({ summary: 'Logout in AMS and MyMonitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt")) - @Post("logout") - async logout(@Request() req: any): Promise { - const token = req.headers.authorization.split(" ")[1]; - return success(await this.authService.logout(token)); - } - @ApiOperation({ summary: 'Start login using Autenticação.Gov(My Monitor)' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - //@UseGuards() - @Get("login") - async loginGov(@Res() response: Response): Promise { - const REDIRECT_URI = process.env.REDIRECT_URI; - const CLIENT_ID = process.env.CLIENT_ID; - response.redirect(`https://preprod.autenticacao.gov.pt/oauth/askauthorization?redirect_uri=${REDIRECT_URI}&client_id=${CLIENT_ID}&response_type=token&scope=http://interop.gov.pt/MDC/Cidadao/NIC%20http://interop.gov.pt/MDC/Cidadao/NomeCompleto`); - } - - @ApiOperation({ summary: 'After a successful login in AGov the user is redirected to this operation to verify the AGov token and login the user in MyMonitor' }) - @ApiResponse({ - status: 200, - description: 'The user login was successfull', - type: String, - }) - @UseGuards(GovAuthGuard) - @Get("loginRedirect") - async verifyToken(@Request() req: any): Promise { - const token = this.authService.login(req.user); - const date = new Date() - .toISOString() - .replace(/T/, " ") - .replace(/\..+/, ""); - const updatedLogin = await this.authService.updateUserLastLogin( - req.user.UserId, - date - ); - if (!updatedLogin) { - throw new InternalServerErrorException(); - } - console.log(token); - return success(token); - } -} +import { + Controller, + InternalServerErrorException, + UnauthorizedException, + Request, + Post, + UseGuards, + Get, + Param, + Query, + Res, + UseInterceptors, +} from "@nestjs/common"; +import { AuthGuard } from "@nestjs/passport"; +import { AuthService } from "./auth.service"; +import { success } from "../lib/response"; +import { Response } from "express"; +import { GovAuthGuard } from "./gov-auth.guard"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { + ApiBasicAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; + +@ApiBasicAuth() +@ApiTags("auth") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("auth") +@UseInterceptors(LoggingInterceptor) +export class AuthController { + constructor(private readonly authService: AuthService) {} + + @ApiOperation({ summary: "Login in AMS" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("local")) + @Post("login") + async login(@Request() req: any): Promise { + const token = this.authService.login(req.user); + if (req.user.Type !== req.body.type) { + throw new UnauthorizedException(); + } else { + const date = new Date() + .toISOString() + .replace(/T/, " ") + .replace(/\..+/, ""); + const updatedLogin = await this.authService.updateUserLastLogin( + req.user.UserId, + date + ); + if (!updatedLogin) { + throw new InternalServerErrorException(); + } + + return success(token); + } + } + + @ApiOperation({ summary: "Logout in AMS and MyMonitor" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt")) + @Post("logout") + async logout(@Request() req: any): Promise { + const token = req.headers.authorization.split(" ")[1]; + return success(await this.authService.logout(token)); + } + @ApiOperation({ summary: "Start login using Autenticação.Gov(My Monitor)" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + //@UseGuards() + @Get("login") + async loginGov(@Res() response: Response): Promise { + const REDIRECT_URI = process.env.REDIRECT_URI; + const CLIENT_ID = process.env.CLIENT_ID; + response.redirect( + `https://preprod.autenticacao.gov.pt/oauth/askauthorization?redirect_uri=${REDIRECT_URI}&client_id=${CLIENT_ID}&response_type=token&scope=http://interop.gov.pt/MDC/Cidadao/NIC%20http://interop.gov.pt/MDC/Cidadao/NomeCompleto` + ); + } + + @ApiOperation({ + summary: + "After a successful login in AGov the user is redirected to this operation to verify the AGov token and login the user in MyMonitor", + }) + @ApiResponse({ + status: 200, + description: "The user login was successfull", + type: String, + }) + @UseGuards(GovAuthGuard) + @Get("loginRedirect") + async verifyToken(@Request() req: any): Promise { + const token = this.authService.login(req.user); + const date = new Date().toISOString().replace(/T/, " ").replace(/\..+/, ""); + const updatedLogin = await this.authService.updateUserLastLogin( + req.user.UserId, + date + ); + if (!updatedLogin) { + throw new InternalServerErrorException(); + } + console.log(token); + return success(token); + } +} diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 54035714..6a987c45 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,36 +1,36 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { JwtModule } from '@nestjs/jwt'; -import { AuthService } from './auth.service'; -import { AuthController } from './auth.controller'; -import { User } from '../user/user.entity'; -import { InvalidToken } from './invalid-token.entity'; -import { LocalStrategy } from './local.strategy'; -import { JwtStrategy } from './jwt.strategy'; -import { JwtAdminStrategy } from './jwt-admin.strategy'; -import { JwtMonitorStrategy } from './jwt-monitor.strategy'; -import { JwtStudyStrategy } from './jwt-study.strategy'; -import { jwtConstants } from './constants'; -import { GovUserModule } from 'src/gov-user/gov-user.module'; - -@Module({ - imports: [ - TypeOrmModule.forFeature([User, InvalidToken]), - GovUserModule, - JwtModule.register({ - secret: jwtConstants.secret, - signOptions: { expiresIn: '1d' }, - }) - ], - exports: [AuthService], - providers: [ - AuthService, - LocalStrategy, - JwtStrategy, - JwtAdminStrategy, - JwtMonitorStrategy, - JwtStudyStrategy - ], - controllers: [AuthController] -}) -export class AuthModule {} +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { JwtModule } from "@nestjs/jwt"; +import { AuthService } from "./auth.service"; +import { AuthController } from "./auth.controller"; +import { User } from "../user/user.entity"; +import { InvalidToken } from "./invalid-token.entity"; +import { LocalStrategy } from "./local.strategy"; +import { JwtStrategy } from "./jwt.strategy"; +import { JwtAdminStrategy } from "./jwt-admin.strategy"; +import { JwtMonitorStrategy } from "./jwt-monitor.strategy"; +import { JwtStudyStrategy } from "./jwt-study.strategy"; +import { jwtConstants } from "./constants"; +import { GovUserModule } from "src/gov-user/gov-user.module"; + +@Module({ + imports: [ + TypeOrmModule.forFeature([User, InvalidToken]), + GovUserModule, + JwtModule.register({ + secret: jwtConstants.secret, + signOptions: { expiresIn: "1d" }, + }), + ], + exports: [AuthService], + providers: [ + AuthService, + LocalStrategy, + JwtStrategy, + JwtAdminStrategy, + JwtMonitorStrategy, + JwtStudyStrategy, + ], + controllers: [AuthController], +}) +export class AuthModule {} diff --git a/src/auth/auth.service.spec.ts b/src/auth/auth.service.spec.ts index def4f24a..d8cef830 100644 --- a/src/auth/auth.service.spec.ts +++ b/src/auth/auth.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AuthService } from './auth.service'; - -describe('AuthService', () => { - let service: AuthService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [AuthService], - }).compile(); - - service = module.get(AuthService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { AuthService } from "./auth.service"; + +describe("AuthService", () => { + let service: AuthService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [AuthService], + }).compile(); + + service = module.get(AuthService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index cb0b62dd..3a5534c3 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -1,187 +1,194 @@ -import { Injectable } from "@nestjs/common"; -import { Cron, CronExpression } from "@nestjs/schedule"; -import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; -import { DataSource, Repository } from "typeorm"; -import { JwtService } from "@nestjs/jwt"; -import { User } from "../user/user.entity"; -import { InvalidToken } from "./invalid-token.entity"; -import { comparePasswordHash } from "../lib/security"; -import axios from "axios"; -import { NAME_CONVERTER, NIC } from "./constants"; -import { GovUserService } from "src/gov-user/gov-user.service"; - -@Injectable() -export class AuthService { - constructor( - @InjectRepository(User) - private readonly userRepository: Repository, - private readonly govUserService: GovUserService, - @InjectRepository(InvalidToken) - private readonly invalidTokenRepository: Repository, - @InjectDataSource() - private readonly connection: DataSource, - private readonly jwtService: JwtService - ) { } - - @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) - async cleanInvalidSessionTokens(): Promise { - // Called at midnight every day - await this.invalidTokenRepository.query( - `DELETE FROM Invalid_Token WHERE Expiration_Date < NOW()` - ); - } - - async isTokenBlackListed(token: string): Promise { - const invalidToken = await this.invalidTokenRepository.findOne({ - where: { Token: token }, - }); - return !!invalidToken; - } - - async updateUserLastLogin(userId: number, date: any): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - let error = false; - try { - await queryRunner.manager.update( - User, - { UserId: userId }, - { Last_Login: date } - ); - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - error = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !error; - } - - async verifyUserCredentials( - username: string, - password: string - ): Promise { - const user = await this.userRepository.findOne({ - where: { Username: username }, - }); - - if (user && (await comparePasswordHash(password, user.Password))) { - delete user.Password; - delete user.Names; - delete user.Emails; - delete user.Last_Login; - delete user.Register_Date; - return user; - } else { - return null; - } - } - - async verifyUserPayload(payload: any): Promise { - const user = await this.userRepository.findOne({ - where: { - UserId: payload.sub, - Username: payload.username, - Type: payload.type, - Unique_Hash: payload.hash, - }, - }); - return !!user; - } - - login(user: any): string { - const payload = { - username: user.Username, - sub: user.UserId, - type: user.Type, - hash: user.Unique_Hash, - }; - return this.signToken(payload); - } - - signToken(payload: any): string { - return this.jwtService.sign(payload,{algorithm:"HS256"}); - } - - verifyJWT(jwt: string): any { - try { - return this.jwtService.verify(jwt); - } catch (err) { - console.log(err); - return undefined; - } - } - - async logout(token: string): Promise { - const tomorrow = new Date(); - tomorrow.setDate(tomorrow.getDate() + 1); - - const invalidToken = new InvalidToken(); - invalidToken.Token = token; - invalidToken.Expiration_Date = tomorrow; - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - let error = false; - try { - const saved = await queryRunner.manager.save(invalidToken); - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - error = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !error; - } - async verifyLoginUser(token: string) { - const atributes = await this.getAtributes(token); - const ccNumber = atributes.cc; - await this.govUserService.updateLogin(ccNumber); - return this.govUserService.findOneByCC(ccNumber); - } - - - async getAtributes(token: string) { - const atributesName = ["http://interop.gov.pt/MDC/Cidadao/NIC", "http://interop.gov.pt/MDC/Cidadao/NomeCompleto"] - const responseStart = await axios.post("https://preprod.autenticacao.gov.pt/oauthresourceserver/api/AttributeManager", { token, atributesName }) - const authenticationContextId = responseStart.data.authenticationContextId; - const responseAtributes = await axios.get(`https://preprod.autenticacao.gov.pt/oauthresourceserver/api/AttributeManager?token=${token}&authenticationContextId=${authenticationContextId}`) - return this.parseAtributes(responseAtributes.data); - } - - private parseAtributes(atributes:any){ - let result = {cc:null,name:""}; - atributes.map((atribute)=>{ - const name = atribute.name; - const realName = NAME_CONVERTER[name]; - result[realName] = atribute.value; - }) - return result; - } -} -/** - * > [ │ - { │ - name: 'http://interop.gov.pt/MDC/Cidadao/NIC', │ - value: '15366302', │ - state: 'Available' │ -}, │ -{ │ - name: 'http://interop.gov.pt/MDC/Cidadao/NomeCompleto', │ - value: 'ANTÓNIO MANUEL SANTOS ESTRIGA', │ - state: 'Available' │ -} │ -│ ] - */ +import { Injectable } from "@nestjs/common"; +import { Cron, CronExpression } from "@nestjs/schedule"; +import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; +import { DataSource, Repository } from "typeorm"; +import { JwtService } from "@nestjs/jwt"; +import { User } from "../user/user.entity"; +import { InvalidToken } from "./invalid-token.entity"; +import { comparePasswordHash } from "../lib/security"; +import axios from "axios"; +import { NAME_CONVERTER, NIC } from "./constants"; +import { GovUserService } from "src/gov-user/gov-user.service"; + +@Injectable() +export class AuthService { + constructor( + @InjectRepository(User) + private readonly userRepository: Repository, + private readonly govUserService: GovUserService, + @InjectRepository(InvalidToken) + private readonly invalidTokenRepository: Repository, + @InjectDataSource() + private readonly connection: DataSource, + private readonly jwtService: JwtService + ) {} + + @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) + async cleanInvalidSessionTokens(): Promise { + // Called at midnight every day + await this.invalidTokenRepository.query( + `DELETE FROM Invalid_Token WHERE Expiration_Date < NOW()` + ); + } + + async isTokenBlackListed(token: string): Promise { + const invalidToken = await this.invalidTokenRepository.findOne({ + where: { Token: token }, + }); + return !!invalidToken; + } + + async updateUserLastLogin(userId: number, date: any): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + let error = false; + try { + await queryRunner.manager.update( + User, + { UserId: userId }, + { Last_Login: date } + ); + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + error = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !error; + } + + async verifyUserCredentials( + username: string, + password: string + ): Promise { + const user = await this.userRepository.findOne({ + where: { Username: username }, + }); + + if (user && (await comparePasswordHash(password, user.Password))) { + delete user.Password; + delete user.Names; + delete user.Emails; + delete user.Last_Login; + delete user.Register_Date; + return user; + } else { + return null; + } + } + + async verifyUserPayload(payload: any): Promise { + const user = await this.userRepository.findOne({ + where: { + UserId: payload.sub, + Username: payload.username, + Type: payload.type, + Unique_Hash: payload.hash, + }, + }); + return !!user; + } + + login(user: any): string { + const payload = { + username: user.Username, + sub: user.UserId, + type: user.Type, + hash: user.Unique_Hash, + }; + return this.signToken(payload); + } + + signToken(payload: any): string { + return this.jwtService.sign(payload, { algorithm: "HS256" }); + } + + verifyJWT(jwt: string): any { + try { + return this.jwtService.verify(jwt); + } catch (err) { + console.log(err); + return undefined; + } + } + + async logout(token: string): Promise { + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + + const invalidToken = new InvalidToken(); + invalidToken.Token = token; + invalidToken.Expiration_Date = tomorrow; + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + let error = false; + try { + const saved = await queryRunner.manager.save(invalidToken); + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + error = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !error; + } + async verifyLoginUser(token: string) { + const atributes = await this.getAtributes(token); + const ccNumber = atributes.cc; + await this.govUserService.updateLogin(ccNumber); + return this.govUserService.findOneByCC(ccNumber); + } + + async getAtributes(token: string) { + const atributesName = [ + "http://interop.gov.pt/MDC/Cidadao/NIC", + "http://interop.gov.pt/MDC/Cidadao/NomeCompleto", + ]; + const responseStart = await axios.post( + "https://preprod.autenticacao.gov.pt/oauthresourceserver/api/AttributeManager", + { token, atributesName } + ); + const authenticationContextId = responseStart.data.authenticationContextId; + const responseAtributes = await axios.get( + `https://preprod.autenticacao.gov.pt/oauthresourceserver/api/AttributeManager?token=${token}&authenticationContextId=${authenticationContextId}` + ); + return this.parseAtributes(responseAtributes.data); + } + + private parseAtributes(atributes: any) { + let result = { cc: null, name: "" }; + atributes.map((atribute) => { + const name = atribute.name; + const realName = NAME_CONVERTER[name]; + result[realName] = atribute.value; + }); + return result; + } +} +/** + * > [ │ + { │ + name: 'http://interop.gov.pt/MDC/Cidadao/NIC', │ + value: '15366302', │ + state: 'Available' │ +}, │ +{ │ + name: 'http://interop.gov.pt/MDC/Cidadao/NomeCompleto', │ + value: 'ANTÓNIO MANUEL SANTOS ESTRIGA', │ + state: 'Available' │ +} │ +│ ] + */ diff --git a/src/auth/gov-auth.guard.ts b/src/auth/gov-auth.guard.ts index 6d72a468..385d3a2e 100644 --- a/src/auth/gov-auth.guard.ts +++ b/src/auth/gov-auth.guard.ts @@ -1,29 +1,29 @@ -import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; -import { Reflector } from '@nestjs/core'; -import { AuthService } from './auth.service'; +import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common"; +import { Reflector } from "@nestjs/core"; +import { AuthService } from "./auth.service"; @Injectable() export class GovAuthGuard implements CanActivate { - constructor( - private reflector: Reflector, - private readonly authService: AuthService, - ) { } - /** - * - */ - //https://stackoverflow.com/questions/58714466/in-nestjs-is-there-any-way-to-pass-data-from-guards-to-the-controller + constructor( + private reflector: Reflector, + private readonly authService: AuthService + ) {} + /** + * + */ + //https://stackoverflow.com/questions/58714466/in-nestjs-is-there-any-way-to-pass-data-from-guards-to-the-controller - async canActivate(context: ExecutionContext): Promise { - const request = context.switchToHttp().getRequest(); - const token = request.query.access_token; - console.log(token); - const user = await this.authService.verifyLoginUser(token); - console.log(user); - const validUser = user?.entities.length > 0 - if (validUser) { - request.user = user.entities[0] - } - console.log(validUser); - return validUser; + async canActivate(context: ExecutionContext): Promise { + const request = context.switchToHttp().getRequest(); + const token = request.query.access_token; + console.log(token); + const user = await this.authService.verifyLoginUser(token); + console.log(user); + const validUser = user?.entities.length > 0; + if (validUser) { + request.user = user.entities[0]; } -} \ No newline at end of file + console.log(validUser); + return validUser; + } +} diff --git a/src/auth/invalid-token.entity.ts b/src/auth/invalid-token.entity.ts index 43bdd5e9..193b1965 100644 --- a/src/auth/invalid-token.entity.ts +++ b/src/auth/invalid-token.entity.ts @@ -1,22 +1,21 @@ -import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; - -@Entity('Invalid_Token') -export class InvalidToken { - - @PrimaryGeneratedColumn({ - type: 'int' - }) - TokenId: number; - - @Column({ - type: 'text', - nullable: false - }) - Token: string; - - @Column({ - type: 'datetime', - nullable: false - }) - Expiration_Date: any; -} \ No newline at end of file +import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"; + +@Entity("Invalid_Token") +export class InvalidToken { + @PrimaryGeneratedColumn({ + type: "int", + }) + TokenId: number; + + @Column({ + type: "text", + nullable: false, + }) + Token: string; + + @Column({ + type: "datetime", + nullable: false, + }) + Expiration_Date: any; +} diff --git a/src/auth/jwt-admin.strategy.ts b/src/auth/jwt-admin.strategy.ts index f8e34ddb..de96483d 100644 --- a/src/auth/jwt-admin.strategy.ts +++ b/src/auth/jwt-admin.strategy.ts @@ -1,31 +1,31 @@ -import { ExtractJwt, Strategy } from 'passport-jwt'; -import { PassportStrategy } from '@nestjs/passport'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { jwtConstants } from './constants'; -import { AuthService } from './auth.service'; - -@Injectable() -export class JwtAdminStrategy extends PassportStrategy(Strategy, 'jwt-admin') { - constructor(private readonly authService: AuthService) { - super({ - jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), - ignoreExpiration: false, - secretOrKey: jwtConstants.secret, - }); - } - - async validate(payload: any): Promise { - const valid = await this.authService.verifyUserPayload(payload); - - delete payload.exp; - const token = this.authService.signToken(payload); - - const isBlackListed = await this.authService.isTokenBlackListed(token); - - if (!valid || payload.type !== 'nimda' || isBlackListed) { - throw new UnauthorizedException(); - } - - return { userId: payload.sub, username: payload.username }; - } -} \ No newline at end of file +import { ExtractJwt, Strategy } from "passport-jwt"; +import { PassportStrategy } from "@nestjs/passport"; +import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { jwtConstants } from "./constants"; +import { AuthService } from "./auth.service"; + +@Injectable() +export class JwtAdminStrategy extends PassportStrategy(Strategy, "jwt-admin") { + constructor(private readonly authService: AuthService) { + super({ + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + ignoreExpiration: false, + secretOrKey: jwtConstants.secret, + }); + } + + async validate(payload: any): Promise { + const valid = await this.authService.verifyUserPayload(payload); + + delete payload.exp; + const token = this.authService.signToken(payload); + + const isBlackListed = await this.authService.isTokenBlackListed(token); + + if (!valid || payload.type !== "nimda" || isBlackListed) { + throw new UnauthorizedException(); + } + + return { userId: payload.sub, username: payload.username }; + } +} diff --git a/src/auth/jwt-monitor.strategy.ts b/src/auth/jwt-monitor.strategy.ts index c252b6f1..86284249 100644 --- a/src/auth/jwt-monitor.strategy.ts +++ b/src/auth/jwt-monitor.strategy.ts @@ -1,11 +1,14 @@ -import { ExtractJwt, Strategy } from 'passport-jwt'; -import { PassportStrategy } from '@nestjs/passport'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { jwtConstants } from './constants'; -import { AuthService } from './auth.service'; +import { ExtractJwt, Strategy } from "passport-jwt"; +import { PassportStrategy } from "@nestjs/passport"; +import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { jwtConstants } from "./constants"; +import { AuthService } from "./auth.service"; @Injectable() -export class JwtMonitorStrategy extends PassportStrategy(Strategy, 'jwt-monitor') { +export class JwtMonitorStrategy extends PassportStrategy( + Strategy, + "jwt-monitor" +) { constructor(private readonly authService: AuthService) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), @@ -21,11 +24,11 @@ export class JwtMonitorStrategy extends PassportStrategy(Strategy, 'jwt-monitor' const token = this.authService.signToken(payload); const isBlackListed = await this.authService.isTokenBlackListed(token); - - if (!valid || payload.type !== 'monitor' || isBlackListed) { - throw new UnauthorizedException(); + + if (!valid || payload.type !== "monitor" || isBlackListed) { + throw new UnauthorizedException(); } - + return { userId: payload.sub, username: payload.username }; } -} \ No newline at end of file +} diff --git a/src/auth/jwt-study.strategy.ts b/src/auth/jwt-study.strategy.ts index ff589788..90f4fef9 100644 --- a/src/auth/jwt-study.strategy.ts +++ b/src/auth/jwt-study.strategy.ts @@ -1,11 +1,11 @@ -import { ExtractJwt, Strategy } from 'passport-jwt'; -import { PassportStrategy } from '@nestjs/passport'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { jwtConstants } from './constants'; -import { AuthService } from './auth.service'; +import { ExtractJwt, Strategy } from "passport-jwt"; +import { PassportStrategy } from "@nestjs/passport"; +import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { jwtConstants } from "./constants"; +import { AuthService } from "./auth.service"; @Injectable() -export class JwtStudyStrategy extends PassportStrategy(Strategy, 'jwt-study') { +export class JwtStudyStrategy extends PassportStrategy(Strategy, "jwt-study") { constructor(private readonly authService: AuthService) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), @@ -21,11 +21,11 @@ export class JwtStudyStrategy extends PassportStrategy(Strategy, 'jwt-study') { const token = this.authService.signToken(payload); const isBlackListed = await this.authService.isTokenBlackListed(token); - - if (!valid || payload.type !== 'studies' || isBlackListed) { - throw new UnauthorizedException(); + + if (!valid || payload.type !== "studies" || isBlackListed) { + throw new UnauthorizedException(); } - + return { userId: payload.sub, username: payload.username }; } -} \ No newline at end of file +} diff --git a/src/auth/jwt.strategy.ts b/src/auth/jwt.strategy.ts index 727a2680..f82f000e 100644 --- a/src/auth/jwt.strategy.ts +++ b/src/auth/jwt.strategy.ts @@ -1,30 +1,30 @@ -import { ExtractJwt, Strategy } from 'passport-jwt'; -import { PassportStrategy } from '@nestjs/passport'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { jwtConstants } from './constants'; -import { AuthService } from './auth.service'; - -@Injectable() -export class JwtStrategy extends PassportStrategy(Strategy) { - constructor(private readonly authService: AuthService) { - super({ - jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), - ignoreExpiration: false, - secretOrKey: jwtConstants.secret, - }); - } - - async validate(payload: any): Promise { - const valid = await this.authService.verifyUserPayload(payload); - - delete payload.exp; - const token = this.authService.signToken(payload); - - const isBlackListed = await this.authService.isTokenBlackListed(token); - if (!valid || isBlackListed) { - throw new UnauthorizedException(); - } - - return { userId: payload.sub, username: payload.username }; - } -} \ No newline at end of file +import { ExtractJwt, Strategy } from "passport-jwt"; +import { PassportStrategy } from "@nestjs/passport"; +import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { jwtConstants } from "./constants"; +import { AuthService } from "./auth.service"; + +@Injectable() +export class JwtStrategy extends PassportStrategy(Strategy) { + constructor(private readonly authService: AuthService) { + super({ + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + ignoreExpiration: false, + secretOrKey: jwtConstants.secret, + }); + } + + async validate(payload: any): Promise { + const valid = await this.authService.verifyUserPayload(payload); + + delete payload.exp; + const token = this.authService.signToken(payload); + + const isBlackListed = await this.authService.isTokenBlackListed(token); + if (!valid || isBlackListed) { + throw new UnauthorizedException(); + } + + return { userId: payload.sub, username: payload.username }; + } +} diff --git a/src/auth/local.strategy.ts b/src/auth/local.strategy.ts index cfd6d35c..01d108c6 100644 --- a/src/auth/local.strategy.ts +++ b/src/auth/local.strategy.ts @@ -1,19 +1,22 @@ -import { Strategy } from 'passport-local'; -import { PassportStrategy } from '@nestjs/passport'; -import { Injectable, UnauthorizedException } from '@nestjs/common'; -import { AuthService } from './auth.service'; - -@Injectable() -export class LocalStrategy extends PassportStrategy(Strategy) { - constructor(private readonly authService: AuthService) { - super(); - } - - async validate(username: string, password: string): Promise { - const user = await this.authService.verifyUserCredentials(username, password); - if (!user) { - throw new UnauthorizedException(); - } - return user; - } -} \ No newline at end of file +import { Strategy } from "passport-local"; +import { PassportStrategy } from "@nestjs/passport"; +import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { AuthService } from "./auth.service"; + +@Injectable() +export class LocalStrategy extends PassportStrategy(Strategy) { + constructor(private readonly authService: AuthService) { + super(); + } + + async validate(username: string, password: string): Promise { + const user = await this.authService.verifyUserCredentials( + username, + password + ); + if (!user) { + throw new UnauthorizedException(); + } + return user; + } +} diff --git a/src/crawler/crawler.controller.spec.ts b/src/crawler/crawler.controller.spec.ts index 85fbf5d3..1bd94399 100644 --- a/src/crawler/crawler.controller.spec.ts +++ b/src/crawler/crawler.controller.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { CrawlerController } from './crawler.controller'; +import { Test, TestingModule } from "@nestjs/testing"; +import { CrawlerController } from "./crawler.controller"; -describe('Crawler Controller', () => { +describe("Crawler Controller", () => { let controller: CrawlerController; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('Crawler Controller', () => { controller = module.get(CrawlerController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/crawler/crawler.controller.ts b/src/crawler/crawler.controller.ts index bc080cd4..ae3281db 100644 --- a/src/crawler/crawler.controller.ts +++ b/src/crawler/crawler.controller.ts @@ -12,7 +12,12 @@ import { AuthGuard } from "@nestjs/passport"; import { CrawlerService } from "./crawler.service"; import { success } from "../lib/response"; import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiResponse, ApiTags, ApiOperation } from "@nestjs/swagger"; +import { + ApiBasicAuth, + ApiResponse, + ApiTags, + ApiOperation, +} from "@nestjs/swagger"; import { CrawlWebsite } from "./crawler.entity"; import { CrawlerConfig } from "./dto/crawler-config.dto"; import { CrawlerCreate } from "./dto/crawler-create.dto"; @@ -21,19 +26,18 @@ import { CrawlerUserWebsite } from "./dto/crawler-user-website.dto"; import { CrawlerDelete } from "./dto/crawler-delete.dto"; import { CrawlerDeleteBulk } from "./dto/crawler-delete-bulk.dto"; - @ApiBasicAuth() -@ApiTags('directory') -@ApiResponse({ status: 403, description: 'Forbidden' }) +@ApiTags("directory") +@ApiResponse({ status: 403, description: "Forbidden" }) @Controller("crawler") @UseInterceptors(LoggingInterceptor) export class CrawlerController { constructor(private readonly crawlerService: CrawlerService) {} - @ApiOperation({ summary: 'Find all crawl website' }) + @ApiOperation({ summary: "Find all crawl website" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-admin")) @@ -42,10 +46,10 @@ export class CrawlerController { return success(await this.crawlerService.findAll()); } - @ApiOperation({ summary: 'Find the crawler config' }) + @ApiOperation({ summary: "Find the crawler config" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -54,11 +58,10 @@ export class CrawlerController { return success(this.crawlerService.getConfig()); } - - @ApiOperation({ summary: 'Change the crawler config' }) + @ApiOperation({ summary: "Change the crawler config" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -69,10 +72,10 @@ export class CrawlerController { return success(this.crawlerService.setConfig(maxDepth, maxPages)); } - @ApiOperation({ summary: 'Change the crawler config' }) + @ApiOperation({ summary: "Change the crawler config" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -95,10 +98,10 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Crawl all websites in a list of tags' }) + @ApiOperation({ summary: "Crawl all websites in a list of tags" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -108,15 +111,18 @@ export class CrawlerController { return success(await this.crawlerService.crawlTags(tagsId)); } - @ApiOperation({ summary: 'Crawl user website(My Monitor)' }) + @ApiOperation({ summary: "Crawl user website(My Monitor)" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-monitor")) @Post("crawlUser") - async crawlUserPage(@Request() req: any, @Body() crawlerUserWebsite: CrawlerUserWebsite): Promise { + async crawlUserPage( + @Request() req: any, + @Body() crawlerUserWebsite: CrawlerUserWebsite + ): Promise { const userId = req.user.userId; const websiteUrl = crawlerUserWebsite.website; const websiteId = await this.crawlerService.getWebsiteId( @@ -136,15 +142,18 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Check user crawl from a specific website' }) + @ApiOperation({ summary: "Check user crawl from a specific website" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-monitor")) @Post("crawlUserCheck") - async checkCrawlUserPage(@Request() req: any, @Body() crawlerUserWebsite: CrawlerUserWebsite): Promise { + async checkCrawlUserPage( + @Request() req: any, + @Body() crawlerUserWebsite: CrawlerUserWebsite + ): Promise { const userId = req.user.userId; const websiteUrl = crawlerUserWebsite.website; const websiteId = await this.crawlerService.getWebsiteId( @@ -157,15 +166,18 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Check user crawl results from a specific website' }) + @ApiOperation({ summary: "Check user crawl results from a specific website" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-monitor")) @Post("crawlUserResults") - async getCrawlUserPageResults(@Request() req: any, @Body() crawlerUserWebsite: CrawlerUserWebsite): Promise { + async getCrawlUserPageResults( + @Request() req: any, + @Body() crawlerUserWebsite: CrawlerUserWebsite + ): Promise { const userId = req.user.userId; const websiteUrl = crawlerUserWebsite.website; const websiteId = await this.crawlerService.getWebsiteId( @@ -178,15 +190,18 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Delete user crawl from a specific website' }) + @ApiOperation({ summary: "Delete user crawl from a specific website" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-monitor")) @Post("crawlUserDelete") - async deleteCrawlUserPage(@Request() req: any, @Body() crawlerUserWebsite: CrawlerUserWebsite): Promise { + async deleteCrawlUserPage( + @Request() req: any, + @Body() crawlerUserWebsite: CrawlerUserWebsite + ): Promise { const userId = req.user.userId; const websiteUrl = crawlerUserWebsite.website; const websiteId = await this.crawlerService.getWebsiteId( @@ -199,15 +214,18 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Crawl user website(Study Monitor)' }) + @ApiOperation({ summary: "Crawl user website(Study Monitor)" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-study")) @Post("crawlStudiesUser") - async crawlStudiesUserPage(@Request() req: any, @Body() crawlerUserWebsite: CrawlerUserWebsite): Promise { + async crawlStudiesUserPage( + @Request() req: any, + @Body() crawlerUserWebsite: CrawlerUserWebsite + ): Promise { const userId = req.user.userId; const websiteUrl = crawlerUserWebsite.website; const websiteId = await this.crawlerService.getWebsiteId( @@ -227,15 +245,20 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Check user crawl results from a specific website(Study Monitor)' }) + @ApiOperation({ + summary: "Check user crawl results from a specific website(Study Monitor)", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-study")) @Post("crawlStudiesUserCheck") - async checkStudiesCrawlUserPage(@Request() req: any, @Body() crawlerUserWebsite: CrawlerUserWebsite): Promise { + async checkStudiesCrawlUserPage( + @Request() req: any, + @Body() crawlerUserWebsite: CrawlerUserWebsite + ): Promise { const userId = req.user.userId; const websiteUrl = crawlerUserWebsite.website; const websiteId = await this.crawlerService.getWebsiteId( @@ -248,10 +271,10 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Find crawl results from a specific tag' }) + @ApiOperation({ summary: "Find crawl results from a specific tag" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-study")) @@ -269,15 +292,18 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Check user crawl results from a specific website' }) + @ApiOperation({ summary: "Check user crawl results from a specific website" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-study")) @Post("crawlStudiesUserResults") - async getCrawlStudiesUserPageResults(@Request() req: any, @Body() crawlerUserWebsite: CrawlerUserWebsite): Promise { + async getCrawlStudiesUserPageResults( + @Request() req: any, + @Body() crawlerUserWebsite: CrawlerUserWebsite + ): Promise { const userId = req.user.userId; const websiteId = crawlerUserWebsite.websiteId; @@ -286,16 +312,20 @@ export class CrawlerController { ); } - - @ApiOperation({ summary: 'Delete user crawl from a specific website(Study Monitor)' }) + @ApiOperation({ + summary: "Delete user crawl from a specific website(Study Monitor)", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-study")) @Post("crawlStudiesUserDelete") - async deleteCrawlStudiesUserPage(@Request() req: any, @Body() crawlerUserWebsite: CrawlerUserWebsite): Promise { + async deleteCrawlStudiesUserPage( + @Request() req: any, + @Body() crawlerUserWebsite: CrawlerUserWebsite + ): Promise { const userId = req.user.userId; const websiteId = crawlerUserWebsite.websiteId; @@ -304,10 +334,10 @@ export class CrawlerController { ); } - @ApiOperation({ summary: 'Delete specific crawl' }) + @ApiOperation({ summary: "Delete specific crawl" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -318,24 +348,26 @@ export class CrawlerController { return success(await this.crawlerService.delete(crawlWebsiteId)); } - @ApiOperation({ summary: 'Delete list of crawls' }) + @ApiOperation({ summary: "Delete list of crawls" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @Post("deleteBulk") - async deleteCrawlers(@Body() crawlerDeleteBulk: CrawlerDeleteBulk): Promise { + async deleteCrawlers( + @Body() crawlerDeleteBulk: CrawlerDeleteBulk + ): Promise { const crawlWebsiteIds = crawlerDeleteBulk.crawlWebsiteIds; return success(await this.crawlerService.deleteBulk(crawlWebsiteIds)); } - @ApiOperation({ summary: 'Find crawl website by id' }) + @ApiOperation({ summary: "Find crawl website by id" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) diff --git a/src/crawler/crawler.service.spec.ts b/src/crawler/crawler.service.spec.ts index 2a266e3f..af09349f 100644 --- a/src/crawler/crawler.service.spec.ts +++ b/src/crawler/crawler.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { CrawlerService } from './crawler.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { CrawlerService } from "./crawler.service"; -describe('CrawlerService', () => { +describe("CrawlerService", () => { let service: CrawlerService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('CrawlerService', () => { service = module.get(CrawlerService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/crawler/crawler.service.ts b/src/crawler/crawler.service.ts index b9f7547d..0638acf7 100644 --- a/src/crawler/crawler.service.ts +++ b/src/crawler/crawler.service.ts @@ -7,7 +7,7 @@ import { readFileSync, writeFileSync } from "fs"; import puppeteer from "puppeteer-extra"; import StealthPlugin from "puppeteer-extra-plugin-stealth"; import { PageService } from "src/page/page.service"; -import { Crawler } from "@qualweb/crawler"; +import { BrowserContext } from "puppeteer"; @Injectable() export class CrawlerService { @@ -19,7 +19,7 @@ export class CrawlerService { private readonly crawlWebsiteRepository: Repository, @InjectDataSource() private readonly connection: DataSource, - private readonly pageService: PageService + private readonly pageService: PageService ) { this.isAdminCrawling = false; this.isUserCrawling = false; @@ -47,25 +47,15 @@ export class CrawlerService { if (website.length > 0) { const browser = await puppeteer.launch({ + headless: "new", args: ["--no-sandbox", "--ignore-certificate-errors"], }); - const incognito:any = await browser.createIncognitoBrowserContext(); - const crawler = new Crawler( - incognito, - website[0].StartingUrl, - undefined, - website[0].Wait_JS === 1 ? "networkidle0" : "domcontentloaded" - ); - - await crawler.crawl({ - maxDepth: website[0].Max_Depth, - maxUrls: website[0].Max_Pages ? website[0].Max_Pages : undefined, - }); - + const incognito: any = + await browser.createIncognitoBrowserContext(); + const urls = await this.MSCrawl(incognito, website[0].StartingUrl); await incognito.close(); await browser.close(); - const urls = crawler.getResults(); if (website[0].Tag !== 1) { for (const url of urls || []) { try { @@ -128,27 +118,19 @@ export class CrawlerService { const browser = await puppeteer.launch({ args: ["--no-sandbox", "--ignore-certificate-errors"], }); - const incognito:any = await browser.createIncognitoBrowserContext(); - const crawler = new Crawler( - incognito, - website[0].StartingUrl, - undefined, - website[0].Wait_JS === 1 ? "networkidle0" : "domcontentloaded" - ); - //await this.crawl(website[0].StartingUrl); - await crawler.crawl({ maxDepth: 0 }); - + const incognito: any = + await browser.createIncognitoBrowserContext(); + const urls = await this.MSCrawl(incognito, website[0].StartingUrl); await incognito.close(); await browser.close(); - const urls = crawler.getResults(); for (const url of urls || []) { - try{ - const newCrawlPage = new CrawlPage(); - newCrawlPage.Uri = decodeURIComponent(url); - newCrawlPage.CrawlWebsiteId = website[0].CrawlWebsiteId; + try { + const newCrawlPage = new CrawlPage(); + newCrawlPage.Uri = decodeURIComponent(url); + newCrawlPage.CrawlWebsiteId = website[0].CrawlWebsiteId; await queryRunner.manager.save(newCrawlPage); - }catch (e) { + } catch (e) { console.log(e); } } @@ -199,10 +181,10 @@ export class CrawlerService { }); return page && page.Done === 1; /*if (page) { - return page.Done === 1; - } else { - throw new InternalServerErrorException(); - }*/ + return page.Done === 1; + } else { + throw new InternalServerErrorException(); + }*/ } async getUserCrawlResults( @@ -231,7 +213,7 @@ export class CrawlerService { userId: number, tagName: string ): Promise { - const websites = await this.crawlWebsiteRepository.query( + const websites = await this.crawlWebsiteRepository.query( ` SELECT w.Name, @@ -403,4 +385,78 @@ export class CrawlerService { return website[0].WebsiteId; } + + private async MSCrawl( + browser: BrowserContext, + pageURL: string + ): Promise { + try { + const page = await browser.newPage(); + await page.goto(pageURL, { waitUntil: "domcontentloaded" }); + const urls = await page.evaluate( + (pageURL) => { + const notHtml = + "css|jpg|jpeg|gif|svg|pdf|docx|js|png|ico|xml|mp4|mp3|mkv|wav|rss|json|pptx|txt|zip".split( + "|" + ); + const links = document.querySelectorAll("body a"); + const urls = new Array(); + links.forEach((link: Element) => { + if (link.hasAttribute("href")) { + let href = link.getAttribute("href").trim(); + if (href.startsWith("//")) { + href = href.replace("//", "https://"); + } + if ( + (href.startsWith(pageURL) || + href.startsWith("/") || + href.startsWith("./") || + (!href.startsWith("http") && !href.startsWith("#"))) && + !href.includes("mailto:") && + !href.includes("tel:") && + !href.includes("javascript:") + ) { + let valid = true; + for (const not of notHtml || []) { + if (href.endsWith(not) || href.includes("." + not + "/")) { + valid = false; + break; + } + const parts = href.split("/"); + if (parts.length > 0) { + const lastPart = parts[parts.length - 1]; + if (lastPart.startsWith("#")) { + valid = false; + break; + } + } + } + if (valid) { + let correctUrl = ""; + if (href.startsWith(pageURL)) { + correctUrl = href; + } else if (href.startsWith("./")) { + correctUrl = pageURL + href.slice(2); + } else if (href.startsWith("/")) { + correctUrl = pageURL + href.slice(1); + } else { + correctUrl = pageURL + href; + } + if (!urls.includes(correctUrl)) { + urls.push(correctUrl); + } + } + } + } + }); + return urls; + }, + pageURL.endsWith("/") ? pageURL : pageURL + "/" + ); + return urls; + } catch (e) { + console.log("Problem during crawling", e); + return []; + } + } } diff --git a/src/crawler/dto/crawler-config.dto.ts b/src/crawler/dto/crawler-config.dto.ts index 8ed7cfa4..c067f9d0 100644 --- a/src/crawler/dto/crawler-config.dto.ts +++ b/src/crawler/dto/crawler-config.dto.ts @@ -1,4 +1,4 @@ - export class CrawlerConfig { - maxDepth:number; - maxPages:number;} \ No newline at end of file + maxDepth: number; + maxPages: number; +} diff --git a/src/crawler/dto/crawler-create.dto.ts b/src/crawler/dto/crawler-create.dto.ts index b9ae94e2..9b4f5a89 100644 --- a/src/crawler/dto/crawler-create.dto.ts +++ b/src/crawler/dto/crawler-create.dto.ts @@ -1,7 +1,6 @@ - export class CrawlerCreate { - maxDepth:number; - maxPages:number; - websites: Array; - waitJS:number; -} \ No newline at end of file + maxDepth: number; + maxPages: number; + websites: Array; + waitJS: number; +} diff --git a/src/crawler/dto/crawler-delete-bulk.dto.ts b/src/crawler/dto/crawler-delete-bulk.dto.ts index 45009475..f0e84ab3 100644 --- a/src/crawler/dto/crawler-delete-bulk.dto.ts +++ b/src/crawler/dto/crawler-delete-bulk.dto.ts @@ -1,4 +1,3 @@ - export class CrawlerDeleteBulk { - crawlWebsiteIds:number[]; -} \ No newline at end of file + crawlWebsiteIds: number[]; +} diff --git a/src/crawler/dto/crawler-delete.dto.ts b/src/crawler/dto/crawler-delete.dto.ts index 4a4cdad2..4f3e7a67 100644 --- a/src/crawler/dto/crawler-delete.dto.ts +++ b/src/crawler/dto/crawler-delete.dto.ts @@ -1,4 +1,3 @@ - export class CrawlerDelete { - crawlWebsiteId:number; -} \ No newline at end of file + crawlWebsiteId: number; +} diff --git a/src/crawler/dto/crawler-tags.dto.ts b/src/crawler/dto/crawler-tags.dto.ts index 7dc7df05..c88e0a8d 100644 --- a/src/crawler/dto/crawler-tags.dto.ts +++ b/src/crawler/dto/crawler-tags.dto.ts @@ -1,4 +1,3 @@ - export class CrawlerTags { - tagsId:number[]; -} \ No newline at end of file + tagsId: number[]; +} diff --git a/src/crawler/dto/crawler-user-website.dto.ts b/src/crawler/dto/crawler-user-website.dto.ts index 7aa26df2..d4d74236 100644 --- a/src/crawler/dto/crawler-user-website.dto.ts +++ b/src/crawler/dto/crawler-user-website.dto.ts @@ -1,5 +1,4 @@ - export class CrawlerUserWebsite { - website:string; - websiteId:number; -} \ No newline at end of file + website: string; + websiteId: number; +} diff --git a/src/directory/directory.controller.spec.ts b/src/directory/directory.controller.spec.ts index b4ee9f8a..2aa574fe 100644 --- a/src/directory/directory.controller.spec.ts +++ b/src/directory/directory.controller.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { DirectoryController } from './directory.controller'; +import { Test, TestingModule } from "@nestjs/testing"; +import { DirectoryController } from "./directory.controller"; -describe('DirectoryController', () => { +describe("DirectoryController", () => { let controller: DirectoryController; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('DirectoryController', () => { controller = module.get(DirectoryController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/directory/directory.controller.ts b/src/directory/directory.controller.ts index d46f8609..b5d12712 100644 --- a/src/directory/directory.controller.ts +++ b/src/directory/directory.controller.ts @@ -13,7 +13,12 @@ import { DirectoryService } from "./directory.service"; import { Directory } from "./directory.entity"; import { success } from "../lib/response"; import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; +import { + ApiBasicAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; import { ReEvaluateDto } from "./dto/reEvaluate-pages.dto"; import { CreateDirectory } from "./dto/create-diretory.dto"; import { UpdateDirectory } from "./dto/update-diretory.dto"; @@ -22,24 +27,25 @@ import { DeleteBulkDirectory } from "./dto/delete-bulk-diretory.dto"; import { Tag } from "src/tag/tag.entity"; import { Website } from "src/website/website.entity"; - @ApiBasicAuth() -@ApiTags('directory') -@ApiResponse({ status: 403, description: 'Forbidden' }) +@ApiTags("directory") +@ApiResponse({ status: 403, description: "Forbidden" }) @Controller("directory") @UseInterceptors(LoggingInterceptor) export class DirectoryController { constructor(private readonly directoryService: DirectoryService) {} - @ApiOperation({ summary: 'Reevaluate all pages from a directory' }) + @ApiOperation({ summary: "Reevaluate all pages from a directory" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @Post("reEvaluate") - async reEvaluateWebsitePages(@Body() reEvaluateDto: ReEvaluateDto): Promise { + async reEvaluateWebsitePages( + @Body() reEvaluateDto: ReEvaluateDto + ): Promise { const directoriesId = reEvaluateDto.directoriesId; const option = reEvaluateDto.option; @@ -48,10 +54,10 @@ export class DirectoryController { ); } - @ApiOperation({ summary: 'Find all directories' }) + @ApiOperation({ summary: "Find all directories" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -60,15 +66,17 @@ export class DirectoryController { return success(await this.directoryService.findAll()); } - @ApiOperation({ summary: 'Create a new directory' }) + @ApiOperation({ summary: "Create a new directory" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @Post("create") - async createDirectory(@Body() createDirectory: CreateDirectory): Promise { + async createDirectory( + @Body() createDirectory: CreateDirectory + ): Promise { const directory = new Directory(); directory.Name = createDirectory.name; directory.Show_in_Observatory = createDirectory.observatory; @@ -89,10 +97,10 @@ export class DirectoryController { return success(true); } - @ApiOperation({ summary: 'Check if directory name exists' }) + @ApiOperation({ summary: "Check if directory name exists" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -105,15 +113,17 @@ export class DirectoryController { ); } - @ApiOperation({ summary: 'Update a specific directory' }) + @ApiOperation({ summary: "Update a specific directory" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @Post("update") - async updateDirectory(@Body() updateDirectory: UpdateDirectory): Promise { + async updateDirectory( + @Body() updateDirectory: UpdateDirectory + ): Promise { const directoryId = updateDirectory.directoryId; const name = updateDirectory.name; const observatory = updateDirectory.observatory; @@ -137,15 +147,17 @@ export class DirectoryController { return success(true); } - @ApiOperation({ summary: 'Delete a specific directory' }) + @ApiOperation({ summary: "Delete a specific directory" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @Post("delete") - async deleteDirectory(@Body() deleteDirectory: DeleteDirectory): Promise { + async deleteDirectory( + @Body() deleteDirectory: DeleteDirectory + ): Promise { const directoryId = deleteDirectory.directoryId; const deleteSuccess = await this.directoryService.delete(directoryId); @@ -156,15 +168,17 @@ export class DirectoryController { return success(true); } - @ApiOperation({ summary: 'Delete a list directories' }) + @ApiOperation({ summary: "Delete a list directories" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @Post("deleteBulk") - async deleteDirectories(@Body() deleteBulkDirectory: DeleteBulkDirectory): Promise { + async deleteDirectories( + @Body() deleteBulkDirectory: DeleteBulkDirectory + ): Promise { const directoriesId = deleteBulkDirectory.directoriesId; const deleteSuccess = await this.directoryService.deleteBulk(directoriesId); @@ -174,15 +188,17 @@ export class DirectoryController { return success(true); } - @ApiOperation({ summary: 'Delete all pages from a list directories' }) + @ApiOperation({ summary: "Delete all pages from a list directories" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @Post("pages/deleteBulk") - async deleteDirectoriesPages(@Body() deleteBulkDirectory: DeleteBulkDirectory): Promise { + async deleteDirectoriesPages( + @Body() deleteBulkDirectory: DeleteBulkDirectory + ): Promise { const directoriesId = deleteBulkDirectory.directoriesId; const deleteSuccess = await this.directoryService.pagesDeleteBulk( @@ -195,10 +211,10 @@ export class DirectoryController { return success(true); } - @ApiOperation({ summary: 'Find number of observatory directories' }) + @ApiOperation({ summary: "Find number of observatory directories" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -207,23 +223,24 @@ export class DirectoryController { return success(await this.directoryService.findNumberOfObservatory()); } - @ApiOperation({ summary: 'Find a specific directory info' }) + @ApiOperation({ summary: "Find a specific directory info" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Directory, }) @UseGuards(AuthGuard("jwt")) @Get("info/:directoryId") - async getDirectoryInfo(@Param("directoryId") directoryId: number): Promise { + async getDirectoryInfo( + @Param("directoryId") directoryId: number + ): Promise { return success(await this.directoryService.findInfo(directoryId)); } - - @ApiOperation({ summary: 'Find all tags from a specific dirctory' }) + @ApiOperation({ summary: "Find all tags from a specific dirctory" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-admin")) @@ -232,10 +249,10 @@ export class DirectoryController { return success(await this.directoryService.findAllDirectoryTags(directory)); } - @ApiOperation({ summary: 'Find all websites from a specific dirctory' }) + @ApiOperation({ summary: "Find all websites from a specific dirctory" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-admin")) @@ -248,11 +265,10 @@ export class DirectoryController { ); } - - @ApiOperation({ summary: 'Find all pages from a specific dirctory' }) + @ApiOperation({ summary: "Find all pages from a specific dirctory" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-admin")) diff --git a/src/directory/directory.service.spec.ts b/src/directory/directory.service.spec.ts index 7c62ddc9..5918b429 100644 --- a/src/directory/directory.service.spec.ts +++ b/src/directory/directory.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { DirectoryService } from './directory.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { DirectoryService } from "./directory.service"; -describe('DirectoryService', () => { +describe("DirectoryService", () => { let service: DirectoryService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('DirectoryService', () => { service = module.get(DirectoryService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/directory/directory.service.ts b/src/directory/directory.service.ts index fdc42589..f085b249 100644 --- a/src/directory/directory.service.ts +++ b/src/directory/directory.service.ts @@ -9,7 +9,8 @@ export class DirectoryService { @InjectRepository(Directory) private readonly directoryRepository: Repository, @InjectDataSource() - private readonly connection: DataSource, ) {} + private readonly connection: DataSource + ) {} async addPagesToEvaluate( directoriesId: number[], @@ -362,7 +363,9 @@ export class DirectoryService { } async findNumberOfObservatory(): Promise { - return this.directoryRepository.count({ where: { Show_in_Observatory: 1 } }); + return this.directoryRepository.count({ + where: { Show_in_Observatory: 1 }, + }); } async findInfo(directoryId: number): Promise { @@ -516,7 +519,6 @@ export class DirectoryService { } async findAllDirectoryWebsitePages(directory: string): Promise { - const _directory = await this.directoryRepository.query( `SELECT * FROM Directory WHERE Name = ? LIMIT 1`, [directory] diff --git a/src/directory/dto/create-diretory.dto.ts b/src/directory/dto/create-diretory.dto.ts index 6da6f98d..0f3d1eaa 100644 --- a/src/directory/dto/create-diretory.dto.ts +++ b/src/directory/dto/create-diretory.dto.ts @@ -1,6 +1,6 @@ export class CreateDirectory { - observatory:number; - name:string; - method:number; - tags: number[]; -} \ No newline at end of file + observatory: number; + name: string; + method: number; + tags: number[]; +} diff --git a/src/directory/dto/delete-bulk-diretory.dto.ts b/src/directory/dto/delete-bulk-diretory.dto.ts index a68c34bc..43e0d36a 100644 --- a/src/directory/dto/delete-bulk-diretory.dto.ts +++ b/src/directory/dto/delete-bulk-diretory.dto.ts @@ -1,2 +1,3 @@ export class DeleteBulkDirectory { - directoriesId:number[];} \ No newline at end of file + directoriesId: number[]; +} diff --git a/src/directory/dto/delete-diretory.dto.ts b/src/directory/dto/delete-diretory.dto.ts index e726c175..ff6bf5cb 100644 --- a/src/directory/dto/delete-diretory.dto.ts +++ b/src/directory/dto/delete-diretory.dto.ts @@ -1,2 +1,3 @@ export class DeleteDirectory { - directoryId:number;} \ No newline at end of file + directoryId: number; +} diff --git a/src/directory/dto/reEvaluate-pages.dto.ts b/src/directory/dto/reEvaluate-pages.dto.ts index 36a5bf52..8ea196d7 100644 --- a/src/directory/dto/reEvaluate-pages.dto.ts +++ b/src/directory/dto/reEvaluate-pages.dto.ts @@ -1,4 +1,4 @@ export class ReEvaluateDto { - directoriesId:number[]; - option:string; -} \ No newline at end of file + directoriesId: number[]; + option: string; +} diff --git a/src/directory/dto/update-diretory.dto.ts b/src/directory/dto/update-diretory.dto.ts index 9d86c02f..acc947c1 100644 --- a/src/directory/dto/update-diretory.dto.ts +++ b/src/directory/dto/update-diretory.dto.ts @@ -1,7 +1,8 @@ export class UpdateDirectory { - observatory:number; - name:string; - method:number; - tags: number[]; - defaultTags:number[]; - directoryId:number;} \ No newline at end of file + observatory: number; + name: string; + method: number; + tags: number[]; + defaultTags: number[]; + directoryId: number; +} diff --git a/src/dump/dump.controller.spec.ts b/src/dump/dump.controller.spec.ts index f0bff788..f795357a 100644 --- a/src/dump/dump.controller.spec.ts +++ b/src/dump/dump.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { DumpController } from './dump.controller'; -import { DumpService } from './dump.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { DumpController } from "./dump.controller"; +import { DumpService } from "./dump.service"; -describe('DumpController', () => { +describe("DumpController", () => { let controller: DumpController; beforeEach(async () => { @@ -14,7 +14,7 @@ describe('DumpController', () => { controller = module.get(DumpController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/dump/dump.controller.ts b/src/dump/dump.controller.ts index a2d88eea..67d07d5b 100644 --- a/src/dump/dump.controller.ts +++ b/src/dump/dump.controller.ts @@ -1,14 +1,13 @@ -import { Controller, Get, Res, UseGuards } from '@nestjs/common'; -import { createReadStream } from 'fs'; -import { join } from 'path'; -import { DumpService } from './dump.service'; -import { Response } from 'express'; -import { AuthGuard } from '@nestjs/passport'; -const execSync = require('child_process').execSync; - +import { Controller, Get, Res, UseGuards } from "@nestjs/common"; +import { createReadStream } from "fs"; +import { join } from "path"; +import { DumpService } from "./dump.service"; +import { Response } from "express"; +import { AuthGuard } from "@nestjs/passport"; +const execSync = require("child_process").execSync; @UseGuards(AuthGuard("jwt-admin")) -@Controller('dump') +@Controller("dump") export class DumpController { constructor(private readonly dumpService: DumpService) {} @@ -17,8 +16,8 @@ export class DumpController { return this.dumpService.createDump(); } - @Get('file') - async getLog(@Res() res: Response,) { + @Get("file") + async getLog(@Res() res: Response) { const path = this.dumpService.path; if (path) { const file = createReadStream(join(process.cwd(), path)); @@ -26,10 +25,8 @@ export class DumpController { } } - @Get('restart') + @Get("restart") async restart() { - execSync('pm2 restart monitor-server'); + execSync("pm2 restart monitor-server"); } - - } diff --git a/src/dump/dump.module.ts b/src/dump/dump.module.ts index ee2e48c7..1a07bdf3 100644 --- a/src/dump/dump.module.ts +++ b/src/dump/dump.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { DumpService } from './dump.service'; -import { DumpController } from './dump.controller'; +import { Module } from "@nestjs/common"; +import { DumpService } from "./dump.service"; +import { DumpController } from "./dump.controller"; @Module({ controllers: [DumpController], - providers: [DumpService] + providers: [DumpService], }) export class DumpModule {} diff --git a/src/dump/dump.service.spec.ts b/src/dump/dump.service.spec.ts index 2e93c1ec..b27f6c29 100644 --- a/src/dump/dump.service.spec.ts +++ b/src/dump/dump.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { DumpService } from './dump.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { DumpService } from "./dump.service"; -describe('DumpService', () => { +describe("DumpService", () => { let service: DumpService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('DumpService', () => { service = module.get(DumpService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/dump/dump.service.ts b/src/dump/dump.service.ts index ca491722..96310e2b 100644 --- a/src/dump/dump.service.ts +++ b/src/dump/dump.service.ts @@ -1,14 +1,11 @@ -import { Injectable } from '@nestjs/common'; -import { readFileSync } from 'fs'; -import mysqldump from 'mysqldump'; - +import { Injectable } from "@nestjs/common"; +import { readFileSync } from "fs"; +import mysqldump from "mysqldump"; @Injectable() export class DumpService { - databaseConfig = JSON.parse( - readFileSync("../monitor_db.json").toString() - ); - path = './dump.sql.gz'; + databaseConfig = JSON.parse(readFileSync("../monitor_db.json").toString()); + path = "./dump.sql.gz"; createDump() { mysqldump({ connection: { @@ -21,5 +18,4 @@ export class DumpService { compressFile: true, }); } - } diff --git a/src/entity/dto/create-entity.dto.ts b/src/entity/dto/create-entity.dto.ts index e59f0d70..ea8f3c1c 100644 --- a/src/entity/dto/create-entity.dto.ts +++ b/src/entity/dto/create-entity.dto.ts @@ -1,5 +1,5 @@ export class CreateEntityDto { - shortName:string; - longName:string; - websites: string[]; -} \ No newline at end of file + shortName: string; + longName: string; + websites: string[]; +} diff --git a/src/entity/dto/delete-bulk-entity.dto.ts b/src/entity/dto/delete-bulk-entity.dto.ts index e73c8244..aa3c0f0d 100644 --- a/src/entity/dto/delete-bulk-entity.dto.ts +++ b/src/entity/dto/delete-bulk-entity.dto.ts @@ -1,4 +1,3 @@ - export class DeleteBulkEntityDto { - entitiesId:number[]; -} \ No newline at end of file + entitiesId: number[]; +} diff --git a/src/entity/dto/delete-entity.dto.ts b/src/entity/dto/delete-entity.dto.ts index c1355d56..d95614f6 100644 --- a/src/entity/dto/delete-entity.dto.ts +++ b/src/entity/dto/delete-entity.dto.ts @@ -1,4 +1,3 @@ - export class DeleteEntityDto { - entityId:number; -} \ No newline at end of file + entityId: number; +} diff --git a/src/entity/dto/reevalute-entity.dto.ts b/src/entity/dto/reevalute-entity.dto.ts index b1c18c81..8d9bfd62 100644 --- a/src/entity/dto/reevalute-entity.dto.ts +++ b/src/entity/dto/reevalute-entity.dto.ts @@ -1,4 +1,4 @@ export class ReevaluateEntityDto { - entitiesId:number[]; - option:string; -} \ No newline at end of file + entitiesId: number[]; + option: string; +} diff --git a/src/entity/dto/update-entity.dto.ts b/src/entity/dto/update-entity.dto.ts index f430ed24..99f6b1d0 100644 --- a/src/entity/dto/update-entity.dto.ts +++ b/src/entity/dto/update-entity.dto.ts @@ -1,8 +1,7 @@ - export class UpdateEntityDto { - entityId:number; - defaultWebsites: number[]; - shortName: string; - longName: string; - websites: number[]; -} \ No newline at end of file + entityId: number; + defaultWebsites: number[]; + shortName: string; + longName: string; + websites: number[]; +} diff --git a/src/entity/entity.controller.spec.ts b/src/entity/entity.controller.spec.ts index 55854b80..7066cac3 100644 --- a/src/entity/entity.controller.spec.ts +++ b/src/entity/entity.controller.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { EntityController } from './entity.controller'; - -describe('Entity Controller', () => { - let controller: EntityController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [EntityController], - }).compile(); - - controller = module.get(EntityController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { EntityController } from "./entity.controller"; + +describe("Entity Controller", () => { + let controller: EntityController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [EntityController], + }).compile(); + + controller = module.get(EntityController); + }); + + it("should be defined", () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/entity/entity.controller.ts b/src/entity/entity.controller.ts index 1828b397..36d8516c 100644 --- a/src/entity/entity.controller.ts +++ b/src/entity/entity.controller.ts @@ -1,282 +1,295 @@ -import { - Controller, - InternalServerErrorException, - Get, - Post, - Request, - Param, - UseGuards, - UseInterceptors, - Body, -} from "@nestjs/common"; -import { AuthGuard } from "@nestjs/passport"; -import { EntityService } from "./entity.service"; -import { EntityTable } from "./entity.entity"; -import { success } from "../lib/response"; -import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; -import { ReevaluateEntityDto } from "./dto/reevalute-entity.dto"; -import { CreateEntityDto } from "./dto/create-entity.dto"; -import { UpdateEntityDto } from "./dto/update-entity.dto"; -import { DeleteEntityDto } from "./dto/delete-entity.dto"; -import { DeleteBulkEntityDto } from "./dto/delete-bulk-entity.dto"; -import { Website } from "src/website/website.entity"; -import { Page } from "src/page/page.entity"; - - -@ApiBasicAuth() -@ApiTags('entity') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller("entity") -@UseInterceptors(LoggingInterceptor) -export class EntityController { - constructor(private readonly entityService: EntityService) {} - - @ApiOperation({ summary: 'Reevaluate all pages from an entity list' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("reEvaluate") - async reEvaluateWebsitePages(@Body() reevaluateEntityDto: ReevaluateEntityDto): Promise { - const entitiesId = reevaluateEntityDto.entitiesId; - const option = reevaluateEntityDto.option; - - return success( - await this.entityService.addPagesToEvaluate(entitiesId, option) - ); - } - - @ApiOperation({ summary: 'Find number of entities in Observatory' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("observatory/total") - async getNumberOfObservatoryEntities(): Promise { - return success(await this.entityService.findNumberOfObservatory()); - } - - @ApiOperation({ summary: 'Find entity by search term in AMS' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("all/count/:search") - async getAdminEntityCount(@Param("search") search: string): Promise { - return success( - await this.entityService.adminCount( - decodeURIComponent(search.substring(7)) - ) - ); - } - - @ApiOperation({ summary: 'Find entity by search term, size, page, sort and sort direction in AMS' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("all/:size/:page/:sort/:direction/:search") - async getAllEntities( - @Param("size") size: string, - @Param("page") page: string, - @Param("sort") sort: string, - @Param("direction") direction: string, - @Param("search") search: string - ): Promise { - return success( - await this.entityService.findAll( - parseInt(size), - parseInt(page), - sort.substring(5), - direction.substring(10), - decodeURIComponent(search.substring(7)) - ) - ); - } - - @ApiOperation({ summary: 'Find entity info by id' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: EntityTable, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("info/:entityId") - async getEntityInfo(@Param("entityId") entityId: number): Promise { - return success(await this.entityService.findInfo(entityId)); - } - - @ApiOperation({ summary: 'Create a new entity' }) - @ApiResponse({ - status: 200, - description: 'A new entity was created', - type: EntityTable, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("create") - async createEntity(@Body() createEntityDto: CreateEntityDto): Promise { - const entity = new EntityTable(); - entity.Short_Name = createEntityDto.shortName; - entity.Long_Name = createEntityDto.longName; - entity.Creation_Date = new Date(); - - const websites = createEntityDto.websites; - - const createSuccess = await this.entityService.createOne(entity, websites); - if (!createSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Update a specific entity' }) - @ApiResponse({ - status: 200, - description: 'The entity was updated', - type: EntityTable, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("update") - async updateEntity(@Body() updateEntityDto: UpdateEntityDto): Promise { - const entityId = updateEntityDto.entityId; - const shortName = updateEntityDto.shortName; - const longName = updateEntityDto.longName; - - const defaultWebsites = updateEntityDto.defaultWebsites; - const websites = updateEntityDto.websites; - - const updateSuccess = await this.entityService.update( - entityId, - shortName, - longName, - websites, - defaultWebsites - ); - if (!updateSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Delete a specific entity' }) - @ApiResponse({ - status: 200, - description: 'The entity was deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("delete") - async deleteEntity(@Body() deleteEntityDto: DeleteEntityDto): Promise { - const entityId = deleteEntityDto.entityId; - - const deleteSuccess = await this.entityService.delete(entityId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Delete a list of entities' }) - @ApiResponse({ - status: 200, - description: 'The entity list was deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("deleteBulk") - async deleteEntities(@Request() deleteBulkEntityDto: DeleteBulkEntityDto): Promise { - const entitiesId = deleteBulkEntityDto.entitiesId; - - const deleteSuccess = await this.entityService.deleteBulk(entitiesId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Delete all pages from a list of entities' }) - @ApiResponse({ - status: 200, - description: 'The page list was deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("pages/deleteBulk") - async deleteEntitiesPages(@Body() deleteBulkEntityDto: DeleteBulkEntityDto): Promise { - const entitiesId = deleteBulkEntityDto.entitiesId; - - const deleteSuccess = await this.entityService.pagesDeleteBulk(entitiesId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Check if entity exists by short-name' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("exists/shortName/:shortName") - async checkIfShortNameExists( - @Param("shortName") shortName: string - ): Promise { - return success(!!(await this.entityService.findByShortName(shortName))); - } - - @ApiOperation({ summary: 'Check if entity exists by long-name' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("exists/longName/:longName") - async checkIfLongNameExists( - @Param("longName") longName: string - ): Promise { - return success(!!(await this.entityService.findByLongName(longName))); - } - - @ApiOperation({ summary: 'Find all the websites in a specific entity' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Array, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("websites/:entity") - async getListOfEntityWebsites(@Param("entity") entity: string): Promise { - return success(await this.entityService.findAllWebsites(entity)); - } - - @ApiOperation({ summary: 'Find all the pages in a specific entity' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Array, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("websites/pages/:entity") - async getListOfEntityWebsitePages( - @Param("entity") entity: string - ): Promise { - return success(await this.entityService.findAllWebsitesPages(entity)); - } -} +import { + Controller, + InternalServerErrorException, + Get, + Post, + Request, + Param, + UseGuards, + UseInterceptors, + Body, +} from "@nestjs/common"; +import { AuthGuard } from "@nestjs/passport"; +import { EntityService } from "./entity.service"; +import { EntityTable } from "./entity.entity"; +import { success } from "../lib/response"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { + ApiBasicAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; +import { ReevaluateEntityDto } from "./dto/reevalute-entity.dto"; +import { CreateEntityDto } from "./dto/create-entity.dto"; +import { UpdateEntityDto } from "./dto/update-entity.dto"; +import { DeleteEntityDto } from "./dto/delete-entity.dto"; +import { DeleteBulkEntityDto } from "./dto/delete-bulk-entity.dto"; +import { Website } from "src/website/website.entity"; +import { Page } from "src/page/page.entity"; + +@ApiBasicAuth() +@ApiTags("entity") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("entity") +@UseInterceptors(LoggingInterceptor) +export class EntityController { + constructor(private readonly entityService: EntityService) {} + + @ApiOperation({ summary: "Reevaluate all pages from an entity list" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("reEvaluate") + async reEvaluateWebsitePages( + @Body() reevaluateEntityDto: ReevaluateEntityDto + ): Promise { + const entitiesId = reevaluateEntityDto.entitiesId; + const option = reevaluateEntityDto.option; + + return success( + await this.entityService.addPagesToEvaluate(entitiesId, option) + ); + } + + @ApiOperation({ summary: "Find number of entities in Observatory" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("observatory/total") + async getNumberOfObservatoryEntities(): Promise { + return success(await this.entityService.findNumberOfObservatory()); + } + + @ApiOperation({ summary: "Find entity by search term in AMS" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("all/count/:search") + async getAdminEntityCount(@Param("search") search: string): Promise { + return success( + await this.entityService.adminCount( + decodeURIComponent(search.substring(7)) + ) + ); + } + + @ApiOperation({ + summary: + "Find entity by search term, size, page, sort and sort direction in AMS", + }) + @ApiResponse({ + status: 200, + description: "Success", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("all/:size/:page/:sort/:direction/:search") + async getAllEntities( + @Param("size") size: string, + @Param("page") page: string, + @Param("sort") sort: string, + @Param("direction") direction: string, + @Param("search") search: string + ): Promise { + return success( + await this.entityService.findAll( + parseInt(size), + parseInt(page), + sort.substring(5), + direction.substring(10), + decodeURIComponent(search.substring(7)) + ) + ); + } + + @ApiOperation({ summary: "Find entity info by id" }) + @ApiResponse({ + status: 200, + description: "Success", + type: EntityTable, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("info/:entityId") + async getEntityInfo(@Param("entityId") entityId: number): Promise { + return success(await this.entityService.findInfo(entityId)); + } + + @ApiOperation({ summary: "Create a new entity" }) + @ApiResponse({ + status: 200, + description: "A new entity was created", + type: EntityTable, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("create") + async createEntity(@Body() createEntityDto: CreateEntityDto): Promise { + const entity = new EntityTable(); + entity.Short_Name = createEntityDto.shortName; + entity.Long_Name = createEntityDto.longName; + entity.Creation_Date = new Date(); + + const websites = createEntityDto.websites; + + const createSuccess = await this.entityService.createOne(entity, websites); + if (!createSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Update a specific entity" }) + @ApiResponse({ + status: 200, + description: "The entity was updated", + type: EntityTable, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("update") + async updateEntity(@Body() updateEntityDto: UpdateEntityDto): Promise { + const entityId = updateEntityDto.entityId; + const shortName = updateEntityDto.shortName; + const longName = updateEntityDto.longName; + + const defaultWebsites = updateEntityDto.defaultWebsites; + const websites = updateEntityDto.websites; + + const updateSuccess = await this.entityService.update( + entityId, + shortName, + longName, + websites, + defaultWebsites + ); + if (!updateSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Delete a specific entity" }) + @ApiResponse({ + status: 200, + description: "The entity was deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("delete") + async deleteEntity(@Body() deleteEntityDto: DeleteEntityDto): Promise { + const entityId = deleteEntityDto.entityId; + + const deleteSuccess = await this.entityService.delete(entityId); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Delete a list of entities" }) + @ApiResponse({ + status: 200, + description: "The entity list was deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("deleteBulk") + async deleteEntities( + @Request() deleteBulkEntityDto: DeleteBulkEntityDto + ): Promise { + const entitiesId = deleteBulkEntityDto.entitiesId; + + const deleteSuccess = await this.entityService.deleteBulk(entitiesId); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Delete all pages from a list of entities" }) + @ApiResponse({ + status: 200, + description: "The page list was deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("pages/deleteBulk") + async deleteEntitiesPages( + @Body() deleteBulkEntityDto: DeleteBulkEntityDto + ): Promise { + const entitiesId = deleteBulkEntityDto.entitiesId; + + const deleteSuccess = await this.entityService.pagesDeleteBulk(entitiesId); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Check if entity exists by short-name" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("exists/shortName/:shortName") + async checkIfShortNameExists( + @Param("shortName") shortName: string + ): Promise { + return success(!!(await this.entityService.findByShortName(shortName))); + } + + @ApiOperation({ summary: "Check if entity exists by long-name" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("exists/longName/:longName") + async checkIfLongNameExists( + @Param("longName") longName: string + ): Promise { + return success(!!(await this.entityService.findByLongName(longName))); + } + + @ApiOperation({ summary: "Find all the websites in a specific entity" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Array, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("websites/:entity") + async getListOfEntityWebsites(@Param("entity") entity: string): Promise { + return success(await this.entityService.findAllWebsites(entity)); + } + + @ApiOperation({ summary: "Find all the pages in a specific entity" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Array, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("websites/pages/:entity") + async getListOfEntityWebsitePages( + @Param("entity") entity: string + ): Promise { + return success(await this.entityService.findAllWebsitesPages(entity)); + } +} diff --git a/src/entity/entity.entity.ts b/src/entity/entity.entity.ts index 11c66d2f..56c32f8e 100644 --- a/src/entity/entity.entity.ts +++ b/src/entity/entity.entity.ts @@ -1,42 +1,42 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - ManyToMany, - JoinTable, -} from "typeorm"; -import { Website } from "../website/website.entity"; - -@Entity("Entity") -export class EntityTable { - @PrimaryGeneratedColumn({ - type: "int", - }) - EntityId: number; - - @Column({ - type: "varchar", - length: 255, - nullable: false, - unique: true, - }) - Short_Name: string; - - @Column({ - type: "varchar", - length: 255, - nullable: false, - unique: true, - }) - Long_Name: string; - - @Column({ - type: "datetime", - nullable: false, - }) - Creation_Date: any; - - @ManyToMany((type) => Website) - @JoinTable() - Websites: Website[]; -} +import { + Entity, + Column, + PrimaryGeneratedColumn, + ManyToMany, + JoinTable, +} from "typeorm"; +import { Website } from "../website/website.entity"; + +@Entity("Entity") +export class EntityTable { + @PrimaryGeneratedColumn({ + type: "int", + }) + EntityId: number; + + @Column({ + type: "varchar", + length: 255, + nullable: false, + unique: true, + }) + Short_Name: string; + + @Column({ + type: "varchar", + length: 255, + nullable: false, + unique: true, + }) + Long_Name: string; + + @Column({ + type: "datetime", + nullable: false, + }) + Creation_Date: any; + + @ManyToMany((type) => Website) + @JoinTable() + Websites: Website[]; +} diff --git a/src/entity/entity.module.ts b/src/entity/entity.module.ts index c7a63566..f51a2954 100644 --- a/src/entity/entity.module.ts +++ b/src/entity/entity.module.ts @@ -1,13 +1,13 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { EntityService } from './entity.service'; -import { EntityTable } from './entity.entity'; -import { EntityController } from './entity.controller'; - -@Module({ - imports: [TypeOrmModule.forFeature([EntityTable])], - exports: [EntityService], - providers: [EntityService], - controllers: [EntityController] -}) -export class EntityModule {} +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { EntityService } from "./entity.service"; +import { EntityTable } from "./entity.entity"; +import { EntityController } from "./entity.controller"; + +@Module({ + imports: [TypeOrmModule.forFeature([EntityTable])], + exports: [EntityService], + providers: [EntityService], + controllers: [EntityController], +}) +export class EntityModule {} diff --git a/src/entity/entity.service.spec.ts b/src/entity/entity.service.spec.ts index c708704e..f93888ec 100644 --- a/src/entity/entity.service.spec.ts +++ b/src/entity/entity.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { EntityService } from './entity.service'; - -describe('EntityService', () => { - let service: EntityService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [EntityService], - }).compile(); - - service = module.get(EntityService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { EntityService } from "./entity.service"; + +describe("EntityService", () => { + let service: EntityService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [EntityService], + }).compile(); + + service = module.get(EntityService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/entity/entity.service.ts b/src/entity/entity.service.ts index c38d355e..ae685197 100644 --- a/src/entity/entity.service.ts +++ b/src/entity/entity.service.ts @@ -1,455 +1,455 @@ -import { Injectable, InternalServerErrorException } from "@nestjs/common"; -import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; -import { Repository, In, DataSource } from "typeorm"; -import { EntityTable } from "./entity.entity"; - -@Injectable() -export class EntityService { - constructor( - @InjectRepository(EntityTable) - private readonly entityRepository: Repository, - @InjectDataSource() - private readonly connection: DataSource, ) {} - - async addPagesToEvaluate( - entitiesId: number[], - option: string - ): Promise { - const pages = await this.entityRepository.query( - ` - SELECT - p.PageId, - p.Uri - FROM - Website as w, - WebsitePage as wp, - Page as p - WHERE - w.EntityId IN (?) AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE ? - `, - [entitiesId, option === "all" ? "1__" : "1_1"] - ); - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - let error = false; - try { - for (const page of pages || []) { - try { - const pageEval = await queryRunner.manager.query( - `SELECT * FROM Evaluation_List WHERE PageId = ? AND UserId = -1 AND Url = ? AND Show_To = ? LIMIT 1`, - [page.PageId, page.Uri, "10"] - ); - if (pageEval.length > 0) { - await queryRunner.manager.query( - `UPDATE Evaluation_List SET Error = NULL, Is_Evaluating = 0 WHERE EvaluationListId = ?`, - [pageEval[0].EvaluationListId] - ); - } else { - await queryRunner.manager.query( - `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, - [page.PageId, -1, page.Uri, "10", new Date()] - ); - } - } catch (_) {} - } - - await queryRunner.manager.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "AMS/Observatory"`, - [pages.length] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.log(err); - error = true; - } finally { - await queryRunner.release(); - } - - return !error; - } - - async adminCount(search: string): Promise { - const name = search.trim() !== "" ? `%${search.trim()}%` : "%"; - const count = await this.entityRepository.query( - ` - SELECT - COUNT(*) as Count - FROM - Entity - WHERE - Short_Name LIKE ? OR - Long_Name LIKE ? - `, - [name, name] - ); - - return count[0].Count; - } - - async findNumberOfObservatory(): Promise { - const data = ( - await this.entityRepository.query( - "SELECT * FROM Observatory ORDER BY Creation_Date DESC LIMIT 1" - ) - )[0].Global_Statistics; - - const parsedData = JSON.parse(data); - return parsedData.nEntities; - } - - async findAll( - size: number, - page: number, - sort: string, - direction: string, - search: string - ): Promise { - const name = search.trim() !== "" ? `%${search.trim()}%` : "%"; - if (!direction.trim()) { - if (size !== -1) { - const entities = await this.entityRepository.query( - `SELECT e.*, COUNT(distinct ew.WebsiteId) as Websites - FROM - Entity as e - LEFT OUTER JOIN EntityWebsite as ew ON ew.EntityId = e.EntityId - WHERE - e.Short_Name LIKE ? OR - e.Long_Name LIKE ? - GROUP BY e.EntityId - LIMIT ? OFFSET ?`, - [name, name, size, page * size] - ); - return entities; - } else { - const entities = await this.entityRepository.query( - `SELECT e.*, COUNT(distinct ew.WebsiteId) as Websites - FROM - Entity as e - LEFT OUTER JOIN EntityWebsite as ew ON ew.EntityId = e.EntityId - WHERE - e.Short_Name LIKE ? OR - e.Long_Name LIKE ? - GROUP BY e.EntityId`, - [name, name] - ); - return entities; - } - } else { - let order = ""; - switch (sort) { - case "Short_Name": - order = "e.Short_Name"; - break; - case "Long_Name": - order = "e.Long_Name"; - break; - case "Creation_Date": - order = "e.Creation_Date"; - break; - case "Websites": - order = `Websites`; - break; - } - - const entities = await this.entityRepository.query( - `SELECT e.*, COUNT(distinct ew.WebsiteId) as Websites - FROM - Entity as e - LEFT OUTER JOIN EntityWebsite as ew ON ew.EntityId = e.EntityId - WHERE - e.Short_Name LIKE ? OR - e.Long_Name LIKE ? - GROUP BY e.EntityId - ORDER BY ${order} ${direction.toUpperCase()} - LIMIT ? OFFSET ?`, - [name, name, size, page * size] - ); - return entities; - } - } - - async findInfo(entityId: number): Promise { - const entity = await this.entityRepository.findOne({ - where: { EntityId: entityId }, - }); - - if (entity) { - entity["websites"] = await this.entityRepository.query( - `SELECT w.* - FROM - EntityWebsite as ew, - Website as w - WHERE - ew.EntityId = ? AND - w.WebsiteId = ew.WebsiteId`, - [entityId] - ); - return entity; - } else { - throw new InternalServerErrorException(); - } - } - - async findByShortName(shortName: string): Promise { - return this.entityRepository.findOne({ where: { Short_Name: shortName } }); - } - - async findByLongName(longName: string): Promise { - return this.entityRepository.findOne({ where: { Long_Name: longName } }); - } - - async findAllWebsites(entity: string): Promise { - - const websites = await this.entityRepository.query( - `SELECT w.*, u.Username as User, COUNT(distinct p.PageId) as Pages, COUNT(distinct ev.PageId) as Evaluated_Pages - FROM - Entity as e - LEFT OUTER JOIN EntityWebsite as ew ON ew.EntityId = e.EntityId - LEFT OUTER JOIN Website as w ON w.WebsiteId = ew.WebsiteId - LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId - LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE "1__" - LEFT OUTER JOIN Evaluation as ev ON ev.PageId = p.PageId - LEFT OUTER JOIN User as u ON u.UserId = w.UserId - WHERE - e.Long_Name = ? - GROUP BY w.WebsiteId`, - [entity] - ); - - return websites; - } - - async findAllWebsitesPages(entity: string): Promise { - const websites = await this.entityRepository.query( - ` - SELECT - w.WebsiteId, - p.*, - e.A, - e.AA, - e.AAA, - e.Score, - e.Errors, - e.Tot, - e.Evaluation_Date - FROM - Entity as en, - EntityWebsite as ew, - Website as w, - WebsitePage as wp, - Page as p - LEFT OUTER JOIN Evaluation e ON e.PageId = p.PageId AND e.Show_To LIKE "1_" AND e.Evaluation_Date = ( - SELECT Evaluation_Date FROM Evaluation - WHERE PageId = p.PageId AND Show_To LIKE "1_" - ORDER BY Evaluation_Date DESC LIMIT 1 - ) - WHERE - en.Long_Name = ? AND - ew.EntityId = en.EntityId AND - w.WebsiteId = ew.WebsiteId AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE "1__" - GROUP BY w.WebsiteId, p.PageId, e.A, e.AA, e.AAA, e.Score, e.Errors, e.Tot, e.Evaluation_Date`, - [entity] - ); - - return websites; //.filter((w) => w.Score !== null); - } - - async createOne(entity: EntityTable, websites: string[]): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const insertEntity = await queryRunner.manager.save(entity); - - for (const websiteId of websites || []) { - await queryRunner.manager.query( - `INSERT INTO EntityWebsite (EntityId, WebsiteId) VALUES (?, ?)`, - [insertEntity.EntityId, websiteId] - ); - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async update( - entityId: number, - shortName: string, - longName: string, - websites: number[], - defaultWebsites: number[] - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.update( - EntityTable, - { EntityId: entityId }, - { Short_Name: shortName, Long_Name: longName } - ); - - for (const id of defaultWebsites || []) { - if (!websites.includes(id)) { - await queryRunner.manager.query( - `DELETE FROM EntityWebsite WHERE EntityId = ? AND WebsiteId = ?`, - [entityId, id] - ); - } - } - - for (const id of websites || []) { - if (!defaultWebsites.includes(id)) { - await queryRunner.manager.query( - `INSERT INTO EntityWebsite (EntityId, WebsiteId) VALUES (?, ?)`, - [entityId, id] - ); - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async delete(entityId: number): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - /*await queryRunner.manager.update( - Website, - { EntityId: entityId }, - { EntityId: null } - );*/ - - await queryRunner.manager.delete(EntityTable, { EntityId: entityId }); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async deleteBulk(entitiesId: Array): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.delete(EntityTable, { - EntityId: In(entitiesId), - }); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async pagesDeleteBulk(entitiesId: Array): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const websites = await queryRunner.manager.query( - ` - SELECT * FROM EntityWebsite WHERE EntityId IN (?) - `, - [entitiesId] - ); - - const pages = await queryRunner.manager.query( - ` - SELECT - PageId - FROM - WebsitePage - WHERE - WebsiteId IN (?) - `, - [websites.map((w) => w.WebsiteId)] - ); - - await queryRunner.manager.query( - ` - DELETE FROM - Page - WHERE - PageId IN (?) - `, - [pages.map((p) => p.PageId)] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } -} +import { Injectable, InternalServerErrorException } from "@nestjs/common"; +import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; +import { Repository, In, DataSource } from "typeorm"; +import { EntityTable } from "./entity.entity"; + +@Injectable() +export class EntityService { + constructor( + @InjectRepository(EntityTable) + private readonly entityRepository: Repository, + @InjectDataSource() + private readonly connection: DataSource + ) {} + + async addPagesToEvaluate( + entitiesId: number[], + option: string + ): Promise { + const pages = await this.entityRepository.query( + ` + SELECT + p.PageId, + p.Uri + FROM + Website as w, + WebsitePage as wp, + Page as p + WHERE + w.EntityId IN (?) AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE ? + `, + [entitiesId, option === "all" ? "1__" : "1_1"] + ); + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + let error = false; + try { + for (const page of pages || []) { + try { + const pageEval = await queryRunner.manager.query( + `SELECT * FROM Evaluation_List WHERE PageId = ? AND UserId = -1 AND Url = ? AND Show_To = ? LIMIT 1`, + [page.PageId, page.Uri, "10"] + ); + if (pageEval.length > 0) { + await queryRunner.manager.query( + `UPDATE Evaluation_List SET Error = NULL, Is_Evaluating = 0 WHERE EvaluationListId = ?`, + [pageEval[0].EvaluationListId] + ); + } else { + await queryRunner.manager.query( + `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, + [page.PageId, -1, page.Uri, "10", new Date()] + ); + } + } catch (_) {} + } + + await queryRunner.manager.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "AMS/Observatory"`, + [pages.length] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.log(err); + error = true; + } finally { + await queryRunner.release(); + } + + return !error; + } + + async adminCount(search: string): Promise { + const name = search.trim() !== "" ? `%${search.trim()}%` : "%"; + const count = await this.entityRepository.query( + ` + SELECT + COUNT(*) as Count + FROM + Entity + WHERE + Short_Name LIKE ? OR + Long_Name LIKE ? + `, + [name, name] + ); + + return count[0].Count; + } + + async findNumberOfObservatory(): Promise { + const data = ( + await this.entityRepository.query( + "SELECT * FROM Observatory ORDER BY Creation_Date DESC LIMIT 1" + ) + )[0].Global_Statistics; + + const parsedData = JSON.parse(data); + return parsedData.nEntities; + } + + async findAll( + size: number, + page: number, + sort: string, + direction: string, + search: string + ): Promise { + const name = search.trim() !== "" ? `%${search.trim()}%` : "%"; + if (!direction.trim()) { + if (size !== -1) { + const entities = await this.entityRepository.query( + `SELECT e.*, COUNT(distinct ew.WebsiteId) as Websites + FROM + Entity as e + LEFT OUTER JOIN EntityWebsite as ew ON ew.EntityId = e.EntityId + WHERE + e.Short_Name LIKE ? OR + e.Long_Name LIKE ? + GROUP BY e.EntityId + LIMIT ? OFFSET ?`, + [name, name, size, page * size] + ); + return entities; + } else { + const entities = await this.entityRepository.query( + `SELECT e.*, COUNT(distinct ew.WebsiteId) as Websites + FROM + Entity as e + LEFT OUTER JOIN EntityWebsite as ew ON ew.EntityId = e.EntityId + WHERE + e.Short_Name LIKE ? OR + e.Long_Name LIKE ? + GROUP BY e.EntityId`, + [name, name] + ); + return entities; + } + } else { + let order = ""; + switch (sort) { + case "Short_Name": + order = "e.Short_Name"; + break; + case "Long_Name": + order = "e.Long_Name"; + break; + case "Creation_Date": + order = "e.Creation_Date"; + break; + case "Websites": + order = `Websites`; + break; + } + + const entities = await this.entityRepository.query( + `SELECT e.*, COUNT(distinct ew.WebsiteId) as Websites + FROM + Entity as e + LEFT OUTER JOIN EntityWebsite as ew ON ew.EntityId = e.EntityId + WHERE + e.Short_Name LIKE ? OR + e.Long_Name LIKE ? + GROUP BY e.EntityId + ORDER BY ${order} ${direction.toUpperCase()} + LIMIT ? OFFSET ?`, + [name, name, size, page * size] + ); + return entities; + } + } + + async findInfo(entityId: number): Promise { + const entity = await this.entityRepository.findOne({ + where: { EntityId: entityId }, + }); + + if (entity) { + entity["websites"] = await this.entityRepository.query( + `SELECT w.* + FROM + EntityWebsite as ew, + Website as w + WHERE + ew.EntityId = ? AND + w.WebsiteId = ew.WebsiteId`, + [entityId] + ); + return entity; + } else { + throw new InternalServerErrorException(); + } + } + + async findByShortName(shortName: string): Promise { + return this.entityRepository.findOne({ where: { Short_Name: shortName } }); + } + + async findByLongName(longName: string): Promise { + return this.entityRepository.findOne({ where: { Long_Name: longName } }); + } + + async findAllWebsites(entity: string): Promise { + const websites = await this.entityRepository.query( + `SELECT w.*, u.Username as User, COUNT(distinct p.PageId) as Pages, COUNT(distinct ev.PageId) as Evaluated_Pages + FROM + Entity as e + LEFT OUTER JOIN EntityWebsite as ew ON ew.EntityId = e.EntityId + LEFT OUTER JOIN Website as w ON w.WebsiteId = ew.WebsiteId + LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId + LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE "1__" + LEFT OUTER JOIN Evaluation as ev ON ev.PageId = p.PageId + LEFT OUTER JOIN User as u ON u.UserId = w.UserId + WHERE + e.Long_Name = ? + GROUP BY w.WebsiteId`, + [entity] + ); + + return websites; + } + + async findAllWebsitesPages(entity: string): Promise { + const websites = await this.entityRepository.query( + ` + SELECT + w.WebsiteId, + p.*, + e.A, + e.AA, + e.AAA, + e.Score, + e.Errors, + e.Tot, + e.Evaluation_Date + FROM + Entity as en, + EntityWebsite as ew, + Website as w, + WebsitePage as wp, + Page as p + LEFT OUTER JOIN Evaluation e ON e.PageId = p.PageId AND e.Show_To LIKE "1_" AND e.Evaluation_Date = ( + SELECT Evaluation_Date FROM Evaluation + WHERE PageId = p.PageId AND Show_To LIKE "1_" + ORDER BY Evaluation_Date DESC LIMIT 1 + ) + WHERE + en.Long_Name = ? AND + ew.EntityId = en.EntityId AND + w.WebsiteId = ew.WebsiteId AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE "1__" + GROUP BY w.WebsiteId, p.PageId, e.A, e.AA, e.AAA, e.Score, e.Errors, e.Tot, e.Evaluation_Date`, + [entity] + ); + + return websites; //.filter((w) => w.Score !== null); + } + + async createOne(entity: EntityTable, websites: string[]): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const insertEntity = await queryRunner.manager.save(entity); + + for (const websiteId of websites || []) { + await queryRunner.manager.query( + `INSERT INTO EntityWebsite (EntityId, WebsiteId) VALUES (?, ?)`, + [insertEntity.EntityId, websiteId] + ); + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async update( + entityId: number, + shortName: string, + longName: string, + websites: number[], + defaultWebsites: number[] + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.update( + EntityTable, + { EntityId: entityId }, + { Short_Name: shortName, Long_Name: longName } + ); + + for (const id of defaultWebsites || []) { + if (!websites.includes(id)) { + await queryRunner.manager.query( + `DELETE FROM EntityWebsite WHERE EntityId = ? AND WebsiteId = ?`, + [entityId, id] + ); + } + } + + for (const id of websites || []) { + if (!defaultWebsites.includes(id)) { + await queryRunner.manager.query( + `INSERT INTO EntityWebsite (EntityId, WebsiteId) VALUES (?, ?)`, + [entityId, id] + ); + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async delete(entityId: number): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + /*await queryRunner.manager.update( + Website, + { EntityId: entityId }, + { EntityId: null } + );*/ + + await queryRunner.manager.delete(EntityTable, { EntityId: entityId }); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async deleteBulk(entitiesId: Array): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.delete(EntityTable, { + EntityId: In(entitiesId), + }); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async pagesDeleteBulk(entitiesId: Array): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const websites = await queryRunner.manager.query( + ` + SELECT * FROM EntityWebsite WHERE EntityId IN (?) + `, + [entitiesId] + ); + + const pages = await queryRunner.manager.query( + ` + SELECT + PageId + FROM + WebsitePage + WHERE + WebsiteId IN (?) + `, + [websites.map((w) => w.WebsiteId)] + ); + + await queryRunner.manager.query( + ` + DELETE FROM + Page + WHERE + PageId IN (?) + `, + [pages.map((p) => p.PageId)] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } +} diff --git a/src/evaluation/evaluation.controller.spec.ts b/src/evaluation/evaluation.controller.spec.ts index 43b3a749..36205a2e 100644 --- a/src/evaluation/evaluation.controller.spec.ts +++ b/src/evaluation/evaluation.controller.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { EvaluationController } from './evaluation.controller'; +import { Test, TestingModule } from "@nestjs/testing"; +import { EvaluationController } from "./evaluation.controller"; -describe('Evaluation Controller', () => { +describe("Evaluation Controller", () => { let controller: EvaluationController; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('Evaluation Controller', () => { controller = module.get(EvaluationController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/evaluation/evaluation.controller.ts b/src/evaluation/evaluation.controller.ts index e5b4cf31..b2de7b8c 100644 --- a/src/evaluation/evaluation.controller.ts +++ b/src/evaluation/evaluation.controller.ts @@ -6,27 +6,36 @@ import { UseGuards, Param, UseInterceptors, + Res, } from "@nestjs/common"; import { AuthGuard } from "@nestjs/passport"; import { EvaluationService } from "./evaluation.service"; import { success } from "../lib/response"; import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; +import { + ApiBasicAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; import { Evaluation } from "./evaluation.entity"; - +import { Readable } from "stream"; +import { Response } from "express"; @ApiBasicAuth() -@ApiTags('evaluation') -@ApiResponse({ status: 403, description: 'Forbidden' }) +@ApiTags("evaluation") +@ApiResponse({ status: 403, description: "Forbidden" }) @Controller("evaluation") @UseInterceptors(LoggingInterceptor) export class EvaluationController { constructor(private readonly evaluationService: EvaluationService) {} - @ApiOperation({ summary: 'Find number of requests done to Observatory from the start date' }) + @ApiOperation({ + summary: "Find number of requests done to Observatory from the start date", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Number, }) @UseGuards(AuthGuard("jwt-admin")) @@ -37,10 +46,12 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Find number of requests done to My Monitor from the start date' }) + @ApiOperation({ + summary: "Find number of requests done to My Monitor from the start date", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Number, }) @UseGuards(AuthGuard("jwt-admin")) @@ -49,10 +60,13 @@ export class EvaluationController { return success(await this.evaluationService.getMyMonitorRequestCounter()); } - @ApiOperation({ summary: 'Find number of requests done to Study Monitor from the start date' }) + @ApiOperation({ + summary: + "Find number of requests done to Study Monitor from the start date", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Number, }) @UseGuards(AuthGuard("jwt-admin")) @@ -63,10 +77,13 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Find number of requests done to Acess Monitor from the start date' }) + @ApiOperation({ + summary: + "Find number of requests done to Acess Monitor from the start date", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Number, }) @UseGuards(AuthGuard("jwt-admin")) @@ -77,10 +94,10 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Reset AMS evaluation queue' }) + @ApiOperation({ summary: "Reset AMS evaluation queue" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -89,10 +106,12 @@ export class EvaluationController { return success(await this.evaluationService.resetAdminWaitingList()); } - @ApiOperation({ summary: 'Delete AMS evaluation queue (including error list)' }) + @ApiOperation({ + summary: "Delete AMS evaluation queue (including error list)", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -101,10 +120,10 @@ export class EvaluationController { return success(await this.evaluationService.deleteAdminWaitingList()); } - @ApiOperation({ summary: 'Reset My Monitor evaluation queue' }) + @ApiOperation({ summary: "Reset My Monitor evaluation queue" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -113,10 +132,12 @@ export class EvaluationController { return success(await this.evaluationService.resetMMWaitingList()); } - @ApiOperation({ summary: 'Delete My Monitor evaluation queue (including error list)' }) + @ApiOperation({ + summary: "Delete My Monitor evaluation queue (including error list)", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -124,10 +145,10 @@ export class EvaluationController { async deleteMMEvaluationList(): Promise { return success(await this.evaluationService.deleteMMWaitingList()); } - @ApiOperation({ summary: 'Reset Study Monitor evaluation queue' }) + @ApiOperation({ summary: "Reset Study Monitor evaluation queue" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -136,10 +157,12 @@ export class EvaluationController { return success(await this.evaluationService.resetSMWaitingList()); } - @ApiOperation({ summary: 'Delete Study Monitor evaluation queue (including error list)' }) + @ApiOperation({ + summary: "Delete Study Monitor evaluation queue (including error list)", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -148,10 +171,12 @@ export class EvaluationController { return success(await this.evaluationService.deleteSMWaitingList()); } - @ApiOperation({ summary: 'Find evaluations from a specific user and website in My Monitor' }) + @ApiOperation({ + summary: "Find evaluations from a specific user and website in My Monitor", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-monitor")) @@ -169,10 +194,13 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Find evaluations from a specific user, website and page in My Monitor' }) + @ApiOperation({ + summary: + "Find evaluations from a specific user, website and page in My Monitor", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-monitor")) @@ -193,10 +221,13 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Find evaluations from a specific user, website and tag in Study Monitor' }) + @ApiOperation({ + summary: + "Find evaluations from a specific user, website and tag in Study Monitor", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-study")) @@ -216,10 +247,13 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Find evaluations from a specific user, website, tag and url in Study Monitor' }) + @ApiOperation({ + summary: + "Find evaluations from a specific user, website, tag and url in Study Monitor", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-study")) @@ -242,10 +276,10 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Find evaluations of a specific page in AMS' }) + @ApiOperation({ summary: "Find evaluations of a specific page in AMS" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @UseGuards(AuthGuard("jwt-admin")) @@ -261,10 +295,10 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Find evaluation by id in AMS' }) + @ApiOperation({ summary: "Find evaluation by id in AMS" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Evaluation, }) @UseGuards(AuthGuard("jwt-admin")) @@ -279,10 +313,10 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Find evaluation by type and url in AMS' }) + @ApiOperation({ summary: "Find evaluation by type and url in AMS" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Evaluation, }) @UseGuards(AuthGuard("jwt-admin")) @@ -297,10 +331,12 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Repeat evaluations from specific evaluation list ' }) + @ApiOperation({ + summary: "Repeat evaluations from specific evaluation list ", + }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Evaluation, }) @UseGuards(AuthGuard("jwt-admin")) @@ -311,10 +347,10 @@ export class EvaluationController { ); } - @ApiOperation({ summary: 'Repeat evaluations from specific evaluation list ' }) + @ApiOperation({ summary: "Return existing evaluations for a website " }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Evaluation, }) @UseGuards(AuthGuard("jwt-admin")) @@ -322,13 +358,22 @@ export class EvaluationController { async getWebsitePageEvaluations( @Request() req: any, @Param("website") website: string, - @Param("sample") sample: string + @Param("sample") sample: string, + @Res() res: Response ): Promise { - return success( - await this.evaluationService.findWebsiteEvaluations( - decodeURIComponent(website), - sample === "true" - ) + const results = await this.evaluationService.findWebsiteEvaluations( + decodeURIComponent(website), + sample === "true" ); + const stream = new Readable({ + read() { + results.forEach((result) => { + this.push(JSON.stringify(result) + "\n"); + }); + this.push(null); + }, + }); + res.setHeader("Content-Type", "application/json"); + stream.pipe(res); } } diff --git a/src/evaluation/evaluation.entity.ts b/src/evaluation/evaluation.entity.ts index d30b71f8..cce6ba77 100644 --- a/src/evaluation/evaluation.entity.ts +++ b/src/evaluation/evaluation.entity.ts @@ -1,105 +1,102 @@ -import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; - -@Entity('Evaluation') -export class Evaluation { - - @PrimaryGeneratedColumn({ - type: 'int' - }) - EvaluationId: number; - - @Column({ - type: 'int', - nullable: false - }) - PageId: number; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Title: string; - - @Column({ - type: 'decimal', - precision: 4, - scale: 1, - nullable: false - }) - Score: string; - - @Column({ - type: 'mediumtext', - nullable: false - }) - Pagecode: string; - - @Column({ - type: 'text', - nullable: false - }) - Tot: string; - - @Column({ - type: 'mediumtext', - nullable: false - }) - Nodes: string; - - @Column({ - type: 'text', - nullable: false - }) - Errors: string; - - @Column({ - type: 'int', - nullable: false - }) - A: number; - - @Column({ - type: 'int', - nullable: false - }) - AA: number; - - @Column({ - type: 'int', - nullable: false - }) - AAA: number; - - @Column({ - type: 'datetime', - nullable: false - }) - Evaluation_Date: any; - - @Column({ - type: 'varchar', - length: 2, - nullable: false - }) - Show_To: string; - - @Column({ - type: 'int', - nullable: true - }) - StudyUserId: number; - - @Column({ - type: 'text', - nullable: false - - }) - Element_Count:string ; - @Column({ - type: 'text', - nullable: false - - }) - Tag_Count:string ; -} \ No newline at end of file +import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"; + +@Entity("Evaluation") +export class Evaluation { + @PrimaryGeneratedColumn({ + type: "int", + }) + EvaluationId: number; + + @Column({ + type: "int", + nullable: false, + }) + PageId: number; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Title: string; + + @Column({ + type: "decimal", + precision: 4, + scale: 1, + nullable: false, + }) + Score: string; + + @Column({ + type: "mediumtext", + nullable: false, + }) + Pagecode: string; + + @Column({ + type: "text", + nullable: false, + }) + Tot: string; + + @Column({ + type: "mediumtext", + nullable: false, + }) + Nodes: string; + + @Column({ + type: "text", + nullable: false, + }) + Errors: string; + + @Column({ + type: "int", + nullable: false, + }) + A: number; + + @Column({ + type: "int", + nullable: false, + }) + AA: number; + + @Column({ + type: "int", + nullable: false, + }) + AAA: number; + + @Column({ + type: "datetime", + nullable: false, + }) + Evaluation_Date: any; + + @Column({ + type: "varchar", + length: 2, + nullable: false, + }) + Show_To: string; + + @Column({ + type: "int", + nullable: true, + }) + StudyUserId: number; + + @Column({ + type: "text", + nullable: false, + }) + Element_Count: string; + @Column({ + type: "text", + nullable: false, + }) + Tag_Count: string; +} diff --git a/src/evaluation/evaluation.module.ts b/src/evaluation/evaluation.module.ts index 1e3639c6..430cb790 100644 --- a/src/evaluation/evaluation.module.ts +++ b/src/evaluation/evaluation.module.ts @@ -1,16 +1,19 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { EvaluationService } from './evaluation.service'; -import { Evaluation } from './evaluation.entity'; -import { EvaluationController } from './evaluation.controller'; - -import { Page } from '../page/page.entity'; -import { AccessibilityStatementModule } from 'src/accessibility-statement-module/accessibility-statement/accessibility-statement.module'; - -@Module({ - imports: [TypeOrmModule.forFeature([Page, Evaluation]), AccessibilityStatementModule], - exports: [EvaluationService], - providers: [EvaluationService], - controllers: [EvaluationController] -}) -export class EvaluationModule {} +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { EvaluationService } from "./evaluation.service"; +import { Evaluation } from "./evaluation.entity"; +import { EvaluationController } from "./evaluation.controller"; + +import { Page } from "../page/page.entity"; +import { AccessibilityStatementModule } from "src/accessibility-statement-module/accessibility-statement/accessibility-statement.module"; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Page, Evaluation]), + AccessibilityStatementModule, + ], + exports: [EvaluationService], + providers: [EvaluationService], + controllers: [EvaluationController], +}) +export class EvaluationModule {} diff --git a/src/evaluation/evaluation.service.spec.ts b/src/evaluation/evaluation.service.spec.ts index da5510c4..580ed2eb 100644 --- a/src/evaluation/evaluation.service.spec.ts +++ b/src/evaluation/evaluation.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { EvaluationService } from './evaluation.service'; - -describe('EvaluationService', () => { - let service: EvaluationService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [EvaluationService], - }).compile(); - - service = module.get(EvaluationService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { EvaluationService } from "./evaluation.service"; + +describe("EvaluationService", () => { + let service: EvaluationService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [EvaluationService], + }).compile(); + + service = module.get(EvaluationService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/evaluation/evaluation.service.ts b/src/evaluation/evaluation.service.ts index 4b308e61..cc5678a7 100644 --- a/src/evaluation/evaluation.service.ts +++ b/src/evaluation/evaluation.service.ts @@ -1,935 +1,915 @@ -import { Injectable, InternalServerErrorException } from "@nestjs/common"; -import { DataSource, Repository } from "typeorm"; -import { Cron, CronExpression } from "@nestjs/schedule"; -import clone from "lodash.clone"; -import fs from "fs"; -import { Evaluation } from "./evaluation.entity"; -import { - executeUrlEvaluation, - executeUrlsEvaluation, - executeHtmlEvaluation, -} from "./middleware"; -import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; - -@Injectable() -export class EvaluationService { - private isEvaluatingAdminInstance: boolean; - private isEvaluatingUserInstance: boolean; - private SKIP = 20; - - constructor( - @InjectDataSource() - private readonly connection: DataSource, - @InjectRepository(Evaluation) - private readonly evaluationRepository: Repository, - ) { - this.isEvaluatingAdminInstance = false; - this.isEvaluatingUserInstance = false; - } - //FIXME confirmar se as paginas têm sempre avaliação - async getLastEvaluationByPage(pageId: number): Promise { - const evaluationList = await this.evaluationRepository.find({ where: { PageId: pageId},take:1,order: { Evaluation_Date:"DESC"}}); - return evaluationList[0]; - } - - @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) - cleanUpErrorFiles(): void { - fs.readdir("./", (err, files: string[]) => { - if (!err) { - for (const file of files ?? []) { - if (file.startsWith("qualweb-errors")) { - fs.unlink(file, (err2) => { - if (err2) { - console.error(err2); - } - }); - } - } - } - }); - } - - @Cron(CronExpression.EVERY_5_SECONDS) // Called every 5 seconds - ADMIN EVALUATIONS - async instanceEvaluateAdminPageList(): Promise { - if ( - (process.env.NAMESPACE === undefined || - process.env.NAMESPACE === "ADMIN") && - !this.isEvaluatingAdminInstance - ) { - this.isEvaluatingAdminInstance = true; - - let pages = []; - if ( - process.env.NAMESPACE === undefined || - parseInt(process.env.AMSID) === 0 - ) { - pages = await this.connection.query( - `SELECT * FROM Evaluation_List WHERE Error IS NULL AND UserId = -1 AND Is_Evaluating = 0 ORDER BY Creation_Date ASC LIMIT 20` - ); - } else { - const skip = parseInt(process.env.AMSID) * this.SKIP; - pages = await this.connection.query( - `SELECT * FROM Evaluation_List WHERE Error IS NULL AND UserId = -1 AND Is_Evaluating = 0 ORDER BY Creation_Date ASC LIMIT 20, ${skip}` - ); - } - await this.evaluateInBackground(pages); - - this.isEvaluatingAdminInstance = false; - } - } - - @Cron(CronExpression.EVERY_5_SECONDS) // Called every 5 seconds - ADMIN EVALUATIONS - async instanceEvaluateUserPageList(): Promise { - if ( - (process.env.NAMESPACE === undefined || - process.env.NAMESPACE === "USER") && - !this.isEvaluatingUserInstance - ) { - this.isEvaluatingUserInstance = true; - - let pages = []; - if ( - process.env.NAMESPACE === undefined || - parseInt(process.env.USRID) === 0 - ) { - pages = await this.connection.query( - `SELECT * FROM Evaluation_List WHERE Error IS NULL AND UserId <> -1 AND Is_Evaluating = 0 ORDER BY Creation_Date ASC LIMIT 20` - ); - } else { - const skip = parseInt(process.env.USRID) * this.SKIP; - pages = await this.connection.query( - `SELECT * FROM Evaluation_List WHERE Error IS NULL AND UserId <> -1 AND Is_Evaluating = 0 ORDER BY Creation_Date ASC LIMIT 20, ${skip}` - ); - } - - await this.evaluateInBackground(pages); - - this.isEvaluatingUserInstance = false; - } - } - - @Cron(CronExpression.EVERY_10_MINUTES) - async evaluateStuckPages(): Promise { - const pages = await this.connection.query( - `SELECT * FROM Evaluation_List WHERE Error IS NULL AND Is_Evaluating = 1 AND Creation_Date < DATE_SUB(NOW(), INTERVAL 2 HOUR)` - ); - - if (pages.length > 0) { - try { - await this.connection.query( - `UPDATE Evaluation_List SET Is_Evaluating = 0 WHERE EvaluationListId IN (?)`, - [pages.map((p) => p.EvaluationListId)] - ); - } catch (err) { - console.error(err); - throw err; - } - } - } - - /*@Cron('0 0 * * 0') - async evaluateOldPages(): Promise { - if (process.env.NAMESPACE !== 'AMP' && process.env.NODE_APP_INSTANCE === '1') { - - const pagesToEvaluate = await getManager().query(` - SELECT DISTINCT p.PageId, p.Uri, e.Evaluation_Date - FROM - Page as p, - Evaluation as e - WHERE - e.PageId = p.PageId AND e.Evaluation_Date = ( - SELECT Evaluation_Date FROM Evaluation - WHERE PageId = p.PageId - ORDER BY Evaluation_Date DESC LIMIT 1 - ) - ORDER BY e.Evaluation_Date ASC LIMIT 100 - `); - - for (const pte of pagesToEvaluate || []) { - let error = null; - let evaluation: any; - try { - evaluation = clone(await this.evaluateUrl(pte.Url)); - } catch (e) { - error = e.stack; - } - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - try { - if (!error && evaluation) { - this.savePageEvaluation(queryRunner, pte.PageId, evaluation, '10'); - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.log(err); - } finally { - await queryRunner.release(); - } - } - } - }*/ - - private async evaluateInBackground(pages: any[]): Promise { - if (pages.length > 0) { - try { - await this.connection.query( - `UPDATE Evaluation_List SET Is_Evaluating = 1 WHERE EvaluationListId IN (?)`, - [pages.map((p) => p.EvaluationListId)] - ); - } catch (err) { - console.error(err); - throw err; - } - - let reports = {}; - - try { - reports = clone(await this.evaluateUrls(pages.map((p) => p.Url))); - } catch (err) { - console.error(err); - } - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - for (const pte of pages ?? []) { - if (reports[pte.Url]) { - this.savePageEvaluation( - queryRunner, - pte.PageId, - reports[pte.Url], - pte.Show_To, - pte.StudyUserId - ); - - await queryRunner.manager.query( - `DELETE FROM Evaluation_List WHERE EvaluationListId = ?`, - [pte.EvaluationListId] - ); - } else { - const error = this.findUrlError(pte.Url); - await queryRunner.manager.query( - `UPDATE Evaluation_List SET Error = "?" , Is_Evaluating = 0 WHERE EvaluationListId = ?`, - [error, pte.EvaluationListId] - ); - } - } - - try { - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.error(err); - } finally { - await queryRunner.release(); - } - - /*for (const pte of pages || []) { - let error = null; - let evaluation: any; - try { - evaluation = clone(await this.evaluateUrl(pte.Url)); - } catch (e) { - error = e.stack; - } - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - try { - if (!error && evaluation) { - this.savePageEvaluation( - queryRunner, - pte.PageId, - evaluation, - pte.Show_To, - pte.StudyUserId - ); - - await queryRunner.manager.query( - `DELETE FROM Evaluation_List WHERE EvaluationListId = ?`, - [pte.EvaluationListId] - ); - } else { - console.log(error); - await queryRunner.manager.query( - `UPDATE Evaluation_List SET Error = "?" , Is_Evaluating = 0 WHERE EvaluationListId = ?`, - [error?.toString() || error, pte.EvaluationListId] - ); - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.error(err); - } finally { - await queryRunner.release(); - } - }*/ - } - } - - private findUrlError(url: string): string { - let error = ""; - const files = fs.readdirSync("./", { encoding: "utf-8" }); - for (const file of files ?? []) { - if (file.startsWith("qualweb-errors") && !error) { - const content = fs.readFileSync(file, { encoding: "utf-8" }); - if (content.includes(url)) { - let split = content.split(url); - split = split[1].split("-----------"); - split = split[0].split(":"); - error = split.splice(1).join(":").trim(); - } - } - } - - return error; - } - - evaluateUrl(url: string): Promise { - return executeUrlEvaluation(url); - } - - evaluateUrls(urls: string[]): Promise { - return executeUrlsEvaluation(urls); - } - - evaluateHtml(html: string): Promise { - return executeHtmlEvaluation(html); - } - - async createOne(evaluation: Evaluation): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.save(evaluation); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async evaluatePageAndSave( - pageId: number, - url: string, - showTo: string - ): Promise { - const evaluation = await this.evaluateUrl(url); - - const newEvaluation = new Evaluation(); - newEvaluation.PageId = pageId; - newEvaluation.Title = evaluation.data.title.replace(/"/g, ""); - newEvaluation.Score = evaluation.data.score; - newEvaluation.Pagecode = Buffer.from(evaluation.pagecode).toString( - "base64" - ); - newEvaluation.Tot = Buffer.from( - JSON.stringify(evaluation.data.tot) - ).toString("base64"); - newEvaluation.Nodes = Buffer.from( - JSON.stringify(evaluation.data.nodes) - ).toString("base64"); - newEvaluation.Errors = Buffer.from( - JSON.stringify(evaluation.data.elems) - ).toString("base64"); - - const conform = evaluation.data.conform.split("@"); - - newEvaluation.A = conform[0]; - newEvaluation.AA = conform[1]; - newEvaluation.AAA = conform[2]; - newEvaluation.Evaluation_Date = evaluation.data.date; - newEvaluation.Show_To = showTo; - - const saveSuccess = await this.createOne(newEvaluation); - - if (saveSuccess) { - return evaluation; - } else { - throw new InternalServerErrorException(); - } - } - - async savePageEvaluation( - queryRunner: any, - pageId: number, - evaluation: any, - showTo: string, - studyUserId: number | null = null - ): Promise { - const newEvaluation = new Evaluation(); - newEvaluation.PageId = pageId; - newEvaluation.Title = evaluation.data.title.replace(/"/g, "").replace(/[\u0800-\uFFFF]/g, ''); - newEvaluation.Score = evaluation.data.score; - newEvaluation.Pagecode = Buffer.from(evaluation.pagecode).toString( - "base64" - ).substring(0, 16000000); - newEvaluation.Tot = Buffer.from( - JSON.stringify(evaluation.data.tot) - ).toString("base64"); - newEvaluation.Nodes = Buffer.from( - JSON.stringify(evaluation.data.nodes) - ).toString("base64"); - newEvaluation.Errors = Buffer.from( - JSON.stringify(evaluation.data.elems) - ).toString("base64"); - - const conform = evaluation.data.conform.split("@"); - newEvaluation.A = conform[0]; - newEvaluation.AA = conform[1]; - newEvaluation.AAA = conform[2]; - newEvaluation.Evaluation_Date = evaluation.data.date; - newEvaluation.Show_To = showTo; - newEvaluation.StudyUserId = studyUserId; - newEvaluation.Element_Count = JSON.stringify( - evaluation.data.tot.info.roles - ); - newEvaluation.Tag_Count = JSON.stringify(evaluation.data.tot.info.cTags); - const savedEvaluation = await queryRunner.manager.save(newEvaluation); - - } - - async increaseAMSObservatoryRequestCounter(): Promise { - await this.connection.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + 1, Last_Request = NOW() WHERE Application = "AMS/Observatory"` - ); - } - - async increaseMyMonitorRequestCounter(): Promise { - - await this.connection.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + 1, Last_Request = NOW() WHERE Application = "MyMonitor"` - ); - } - - async increaseStudyMonitorRequestCounter(): Promise { - - await this.connection.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + 1, Last_Request = NOW() WHERE Application = "StudyMonitor"` - ); - } - - async increaseAccessMonitorRequestCounter(): Promise { - - await this.connection.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + 1, Last_Request = NOW() WHERE Application = "AccessMonitor"` - ); - } - - async getAMSObservatoryRequestCounter(): Promise { - - const counter = await this.connection.query( - `SELECT * FROM Evaluation_Request_Counter WHERE Application = "AMS/Observatory" LIMIT 1` - ); - return { counter: counter[0].Counter, date: counter[0].Start_Date }; - } - - async getMyMonitorRequestCounter(): Promise { - - const counter = await this.connection.query( - `SELECT * FROM Evaluation_Request_Counter WHERE Application = "MyMonitor" LIMIT 1` - ); - return { counter: counter[0].Counter, date: counter[0].Start_Date }; - } - - async getStudyMonitorRequestCounter(): Promise { - - const counter = await this.connection.query( - `SELECT * FROM Evaluation_Request_Counter WHERE Application = "StudyMonitor" LIMIT 1` - ); - return { counter: counter[0].Counter, date: counter[0].Start_Date }; - } - - async getAccessMonitorRequestCounter(): Promise { - - const counter = await this.connection.query( - `SELECT * FROM Evaluation_Request_Counter WHERE Application = "AccessMonitor" LIMIT 1` - ); - return { counter: counter[0].Counter, date: counter[0].Start_Date }; - } - - async resetAdminWaitingList(): Promise { - - await this.connection.query( - `UPDATE Evaluation_List SET Is_Evaluating = 0, Error = NULL WHERE UserId = -1` - ); - return true; - } - - async deleteAdminWaitingList(): Promise { - - await this.connection.query(`DELETE FROM Evaluation_List WHERE UserId = -1`); - return true; - } - - async resetMMWaitingList(): Promise { - - await this.connection.query( - `UPDATE - Evaluation_List as el, User as u - SET - el.Is_Evaluating = 0, - el.Error = NULL - WHERE - el.UserId <> -1 AND - u.UserId = el.UserId AND - u.Type = "monitor"` - ); - return true; - } - - async deleteMMWaitingList(): Promise { - - await this.connection.query( - `DELETE el.* FROM Evaluation_List as el, User as u - WHERE - el.UserId <> -1 AND - u.UserId = el.UserId AND - u.Type = "monitor"` - ); - return true; - } - - async resetSMWaitingList(): Promise { - - await this.connection.query( - `UPDATE - Evaluation_List as el, User as u - SET - el.Is_Evaluating = 0, - el.Error = NULL - WHERE - el.UserId <> -1 AND - u.UserId = el.UserId AND - u.Type = "studies"` - ); - return true; - } - - async deleteSMWaitingList(): Promise { - - await this.connection.query( - `DELETE el.* FROM Evaluation_List as el, User as u - WHERE - el.UserId <> -1 AND - u.UserId = el.UserId AND - u.Type = "studies"` - ); - return true; - } - - async findMyMonitorUserWebsitePageEvaluations( - userId: number, - website: string - ): Promise { - - - const evaluations = await this.connection.query( - `SELECT e.*, p.Uri - FROM - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - WHERE - w.Name = ? AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE '_1_' AND - e.PageId = p.PageId AND - e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND Show_To LIKE '_1') - `, - [website, userId] - ); - - const reports = new Array(); - - for (const evaluation of evaluations || []) { - const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); - reports.push({ - pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), - data: { - title: evaluation.Title, - score: evaluation.Score, - rawUrl: evaluation.Uri, - tot: tot, - nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), - conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, - elems: tot.elems, - date: evaluation.Evaluation_Date, - }, - }); - } - - return reports; - } - - async findMyMonitorUserWebsitePageNewestEvaluation( - userId: number, - website: string, - url: string - ): Promise { - - - const evaluation = ( - await this.connection.query( - `SELECT e.* - FROM - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - WHERE - w.Name = ? AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Uri = ? AND - e.PageId = p.PageId AND - e.Show_To LIKE '_1' - ORDER BY e.Evaluation_Date DESC - LIMIT 1`, - [website, userId, url] - ) - )[0]; - - if (evaluation) { - const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); - return { - pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), - data: { - title: evaluation.Title, - score: evaluation.Score, - rawUrl: url, - tot: tot, - nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), - conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, - elems: tot.elems, - date: evaluation.Evaluation_Date, - }, - }; - } else { - throw new InternalServerErrorException(); - } - } - - async findStudyMonitorUserTagWebsitePageEvaluations( - userId: number, - tag: string, - website: string - ): Promise { - - - const evaluations = await this.connection.query( - `SELECT e.*, p.Uri - FROM - Tag as t, - TagWebsite as tw, - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.Name = ? AND - w.UserId = t.UserId AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - e.PageId = p.PageId AND - e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND StudyUserId = w.UserId) - `, - [tag, userId, website] - ); - - const reports = new Array(); - - for (const evaluation of evaluations || []) { - const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); - reports.push({ - pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), - data: { - title: evaluation.Title, - score: evaluation.Score, - rawUrl: evaluation.Uri, - tot: tot, - nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), - conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, - elems: tot.elems, - date: evaluation.Evaluation_Date, - }, - }); - } - - return reports; - } - - async findStudyMonitorUserTagWebsitePageNewestEvaluation( - userId: number, - tag: string, - website: string, - url: string - ): Promise { - - - const evaluation = ( - await this.connection.query( - `SELECT e.* - FROM - Tag as t, - TagWebsite as tw, - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.Name = ? AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Uri = ? AND - e.PageId = p.PageId AND - e.StudyUserId = ? - ORDER BY e.Evaluation_Date DESC - LIMIT 1`, - [tag, userId, website, userId, url, userId] - ) - )[0]; - - if (evaluation) { - const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); - return { - pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), - data: { - title: evaluation.Title, - score: evaluation.Score, - rawUrl: url, - tot: tot, - nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), - conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, - elems: tot.elems, - date: evaluation.Evaluation_Date, - }, - }; - } else { - throw new InternalServerErrorException(); - } - } - - async findAllEvaluationsFromPage(type: string, page: string): Promise { - - let query = ""; - - if (type === "admin") { - query = `SELECT distinct e.EvaluationId, e.Score, e.A, e.AA, e.AAA, e.Evaluation_Date, e.Element_Count, e.Tag_Count - FROM - User as u, - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - WHERE - p.Uri = ? AND - p.Show_In LIKE "1%%" AND - e.PageId = p.PageId AND - e.Show_To LIKE "1_" AND - wp.PageId = p.PageId AND - w.WebsiteId = wp.WebsiteId AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type = "monitor")) - ORDER BY e.Evaluation_Date DESC`; - } else if (type === "monitor") { - query = `SELECT distinct e.EvaluationId, e.Score, e.A, e.AA, e.AAA, e.Evaluation_Date - FROM - User as u, - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - WHERE - p.Uri = ? AND - p.Show_In LIKE "11%" AND - e.PageId = p.PageId AND - e.Show_To LIKE "_1" AND - wp.PageId = p.PageId AND - w.WebsiteId = wp.WebsiteId AND - u.UserId = w.UserId AND - u.Type = "monitor" - ORDER BY e.Evaluation_Date DESC`; - } else if (type === "studies") { - query = `SELECT distinct e.EvaluationId, e.Score, e.A, e.AA, e.AAA, e.Evaluation_Date - FROM - Page as p, - Evaluation as e - WHERE - p.Uri = ? AND - e.PageId = p.PageId - ORDER BY e.Evaluation_Date DESC - LIMIT 1`; - } else { - throw new InternalServerErrorException(); - } - - const evaluations = await this.connection.query(query, [page]); - return evaluations; - } - - async findEvaluationById(url: string, id: number): Promise { - - - const evaluation = await this.evaluationRepository.findOne({ - where: { EvaluationId: id }, - }); - - const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); - - return { - pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), - data: { - title: evaluation.Title, - score: evaluation.Score, - rawUrl: url, - tot: tot, - nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), - conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, - elems: tot.elems, - date: evaluation.Evaluation_Date, - }, - }; - } - - async findUserPageEvaluation(url: string, type: string): Promise { - let query = null; - if (type === "monitor") { - query = `SELECT e.* FROM Page as p, Evaluation as e WHERE p.Uri LIKE ? AND e.PageId = p.PageId AND e.Show_To LIKE "_1" ORDER BY e.Evaluation_Date DESC LIMIT 1`; - } else if (type === "studies") { - query = `SELECT e.* FROM Page as p, Evaluation as e WHERE p.Uri LIKE ? AND e.PageId = p.PageId ORDER BY e.Evaluation_Date DESC LIMIT 1`; - } else { - throw new InternalServerErrorException(); - } - - - - const evaluation = (await this.connection.query(query, [url]))[0]; - - const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); - - return { - pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), - data: { - title: evaluation.Title, - score: evaluation.Score, - rawUrl: url, - tot: tot, - nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), - conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, - elems: tot.elems, - date: evaluation.Evaluation_Date, - }, - }; - } - - async tryAgainEvaluation(evaluationListId: number): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.query( - `UPDATE Evaluation_List SET Error = NULL, Is_Evaluating = 0 WHERE EvaluationListId = ?`, - [evaluationListId] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async findWebsiteEvaluations(website: string, sample: boolean): Promise { - - - const evaluations = await this.connection.query( - `SELECT distinct e.*, p.Uri - FROM - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - WHERE - w.StartingUrl = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE ? AND - e.PageId = p.PageId AND - e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND Show_To LIKE '1_') - `, - [website, sample ? "1__" : "1_1"] - ); - - const reports = new Array(); - - for (const evaluation of evaluations || []) { - const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); - reports.push({ - pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), - data: { - title: evaluation.Title, - score: evaluation.Score, - rawUrl: evaluation.Uri, - tot: tot, - nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), - conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, - elems: tot.elems, - date: evaluation.Evaluation_Date, - }, - }); - } - - return reports; - } -} +import { Injectable, InternalServerErrorException } from "@nestjs/common"; +import { DataSource, Repository } from "typeorm"; +import { Cron, CronExpression } from "@nestjs/schedule"; +import clone from "lodash.clone"; +import fs from "fs"; +import { Evaluation } from "./evaluation.entity"; +import { + executeUrlEvaluation, + executeUrlsEvaluation, + executeHtmlEvaluation, +} from "./middleware"; +import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; + +@Injectable() +export class EvaluationService { + private isEvaluatingAdminInstance: boolean; + private isEvaluatingUserInstance: boolean; + private SKIP = 20; + + constructor( + @InjectDataSource() + private readonly connection: DataSource, + @InjectRepository(Evaluation) + private readonly evaluationRepository: Repository + ) { + this.isEvaluatingAdminInstance = false; + this.isEvaluatingUserInstance = false; + } + //FIXME confirmar se as paginas têm sempre avaliação + async getLastEvaluationByPage(pageId: number): Promise { + const evaluationList = await this.evaluationRepository.find({ + where: { PageId: pageId }, + take: 1, + order: { Evaluation_Date: "DESC" }, + }); + return evaluationList[0]; + } + + @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) + cleanUpErrorFiles(): void { + fs.readdir("./", (err, files: string[]) => { + if (!err) { + for (const file of files ?? []) { + if (file.startsWith("qualweb-errors")) { + fs.unlink(file, (err2) => { + if (err2) { + console.error(err2); + } + }); + } + } + } + }); + } + + @Cron(CronExpression.EVERY_5_SECONDS) // Called every 5 seconds - ADMIN EVALUATIONS + async instanceEvaluateAdminPageList(): Promise { + if ( + (process.env.NAMESPACE === undefined || + process.env.NAMESPACE === "ADMIN") && + !this.isEvaluatingAdminInstance + ) { + this.isEvaluatingAdminInstance = true; + + let pages = []; + if ( + process.env.NAMESPACE === undefined || + parseInt(process.env.AMSID) === 0 + ) { + pages = await this.connection.query( + `SELECT * FROM Evaluation_List WHERE Error IS NULL AND UserId = -1 AND Is_Evaluating = 0 ORDER BY Creation_Date ASC LIMIT 20` + ); + } else { + const skip = parseInt(process.env.AMSID) * this.SKIP; + pages = await this.connection.query( + `SELECT * FROM Evaluation_List WHERE Error IS NULL AND UserId = -1 AND Is_Evaluating = 0 ORDER BY Creation_Date ASC LIMIT 20, ${skip}` + ); + } + await this.evaluateInBackground(pages); + + this.isEvaluatingAdminInstance = false; + } + } + + @Cron(CronExpression.EVERY_5_SECONDS) // Called every 5 seconds - ADMIN EVALUATIONS + async instanceEvaluateUserPageList(): Promise { + if ( + (process.env.NAMESPACE === undefined || + process.env.NAMESPACE === "USER") && + !this.isEvaluatingUserInstance + ) { + this.isEvaluatingUserInstance = true; + + let pages = []; + if ( + process.env.NAMESPACE === undefined || + parseInt(process.env.USRID) === 0 + ) { + pages = await this.connection.query( + `SELECT * FROM Evaluation_List WHERE Error IS NULL AND UserId <> -1 AND Is_Evaluating = 0 ORDER BY Creation_Date ASC LIMIT 20` + ); + } else { + const skip = parseInt(process.env.USRID) * this.SKIP; + pages = await this.connection.query( + `SELECT * FROM Evaluation_List WHERE Error IS NULL AND UserId <> -1 AND Is_Evaluating = 0 ORDER BY Creation_Date ASC LIMIT 20, ${skip}` + ); + } + + await this.evaluateInBackground(pages); + + this.isEvaluatingUserInstance = false; + } + } + + @Cron(CronExpression.EVERY_10_MINUTES) + async evaluateStuckPages(): Promise { + const pages = await this.connection.query( + `SELECT * FROM Evaluation_List WHERE Error IS NULL AND Is_Evaluating = 1 AND Creation_Date < DATE_SUB(NOW(), INTERVAL 2 HOUR)` + ); + + if (pages.length > 0) { + try { + await this.connection.query( + `UPDATE Evaluation_List SET Is_Evaluating = 0 WHERE EvaluationListId IN (?)`, + [pages.map((p) => p.EvaluationListId)] + ); + } catch (err) { + console.error(err); + throw err; + } + } + } + + /*@Cron('0 0 * * 0') + async evaluateOldPages(): Promise { + if (process.env.NAMESPACE !== 'AMP' && process.env.NODE_APP_INSTANCE === '1') { + + const pagesToEvaluate = await getManager().query(` + SELECT DISTINCT p.PageId, p.Uri, e.Evaluation_Date + FROM + Page as p, + Evaluation as e + WHERE + e.PageId = p.PageId AND e.Evaluation_Date = ( + SELECT Evaluation_Date FROM Evaluation + WHERE PageId = p.PageId + ORDER BY Evaluation_Date DESC LIMIT 1 + ) + ORDER BY e.Evaluation_Date ASC LIMIT 100 + `); + + for (const pte of pagesToEvaluate || []) { + let error = null; + let evaluation: any; + try { + evaluation = clone(await this.evaluateUrl(pte.Url)); + } catch (e) { + error = e.stack; + } + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + try { + if (!error && evaluation) { + this.savePageEvaluation(queryRunner, pte.PageId, evaluation, '10'); + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.log(err); + } finally { + await queryRunner.release(); + } + } + } + }*/ + + private async evaluateInBackground(pages: any[]): Promise { + if (pages.length > 0) { + try { + await this.connection.query( + `UPDATE Evaluation_List SET Is_Evaluating = 1 WHERE EvaluationListId IN (?)`, + [pages.map((p) => p.EvaluationListId)] + ); + } catch (err) { + console.error(err); + throw err; + } + + let reports = {}; + + try { + reports = clone(await this.evaluateUrls(pages.map((p) => p.Url))); + } catch (err) { + console.error(err); + } + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + for (const pte of pages ?? []) { + if (reports[pte.Url]) { + this.savePageEvaluation( + queryRunner, + pte.PageId, + reports[pte.Url], + pte.Show_To, + pte.StudyUserId + ); + + await queryRunner.manager.query( + `DELETE FROM Evaluation_List WHERE EvaluationListId = ?`, + [pte.EvaluationListId] + ); + } else { + const error = this.findUrlError(pte.Url); + await queryRunner.manager.query( + `UPDATE Evaluation_List SET Error = "?" , Is_Evaluating = 0 WHERE EvaluationListId = ?`, + [error, pte.EvaluationListId] + ); + } + } + + try { + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.error(err); + } finally { + await queryRunner.release(); + } + + /*for (const pte of pages || []) { + let error = null; + let evaluation: any; + try { + evaluation = clone(await this.evaluateUrl(pte.Url)); + } catch (e) { + error = e.stack; + } + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + try { + if (!error && evaluation) { + this.savePageEvaluation( + queryRunner, + pte.PageId, + evaluation, + pte.Show_To, + pte.StudyUserId + ); + + await queryRunner.manager.query( + `DELETE FROM Evaluation_List WHERE EvaluationListId = ?`, + [pte.EvaluationListId] + ); + } else { + console.log(error); + await queryRunner.manager.query( + `UPDATE Evaluation_List SET Error = "?" , Is_Evaluating = 0 WHERE EvaluationListId = ?`, + [error?.toString() || error, pte.EvaluationListId] + ); + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.error(err); + } finally { + await queryRunner.release(); + } + }*/ + } + } + + private findUrlError(url: string): string { + let error = ""; + const files = fs.readdirSync("./", { encoding: "utf-8" }); + for (const file of files ?? []) { + if (file.startsWith("qualweb-errors") && !error) { + const content = fs.readFileSync(file, { encoding: "utf-8" }); + if (content.includes(url)) { + let split = content.split(url); + split = split[1].split("-----------"); + split = split[0].split(":"); + error = split.splice(1).join(":").trim(); + } + } + } + + return error; + } + + evaluateUrl(url: string): Promise { + return executeUrlEvaluation(url); + } + + evaluateUrls(urls: string[]): Promise { + return executeUrlsEvaluation(urls); + } + + evaluateHtml(html: string): Promise { + return executeHtmlEvaluation(html); + } + + async createOne(evaluation: Evaluation): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.save(evaluation); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async evaluatePageAndSave( + pageId: number, + url: string, + showTo: string + ): Promise { + const evaluation = await this.evaluateUrl(url); + + const newEvaluation = new Evaluation(); + newEvaluation.PageId = pageId; + newEvaluation.Title = evaluation.data.title.replace(/"/g, ""); + newEvaluation.Score = evaluation.data.score; + newEvaluation.Pagecode = Buffer.from(evaluation.pagecode).toString( + "base64" + ); + newEvaluation.Tot = Buffer.from( + JSON.stringify(evaluation.data.tot) + ).toString("base64"); + newEvaluation.Nodes = Buffer.from( + JSON.stringify(evaluation.data.nodes) + ).toString("base64"); + newEvaluation.Errors = Buffer.from( + JSON.stringify(evaluation.data.elems) + ).toString("base64"); + + const conform = evaluation.data.conform.split("@"); + + newEvaluation.A = conform[0]; + newEvaluation.AA = conform[1]; + newEvaluation.AAA = conform[2]; + newEvaluation.Evaluation_Date = evaluation.data.date; + newEvaluation.Show_To = showTo; + + const saveSuccess = await this.createOne(newEvaluation); + + if (saveSuccess) { + return evaluation; + } else { + throw new InternalServerErrorException(); + } + } + + async savePageEvaluation( + queryRunner: any, + pageId: number, + evaluation: any, + showTo: string, + studyUserId: number | null = null + ): Promise { + const newEvaluation = new Evaluation(); + newEvaluation.PageId = pageId; + newEvaluation.Title = evaluation.data.title + .replace(/"/g, "") + .replace(/[\u0800-\uFFFF]/g, ""); + newEvaluation.Score = evaluation.data.score; + newEvaluation.Pagecode = Buffer.from(evaluation.pagecode) + .toString("base64") + .substring(0, 16000000); + newEvaluation.Tot = Buffer.from( + JSON.stringify(evaluation.data.tot) + ).toString("base64"); + newEvaluation.Nodes = Buffer.from( + JSON.stringify(evaluation.data.nodes) + ).toString("base64"); + newEvaluation.Errors = Buffer.from( + JSON.stringify(evaluation.data.elems) + ).toString("base64"); + + const conform = evaluation.data.conform.split("@"); + newEvaluation.A = conform[0]; + newEvaluation.AA = conform[1]; + newEvaluation.AAA = conform[2]; + newEvaluation.Evaluation_Date = evaluation.data.date; + newEvaluation.Show_To = showTo; + newEvaluation.StudyUserId = studyUserId; + newEvaluation.Element_Count = JSON.stringify( + evaluation.data.tot.info.roles + ); + newEvaluation.Tag_Count = JSON.stringify(evaluation.data.tot.info.cTags); + const savedEvaluation = await queryRunner.manager.save(newEvaluation); + } + + async increaseAMSObservatoryRequestCounter(): Promise { + await this.connection.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + 1, Last_Request = NOW() WHERE Application = "AMS/Observatory"` + ); + } + + async increaseMyMonitorRequestCounter(): Promise { + await this.connection.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + 1, Last_Request = NOW() WHERE Application = "MyMonitor"` + ); + } + + async increaseStudyMonitorRequestCounter(): Promise { + await this.connection.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + 1, Last_Request = NOW() WHERE Application = "StudyMonitor"` + ); + } + + async increaseAccessMonitorRequestCounter(): Promise { + await this.connection.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + 1, Last_Request = NOW() WHERE Application = "AccessMonitor"` + ); + } + + async getAMSObservatoryRequestCounter(): Promise { + const counter = await this.connection.query( + `SELECT * FROM Evaluation_Request_Counter WHERE Application = "AMS/Observatory" LIMIT 1` + ); + return { counter: counter[0].Counter, date: counter[0].Start_Date }; + } + + async getMyMonitorRequestCounter(): Promise { + const counter = await this.connection.query( + `SELECT * FROM Evaluation_Request_Counter WHERE Application = "MyMonitor" LIMIT 1` + ); + return { counter: counter[0].Counter, date: counter[0].Start_Date }; + } + + async getStudyMonitorRequestCounter(): Promise { + const counter = await this.connection.query( + `SELECT * FROM Evaluation_Request_Counter WHERE Application = "StudyMonitor" LIMIT 1` + ); + return { counter: counter[0].Counter, date: counter[0].Start_Date }; + } + + async getAccessMonitorRequestCounter(): Promise { + const counter = await this.connection.query( + `SELECT * FROM Evaluation_Request_Counter WHERE Application = "AccessMonitor" LIMIT 1` + ); + return { counter: counter[0].Counter, date: counter[0].Start_Date }; + } + + async resetAdminWaitingList(): Promise { + await this.connection.query( + `UPDATE Evaluation_List SET Is_Evaluating = 0, Error = NULL WHERE UserId = -1` + ); + return true; + } + + async deleteAdminWaitingList(): Promise { + await this.connection.query( + `DELETE FROM Evaluation_List WHERE UserId = -1` + ); + return true; + } + + async resetMMWaitingList(): Promise { + await this.connection.query( + `UPDATE + Evaluation_List as el, User as u + SET + el.Is_Evaluating = 0, + el.Error = NULL + WHERE + el.UserId <> -1 AND + u.UserId = el.UserId AND + u.Type = "monitor"` + ); + return true; + } + + async deleteMMWaitingList(): Promise { + await this.connection.query( + `DELETE el.* FROM Evaluation_List as el, User as u + WHERE + el.UserId <> -1 AND + u.UserId = el.UserId AND + u.Type = "monitor"` + ); + return true; + } + + async resetSMWaitingList(): Promise { + await this.connection.query( + `UPDATE + Evaluation_List as el, User as u + SET + el.Is_Evaluating = 0, + el.Error = NULL + WHERE + el.UserId <> -1 AND + u.UserId = el.UserId AND + u.Type = "studies"` + ); + return true; + } + + async deleteSMWaitingList(): Promise { + await this.connection.query( + `DELETE el.* FROM Evaluation_List as el, User as u + WHERE + el.UserId <> -1 AND + u.UserId = el.UserId AND + u.Type = "studies"` + ); + return true; + } + + async findMyMonitorUserWebsitePageEvaluations( + userId: number, + website: string + ): Promise { + const evaluations = await this.connection.query( + `SELECT e.*, p.Uri + FROM + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + WHERE + w.Name = ? AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE '_1_' AND + e.PageId = p.PageId AND + e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND Show_To LIKE '_1') + `, + [website, userId] + ); + + const reports = new Array(); + + for (const evaluation of evaluations || []) { + const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); + reports.push({ + pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), + data: { + title: evaluation.Title, + score: evaluation.Score, + rawUrl: evaluation.Uri, + tot: tot, + nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), + conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, + elems: tot.elems, + date: evaluation.Evaluation_Date, + }, + }); + } + + return reports; + } + + async findMyMonitorUserWebsitePageNewestEvaluation( + userId: number, + website: string, + url: string + ): Promise { + const evaluation = ( + await this.connection.query( + `SELECT e.* + FROM + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + WHERE + w.Name = ? AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Uri = ? AND + e.PageId = p.PageId AND + e.Show_To LIKE '_1' + ORDER BY e.Evaluation_Date DESC + LIMIT 1`, + [website, userId, url] + ) + )[0]; + + if (evaluation) { + const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); + return { + pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), + data: { + title: evaluation.Title, + score: evaluation.Score, + rawUrl: url, + tot: tot, + nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), + conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, + elems: tot.elems, + date: evaluation.Evaluation_Date, + }, + }; + } else { + throw new InternalServerErrorException(); + } + } + + async findStudyMonitorUserTagWebsitePageEvaluations( + userId: number, + tag: string, + website: string + ): Promise { + const evaluations = await this.connection.query( + `SELECT e.*, p.Uri + FROM + Tag as t, + TagWebsite as tw, + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.Name = ? AND + w.UserId = t.UserId AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + e.PageId = p.PageId AND + e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND StudyUserId = w.UserId) + `, + [tag, userId, website] + ); + + const reports = new Array(); + + for (const evaluation of evaluations || []) { + const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); + reports.push({ + pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), + data: { + title: evaluation.Title, + score: evaluation.Score, + rawUrl: evaluation.Uri, + tot: tot, + nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), + conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, + elems: tot.elems, + date: evaluation.Evaluation_Date, + }, + }); + } + + return reports; + } + + async findStudyMonitorUserTagWebsitePageNewestEvaluation( + userId: number, + tag: string, + website: string, + url: string + ): Promise { + const evaluation = ( + await this.connection.query( + `SELECT e.* + FROM + Tag as t, + TagWebsite as tw, + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.Name = ? AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Uri = ? AND + e.PageId = p.PageId AND + e.StudyUserId = ? + ORDER BY e.Evaluation_Date DESC + LIMIT 1`, + [tag, userId, website, userId, url, userId] + ) + )[0]; + + if (evaluation) { + const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); + return { + pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), + data: { + title: evaluation.Title, + score: evaluation.Score, + rawUrl: url, + tot: tot, + nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), + conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, + elems: tot.elems, + date: evaluation.Evaluation_Date, + }, + }; + } else { + throw new InternalServerErrorException(); + } + } + + async findAllEvaluationsFromPage(type: string, page: string): Promise { + let query = ""; + + if (type === "admin") { + query = `SELECT distinct e.EvaluationId, e.Score, e.A, e.AA, e.AAA, e.Evaluation_Date, e.Element_Count, e.Tag_Count + FROM + User as u, + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + WHERE + p.Uri = ? AND + p.Show_In LIKE "1%%" AND + e.PageId = p.PageId AND + e.Show_To LIKE "1_" AND + wp.PageId = p.PageId AND + w.WebsiteId = wp.WebsiteId AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type = "monitor")) + ORDER BY e.Evaluation_Date DESC`; + } else if (type === "monitor") { + query = `SELECT distinct e.EvaluationId, e.Score, e.A, e.AA, e.AAA, e.Evaluation_Date + FROM + User as u, + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + WHERE + p.Uri = ? AND + p.Show_In LIKE "11%" AND + e.PageId = p.PageId AND + e.Show_To LIKE "_1" AND + wp.PageId = p.PageId AND + w.WebsiteId = wp.WebsiteId AND + u.UserId = w.UserId AND + u.Type = "monitor" + ORDER BY e.Evaluation_Date DESC`; + } else if (type === "studies") { + query = `SELECT distinct e.EvaluationId, e.Score, e.A, e.AA, e.AAA, e.Evaluation_Date + FROM + Page as p, + Evaluation as e + WHERE + p.Uri = ? AND + e.PageId = p.PageId + ORDER BY e.Evaluation_Date DESC + LIMIT 1`; + } else { + throw new InternalServerErrorException(); + } + + const evaluations = await this.connection.query(query, [page]); + return evaluations; + } + + async findEvaluationById(url: string, id: number): Promise { + const evaluation = await this.evaluationRepository.findOne({ + where: { EvaluationId: id }, + }); + + const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); + + return { + pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), + data: { + title: evaluation.Title, + score: evaluation.Score, + rawUrl: url, + tot: tot, + nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), + conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, + elems: tot.elems, + date: evaluation.Evaluation_Date, + }, + }; + } + + async findUserPageEvaluation(url: string, type: string): Promise { + let query = null; + if (type === "monitor") { + query = `SELECT e.* FROM Page as p, Evaluation as e WHERE p.Uri LIKE ? AND e.PageId = p.PageId AND e.Show_To LIKE "_1" ORDER BY e.Evaluation_Date DESC LIMIT 1`; + } else if (type === "studies") { + query = `SELECT e.* FROM Page as p, Evaluation as e WHERE p.Uri LIKE ? AND e.PageId = p.PageId ORDER BY e.Evaluation_Date DESC LIMIT 1`; + } else { + throw new InternalServerErrorException(); + } + + const evaluation = (await this.connection.query(query, [url]))[0]; + + const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); + + return { + pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), + data: { + title: evaluation.Title, + score: evaluation.Score, + rawUrl: url, + tot: tot, + nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), + conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, + elems: tot.elems, + date: evaluation.Evaluation_Date, + }, + }; + } + + async tryAgainEvaluation(evaluationListId: number): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.query( + `UPDATE Evaluation_List SET Error = NULL, Is_Evaluating = 0 WHERE EvaluationListId = ?`, + [evaluationListId] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async findWebsiteEvaluations(website: string, sample: boolean): Promise { + const evaluations = await this.connection.query( + `SELECT distinct e.*, p.Uri + FROM + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + WHERE + w.StartingUrl = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE ? AND + e.PageId = p.PageId AND + e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND Show_To LIKE '1_') + `, + [website, sample ? "1__" : "1_1"] + ); + + const reports = new Array(); + + for (const evaluation of evaluations || []) { + const tot = JSON.parse(Buffer.from(evaluation.Tot, "base64").toString()); + reports.push({ + // pagecode: Buffer.from(evaluation.Pagecode, "base64").toString(), // removed because is not used upstream and is too big + pagecode: "", + data: { + title: evaluation.Title, + score: evaluation.Score, + rawUrl: evaluation.Uri, + tot: tot, + nodes: JSON.parse(Buffer.from(evaluation.Nodes, "base64").toString()), + conform: `${evaluation.A}@${evaluation.AA}@${evaluation.AAA}`, + elems: tot.elems, + date: evaluation.Evaluation_Date, + }, + }); + } + + return reports; + } +} diff --git a/src/evaluation/mapping.ts b/src/evaluation/mapping.ts index 098a0a39..86f6ad5f 100644 --- a/src/evaluation/mapping.ts +++ b/src/evaluation/mapping.ts @@ -1,2044 +1,2076 @@ -const act_mapping = { - "QW-ACT-R1": QW_ACT_R1, - "QW-ACT-R2": QW_ACT_R2, - "QW-ACT-R4": QW_ACT_R4, - "QW-ACT-R5": QW_ACT_R5, - "QW-ACT-R6": QW_ACT_R6, - "QW-ACT-R7": QW_ACT_R7, - "QW-ACT-R9": QW_ACT_R9, - "QW-ACT-R10": QW_ACT_R10, - "QW-ACT-R11": QW_ACT_R11, - "QW-ACT-R12": QW_ACT_R12, - "QW-ACT-R13": QW_ACT_R13, - "QW-ACT-R14": QW_ACT_R14, - "QW-ACT-R15": QW_ACT_R15, - "QW-ACT-R16": QW_ACT_R16, - "QW-ACT-R17": QW_ACT_R17, - "QW-ACT-R19": QW_ACT_R19, - "QW-ACT-R20": QW_ACT_R20, - "QW-ACT-R21": QW_ACT_R21, - "QW-ACT-R22": QW_ACT_R22, - "QW-ACT-R23": QW_ACT_R23, - "QW-ACT-R24": QW_ACT_R24, - "QW-ACT-R25": QW_ACT_R25, - "QW-ACT-R26": QW_ACT_R26, - "QW-ACT-R27": QW_ACT_R27, - "QW-ACT-R28": QW_ACT_R28, - "QW-ACT-R30": QW_ACT_R30, - "QW-ACT-R33": QW_ACT_R33, - "QW-ACT-R34": QW_ACT_R34, - "QW-ACT-R35": QW_ACT_R35, - "QW-ACT-R36": QW_ACT_R36, - "QW-ACT-R37": QW_ACT_R37, - "QW-ACT-R38": QW_ACT_R38, - "QW-ACT-R39": QW_ACT_R39, - "QW-ACT-R40": QW_ACT_R40, - "QW-ACT-R42": QW_ACT_R42, - "QW-ACT-R43": QW_ACT_R43, - "QW-ACT-R44": QW_ACT_R44, - "QW-ACT-R48": QW_ACT_R48, - "QW-ACT-R62": QW_ACT_R62, - "QW-ACT-R65": QW_ACT_R65, - "QW-ACT-R66": QW_ACT_R66, - "QW-ACT-R67": QW_ACT_R67, - "QW-ACT-R68": QW_ACT_R68, - "QW-ACT-R69": QW_ACT_R69, - "QW-ACT-R70": QW_ACT_R70, - "QW-ACT-R71": QW_ACT_R71, - "QW-ACT-R76": QW_ACT_R76, - "QW-ACT-R77": QW_ACT_R77, -}; - -const wcag_mapping = { - "QW-WCAG-T1": QW_WCAG_T1, - "QW-WCAG-T2": QW_WCAG_T2, - "QW-WCAG-T3": QW_WCAG_T3, - "QW-WCAG-T6": QW_WCAG_T6, - "QW-WCAG-T7": QW_WCAG_T7, - "QW-WCAG-T8": QW_WCAG_T8, - "QW-WCAG-T9": QW_WCAG_T9, - "QW-WCAG-T14": QW_WCAG_T14, - "QW-WCAG-T15": QW_WCAG_T15, - "QW-WCAG-T16": QW_WCAG_T16, - "QW-WCAG-T17": QW_WCAG_T17, - "QW-WCAG-T18": QW_WCAG_T18, - "QW-WCAG-T19": QW_WCAG_T19, - "QW-WCAG-T20": QW_WCAG_T20, - "QW-WCAG-T21": QW_WCAG_T21, - "QW-WCAG-T22": QW_WCAG_T22, - "QW-WCAG-T23": QW_WCAG_T23, - "QW-WCAG-T24": QW_WCAG_T24, - "QW-WCAG-T25": QW_WCAG_T25, - "QW-WCAG-T26": QW_WCAG_T26, - "QW-WCAG-T27": QW_WCAG_T27, - "QW-WCAG-T28": QW_WCAG_T28, - "QW-WCAG-T29": QW_WCAG_T29, - "QW-WCAG-T30": QW_WCAG_T30, - "QW-WCAG-T31": QW_WCAG_T31, - "QW-WCAG-T33": QW_WCAG_T33, - "QW-WCAG-T34": QW_WCAG_T34, - "QW-WCAG-T35": QW_WCAG_T35, -}; - -const bp_mapping = { - "QW-BP1": QW_BP1, - "QW-BP2": QW_BP2, - "QW-BP4": QW_BP4, - "QW-BP5": QW_BP5, - "QW-BP6": QW_BP6, - "QW-BP7": QW_BP7, - "QW-BP8": QW_BP8, - "QW-BP9": QW_BP9, - "QW-BP10": QW_BP10, - "QW-BP11": QW_BP11, - "QW-BP13": QW_BP13, - "QW-BP14": QW_BP14, - // "QW-BP15": QW_BP15, - "QW-BP17": QW_BP17, - // "QW-BP18": QW_BP18, - "QW-BP19": QW_BP19, - "QW-BP20": QW_BP20, - "QW-BP21": QW_BP21, - "QW-BP22": QW_BP22, - "QW-BP23": QW_BP23, - "QW-BP24": QW_BP24, - "QW-BP25": QW_BP25, - "QW-BP26": QW_BP26, - "QW-BP27": QW_BP27, - "QW-BP29": QW_BP29 -}; - -function QW_ACT_R1(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "failed") { - const noTitle = rule.results.filter((r: any) => r.resultCode === "F1"); - if (noTitle.length !== 0) { - addToElements(elements, "titleNo", noTitle.length); - addToResults(results, "title_02"); - addToNodes(nodes, "titleNo", null); - } - - const titleEmpty = rule.results.filter((r: any) => r.resultCode === "F2"); - if (titleEmpty.length !== 0) { - addToElements(elements, "titleNull", titleEmpty.length); - addToResults(results, "title_03"); - addToNodes(nodes, "titleNull", titleEmpty); - } - } else if (rule.metadata.outcome === "passed") { - addToElements(elements, "titleOk", rule.metadata.passed); - addToResults(results, "title_06"); - addToNodes( - nodes, - "titleOk", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} - -function QW_ACT_R2(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "failed") { - addToElements(elements, "langNo", rule.metadata.failed); - addToResults(results, "lang_03"); - addToNodes( - nodes, - "langNo", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } else if (rule.metadata.outcome === "passed") { - addToElements(elements, "lang", rule.metadata.passed); - addToResults(results, "lang_01"); - addToNodes( - nodes, - "lang", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} - -function QW_ACT_R4(elements: any, results: any, nodes: any, rule: any): void { - const failRefresh = rule.results.filter((r: any) => r.resultCode === "F1"); - if (failRefresh.length !== 0) { - addToElements(elements, "metaRefresh", failRefresh.length); - addToResults(results, "meta_01"); - addToNodes(nodes, "metaRefresh", failRefresh); - } - - const failRedirect = rule.results.filter((r: any) => r.resultCode === "F2"); - if (failRedirect.length !== 0) { - addToElements(elements, "metaRedir", failRedirect.length); - addToResults(results, "meta_02"); - addToNodes(nodes, "metaRedir", failRedirect); - } -} - -function QW_ACT_R5(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "failed") { - addToElements(elements, "langCodeNo", "lang"); - addToResults(results, "lang_02"); - addToNodes( - nodes, - "langCodeNo", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R6(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "inpImgAltYes", undefined); - addToResults(results, "inp_img_01a"); - addToNodes( - nodes, - "inpImgAltYes", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "inpImgAltNo", rule.metadata.failed); - addToResults(results, "inp_img_01b"); - addToNodes( - nodes, - "inpImgAltNo", - rule.results.filter((r: any) => r.verdict === "failed") - ); - addToElements( - elements, - "inp_img_01b", - rule.results.filter((r: any) => r.verdict !== "inapplicable").length - ); - } -} -function QW_ACT_R7(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "orientationCSS", rule.metadata.passed); - addToResults(results, "orientation_01"); - addToNodes( - nodes, - "orientationCSS", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "orientationCSSNot", rule.metadata.failed); - addToResults(results, "orientation_02"); - addToNodes( - nodes, - "orientationCSSNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R9(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "warning") { - addToElements(elements, "aSameText", rule.metadata.warning); - addToResults(results, "a_09"); - addToNodes( - nodes, - "aSameText", - rule.results.filter((r: any) => r.verdict === "warning") - ); - } -} -function QW_ACT_R10(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "iframeSame", rule.results.length); - if (rule.metadata.outcome === "passed") { - addToElements(elements, "iframeSameAName", rule.metadata.passed); - addToResults(results, "iframe_02"); - addToNodes( - nodes, - "iframeSameAName", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "iframeSameANameDiferent", rule.metadata.failed); - addToResults(results, "iframe_03"); - addToNodes( - nodes, - "iframeSameANameDiferent", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R11(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "button", rule.results.length); - if (rule.metadata.outcome === "passed") { - addToElements(elements, "buttonAname", rule.metadata.passed); - addToResults(results, "button_01"); - addToNodes( - nodes, - "buttonAname", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "buttonNotAname", rule.metadata.failed); - addToResults(results, "button_02"); - addToNodes( - nodes, - "buttonNotAname", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R12(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "a", rule.results.length); - if (rule.metadata.outcome === "passed") { - addToElements(elements, "linkAName", rule.metadata.passed); - addToResults(results, "a_10"); - addToNodes( - nodes, - "linkAName", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "linkNotAName", rule.metadata.failed); - addToResults(results, "a_11"); - addToNodes( - nodes, - "linkNotAName", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R13(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "elementDec", rule.metadata.passed); - addToResults(results, "element_02"); - addToNodes( - nodes, - "elementDec", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "elementNotDec", rule.metadata.failed); - addToResults(results, "element_03"); - addToNodes( - nodes, - "elementNotDec", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R14(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "metaViewport", rule.metadata.passed); - addToResults(results, "meta_05"); - addToNodes( - nodes, - "metaViewport", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} -function QW_ACT_R15(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "audioAvoidsAutoPlay", undefined); - addToResults(results, "audio_video_01"); - addToNodes( - nodes, - "audioAvoidsAutoPlay", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "audioAutoPlay", rule.metadata.failed); - addToResults(results, "audio_video_02"); - addToNodes( - nodes, - "audioAutoPlay", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R16(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "inputLabel", undefined); - addToResults(results, "input_02b"); - addToNodes( - nodes, - "inputLabel", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "inputLabelNo", rule.metadata.failed); - addToResults(results, "input_02"); - addToNodes( - nodes, - "inputLabelNo", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R17(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "img", rule.results.length); - if (rule.metadata.outcome === "passed") { - addToElements(elements, "imgAlt", undefined); - addToResults(results, "img_01a"); - addToNodes( - nodes, - "imgAlt", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "imgAltNo", rule.metadata.failed); - addToResults(results, "img_01b"); - addToNodes( - nodes, - "imgAltNo", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } - - const imgEmptyAlt = rule.results.filter((r: any) => r.resultCode === "P1"); - - if (imgEmptyAlt.length > 0) { - addToElements(elements, "imgAltNull", imgEmptyAlt.length); - addToResults(results, "img_02"); - addToNodes(nodes, "imgAltNull", imgEmptyAlt); - } -} - -function QW_ACT_R19(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "failed") { - addToElements(elements, "iframeTitleNo", rule.metadata.failed); - addToResults(results, "iframe_01"); - addToNodes( - nodes, - "iframeTitleNo", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R21(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "svg", rule.results.length); - if (rule.metadata.outcome === "passed") { - addToElements(elements, "svgAName", rule.metadata.passed); - addToResults(results, "svg_01"); - addToNodes( - nodes, - "svgAName", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "svgNotAName", rule.metadata.failed); - addToResults(results, "svg_02"); - addToNodes( - nodes, - "svgNotAName", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R20(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "roleValid", rule.metadata.passed); - addToResults(results, "role_01"); - addToNodes( - nodes, - "roleValid", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "roleValidNot", rule.metadata.failed); - addToResults(results, "role_02"); - addToNodes( - nodes, - "roleValidNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R22(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "elementLang", rule.metadata.passed); - addToResults(results, "element_06"); - addToNodes( - nodes, - "elementLang", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "elementNotLang", rule.metadata.failed); - addToResults(results, "element_07"); - addToNodes( - nodes, - "elementNotLang", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R23(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "videoVisual", rule.metadata.passed); - addToResults(results, "video_02"); - addToNodes( - nodes, - "videoVisual", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} -function QW_ACT_R24(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "autoCmpltValid", rule.metadata.passed); - addToResults(results, "autocomplete_01"); - addToNodes( - nodes, - "autoCmpltValid", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "autoCmpltNotValid", rule.metadata.failed); - addToResults(results, "autocomplete_02"); - addToNodes( - nodes, - "autoCmpltNotValid", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R25(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "ariaStPermitted", rule.metadata.passed); - addToResults(results, "aria_05"); - addToNodes( - nodes, - "ariaStPermitted", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "ariaStNotPermitted", rule.metadata.failed); - addToResults(results, "aria_06"); - addToNodes( - nodes, - "ariaStNotPermitted", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R26(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "videoAudit", rule.metadata.passed); - addToResults(results, "video_01"); - addToNodes( - nodes, - "videoAudit", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} -function QW_ACT_R27(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "ariaAtribDefined", rule.metadata.passed); - addToResults(results, "aria_07"); - addToNodes( - nodes, - "ariaAtribDefined", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "ariaAtribNotDefined", rule.metadata.failed); - addToResults(results, "aria_08"); - addToNodes( - nodes, - "ariaAtribNotDefined", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R28(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "elementRole", rule.metadata.passed); - addToResults(results, "element_10"); - addToNodes( - nodes, - "elementRole", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} -function QW_ACT_R30(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "labelAName", rule.metadata.passed); - addToResults(results, "label_01"); - addToNodes( - nodes, - "labelAName", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "labelANameNot", rule.metadata.failed); - addToResults(results, "label_03"); - addToNodes( - nodes, - "labelANameNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R33(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "ariaCntxRole", rule.metadata.passed); - addToResults(results, "aria_01"); - addToNodes( - nodes, - "ariaCntxRole", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} -function QW_ACT_R34(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "ariaStValid", rule.metadata.passed); - addToResults(results, "aria_03"); - addToNodes( - nodes, - "ariaStValid", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "ariaStNotValid", rule.metadata.failed); - addToResults(results, "aria_04"); - addToNodes( - nodes, - "ariaStNotValid", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R35(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "hxHasAName", rule.metadata.passed); - addToResults(results, "heading_01"); - addToNodes( - nodes, - "hxHasAName", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "hxWithoutAName", rule.metadata.failed); - addToResults(results, "heading_02"); - addToNodes( - nodes, - "hxWithoutAName", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R36(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "headers", rule.results.length); - if (rule.metadata.outcome === "passed") { - addToElements(elements, "headerAtt", rule.metadata.passed); - addToResults(results, "headers_01"); - addToNodes( - nodes, - "headerAtt", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "headerAttNot", rule.metadata.failed); - addToResults(results, "headers_02"); - addToNodes( - nodes, - "headerAttNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R37(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "id", rule.results.length); - if (rule.metadata.outcome === "failed") { - addToElements(elements, "colorContrast", rule.metadata.failed); - addToResults(results, "color_02"); - addToNodes( - nodes, - "colorContrast", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R38(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "ariaReqElem", rule.metadata.passed); - addToResults(results, "aria_02"); - addToNodes( - nodes, - "ariaReqElem", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} -function QW_ACT_R39(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "tableHdr", rule.metadata.passed); - addToResults(results, "table_07"); - addToNodes( - nodes, - "tableHdr", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "tableHdrNot", rule.metadata.failed); - addToResults(results, "table_08"); - addToNodes( - nodes, - "tableHdrNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R40(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "overflow", rule.metadata.passed); - addToResults(results, "css_02"); - addToNodes( - nodes, - "overflow", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} -function QW_ACT_R42(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "objectAName", rule.metadata.passed); - addToResults(results, "object_01"); - addToNodes( - nodes, - "objectAName", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "objectANameNot", rule.metadata.failed); - addToResults(results, "object_02"); - addToNodes( - nodes, - "objectANameNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R43(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "scrollable", rule.results.length); - if (rule.metadata.outcome === "passed") { - addToElements(elements, "scrollableAccess", rule.metadata.passed); - addToResults(results, "scrollable_01"); - addToNodes( - nodes, - "scrollableAccess", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "scrollableAccessNot", rule.metadata.failed); - addToResults(results, "scrollable_02"); - addToNodes( - nodes, - "scrollableAccessNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R44(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "linkIdentAName", rule.metadata.passed); - addToResults(results, "a_12"); - addToNodes( - nodes, - "linkIdentAName", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "linkIdentANameNot", rule.metadata.failed); - addToResults(results, "a_13"); - addToNodes( - nodes, - "linkIdentANameNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R48(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "elementHiddenFocus", rule.metadata.passed); - addToResults(results, "element_04"); - addToNodes( - nodes, - "elementHiddenFocus", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "elementNotHiddenFocus", rule.metadata.failed); - addToResults(results, "element_05"); - addToNodes( - nodes, - "elementNotHiddenFocus", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R62(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "seqFocus", rule.metadata.passed); - addToResults(results, "element_01"); - addToNodes( - nodes, - "seqFocus", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } -} -function QW_ACT_R65(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements( - elements, - "elementPresentChildrenNoFocus", - rule.metadata.passed - ); - addToResults(results, "element_08"); - addToNodes( - nodes, - "elementPresentChildrenNoFocus", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements( - elements, - "elementPresentChildrenFocus", - rule.metadata.failed - ); - addToResults(results, "element_09"); - addToNodes( - nodes, - "elementPresentChildrenFocus", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R66(elements: any, results: any, nodes: any, rule: any): void { - addToElements(elements, "menuItem", rule.results.length); - if (rule.metadata.outcome === "passed") { - addToElements(elements, "menuItemAName", rule.metadata.passed); - addToResults(results, "menuItem_01"); - addToNodes( - nodes, - "menuItemAName", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "menuItemANameNot", rule.metadata.failed); - addToResults(results, "menuItem_02"); - addToNodes( - nodes, - "menuItemANameNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R67(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "letterSpacing", rule.metadata.passed); - addToResults(results, "letter_01"); - addToNodes( - nodes, - "letterSpacing", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "letterSpacingNot", rule.metadata.failed); - addToResults(results, "letter_02"); - addToNodes( - nodes, - "letterSpacingNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R68(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "failed") { - addToElements(elements, "lineHeightNo", rule.metadata.failed); - addToResults(results, "css_01"); - addToNodes( - nodes, - "lineHeightNo", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R69(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "wordSpacing", rule.metadata.passed); - addToResults(results, "word_01"); - addToNodes( - nodes, - "wordSpacing", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "wordSpacingNot", rule.metadata.failed); - addToResults(results, "word_02"); - addToNodes( - nodes, - "wordSpacingNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R70(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "iframeNegTabIndex", rule.metadata.passed); - addToResults(results, "iframe_04"); - addToNodes( - nodes, - "iframeNegTabIndex", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "iframeNegTabIndexNot", rule.metadata.failed); - addToResults(results, "iframe_05"); - addToNodes( - nodes, - "iframeNegTabIndexNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R71(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "metaRefresh", rule.metadata.passed); - addToResults(results, "meta_03"); - addToNodes( - nodes, - "metaRefresh", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "metaRefreshNot", rule.metadata.failed); - addToResults(results, "meta_04"); - addToNodes( - nodes, - "metaRefreshNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} -function QW_ACT_R76(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "textContrastH", rule.metadata.passed); - addToResults(results, "textC_01"); - addToNodes( - nodes, - "textContrastH", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "textContrastHNot", rule.metadata.failed); - addToResults(results, "textC_02"); - addToNodes( - nodes, - "textContrastHNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_ACT_R77(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "ariaControlsIdFound", rule.metadata.passed); - addToResults(results, "aria_10"); - addToNodes( - nodes, - "ariaControlsIdFound", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "ariaControlsIdNotFound", rule.metadata.failed); - addToResults(results, "aria_09"); - addToNodes( - nodes, - "ariaControlsIdNotFound", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T1( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "areaAltNo", technique.metadata.failed); - addToResults(results, "area_01b"); - addToNodes( - nodes, - "areaAltNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } else if ( - technique.metadata.outcome === "passed" || - technique.metadata.outcome === "warning" - ) { - addToElements(elements, "areaAltYes", undefined); - addToResults(results, "area_01a"); - addToNodes( - nodes, - "areaAltYes", - technique.results.filter( - (r: any) => r.verdict === "passed" || r.verdict === "warning" - ) - ); - } -} - -function QW_WCAG_T2( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "tableDataCaption", technique.metadata.failed); - addToResults(results, "table_02"); - addToNodes( - nodes, - "tableDataCaption", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T3( - elements: any, - results: any, - nodes: any, - technique: any -): void { - const outsideFieldset = technique.results.filter( - (r: any) => r.resultCode === "W1" - ); - if (outsideFieldset.length !== 0) { - addToElements(elements, "fieldNoForm", outsideFieldset.length); - addToResults(results, "field_02"); - addToNodes(nodes, "fieldNoForm", outsideFieldset); - } - - const fieldsetNoLegend = technique.results.filter( - (r: any) => r.resultCode === "F1" || r.resultCode === "F2" - ); - if (fieldsetNoLegend.length !== 0) { - addToElements(elements, "fieldLegNo", fieldsetNoLegend.length); - addToResults(results, "field_01"); - addToNodes(nodes, "fieldLegNo", fieldsetNoLegend); - } -} - -function QW_WCAG_T6( - elements: any, - results: any, - nodes: any, - technique: any -): void { - const passed = technique.results.filter((r: any) => r.verdict === "passed"); - if (passed.length > 0) { - addToElements(elements, "ehandBoth", passed.length); - addToResults(results, "ehandler_03"); - addToNodes(nodes, "ehandBoth", passed); - } - - const failed = technique.results.filter((r: any) => r.verdict === "failed"); - if (failed.length > 0) { - addToElements(elements, "ehandBothNo", failed.length); - addToResults(results, "ehandler_02"); - addToNodes(nodes, "ehandBothNo", failed); - } -} - -function QW_WCAG_T7( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "abbrNo", technique.metadata.failed); - addToResults(results, "abbr_01"); - addToNodes( - nodes, - "abbrNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T8( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "imgAltNot", technique.metadata.failed); - addToResults(results, "img_03"); - addToNodes( - nodes, - "imgAltNot", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T9( - elements: any, - results: any, - nodes: any, - technique: any -): void { - const failsH1Results = technique.results.filter( - (r: any) => r.resultCode === "F3" - ); - if (failsH1Results.length > 0) { - addToElements(elements, "h1", undefined); - addToResults(results, "hx_01c"); - addToNodes(nodes, "h1", failsH1Results); - } - - const incorrectOrderResults = technique.results.filter( - (r: any) => r.resultCode === "F1" - ); - if (incorrectOrderResults.length > 0) { - addToElements(elements, "hxSkip", incorrectOrderResults.length); - addToResults(results, "hx_03"); - addToNodes(nodes, "hxSkip", incorrectOrderResults); - } -} - -function QW_WCAG_T14( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "tableComplexError", technique.metadata.failed); - addToResults(results, "table_06"); - addToNodes( - nodes, - "tableComplexError", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T15( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "linkRel", technique.metadata.failed); - addToResults(results, "link_01"); - addToNodes( - nodes, - "linkRel", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T16( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "w3cValidator", "true"); - addToElements(elements, "w3cValidatorErrors", technique.metadata.failed); - addToResults(results, "w3c_validator_01b"); - addToNodes( - nodes, - "w3cValidatorErrors", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } else if ( - technique.metadata.outcome === "passed" || - technique.metadata.outcome === "warning" - ) { - addToElements(elements, "w3cValidator", "true"); - addToElements(elements, "w3cValidatorErrorsNo", 0); - addToResults(results, "w3c_validator_01a"); - addToNodes( - nodes, - "w3cValidatorErrorsNo", - technique.results.filter( - (r: any) => r.verdict === "passed" || r.verdict === "warning" - ) - ); - } -} - -function QW_WCAG_T17( - elements: any, - results: any, - nodes: any, - technique: any -): void { - const incorrectLabelResults = technique.results.filter( - (r: any) => r.verdict === "failed" - ); - if (incorrectLabelResults.length > 0) { - addToElements(elements, "labelPosNo", incorrectLabelResults.length); - addToResults(results, "label_02"); - addToNodes(nodes, "labelPosNo", incorrectLabelResults); - } -} - -function QW_WCAG_T32( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "liNoList", technique.metadata.failed); - addToResults(results, "list_01"); - addToNodes( - nodes, - "liNoList", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T18( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "tableLayout", technique.metadata.failed); - addToResults(results, "table_05a"); - addToNodes( - nodes, - "tableLayout", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T19( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "formSubmit", undefined); - addToResults(results, "form_01a"); - addToNodes( - nodes, - "formSubmit", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } else if (technique.metadata.outcome === "failed") { - addToElements(elements, "formSubmitNo", technique.metadata.failed); - addToResults(results, "form_01b"); - addToNodes( - nodes, - "formSubmitNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T20( - elements: any, - results: any, - nodes: any, - technique: any -): void { - const titleMatchResults = technique.results.filter( - (r: any) => r.resultCode === "F2" - ); - if (titleMatchResults.length > 0) { - addToElements(elements, "aTitleMatch", titleMatchResults.length); - addToResults(results, "a_05"); - addToNodes(nodes, "aTitleMatch", titleMatchResults); - } -} - -function QW_WCAG_T21( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "aImgAltNo", technique.metadata.failed); - addToResults(results, "a_03"); - addToNodes( - nodes, - "aImgAltNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T22( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "newWinOnLoad", technique.metadata.failed); - addToResults(results, "win_01"); - addToNodes( - nodes, - "newWinOnLoad", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -/*function QW_WCAG_T37(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.outcome === 'warning') { - addToElements(elements, 'aSkip', technique.metadata.warning); - addToResults(results, 'a_02b'); - addToNodes(nodes, 'aSkip', technique.results.filter((r: any) => r.verdict === 'warning')); - } else if (technique.metadata.outcome === 'failed') { - addToElements(elements, 'aSkip', undefined); - addToResults(results, 'a_02a'); - addToNodes(nodes, 'aSkip', technique.results.filter((r: any) => r.verdict === 'failed')); - } -}*/ - -function QW_WCAG_T23( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "warning") { - addToElements(elements, "aSkipFirst", technique.metadata.warning); - addToResults(results, "a_01a"); - addToNodes( - nodes, - "aSkipFirst", - technique.results.filter((r: any) => r.verdict === "warning") - ); - } else if (technique.metadata.outcome === "failed") { - addToElements(elements, "aSkipFirstNo", technique.metadata.failed); - addToResults(results, "a_01b"); - addToNodes( - nodes, - "aSkipFirstNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T24( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "focusBlur", technique.metadata.failed); - addToResults(results, "focus_01"); - addToNodes( - nodes, - "focusBlur", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T25( - elements: any, - results: any, - nodes: any, - technique: any -): void { - const incorrectScope = technique.results.filter( - (r: any) => r.resultCode === "F2" || r.resultCode === "F3" - ); - if (incorrectScope.length > 0) { - addToElements(elements, "scopeNo", incorrectScope.length); - addToResults(results, "scope_01"); - addToNodes(nodes, "scopeNo", incorrectScope); - } -} - -function QW_WCAG_T26( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "ehandTagNo", technique.metadata.failed); - addToResults(results, "ehandler_04"); - addToNodes( - nodes, - "ehandTagNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T27( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "justifiedTxt", technique.metadata.failed); - addToResults(results, "justif_txt_01"); - addToNodes( - nodes, - "justifiedTxt", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T28( - elements: any, - results: any, - nodes: any, - technique: any -): void { - addToElements(elements, "fontValues", technique.results.length); - if (technique.metadata.outcome === "failed") { - addToElements(elements, "fontAbsVal", technique.metadata.failed); - addToResults(results, "font_02"); - addToNodes( - nodes, - "fontAbsVal", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T29( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "justifiedCss", technique.metadata.failed); - addToResults(results, "justif_txt_02"); - addToNodes( - nodes, - "justifiedCss", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T30( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "cssBlink", technique.metadata.failed); - addToResults(results, "blink_02"); - addToNodes(nodes, "cssBlink", [ - technique.results.filter((r) => r.verdict === "failed"), - ]); - } -} - -function QW_WCAG_T31( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "colorFgBgNo", technique.metadata.failed); - addToResults(results, "color_01"); - addToNodes( - nodes, - "colorFgBgNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - - -function QW_WCAG_T33( - elements: any, - results: any, - nodes: any, - technique: any -): void { - addToElements(elements, "dd,dt", technique.results.length); - - if (technique.metadata.outcome === "passed") { - addToElements(elements, "descListElement", technique.metadata.passed); - addToResults(results, "list_04"); - addToNodes( - nodes, - "descListElement", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } else if (technique.metadata.outcome === "failed") { - addToElements(elements, "notDescListElement", undefined); - addToResults(results, "list_05"); - addToNodes( - nodes, - "notDescListElement", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T34( - elements: any, - results: any, - nodes: any, - technique: any -): void { - addToElements(elements, "dl", technique.results.length); - if (technique.metadata.outcome === "passed") { - addToElements(elements, "descList", technique.metadata.passed); - addToResults(results, "list_06"); - addToNodes( - nodes, - "descList", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } else if (technique.metadata.outcome === "failed") { - addToElements(elements, "notDescList", undefined); - addToResults(results, "list_07"); - addToNodes( - nodes, - "notDescList", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_WCAG_T35(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "passed") { - addToElements(elements, "idAtt", rule.metadata.passed); - addToResults(results, "id_01"); - addToNodes( - nodes, - "idAtt", - rule.results.filter((r: any) => r.verdict === "passed") - ); - } else if (rule.metadata.outcome === "failed") { - addToElements(elements, "idAttNot", rule.metadata.failed); - addToResults(results, "id_02"); - addToNodes( - nodes, - "idAttNot", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP1(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "hxNone", technique.metadata.failed); - addToResults(results, "hx_01a"); - addToNodes(nodes, "hxNone", technique.results.filter((r: any) => r.verdict === "failed")); - } else if (technique.metadata.outcome === "warning") { - addToElements(elements, "hx", technique.metadata.warning); - addToResults(results, "hx_01b"); - addToNodes( - nodes, - "hx", - technique.results.filter((r: any) => r.verdict === "warning") - ); - } -} - -function QW_BP2(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "imgAltLong", technique.metadata.failed); - addToResults(results, "img_04"); - addToNodes( - nodes, - "imgAltLong", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP4(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "aGroupNo", technique.metadata.failed); - addToResults(results, "a_07"); - addToNodes( - nodes, - "aGroupNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP5(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "tableNested", technique.metadata.failed); - addToResults(results, "table_04"); - addToNodes( - nodes, - "tableNested", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP6(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "titleLong", technique.metadata.failed); - addToResults(results, "title_04"); - addToNodes( - nodes, - "titleLong", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP7(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "titleChars", technique.metadata.failed); - addToResults(results, "title_05"); - addToNodes( - nodes, - "titleChars", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP8(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "hxNo", technique.metadata.failed); - addToResults(results, "hx_02"); - addToNodes( - nodes, - "hxNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP9(elements: any, results: any, nodes: any, technique: any): void { - if (technique.metadata.passed > 0) { - addToElements(elements, "tableLayoutCaption", technique.metadata.passed); - addToResults(results, "table_01"); - addToNodes( - nodes, - "tableLayoutCaption", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } -} - -function QW_BP10( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "layoutElem", technique.metadata.failed); - addToResults(results, "layout_01b"); - addToNodes( - nodes, - "layoutElem", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } else if (technique.metadata.outcome === "passed") { - addToElements(elements, "layoutElemNo", undefined); - addToResults(results, "layout_01a"); - addToNodes(nodes, "layoutElemNo", undefined); - } -} - -function QW_BP11( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "brSec", technique.metadata.failed); - addToResults(results, "br_01"); - addToNodes( - nodes, - "brSec", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP13( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "aAdjacentSame", technique.metadata.failed); - addToResults(results, "a_06"); - addToNodes( - nodes, - "aAdjacentSame", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP14( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "layoutFixed", technique.metadata.failed); - addToResults(results, "layout_03"); - addToNodes( - nodes, - "layoutFixed", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP15( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "valueRelHtml", technique.metadata.passed); - addToResults(results, "values_01b"); - addToNodes( - nodes, - "valueRelHtml", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } else if (technique.metadata.outcome === "failed") { - addToElements(elements, "valueAbsHtml", technique.metadata.failed); - addToResults(results, "values_01a"); - addToNodes( - nodes, - "valueAbsHtml", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP17( - elements: any, - results: any, - nodes: any, - technique: any -): void { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "a", technique.results.length); - addToResults(results, "a_04"); - addToNodes(nodes, "a", []); - } else { - addToElements(elements, "a", technique.results.length); - addToNodes(nodes, "a", technique.results); - } - - if (technique.metadata.outcome === "warning") { - addToElements(elements, "aSkip", technique.metadata.warning); - addToResults(results, "a_02b"); - addToNodes( - nodes, - "aSkip", - technique.results.filter((r: any) => r.verdict === "warning") - ); - } else if (technique.metadata.outcome === "failed") { - addToElements(elements, "aSkipNo", technique.metadata.failed); - addToResults(results, "a_02a"); - addToNodes( - nodes, - "aSkipNo", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } -} - -function QW_BP18(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "failed") { - addToElements(elements, "valueAbsCss", technique.metadata.failed); - addToResults(results, "values_02a"); - addToNodes( - nodes, - "valueAbsCss", - technique.results.filter((r: any) => r.verdict === "failed") - ); - } - if (technique.metadata.passed > 0) { - addToElements(elements, "valueRelCss", technique.metadata.passed); - addToResults(results, "values_02b"); - addToNodes(nodes, "valueRelCss", [ - technique.results.filter((r) => r.verdict === "passed"), - ]); - } -} - -function QW_BP19(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "bannerTopLevel", technique.metadata.passed); - addToResults(results, "landmark_01"); - addToNodes( - nodes, - "bannerTopLevel", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "bannerNotTopLevel", technique.metadata.failed); - addToResults(results, "landmark_02"); - addToNodes(nodes, "bannerNotTopLevel", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP20(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "noDuplicateBanner", technique.metadata.passed); - addToResults(results, "landmark_09"); - addToNodes( - nodes, - "noDuplicateBanner", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "duplicateBanner", technique.metadata.failed); - addToResults(results, "landmark_10"); - addToNodes(nodes, "duplicateBanner", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP21(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "noDuplicateContentinfo", technique.metadata.passed); - addToResults(results, "landmark_11"); - addToNodes( - nodes, - "noDuplicateContentinfo", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "duplicateContentinfo", technique.metadata.failed); - addToResults(results, "landmark_12"); - addToNodes(nodes, "duplicateContentinfo", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP22(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "noDuplicateMain", technique.metadata.passed); - addToResults(results, "landmark_13"); - addToNodes( - nodes, - "noDuplicateMain", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "duplicateMain", technique.metadata.failed); - addToResults(results, "landmark_14"); - addToNodes(nodes, "duplicateMain", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP23(elements: any, results: any, nodes: any, technique: any) { - addToElements(elements, "li", technique.results.length); - if (technique.metadata.outcome === "passed") { - addToElements(elements, "liSemantically", technique.metadata.passed); - addToResults(results, "listitem_01"); - addToNodes( - nodes, - "liSemantically", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "liNotSemantically", technique.metadata.failed); - addToResults(results, "listitem_02"); - addToNodes(nodes, "liNotSemantically", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP24(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "listCorrectly", technique.metadata.passed); - addToResults(results, "list_02"); - addToNodes( - nodes, - "listCorrectly", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "listNotCorrectly", technique.metadata.failed); - addToResults(results, "list_03"); - addToNodes(nodes, "listNotCorrectly", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP25(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "complementaryTopLevel", technique.metadata.passed); - addToResults(results, "landmark_03"); - addToNodes( - nodes, - "complementaryTopLevel", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "complementaryNotTopLevel", technique.metadata.failed); - addToResults(results, "landmark_04"); - addToNodes(nodes, "complementaryNotTopLevel", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP26(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "contentinfoTopLevel", technique.metadata.passed); - addToResults(results, "landmark_05"); - addToNodes( - nodes, - "contentinfoTopLevel", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "contentinfoNotTopLevel", technique.metadata.failed); - addToResults(results, "landmark_06"); - addToNodes(nodes, "contentinfoNotTopLevel", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP27(elements: any, results: any, nodes: any, technique: any) { - if (technique.metadata.outcome === "passed") { - addToElements(elements, "mainTopLevel", technique.metadata.passed); - addToResults(results, "landmark_07"); - addToNodes( - nodes, - "mainTopLevel", - technique.results.filter((r: any) => r.verdict === "passed") - ); - } - else if (technique.metadata.outcome === "failed") { - addToElements(elements, "mainNotTopLevel", technique.metadata.failed); - addToResults(results, "landmark_08"); - addToNodes(nodes, "mainNotTopLevel", - technique.results.filter((r) => r.verdict === "failed")); - } -} - -function QW_BP29(elements: any, results: any, nodes: any, rule: any): void { - if (rule.metadata.outcome === "failed") { - addToElements(elements, "langMatchNo", rule.metadata.failed); - addToResults(results, "lang_04"); - addToNodes( - nodes, - "langMatchNo", - rule.results.filter((r: any) => r.verdict === "failed") - ); - } -} - - -function addToElements( - elements: any, - key: string, - value: string | number -): void { - if (elements[key] === undefined) { - elements[key] = value; - } else { - elements[key] += value; - } -} - -function addToResults(results: any, key: string): void { - results[key] = "something"; -} - -function addToNodes(nodes: any, key: string, elements: any[]): void { - nodes[key] = elements; -} - -export function getElementsMapping(evaluation: any): any { - const elements = {}; - const results = {}; - const nodes = {}; - for (const rule of Object.keys(evaluation.modules["act-rules"].assertions) || - []) { - if (act_mapping[rule] !== undefined) { - act_mapping[rule]( - elements, - results, - nodes, - evaluation.modules["act-rules"].assertions[rule] - ); - } - } - - for (const technique of Object.keys( - evaluation.modules["wcag-techniques"].assertions - ) || []) { - if (wcag_mapping[technique] !== undefined) { - wcag_mapping[technique]( - elements, - results, - nodes, - evaluation.modules["wcag-techniques"].assertions[technique] - ); - // if (technique === "QW-WCAG-T9") - // console.log(technique, "\n*\n", evaluation.modules["wcag-techniques"].assertions[technique]) - } - } - - for (const technique of Object.keys( - evaluation.modules["best-practices"].assertions - ) || []) { - if (bp_mapping[technique] !== undefined) { - bp_mapping[technique]( - elements, - results, - nodes, - evaluation.modules["best-practices"].assertions[technique] - ); - } - } - - return { elements, results, nodes }; -} +const act_mapping = { + "QW-ACT-R1": QW_ACT_R1, + "QW-ACT-R2": QW_ACT_R2, + "QW-ACT-R4": QW_ACT_R4, + "QW-ACT-R5": QW_ACT_R5, + "QW-ACT-R6": QW_ACT_R6, + "QW-ACT-R7": QW_ACT_R7, + "QW-ACT-R9": QW_ACT_R9, + "QW-ACT-R10": QW_ACT_R10, + "QW-ACT-R11": QW_ACT_R11, + "QW-ACT-R12": QW_ACT_R12, + "QW-ACT-R13": QW_ACT_R13, + "QW-ACT-R14": QW_ACT_R14, + "QW-ACT-R15": QW_ACT_R15, + "QW-ACT-R16": QW_ACT_R16, + "QW-ACT-R17": QW_ACT_R17, + "QW-ACT-R19": QW_ACT_R19, + "QW-ACT-R20": QW_ACT_R20, + "QW-ACT-R21": QW_ACT_R21, + "QW-ACT-R22": QW_ACT_R22, + "QW-ACT-R23": QW_ACT_R23, + "QW-ACT-R24": QW_ACT_R24, + "QW-ACT-R25": QW_ACT_R25, + "QW-ACT-R26": QW_ACT_R26, + "QW-ACT-R27": QW_ACT_R27, + "QW-ACT-R28": QW_ACT_R28, + "QW-ACT-R30": QW_ACT_R30, + "QW-ACT-R33": QW_ACT_R33, + "QW-ACT-R34": QW_ACT_R34, + "QW-ACT-R35": QW_ACT_R35, + "QW-ACT-R36": QW_ACT_R36, + "QW-ACT-R37": QW_ACT_R37, + "QW-ACT-R38": QW_ACT_R38, + "QW-ACT-R39": QW_ACT_R39, + "QW-ACT-R40": QW_ACT_R40, + "QW-ACT-R42": QW_ACT_R42, + "QW-ACT-R43": QW_ACT_R43, + "QW-ACT-R44": QW_ACT_R44, + "QW-ACT-R48": QW_ACT_R48, + "QW-ACT-R62": QW_ACT_R62, + "QW-ACT-R65": QW_ACT_R65, + "QW-ACT-R66": QW_ACT_R66, + "QW-ACT-R67": QW_ACT_R67, + "QW-ACT-R68": QW_ACT_R68, + "QW-ACT-R69": QW_ACT_R69, + "QW-ACT-R70": QW_ACT_R70, + "QW-ACT-R71": QW_ACT_R71, + "QW-ACT-R76": QW_ACT_R76, + "QW-ACT-R77": QW_ACT_R77, +}; + +const wcag_mapping = { + "QW-WCAG-T1": QW_WCAG_T1, + "QW-WCAG-T2": QW_WCAG_T2, + "QW-WCAG-T3": QW_WCAG_T3, + "QW-WCAG-T6": QW_WCAG_T6, + "QW-WCAG-T7": QW_WCAG_T7, + "QW-WCAG-T8": QW_WCAG_T8, + "QW-WCAG-T9": QW_WCAG_T9, + "QW-WCAG-T14": QW_WCAG_T14, + "QW-WCAG-T15": QW_WCAG_T15, + "QW-WCAG-T16": QW_WCAG_T16, + "QW-WCAG-T17": QW_WCAG_T17, + "QW-WCAG-T18": QW_WCAG_T18, + "QW-WCAG-T19": QW_WCAG_T19, + "QW-WCAG-T20": QW_WCAG_T20, + "QW-WCAG-T21": QW_WCAG_T21, + "QW-WCAG-T22": QW_WCAG_T22, + "QW-WCAG-T23": QW_WCAG_T23, + "QW-WCAG-T24": QW_WCAG_T24, + "QW-WCAG-T25": QW_WCAG_T25, + "QW-WCAG-T26": QW_WCAG_T26, + "QW-WCAG-T27": QW_WCAG_T27, + "QW-WCAG-T28": QW_WCAG_T28, + "QW-WCAG-T29": QW_WCAG_T29, + "QW-WCAG-T30": QW_WCAG_T30, + "QW-WCAG-T31": QW_WCAG_T31, + "QW-WCAG-T33": QW_WCAG_T33, + "QW-WCAG-T34": QW_WCAG_T34, + "QW-WCAG-T35": QW_WCAG_T35, +}; + +const bp_mapping = { + "QW-BP1": QW_BP1, + "QW-BP2": QW_BP2, + "QW-BP4": QW_BP4, + "QW-BP5": QW_BP5, + "QW-BP6": QW_BP6, + "QW-BP7": QW_BP7, + "QW-BP8": QW_BP8, + "QW-BP9": QW_BP9, + "QW-BP10": QW_BP10, + "QW-BP11": QW_BP11, + "QW-BP13": QW_BP13, + "QW-BP14": QW_BP14, + // "QW-BP15": QW_BP15, + "QW-BP17": QW_BP17, + // "QW-BP18": QW_BP18, + "QW-BP19": QW_BP19, + "QW-BP20": QW_BP20, + "QW-BP21": QW_BP21, + "QW-BP22": QW_BP22, + "QW-BP23": QW_BP23, + "QW-BP24": QW_BP24, + "QW-BP25": QW_BP25, + "QW-BP26": QW_BP26, + "QW-BP27": QW_BP27, + "QW-BP29": QW_BP29, +}; + +function QW_ACT_R1(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "failed") { + const noTitle = rule.results.filter((r: any) => r.resultCode === "F1"); + if (noTitle.length !== 0) { + addToElements(elements, "titleNo", noTitle.length); + addToResults(results, "title_02"); + addToNodes(nodes, "titleNo", null); + } + + const titleEmpty = rule.results.filter((r: any) => r.resultCode === "F2"); + if (titleEmpty.length !== 0) { + addToElements(elements, "titleNull", titleEmpty.length); + addToResults(results, "title_03"); + addToNodes(nodes, "titleNull", titleEmpty); + } + } else if (rule.metadata.outcome === "passed") { + addToElements(elements, "titleOk", rule.metadata.passed); + addToResults(results, "title_06"); + addToNodes( + nodes, + "titleOk", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} + +function QW_ACT_R2(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "failed") { + addToElements(elements, "langNo", rule.metadata.failed); + addToResults(results, "lang_03"); + addToNodes( + nodes, + "langNo", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } else if (rule.metadata.outcome === "passed") { + addToElements(elements, "lang", rule.metadata.passed); + addToResults(results, "lang_01"); + addToNodes( + nodes, + "lang", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} + +function QW_ACT_R4(elements: any, results: any, nodes: any, rule: any): void { + const failRefresh = rule.results.filter((r: any) => r.resultCode === "F1"); + if (failRefresh.length !== 0) { + addToElements(elements, "metaRefresh", failRefresh.length); + addToResults(results, "meta_01"); + addToNodes(nodes, "metaRefresh", failRefresh); + } + + const failRedirect = rule.results.filter((r: any) => r.resultCode === "F2"); + if (failRedirect.length !== 0) { + addToElements(elements, "metaRedir", failRedirect.length); + addToResults(results, "meta_02"); + addToNodes(nodes, "metaRedir", failRedirect); + } +} + +function QW_ACT_R5(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "failed") { + addToElements(elements, "langCodeNo", "lang"); + addToResults(results, "lang_02"); + addToNodes( + nodes, + "langCodeNo", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R6(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "inpImgAltYes", undefined); + addToResults(results, "inp_img_01a"); + addToNodes( + nodes, + "inpImgAltYes", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "inpImgAltNo", rule.metadata.failed); + addToResults(results, "inp_img_01b"); + addToNodes( + nodes, + "inpImgAltNo", + rule.results.filter((r: any) => r.verdict === "failed") + ); + addToElements( + elements, + "inp_img_01b", + rule.results.filter((r: any) => r.verdict !== "inapplicable").length + ); + } +} +function QW_ACT_R7(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "orientationCSS", rule.metadata.passed); + addToResults(results, "orientation_01"); + addToNodes( + nodes, + "orientationCSS", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "orientationCSSNot", rule.metadata.failed); + addToResults(results, "orientation_02"); + addToNodes( + nodes, + "orientationCSSNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R9(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "warning") { + addToElements(elements, "aSameText", rule.metadata.warning); + addToResults(results, "a_09"); + addToNodes( + nodes, + "aSameText", + rule.results.filter((r: any) => r.verdict === "warning") + ); + } +} +function QW_ACT_R10(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "iframeSame", rule.results.length); + if (rule.metadata.outcome === "passed") { + addToElements(elements, "iframeSameAName", rule.metadata.passed); + addToResults(results, "iframe_02"); + addToNodes( + nodes, + "iframeSameAName", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "iframeSameANameDiferent", rule.metadata.failed); + addToResults(results, "iframe_03"); + addToNodes( + nodes, + "iframeSameANameDiferent", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R11(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "button", rule.results.length); + if (rule.metadata.outcome === "passed") { + addToElements(elements, "buttonAname", rule.metadata.passed); + addToResults(results, "button_01"); + addToNodes( + nodes, + "buttonAname", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "buttonNotAname", rule.metadata.failed); + addToResults(results, "button_02"); + addToNodes( + nodes, + "buttonNotAname", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R12(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "a", rule.results.length); + if (rule.metadata.outcome === "passed") { + addToElements(elements, "linkAName", rule.metadata.passed); + addToResults(results, "a_10"); + addToNodes( + nodes, + "linkAName", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "linkNotAName", rule.metadata.failed); + addToResults(results, "a_11"); + addToNodes( + nodes, + "linkNotAName", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R13(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "elementDec", rule.metadata.passed); + addToResults(results, "element_02"); + addToNodes( + nodes, + "elementDec", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "elementNotDec", rule.metadata.failed); + addToResults(results, "element_03"); + addToNodes( + nodes, + "elementNotDec", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R14(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "metaViewport", rule.metadata.passed); + addToResults(results, "meta_05"); + addToNodes( + nodes, + "metaViewport", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} +function QW_ACT_R15(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "audioAvoidsAutoPlay", undefined); + addToResults(results, "audio_video_01"); + addToNodes( + nodes, + "audioAvoidsAutoPlay", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "audioAutoPlay", rule.metadata.failed); + addToResults(results, "audio_video_02"); + addToNodes( + nodes, + "audioAutoPlay", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R16(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "inputLabel", undefined); + addToResults(results, "input_02b"); + addToNodes( + nodes, + "inputLabel", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "inputLabelNo", rule.metadata.failed); + addToResults(results, "input_02"); + addToNodes( + nodes, + "inputLabelNo", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R17(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "img", rule.results.length); + if (rule.metadata.outcome === "passed") { + addToElements(elements, "imgAlt", undefined); + addToResults(results, "img_01a"); + addToNodes( + nodes, + "imgAlt", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "imgAltNo", rule.metadata.failed); + addToResults(results, "img_01b"); + addToNodes( + nodes, + "imgAltNo", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } + + const imgEmptyAlt = rule.results.filter((r: any) => r.resultCode === "P1"); + + if (imgEmptyAlt.length > 0) { + addToElements(elements, "imgAltNull", imgEmptyAlt.length); + addToResults(results, "img_02"); + addToNodes(nodes, "imgAltNull", imgEmptyAlt); + } +} + +function QW_ACT_R19(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "failed") { + addToElements(elements, "iframeTitleNo", rule.metadata.failed); + addToResults(results, "iframe_01"); + addToNodes( + nodes, + "iframeTitleNo", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R21(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "svg", rule.results.length); + if (rule.metadata.outcome === "passed") { + addToElements(elements, "svgAName", rule.metadata.passed); + addToResults(results, "svg_01"); + addToNodes( + nodes, + "svgAName", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "svgNotAName", rule.metadata.failed); + addToResults(results, "svg_02"); + addToNodes( + nodes, + "svgNotAName", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R20(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "roleValid", rule.metadata.passed); + addToResults(results, "role_01"); + addToNodes( + nodes, + "roleValid", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "roleValidNot", rule.metadata.failed); + addToResults(results, "role_02"); + addToNodes( + nodes, + "roleValidNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R22(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "elementLang", rule.metadata.passed); + addToResults(results, "element_06"); + addToNodes( + nodes, + "elementLang", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "elementNotLang", rule.metadata.failed); + addToResults(results, "element_07"); + addToNodes( + nodes, + "elementNotLang", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R23(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "videoVisual", rule.metadata.passed); + addToResults(results, "video_02"); + addToNodes( + nodes, + "videoVisual", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} +function QW_ACT_R24(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "autoCmpltValid", rule.metadata.passed); + addToResults(results, "autocomplete_01"); + addToNodes( + nodes, + "autoCmpltValid", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "autoCmpltNotValid", rule.metadata.failed); + addToResults(results, "autocomplete_02"); + addToNodes( + nodes, + "autoCmpltNotValid", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R25(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "ariaStPermitted", rule.metadata.passed); + addToResults(results, "aria_05"); + addToNodes( + nodes, + "ariaStPermitted", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "ariaStNotPermitted", rule.metadata.failed); + addToResults(results, "aria_06"); + addToNodes( + nodes, + "ariaStNotPermitted", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R26(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "videoAudit", rule.metadata.passed); + addToResults(results, "video_01"); + addToNodes( + nodes, + "videoAudit", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} +function QW_ACT_R27(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "ariaAtribDefined", rule.metadata.passed); + addToResults(results, "aria_07"); + addToNodes( + nodes, + "ariaAtribDefined", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "ariaAtribNotDefined", rule.metadata.failed); + addToResults(results, "aria_08"); + addToNodes( + nodes, + "ariaAtribNotDefined", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R28(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "elementRole", rule.metadata.passed); + addToResults(results, "element_10"); + addToNodes( + nodes, + "elementRole", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} +function QW_ACT_R30(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "labelAName", rule.metadata.passed); + addToResults(results, "label_01"); + addToNodes( + nodes, + "labelAName", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "labelANameNot", rule.metadata.failed); + addToResults(results, "label_03"); + addToNodes( + nodes, + "labelANameNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R33(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "ariaCntxRole", rule.metadata.passed); + addToResults(results, "aria_01"); + addToNodes( + nodes, + "ariaCntxRole", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} +function QW_ACT_R34(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "ariaStValid", rule.metadata.passed); + addToResults(results, "aria_03"); + addToNodes( + nodes, + "ariaStValid", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "ariaStNotValid", rule.metadata.failed); + addToResults(results, "aria_04"); + addToNodes( + nodes, + "ariaStNotValid", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R35(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "hxHasAName", rule.metadata.passed); + addToResults(results, "heading_01"); + addToNodes( + nodes, + "hxHasAName", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "hxWithoutAName", rule.metadata.failed); + addToResults(results, "heading_02"); + addToNodes( + nodes, + "hxWithoutAName", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R36(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "headers", rule.results.length); + if (rule.metadata.outcome === "passed") { + addToElements(elements, "headerAtt", rule.metadata.passed); + addToResults(results, "headers_01"); + addToNodes( + nodes, + "headerAtt", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "headerAttNot", rule.metadata.failed); + addToResults(results, "headers_02"); + addToNodes( + nodes, + "headerAttNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R37(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "id", rule.results.length); + if (rule.metadata.outcome === "failed") { + addToElements(elements, "colorContrast", rule.metadata.failed); + addToResults(results, "color_02"); + addToNodes( + nodes, + "colorContrast", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R38(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "ariaReqElem", rule.metadata.passed); + addToResults(results, "aria_02"); + addToNodes( + nodes, + "ariaReqElem", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} +function QW_ACT_R39(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "tableHdr", rule.metadata.passed); + addToResults(results, "table_07"); + addToNodes( + nodes, + "tableHdr", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "tableHdrNot", rule.metadata.failed); + addToResults(results, "table_08"); + addToNodes( + nodes, + "tableHdrNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R40(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "overflow", rule.metadata.passed); + addToResults(results, "css_02"); + addToNodes( + nodes, + "overflow", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} +function QW_ACT_R42(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "objectAName", rule.metadata.passed); + addToResults(results, "object_01"); + addToNodes( + nodes, + "objectAName", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "objectANameNot", rule.metadata.failed); + addToResults(results, "object_02"); + addToNodes( + nodes, + "objectANameNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R43(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "scrollable", rule.results.length); + if (rule.metadata.outcome === "passed") { + addToElements(elements, "scrollableAccess", rule.metadata.passed); + addToResults(results, "scrollable_01"); + addToNodes( + nodes, + "scrollableAccess", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "scrollableAccessNot", rule.metadata.failed); + addToResults(results, "scrollable_02"); + addToNodes( + nodes, + "scrollableAccessNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R44(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "linkIdentAName", rule.metadata.passed); + addToResults(results, "a_12"); + addToNodes( + nodes, + "linkIdentAName", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "linkIdentANameNot", rule.metadata.failed); + addToResults(results, "a_13"); + addToNodes( + nodes, + "linkIdentANameNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R48(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "elementHiddenFocus", rule.metadata.passed); + addToResults(results, "element_04"); + addToNodes( + nodes, + "elementHiddenFocus", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "elementNotHiddenFocus", rule.metadata.failed); + addToResults(results, "element_05"); + addToNodes( + nodes, + "elementNotHiddenFocus", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R62(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "seqFocus", rule.metadata.passed); + addToResults(results, "element_01"); + addToNodes( + nodes, + "seqFocus", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } +} +function QW_ACT_R65(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements( + elements, + "elementPresentChildrenNoFocus", + rule.metadata.passed + ); + addToResults(results, "element_08"); + addToNodes( + nodes, + "elementPresentChildrenNoFocus", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements( + elements, + "elementPresentChildrenFocus", + rule.metadata.failed + ); + addToResults(results, "element_09"); + addToNodes( + nodes, + "elementPresentChildrenFocus", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R66(elements: any, results: any, nodes: any, rule: any): void { + addToElements(elements, "menuItem", rule.results.length); + if (rule.metadata.outcome === "passed") { + addToElements(elements, "menuItemAName", rule.metadata.passed); + addToResults(results, "menuItem_01"); + addToNodes( + nodes, + "menuItemAName", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "menuItemANameNot", rule.metadata.failed); + addToResults(results, "menuItem_02"); + addToNodes( + nodes, + "menuItemANameNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R67(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "letterSpacing", rule.metadata.passed); + addToResults(results, "letter_01"); + addToNodes( + nodes, + "letterSpacing", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "letterSpacingNot", rule.metadata.failed); + addToResults(results, "letter_02"); + addToNodes( + nodes, + "letterSpacingNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R68(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "failed") { + addToElements(elements, "lineHeightNo", rule.metadata.failed); + addToResults(results, "css_01"); + addToNodes( + nodes, + "lineHeightNo", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R69(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "wordSpacing", rule.metadata.passed); + addToResults(results, "word_01"); + addToNodes( + nodes, + "wordSpacing", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "wordSpacingNot", rule.metadata.failed); + addToResults(results, "word_02"); + addToNodes( + nodes, + "wordSpacingNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R70(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "iframeNegTabIndex", rule.metadata.passed); + addToResults(results, "iframe_04"); + addToNodes( + nodes, + "iframeNegTabIndex", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "iframeNegTabIndexNot", rule.metadata.failed); + addToResults(results, "iframe_05"); + addToNodes( + nodes, + "iframeNegTabIndexNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R71(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "metaRefresh", rule.metadata.passed); + addToResults(results, "meta_03"); + addToNodes( + nodes, + "metaRefresh", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "metaRefreshNot", rule.metadata.failed); + addToResults(results, "meta_04"); + addToNodes( + nodes, + "metaRefreshNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} +function QW_ACT_R76(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "textContrastH", rule.metadata.passed); + addToResults(results, "textC_01"); + addToNodes( + nodes, + "textContrastH", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "textContrastHNot", rule.metadata.failed); + addToResults(results, "textC_02"); + addToNodes( + nodes, + "textContrastHNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_ACT_R77(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "ariaControlsIdFound", rule.metadata.passed); + addToResults(results, "aria_10"); + addToNodes( + nodes, + "ariaControlsIdFound", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "ariaControlsIdNotFound", rule.metadata.failed); + addToResults(results, "aria_09"); + addToNodes( + nodes, + "ariaControlsIdNotFound", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T1( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "areaAltNo", technique.metadata.failed); + addToResults(results, "area_01b"); + addToNodes( + nodes, + "areaAltNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } else if ( + technique.metadata.outcome === "passed" || + technique.metadata.outcome === "warning" + ) { + addToElements(elements, "areaAltYes", undefined); + addToResults(results, "area_01a"); + addToNodes( + nodes, + "areaAltYes", + technique.results.filter( + (r: any) => r.verdict === "passed" || r.verdict === "warning" + ) + ); + } +} + +function QW_WCAG_T2( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "tableDataCaption", technique.metadata.failed); + addToResults(results, "table_02"); + addToNodes( + nodes, + "tableDataCaption", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T3( + elements: any, + results: any, + nodes: any, + technique: any +): void { + const outsideFieldset = technique.results.filter( + (r: any) => r.resultCode === "W1" + ); + if (outsideFieldset.length !== 0) { + addToElements(elements, "fieldNoForm", outsideFieldset.length); + addToResults(results, "field_02"); + addToNodes(nodes, "fieldNoForm", outsideFieldset); + } + + const fieldsetNoLegend = technique.results.filter( + (r: any) => r.resultCode === "F1" || r.resultCode === "F2" + ); + if (fieldsetNoLegend.length !== 0) { + addToElements(elements, "fieldLegNo", fieldsetNoLegend.length); + addToResults(results, "field_01"); + addToNodes(nodes, "fieldLegNo", fieldsetNoLegend); + } +} + +function QW_WCAG_T6( + elements: any, + results: any, + nodes: any, + technique: any +): void { + const passed = technique.results.filter((r: any) => r.verdict === "passed"); + if (passed.length > 0) { + addToElements(elements, "ehandBoth", passed.length); + addToResults(results, "ehandler_03"); + addToNodes(nodes, "ehandBoth", passed); + } + + const failed = technique.results.filter((r: any) => r.verdict === "failed"); + if (failed.length > 0) { + addToElements(elements, "ehandBothNo", failed.length); + addToResults(results, "ehandler_02"); + addToNodes(nodes, "ehandBothNo", failed); + } +} + +function QW_WCAG_T7( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "abbrNo", technique.metadata.failed); + addToResults(results, "abbr_01"); + addToNodes( + nodes, + "abbrNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T8( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "imgAltNot", technique.metadata.failed); + addToResults(results, "img_03"); + addToNodes( + nodes, + "imgAltNot", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T9( + elements: any, + results: any, + nodes: any, + technique: any +): void { + const failsH1Results = technique.results.filter( + (r: any) => r.resultCode === "F3" + ); + if (failsH1Results.length > 0) { + addToElements(elements, "h1", undefined); + addToResults(results, "hx_01c"); + addToNodes(nodes, "h1", failsH1Results); + } + + const incorrectOrderResults = technique.results.filter( + (r: any) => r.resultCode === "F1" + ); + if (incorrectOrderResults.length > 0) { + addToElements(elements, "hxSkip", incorrectOrderResults.length); + addToResults(results, "hx_03"); + addToNodes(nodes, "hxSkip", incorrectOrderResults); + } +} + +function QW_WCAG_T14( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "tableComplexError", technique.metadata.failed); + addToResults(results, "table_06"); + addToNodes( + nodes, + "tableComplexError", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T15( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "linkRel", technique.metadata.failed); + addToResults(results, "link_01"); + addToNodes( + nodes, + "linkRel", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T16( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "w3cValidator", "true"); + addToElements(elements, "w3cValidatorErrors", technique.metadata.failed); + addToResults(results, "w3c_validator_01b"); + addToNodes( + nodes, + "w3cValidatorErrors", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } else if ( + technique.metadata.outcome === "passed" || + technique.metadata.outcome === "warning" + ) { + addToElements(elements, "w3cValidator", "true"); + addToElements(elements, "w3cValidatorErrorsNo", 0); + addToResults(results, "w3c_validator_01a"); + addToNodes( + nodes, + "w3cValidatorErrorsNo", + technique.results.filter( + (r: any) => r.verdict === "passed" || r.verdict === "warning" + ) + ); + } +} + +function QW_WCAG_T17( + elements: any, + results: any, + nodes: any, + technique: any +): void { + const incorrectLabelResults = technique.results.filter( + (r: any) => r.verdict === "failed" + ); + if (incorrectLabelResults.length > 0) { + addToElements(elements, "labelPosNo", incorrectLabelResults.length); + addToResults(results, "label_02"); + addToNodes(nodes, "labelPosNo", incorrectLabelResults); + } +} + +function QW_WCAG_T32( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "liNoList", technique.metadata.failed); + addToResults(results, "list_01"); + addToNodes( + nodes, + "liNoList", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T18( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "tableLayout", technique.metadata.failed); + addToResults(results, "table_05a"); + addToNodes( + nodes, + "tableLayout", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T19( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "formSubmit", undefined); + addToResults(results, "form_01a"); + addToNodes( + nodes, + "formSubmit", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "formSubmitNo", technique.metadata.failed); + addToResults(results, "form_01b"); + addToNodes( + nodes, + "formSubmitNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T20( + elements: any, + results: any, + nodes: any, + technique: any +): void { + const titleMatchResults = technique.results.filter( + (r: any) => r.resultCode === "F2" + ); + if (titleMatchResults.length > 0) { + addToElements(elements, "aTitleMatch", titleMatchResults.length); + addToResults(results, "a_05"); + addToNodes(nodes, "aTitleMatch", titleMatchResults); + } +} + +function QW_WCAG_T21( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "aImgAltNo", technique.metadata.failed); + addToResults(results, "a_03"); + addToNodes( + nodes, + "aImgAltNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T22( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "newWinOnLoad", technique.metadata.failed); + addToResults(results, "win_01"); + addToNodes( + nodes, + "newWinOnLoad", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +/*function QW_WCAG_T37(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.outcome === 'warning') { + addToElements(elements, 'aSkip', technique.metadata.warning); + addToResults(results, 'a_02b'); + addToNodes(nodes, 'aSkip', technique.results.filter((r: any) => r.verdict === 'warning')); + } else if (technique.metadata.outcome === 'failed') { + addToElements(elements, 'aSkip', undefined); + addToResults(results, 'a_02a'); + addToNodes(nodes, 'aSkip', technique.results.filter((r: any) => r.verdict === 'failed')); + } +}*/ + +function QW_WCAG_T23( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "warning") { + addToElements(elements, "aSkipFirst", technique.metadata.warning); + addToResults(results, "a_01a"); + addToNodes( + nodes, + "aSkipFirst", + technique.results.filter((r: any) => r.verdict === "warning") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "aSkipFirstNo", technique.metadata.failed); + addToResults(results, "a_01b"); + addToNodes( + nodes, + "aSkipFirstNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T24( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "focusBlur", technique.metadata.failed); + addToResults(results, "focus_01"); + addToNodes( + nodes, + "focusBlur", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T25( + elements: any, + results: any, + nodes: any, + technique: any +): void { + const incorrectScope = technique.results.filter( + (r: any) => r.resultCode === "F2" || r.resultCode === "F3" + ); + if (incorrectScope.length > 0) { + addToElements(elements, "scopeNo", incorrectScope.length); + addToResults(results, "scope_01"); + addToNodes(nodes, "scopeNo", incorrectScope); + } +} + +function QW_WCAG_T26( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "ehandTagNo", technique.metadata.failed); + addToResults(results, "ehandler_04"); + addToNodes( + nodes, + "ehandTagNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T27( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "justifiedTxt", technique.metadata.failed); + addToResults(results, "justif_txt_01"); + addToNodes( + nodes, + "justifiedTxt", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T28( + elements: any, + results: any, + nodes: any, + technique: any +): void { + addToElements(elements, "fontValues", technique.results.length); + if (technique.metadata.outcome === "failed") { + addToElements(elements, "fontAbsVal", technique.metadata.failed); + addToResults(results, "font_02"); + addToNodes( + nodes, + "fontAbsVal", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T29( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "justifiedCss", technique.metadata.failed); + addToResults(results, "justif_txt_02"); + addToNodes( + nodes, + "justifiedCss", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T30( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "cssBlink", technique.metadata.failed); + addToResults(results, "blink_02"); + addToNodes(nodes, "cssBlink", [ + technique.results.filter((r) => r.verdict === "failed"), + ]); + } +} + +function QW_WCAG_T31( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "colorFgBgNo", technique.metadata.failed); + addToResults(results, "color_01"); + addToNodes( + nodes, + "colorFgBgNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T33( + elements: any, + results: any, + nodes: any, + technique: any +): void { + addToElements(elements, "dd,dt", technique.results.length); + + if (technique.metadata.outcome === "passed") { + addToElements(elements, "descListElement", technique.metadata.passed); + addToResults(results, "list_04"); + addToNodes( + nodes, + "descListElement", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "notDescListElement", undefined); + addToResults(results, "list_05"); + addToNodes( + nodes, + "notDescListElement", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T34( + elements: any, + results: any, + nodes: any, + technique: any +): void { + addToElements(elements, "dl", technique.results.length); + if (technique.metadata.outcome === "passed") { + addToElements(elements, "descList", technique.metadata.passed); + addToResults(results, "list_06"); + addToNodes( + nodes, + "descList", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "notDescList", undefined); + addToResults(results, "list_07"); + addToNodes( + nodes, + "notDescList", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_WCAG_T35(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "passed") { + addToElements(elements, "idAtt", rule.metadata.passed); + addToResults(results, "id_01"); + addToNodes( + nodes, + "idAtt", + rule.results.filter((r: any) => r.verdict === "passed") + ); + } else if (rule.metadata.outcome === "failed") { + addToElements(elements, "idAttNot", rule.metadata.failed); + addToResults(results, "id_02"); + addToNodes( + nodes, + "idAttNot", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP1(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "hxNone", technique.metadata.failed); + addToResults(results, "hx_01a"); + addToNodes( + nodes, + "hxNone", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } else if (technique.metadata.outcome === "warning") { + addToElements(elements, "hx", technique.metadata.warning); + addToResults(results, "hx_01b"); + addToNodes( + nodes, + "hx", + technique.results.filter((r: any) => r.verdict === "warning") + ); + } +} + +function QW_BP2(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "imgAltLong", technique.metadata.failed); + addToResults(results, "img_04"); + addToNodes( + nodes, + "imgAltLong", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP4(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "aGroupNo", technique.metadata.failed); + addToResults(results, "a_07"); + addToNodes( + nodes, + "aGroupNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP5(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "tableNested", technique.metadata.failed); + addToResults(results, "table_04"); + addToNodes( + nodes, + "tableNested", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP6(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "titleLong", technique.metadata.failed); + addToResults(results, "title_04"); + addToNodes( + nodes, + "titleLong", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP7(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "titleChars", technique.metadata.failed); + addToResults(results, "title_05"); + addToNodes( + nodes, + "titleChars", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP8(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "hxNo", technique.metadata.failed); + addToResults(results, "hx_02"); + addToNodes( + nodes, + "hxNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP9(elements: any, results: any, nodes: any, technique: any): void { + if (technique.metadata.passed > 0) { + addToElements(elements, "tableLayoutCaption", technique.metadata.passed); + addToResults(results, "table_01"); + addToNodes( + nodes, + "tableLayoutCaption", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } +} + +function QW_BP10( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "layoutElem", technique.metadata.failed); + addToResults(results, "layout_01b"); + addToNodes( + nodes, + "layoutElem", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } else if (technique.metadata.outcome === "passed") { + addToElements(elements, "layoutElemNo", undefined); + addToResults(results, "layout_01a"); + addToNodes(nodes, "layoutElemNo", undefined); + } +} + +function QW_BP11( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "brSec", technique.metadata.failed); + addToResults(results, "br_01"); + addToNodes( + nodes, + "brSec", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP13( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "aAdjacentSame", technique.metadata.failed); + addToResults(results, "a_06"); + addToNodes( + nodes, + "aAdjacentSame", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP14( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "layoutFixed", technique.metadata.failed); + addToResults(results, "layout_03"); + addToNodes( + nodes, + "layoutFixed", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP15( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "valueRelHtml", technique.metadata.passed); + addToResults(results, "values_01b"); + addToNodes( + nodes, + "valueRelHtml", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "valueAbsHtml", technique.metadata.failed); + addToResults(results, "values_01a"); + addToNodes( + nodes, + "valueAbsHtml", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP17( + elements: any, + results: any, + nodes: any, + technique: any +): void { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "a", technique.results.length); + addToResults(results, "a_04"); + addToNodes(nodes, "a", []); + } else { + addToElements(elements, "a", technique.results.length); + addToNodes(nodes, "a", technique.results); + } + + if (technique.metadata.outcome === "warning") { + addToElements(elements, "aSkip", technique.metadata.warning); + addToResults(results, "a_02b"); + addToNodes( + nodes, + "aSkip", + technique.results.filter((r: any) => r.verdict === "warning") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "aSkipNo", technique.metadata.failed); + addToResults(results, "a_02a"); + addToNodes( + nodes, + "aSkipNo", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function QW_BP18(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "failed") { + addToElements(elements, "valueAbsCss", technique.metadata.failed); + addToResults(results, "values_02a"); + addToNodes( + nodes, + "valueAbsCss", + technique.results.filter((r: any) => r.verdict === "failed") + ); + } + if (technique.metadata.passed > 0) { + addToElements(elements, "valueRelCss", technique.metadata.passed); + addToResults(results, "values_02b"); + addToNodes(nodes, "valueRelCss", [ + technique.results.filter((r) => r.verdict === "passed"), + ]); + } +} + +function QW_BP19(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "bannerTopLevel", technique.metadata.passed); + addToResults(results, "landmark_01"); + addToNodes( + nodes, + "bannerTopLevel", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "bannerNotTopLevel", technique.metadata.failed); + addToResults(results, "landmark_02"); + addToNodes( + nodes, + "bannerNotTopLevel", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP20(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "noDuplicateBanner", technique.metadata.passed); + addToResults(results, "landmark_09"); + addToNodes( + nodes, + "noDuplicateBanner", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "duplicateBanner", technique.metadata.failed); + addToResults(results, "landmark_10"); + addToNodes( + nodes, + "duplicateBanner", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP21(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "passed") { + addToElements( + elements, + "noDuplicateContentinfo", + technique.metadata.passed + ); + addToResults(results, "landmark_11"); + addToNodes( + nodes, + "noDuplicateContentinfo", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "duplicateContentinfo", technique.metadata.failed); + addToResults(results, "landmark_12"); + addToNodes( + nodes, + "duplicateContentinfo", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP22(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "noDuplicateMain", technique.metadata.passed); + addToResults(results, "landmark_13"); + addToNodes( + nodes, + "noDuplicateMain", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "duplicateMain", technique.metadata.failed); + addToResults(results, "landmark_14"); + addToNodes( + nodes, + "duplicateMain", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP23(elements: any, results: any, nodes: any, technique: any) { + addToElements(elements, "li", technique.results.length); + if (technique.metadata.outcome === "passed") { + addToElements(elements, "liSemantically", technique.metadata.passed); + addToResults(results, "listitem_01"); + addToNodes( + nodes, + "liSemantically", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "liNotSemantically", technique.metadata.failed); + addToResults(results, "listitem_02"); + addToNodes( + nodes, + "liNotSemantically", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP24(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "listCorrectly", technique.metadata.passed); + addToResults(results, "list_02"); + addToNodes( + nodes, + "listCorrectly", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "listNotCorrectly", technique.metadata.failed); + addToResults(results, "list_03"); + addToNodes( + nodes, + "listNotCorrectly", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP25(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "complementaryTopLevel", technique.metadata.passed); + addToResults(results, "landmark_03"); + addToNodes( + nodes, + "complementaryTopLevel", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements( + elements, + "complementaryNotTopLevel", + technique.metadata.failed + ); + addToResults(results, "landmark_04"); + addToNodes( + nodes, + "complementaryNotTopLevel", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP26(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "contentinfoTopLevel", technique.metadata.passed); + addToResults(results, "landmark_05"); + addToNodes( + nodes, + "contentinfoTopLevel", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements( + elements, + "contentinfoNotTopLevel", + technique.metadata.failed + ); + addToResults(results, "landmark_06"); + addToNodes( + nodes, + "contentinfoNotTopLevel", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP27(elements: any, results: any, nodes: any, technique: any) { + if (technique.metadata.outcome === "passed") { + addToElements(elements, "mainTopLevel", technique.metadata.passed); + addToResults(results, "landmark_07"); + addToNodes( + nodes, + "mainTopLevel", + technique.results.filter((r: any) => r.verdict === "passed") + ); + } else if (technique.metadata.outcome === "failed") { + addToElements(elements, "mainNotTopLevel", technique.metadata.failed); + addToResults(results, "landmark_08"); + addToNodes( + nodes, + "mainNotTopLevel", + technique.results.filter((r) => r.verdict === "failed") + ); + } +} + +function QW_BP29(elements: any, results: any, nodes: any, rule: any): void { + if (rule.metadata.outcome === "failed") { + addToElements(elements, "langMatchNo", rule.metadata.failed); + addToResults(results, "lang_04"); + addToNodes( + nodes, + "langMatchNo", + rule.results.filter((r: any) => r.verdict === "failed") + ); + } +} + +function addToElements( + elements: any, + key: string, + value: string | number +): void { + if (elements[key] === undefined) { + elements[key] = value; + } else { + elements[key] += value; + } +} + +function addToResults(results: any, key: string): void { + results[key] = "something"; +} + +function addToNodes(nodes: any, key: string, elements: any[]): void { + nodes[key] = elements; +} + +export function getElementsMapping(evaluation: any): any { + const elements = {}; + const results = {}; + const nodes = {}; + for (const rule of Object.keys(evaluation.modules["act-rules"].assertions) || + []) { + if (act_mapping[rule] !== undefined) { + act_mapping[rule]( + elements, + results, + nodes, + evaluation.modules["act-rules"].assertions[rule] + ); + } + } + + for (const technique of Object.keys( + evaluation.modules["wcag-techniques"].assertions + ) || []) { + if (wcag_mapping[technique] !== undefined) { + wcag_mapping[technique]( + elements, + results, + nodes, + evaluation.modules["wcag-techniques"].assertions[technique] + ); + // if (technique === "QW-WCAG-T9") + // console.log(technique, "\n*\n", evaluation.modules["wcag-techniques"].assertions[technique]) + } + } + + for (const technique of Object.keys( + evaluation.modules["best-practices"].assertions + ) || []) { + if (bp_mapping[technique] !== undefined) { + bp_mapping[technique]( + elements, + results, + nodes, + evaluation.modules["best-practices"].assertions[technique] + ); + } + } + + return { elements, results, nodes }; +} diff --git a/src/evaluation/middleware.ts b/src/evaluation/middleware.ts index 2a784a05..925a0de3 100644 --- a/src/evaluation/middleware.ts +++ b/src/evaluation/middleware.ts @@ -1,330 +1,330 @@ -import * as htmlparser from "htmlparser2"; -import * as CSSselect from "css-select"; -import clone from "lodash.clone"; -import * as qualweb from "./qualweb"; - -import tests from "./tests"; -import testsColors from "./testsColors"; - -import { generateMd5Hash } from "../lib/security"; -import { getElementsMapping } from "./mapping"; - -function completeMissingReportElements(report: any): void { - let _dom = {}; - - const handler = new htmlparser.DomHandler((error, dom) => { - if (error) { - throw new Error(); - } else { - _dom = clone(dom); - } - }); - - const parser = new htmlparser.Parser(handler); - parser.write(report.pagecode.replace(/(\r\n|\n|\r|\t)/gm, "")); - parser.end(); - - if (report.data.elems["img"] === undefined) { - const img = CSSselect.selectAll("img", _dom); - report.data.elems["img"] = img.length; - } - - const area = CSSselect.selectAll("area", _dom); - report.data.elems["area"] = area.length; - - const inpImg = CSSselect.selectAll("a", _dom); - report.data.elems["inpImg"] = inpImg.length; - - const roles = [ - "checkbox", - "combobox", - "listbox", - "menuitemcheckbox", - "menuitemradio", - "radio", - "searchbox", - "slider", - "spinbutton", - "switch", - "textbox", - ]; - - const label = CSSselect.selectAll( - "input, select, textarea, " + roles.map((r) => `[role="${r}"]`).join(", "), - _dom - ); - report.data.elems["label"] = label.length; - - const form = CSSselect.selectAll("form", _dom); - report.data.elems["form"] = form.length; - - const table = CSSselect.selectAll("table", _dom); - if (report.data.elems["tableData"] === undefined) { - report.data.elems["tableData"] = table.length; - } - if (report.data.elems["tableLayout"] === undefined) { - report.data.elems["tableLayout"] = table.length; - } - if (report.data.elems["tableComplex"] === undefined) { - report.data.elems["tableComplex"] = table.length; - } - - //const tabletable = CSSselect.selectAll("table table", _dom); - //report.data.elems["tableNested"] = tabletable.length; - - const iframe = CSSselect.selectAll("iframe", _dom); - report.data.elems["iframe"] = iframe.length; - - const ehandler = CSSselect.selectAll( - "*[onmousedown], *[onmouseup], *[onclick], *[onmouseover], *[onmouseout]", - _dom - ); - report.data.elems["ehandler"] = ehandler.length; - - report.data.tot.elems = clone(report.data.elems); -} - -function generateScore(report: any): string { - let rel = 0; - let pon = 0; - - for (const test in report.data.tot.results) { - const value = tests[test]; - - if (value.result === "warning") { - continue; - } - - let calc = false; - switch (value["type"]) { - case "true": - case "decr": - if ( - value["elem"] === "all" || - report.data["elems"][value["elem"]] !== undefined - ) { - if (report.data["elems"][value["test"]] !== undefined) { - calc = true; - } - } - break; - case "fals": - if ( - value["elem"] === "all" || - report.data["elems"][value["elem"]] !== undefined - ) { - // if (report.data["elems"][value["test"]] !== undefined) { - calc = true; - // } - } - break; - case "prop": - if ( - report.data["elems"][value["elem"]] !== undefined && - report.data["elems"][value["test"]] !== undefined - ) { - calc = true; - } - break; - } - // if (value["test"] === "liNotSemantically") - // console.log({ calc, value, elems: report.data["elems"] }) - - if (calc) { - let temp = null; - if (tests[test]["type"] === "prop") { - temp = calculateProp(value, report); - } else if (tests[test]["type"] === "decr") { - temp = calculateDecr(value, report); - } else { - temp = calculateTrueFalse(value); - } - - const pp = temp["p"] / 5; - const ss = temp["s"] * pp; - rel += ss; - pon += pp; - - report.data.tot.results[test] = value["score"] + "@" + ss; - } - } - - return (rel / pon).toFixed(1); -} - -function calculateTrueFalse(v: any): any { - const score = v["score"]; - const ret = { s: score, p: 0 }; - for (const w in v["dis"]) { - if (parseInt(w) > 1) { - const p = +v["trust"] * parseInt(w); - ret["p"] += p; - } - } - return ret; -} - -function calculateDecr(v: any, report: any): any { - const test = report.data.elems[v["test"]]; - const limit = v["top"]; - const steps = v["steps"]; - const score = v["score"]; - const errors = test - limit; - const minus = errors > 0 ? Math.round(errors / steps) : 0; - const op = score - minus; - const rr = op < 1 ? 1 : op; - const ret = { s: rr, p: 0 }; - for (const w of v["dis"]) { - if (parseInt(w) > 1) { - const p = +v["trust"] * parseInt(w); - ret["p"] += p; - } - } - return ret; -} - -function calculateProp(v: any, report: any): any { - const elem = report.data.elems[v["elem"]]; - const test = report.data.elems[v["test"]]; - const score = v["score"]; - const op = score - (score / elem) * test; - const rr = op < 1 ? 1 : op; - const ret = { s: rr, p: 0 }; - for (const w of v["dis"]) { - if (parseInt(w) > 1) { - const p = +v["trust"] * parseInt(w); - ret["p"] += p; - } - } - return clone(ret); -} - -function getHtmlLang(html: string): string { - let lang = ""; - let _dom = {}; - - const handler = new htmlparser.DomHandler((error, dom) => { - if (error) { - throw new Error(); - } else { - _dom = clone(dom); - } - }); - - const parser = new htmlparser.Parser(handler); - parser.write(html.replace(/(\r\n|\n|\r|\t)/gm, "")); - parser.end(); - - const htmlElement: any = CSSselect.selectOne("html", _dom); - - if (htmlElement && htmlElement.attribs && htmlElement.attribs.lang) { - lang = htmlElement.attribs.lang; - } - - return lang; -} - -function calculateConform(results: any): string { - const errors = { - A: 0, - AA: 0, - AAA: 0, - }; - for (const ee in results || {}) { - if (ee) { - let level = tests[ee]["level"].toUpperCase(); - if (testsColors[ee] === "R") { - errors[level]++; - } - } - } - - return `${errors.A}@${errors.AA}@${errors.AAA}`; -} - -function parseEvaluation(evaluation: any): any { - const { elements, results, nodes } = getElementsMapping(evaluation); - - const report: any = {}; - - report.pagecode = evaluation.system.page.dom.html; - report["data"] = {}; - report["data"].title = evaluation.system.page.dom.title; - report["data"].rawUrl = evaluation?.system?.url?.completeUrl || ""; - report["data"].elems = clone(elements); - report["data"].nodes = clone(nodes); - report["data"].date = new Date() - .toISOString() - .replace(/T/, " ") - .replace(/\..+/, ""); - report["data"].tot = {}; - report["data"].tot.info = {}; - report["data"].tot.info.url = clone(report["data"].rawUrl); - report["data"].tot.info.title = clone(report["data"].title); - report["data"].tot.info.date = clone(report["data"].date); - report["data"].tot.info.htmlTags = evaluation.system.page.dom.elementCount; //count_html_tags(evaluation.postProcessingHTML); - report["data"].tot.info.roles = evaluation.modules.counter.data.roles; - report["data"].tot.info.cTags = evaluation.modules.counter.data.tags; - report["data"].tot.info.size = - encodeURI(report.pagecode).split(/%..|./).length - 1; - //report['data'].tot.info.cssRules = calculateCssRules(evaluation); - report["data"].tot.info.encoding = "utf-8"; - report["data"].tot.info.lang = getHtmlLang(evaluation.system.page.dom.html); - report["data"].tot.info.content = "text/html"; - report["data"].tot.info.hash = generateMd5Hash(report["data"].date); - report["data"].tot.info.tests = Object.keys(results).length; - report["data"].tot.elems = clone(report["data"].elems); - report["data"].tot.results = clone(results); - report["data"].conform = calculateConform(report["data"].tot.results); - report["data"].tot.info.conform = clone(report["data"].conform); - - completeMissingReportElements(report); - - report["data"].score = generateScore(report); - report["data"].tot.info.score = clone(report["data"].score); - return report; -} - -export async function executeUrlEvaluation(url: string): Promise { - const params = { - url, - }; - - params.url = params.url.trim(); - if (!params.url.startsWith("http://") && !params.url.startsWith("https://")) { - params.url = "http://" + params.url; - } - - const reports = await qualweb.evaluate(params); - return parseEvaluation(reports[params.url]); -} - -export async function executeUrlsEvaluation(urls: string[]): Promise { - const normalized = new Array(); - - for (const url of urls ?? []) { - const _url = url.trim(); - if (!_url.startsWith("http://") && !_url.startsWith("https://")) { - normalized.push("http://" + _url); - } else { - normalized.push(_url); - } - } - - const params = { - urls: normalized, - }; - - const reports = await qualweb.evaluate(params); - for (const url in reports ?? {}) { - if (url && reports[url]) { - reports[url] = parseEvaluation(reports[url]); - } - } - return reports; -} - -export async function executeHtmlEvaluation(html: string): Promise { - const reports = await qualweb.evaluate({ html }); - return parseEvaluation(reports["customHtml"]); -} +import * as htmlparser from "htmlparser2"; +import * as CSSselect from "css-select"; +import clone from "lodash.clone"; +import * as qualweb from "./qualweb"; + +import tests from "./tests"; +import testsColors from "./testsColors"; + +import { generateMd5Hash } from "../lib/security"; +import { getElementsMapping } from "./mapping"; + +function completeMissingReportElements(report: any): void { + let _dom = {}; + + const handler = new htmlparser.DomHandler((error, dom) => { + if (error) { + throw new Error(); + } else { + _dom = clone(dom); + } + }); + + const parser = new htmlparser.Parser(handler); + parser.write(report.pagecode.replace(/(\r\n|\n|\r|\t)/gm, "")); + parser.end(); + + if (report.data.elems["img"] === undefined) { + const img = CSSselect.selectAll("img", _dom); + report.data.elems["img"] = img.length; + } + + const area = CSSselect.selectAll("area", _dom); + report.data.elems["area"] = area.length; + + const inpImg = CSSselect.selectAll("a", _dom); + report.data.elems["inpImg"] = inpImg.length; + + const roles = [ + "checkbox", + "combobox", + "listbox", + "menuitemcheckbox", + "menuitemradio", + "radio", + "searchbox", + "slider", + "spinbutton", + "switch", + "textbox", + ]; + + const label = CSSselect.selectAll( + "input, select, textarea, " + roles.map((r) => `[role="${r}"]`).join(", "), + _dom + ); + report.data.elems["label"] = label.length; + + const form = CSSselect.selectAll("form", _dom); + report.data.elems["form"] = form.length; + + const table = CSSselect.selectAll("table", _dom); + if (report.data.elems["tableData"] === undefined) { + report.data.elems["tableData"] = table.length; + } + if (report.data.elems["tableLayout"] === undefined) { + report.data.elems["tableLayout"] = table.length; + } + if (report.data.elems["tableComplex"] === undefined) { + report.data.elems["tableComplex"] = table.length; + } + + //const tabletable = CSSselect.selectAll("table table", _dom); + //report.data.elems["tableNested"] = tabletable.length; + + const iframe = CSSselect.selectAll("iframe", _dom); + report.data.elems["iframe"] = iframe.length; + + const ehandler = CSSselect.selectAll( + "*[onmousedown], *[onmouseup], *[onclick], *[onmouseover], *[onmouseout]", + _dom + ); + report.data.elems["ehandler"] = ehandler.length; + + report.data.tot.elems = clone(report.data.elems); +} + +function generateScore(report: any): string { + let rel = 0; + let pon = 0; + + for (const test in report.data.tot.results) { + const value = tests[test]; + + if (value.result === "warning") { + continue; + } + + let calc = false; + switch (value["type"]) { + case "true": + case "decr": + if ( + value["elem"] === "all" || + report.data["elems"][value["elem"]] !== undefined + ) { + if (report.data["elems"][value["test"]] !== undefined) { + calc = true; + } + } + break; + case "fals": + if ( + value["elem"] === "all" || + report.data["elems"][value["elem"]] !== undefined + ) { + // if (report.data["elems"][value["test"]] !== undefined) { + calc = true; + // } + } + break; + case "prop": + if ( + report.data["elems"][value["elem"]] !== undefined && + report.data["elems"][value["test"]] !== undefined + ) { + calc = true; + } + break; + } + // if (value["test"] === "liNotSemantically") + // console.log({ calc, value, elems: report.data["elems"] }) + + if (calc) { + let temp = null; + if (tests[test]["type"] === "prop") { + temp = calculateProp(value, report); + } else if (tests[test]["type"] === "decr") { + temp = calculateDecr(value, report); + } else { + temp = calculateTrueFalse(value); + } + + const pp = temp["p"] / 5; + const ss = temp["s"] * pp; + rel += ss; + pon += pp; + + report.data.tot.results[test] = value["score"] + "@" + ss; + } + } + + return (rel / pon).toFixed(1); +} + +function calculateTrueFalse(v: any): any { + const score = v["score"]; + const ret = { s: score, p: 0 }; + for (const w in v["dis"]) { + if (parseInt(w) > 1) { + const p = +v["trust"] * parseInt(w); + ret["p"] += p; + } + } + return ret; +} + +function calculateDecr(v: any, report: any): any { + const test = report.data.elems[v["test"]]; + const limit = v["top"]; + const steps = v["steps"]; + const score = v["score"]; + const errors = test - limit; + const minus = errors > 0 ? Math.round(errors / steps) : 0; + const op = score - minus; + const rr = op < 1 ? 1 : op; + const ret = { s: rr, p: 0 }; + for (const w of v["dis"]) { + if (parseInt(w) > 1) { + const p = +v["trust"] * parseInt(w); + ret["p"] += p; + } + } + return ret; +} + +function calculateProp(v: any, report: any): any { + const elem = report.data.elems[v["elem"]]; + const test = report.data.elems[v["test"]]; + const score = v["score"]; + const op = score - (score / elem) * test; + const rr = op < 1 ? 1 : op; + const ret = { s: rr, p: 0 }; + for (const w of v["dis"]) { + if (parseInt(w) > 1) { + const p = +v["trust"] * parseInt(w); + ret["p"] += p; + } + } + return clone(ret); +} + +function getHtmlLang(html: string): string { + let lang = ""; + let _dom = {}; + + const handler = new htmlparser.DomHandler((error, dom) => { + if (error) { + throw new Error(); + } else { + _dom = clone(dom); + } + }); + + const parser = new htmlparser.Parser(handler); + parser.write(html.replace(/(\r\n|\n|\r|\t)/gm, "")); + parser.end(); + + const htmlElement: any = CSSselect.selectOne("html", _dom); + + if (htmlElement && htmlElement.attribs && htmlElement.attribs.lang) { + lang = htmlElement.attribs.lang; + } + + return lang; +} + +function calculateConform(results: any): string { + const errors = { + A: 0, + AA: 0, + AAA: 0, + }; + for (const ee in results || {}) { + if (ee) { + let level = tests[ee]["level"].toUpperCase(); + if (testsColors[ee] === "R") { + errors[level]++; + } + } + } + + return `${errors.A}@${errors.AA}@${errors.AAA}`; +} + +function parseEvaluation(evaluation: any): any { + const { elements, results, nodes } = getElementsMapping(evaluation); + + const report: any = {}; + + report.pagecode = evaluation.system.page.dom.html; + report["data"] = {}; + report["data"].title = evaluation.system.page.dom.title; + report["data"].rawUrl = evaluation?.system?.url?.completeUrl || ""; + report["data"].elems = clone(elements); + report["data"].nodes = clone(nodes); + report["data"].date = new Date() + .toISOString() + .replace(/T/, " ") + .replace(/\..+/, ""); + report["data"].tot = {}; + report["data"].tot.info = {}; + report["data"].tot.info.url = clone(report["data"].rawUrl); + report["data"].tot.info.title = clone(report["data"].title); + report["data"].tot.info.date = clone(report["data"].date); + report["data"].tot.info.htmlTags = evaluation.system.page.dom.elementCount; //count_html_tags(evaluation.postProcessingHTML); + report["data"].tot.info.roles = evaluation.modules.counter.data.roles; + report["data"].tot.info.cTags = evaluation.modules.counter.data.tags; + report["data"].tot.info.size = + encodeURI(report.pagecode).split(/%..|./).length - 1; + //report['data'].tot.info.cssRules = calculateCssRules(evaluation); + report["data"].tot.info.encoding = "utf-8"; + report["data"].tot.info.lang = getHtmlLang(evaluation.system.page.dom.html); + report["data"].tot.info.content = "text/html"; + report["data"].tot.info.hash = generateMd5Hash(report["data"].date); + report["data"].tot.info.tests = Object.keys(results).length; + report["data"].tot.elems = clone(report["data"].elems); + report["data"].tot.results = clone(results); + report["data"].conform = calculateConform(report["data"].tot.results); + report["data"].tot.info.conform = clone(report["data"].conform); + + completeMissingReportElements(report); + + report["data"].score = generateScore(report); + report["data"].tot.info.score = clone(report["data"].score); + return report; +} + +export async function executeUrlEvaluation(url: string): Promise { + const params = { + url, + }; + + params.url = params.url.trim(); + if (!params.url.startsWith("http://") && !params.url.startsWith("https://")) { + params.url = "http://" + params.url; + } + + const reports = await qualweb.evaluate(params); + return parseEvaluation(reports[params.url]); +} + +export async function executeUrlsEvaluation(urls: string[]): Promise { + const normalized = new Array(); + + for (const url of urls ?? []) { + const _url = url.trim(); + if (!_url.startsWith("http://") && !_url.startsWith("https://")) { + normalized.push("http://" + _url); + } else { + normalized.push(_url); + } + } + + const params = { + urls: normalized, + }; + + const reports = await qualweb.evaluate(params); + for (const url in reports ?? {}) { + if (url && reports[url]) { + reports[url] = parseEvaluation(reports[url]); + } + } + return reports; +} + +export async function executeHtmlEvaluation(html: string): Promise { + const reports = await qualweb.evaluate({ html }); + return parseEvaluation(reports["customHtml"]); +} diff --git a/src/evaluation/qualweb.ts b/src/evaluation/qualweb.ts index 7d448955..223dea03 100644 --- a/src/evaluation/qualweb.ts +++ b/src/evaluation/qualweb.ts @@ -82,7 +82,7 @@ export async function evaluate(params: any): Promise { "QW-WCAG-T25", "QW-WCAG-T26", "QW-WCAG-T27", - // "QW-WCAG-T28", + // "QW-WCAG-T28", "QW-WCAG-T29", "QW-WCAG-T30", "QW-WCAG-T31", @@ -117,7 +117,7 @@ export async function evaluate(params: any): Promise { "QW-BP25", "QW-BP26", "QW-BP27", - "QW-BP29" + "QW-BP29", ], }, waitUntil: ["load", "networkidle0"], diff --git a/src/evaluation/tests.ts b/src/evaluation/tests.ts index 1c051d9e..5033111b 100644 --- a/src/evaluation/tests.ts +++ b/src/evaluation/tests.ts @@ -1,2092 +1,2092 @@ -export default { - img_01a: { - type: "fals", - elem: "img", - test: "imgAlt", - score: 10, - level: "a", - trust: "0.5", - ref: "H37", - scs: "1.1.1", - dis: "53322", - result: "passed", - }, - img_01b: { - type: "prop", - elem: "img", - test: "imgAltNo", - score: 1, - level: "A", - trust: "1", - ref: "F65", - scs: "1.1.1", - dis: "53322", - result: "failed", - }, - img_02: { - type: "prop", - elem: "img", - test: "imgAltNull", - score: 7, - level: "a", - trust: "1", - ref: "C9", - scs: "1.1.1", - dis: "41111", - result: "warning", - }, - img_03: { - type: "decr", - elem: "img", - test: "imgAltNot", - score: 1, - level: "A", - trust: "1", - top: 1, - steps: 1, - ref: "F30", - scs: "1.1.1,1.2.1", - dis: "53211", - result: "failed", - }, - img_04: { - type: "prop", - elem: "img", - test: "imgAltLong", - score: 1, - level: "a", - trust: "0.3", - ref: "H45", - scs: "1.1.1", - dis: "54153", - result: "warning", - }, - area_01a: { - type: "fals", - elem: "area", - test: "areaAltYes", - score: 10, - level: "a", - trust: "0.5", - ref: "H24", - scs: "1.1.1,2.4.4,2.4.9", - dis: "54222", - result: "passed", - }, - area_01b: { - type: "prop", - elem: "area", - test: "areaAltNo", - score: 1, - level: "A", - trust: "1", - ref: "F65", - scs: "1.1.1", - dis: "53322", - result: "failed", - }, - inp_img_01a: { - type: "fals", - elem: "inpImg", - test: "inpImgAltYes", - score: 10, - level: "a", - trust: "0.9", - ref: "H36", - scs: "1.1.1,4.1.2", - dis: "54211", - result: "passed", - }, - inp_img_01b: { - type: "prop", - elem: "inpImg", - test: "inpImgAltNo", - score: 1, - level: "A", - trust: "1", - ref: "F65", - scs: "1.1.1,4.1.2", - dis: "53322", - result: "failed", - }, - a_04: { - type: "fals", - elem: "all", - test: "a", - score: 7, - level: "AA", - trust: "1", - ref: "G125", - scs: "2.4.5", - dis: "54353", - result: "failed", - }, - a_03: { - type: "decr", - elem: "a", - test: "aImgAltNo", - score: 1, - level: "A", - trust: "1", - top: 1, - steps: 1, - ref: "F89", - scs: "2.4.4,2.4.9,4.1.2", - dis: "53322", - result: "failed", - }, - a_05: { - type: "prop", - elem: "a", - test: "aTitleMatch", - score: 1, - level: "a", - trust: "1", - ref: "H33", - scs: "2.4.4,2.4.9", - dis: "52132", - result: "failed", - }, - a_09: { - type: "decr", - elem: "a", - test: "aSameText", - score: 5, - level: "AAA", - trust: "1", - top: 1, - steps: 1, - ref: "F84", - scs: "2.4.9", - dis: "52122", - result: "warning", - }, - a_06: { - type: "decr", - elem: "a", - test: "aAdjacentSame", - score: 1, - level: "A", - trust: "1", - top: 1, - steps: 1, - ref: "H2", - scs: "1.1.1,2.4.4,2.4.9", - dis: "54353", - result: "failed", - }, - a_01a: { - type: "true", - elem: "a", - test: "aSkipFirst", - score: 10, - level: "a", - trust: "0.5", - ref: "G1", - scs: "2.4.1", - dis: "43522", - result: "warning", - }, - a_01b: { - type: "fals", - elem: "a", - test: "aSkipFirstNo", - score: 1, - level: "a", - trust: "0.5", - ref: "G1", - scs: "2.4.1", - dis: "43522", - result: "warning", - }, - a_02a: { - type: "fals", - elem: "a", - test: "aSkipNo", - score: 1, - level: "a", - trust: "0.5", - ref: "G123", - scs: "2.4.1", - dis: "43522", - result: "failed", - }, - a_02b: { - type: "true", - elem: "a", - test: "aSkip", - score: 10, - level: "a", - trust: "0.5", - ref: "G123", - scs: "2.4.1", - dis: "43522", - result: "warning", - }, - hx_01a: { - type: "fals", - elem: "all", - test: "hxNone", - score: 1, - level: "A", - trust: "1", - ref: "H42", - scs: "1.3.1", - dis: "54322", - result: "failed", - }, - hx_01b: { - type: "true", - elem: "all", - test: "hx", - score: 10, - level: "aaa", - trust: "1", - ref: "G141", - scs: "1.3.1,2.4.10", - dis: "54343", - result: "warning", - }, - hx_01c: { - type: "fals", - elem: "hx", - test: "h1", - score: 5, - level: "aaa", - trust: "1", - ref: "G141", - scs: "1.3.1,2.4.10", - dis: "54343", - result: "failed", - }, - hx_03: { - type: "prop", - elem: "hx", - test: "hxSkip", - score: 5, - level: "AAA", - trust: "1", - ref: "G141", - scs: "1.3.1,2.4.10", - dis: "54343", - result: "failed", - }, - hx_02: { - type: "true", - elem: "hx", - test: "hxNo", - score: 1, - level: "AA", - trust: "1", - ref: "G130", - scs: "2.4.6", - dis: "54253", - result: "failed", - }, - list_01: { - type: "decr", - elem: "all", - test: "liNoList", - score: 1, - level: "A", - trust: "1", - top: 3, - steps: 3, - ref: "H48", - scs: "1.3.1", - dis: "53342", - result: "failed", - }, - br_01: { - type: "decr", - elem: "all", - test: "brSec", - score: 1, - level: "a", - trust: "0.5", - top: 1, - steps: 1, - ref: "H48", - scs: "1.3.1", - dis: "53342", - result: "failed", - }, - field_02: { - type: "decr", - elem: "all", - test: "fieldNoForm", - score: 1, - level: "A", - trust: "0.5", - top: 1, - steps: 1, - ref: "H71", - scs: "1.3.1,3.3.2", - dis: "54152", - result: "warning", - }, - field_01: { - type: "true", - elem: "all", - test: "fieldLegNo", - score: 1, - level: "A", - trust: "1", - ref: "H71", - scs: "1.3.1,3.3.2", - dis: "54152", - result: "failed", - }, - label_02: { - type: "decr", - elem: "all", - test: "labelPosNo", - score: 1, - level: "A", - trust: "0.7", - top: 1, - steps: 1, - ref: "G162", - scs: "1.3.1,3.3.2", - dis: "43353", - result: "failed", - }, - input_02b: { - type: "fals", - elem: "all", - test: "inputLabel", - score: 10, - level: "a", - trust: "0.5", - ref: "H44", - scs: "1.1.1,1.3.1,3.3.2,4.1.2", - dis: "54532", - result: "passed", - }, - input_02: { - type: "prop", - elem: "label", - test: "inputLabelNo", - score: 1, - level: "a", - trust: "1", - ref: "H44", - scs: "1.1.1,1.3.1,3.3.2,4.1.2", - dis: "54532", - result: "failed", - }, - input_01: { - type: "prop", - elem: "inputLabel", - test: "inputIdTitleNo", - score: 1, - level: "A", - trust: "1", - ref: "H65", - scs: "1.1.1,1.3.1,3.3.2,4.1.2", - dis: "53122", - result: "failed", - }, - focus_01: { - type: "true", - elem: "all", - test: "focusBlur", - score: 1, - level: "a", - trust: "0.8", - ref: "F55", - scs: "2.1.1,2.4.7,3.2.1", - dis: "54142", - result: "failed", - }, - input_03: { - type: "true", - elem: "all", - test: "inputAltNo", - score: 5, - level: "a", - trust: "1", - ref: "H36", - scs: "1.1.1", - dis: "54211", - result: "failed", - }, - form_01a: { - type: "fals", - elem: "form", - test: "formSubmit", - score: 10, - level: "a", - trust: "1", - ref: "H32", - scs: "3.2.2", - dis: "21211", - result: "passed", - }, - form_01b: { - type: "prop", - elem: "form", - test: "formSubmitNo", - score: 1, - level: "A", - trust: "0.7", - ref: "H32", - scs: "3.2.2", - dis: "21211", - result: "failed", - }, - table_02: { - type: "prop", - elem: "tableData", - test: "tableDataCaption", - score: 1, - level: "A", - trust: "1", - ref: "H39", - scs: "1.3.1", - dis: "52211", - result: "failed", - }, - table_03: { - type: "prop", - elem: "table", - test: "tableCaptionSummary", - score: 5, - level: "A", - trust: "1", - ref: "H73", - scs: "1.3.1", - dis: "33152", - result: "failed", - }, - table_01: { - type: "prop", - elem: "tableLayout", - test: "tableLayoutCaption", - score: 1, - level: "A", - trust: "1", - ref: "F46", - scs: "1.3.1", - dis: "51421", - result: "warning", - }, - table_06: { - type: "decr", - elem: "tableComplex", - test: "tableComplexError", - score: 1, - level: "a", - trust: "0.8", - top: 1, - steps: 1, - ref: "H43", - scs: "1.3.1", - dis: "53211", - result: "failed", - }, - scope_01: { - type: "decr", - elem: "table", - test: "scopeNo", - score: 1, - level: "A", - trust: "1", - top: 1, - steps: 1, - ref: "H63", - scs: "1.3.1", - dis: "53353", - result: "failed", - }, - table_05a: { - type: "decr", - elem: "all", - test: "tableLayout", - score: 1, - level: "a", - trust: "1", - top: 1, - steps: 1, - ref: "H51", - scs: "1.3.1", - dis: "53352", - result: "failed", - }, - table_04: { - type: "prop", - elem: "table", - test: "tableNested", - score: 1, - level: "a", - trust: "1", - ref: "F49", - scs: "1.3.2", - dis: "53311", - result: "failed", - }, - iframe_01: { - type: "prop", - elem: "iframe", - test: "iframeTitleNo", - score: 1, - level: "A", - trust: "1", - ref: "H64", - scs: "2.4.1,4.1.2", - dis: "53222", - result: "failed", - }, - frame_01: { - type: "prop", - elem: "frame", - test: "frameTitleNo", - score: 3, - level: "A", - trust: "1", - ref: "H64", - scs: "2.4.1,4.1.2", - dis: "53222", - result: "failed", - }, - win_01: { - type: "true", - elem: "all", - test: "newWinOnLoad", - score: 3, - level: "AAA", - trust: "0.9", - ref: "F52", - scs: "3.2.5", - dis: "53454", - result: "warning", - }, - abbr_01: { - type: "true", - elem: "all", - test: "abbrNo", - score: 5, - level: "AAA", - trust: "1", - ref: "G102", - scs: "3.1.4", - dis: "42153", - result: "failed", - }, - css_01: { - type: "decr", - elem: "all", - test: "lineHeightNo", - score: 3, - level: "AA", - trust: "1", - top: 1, - steps: 1, - ref: "C21", - scs: "1.4.8,1.4.12", - dis: "15153", - result: "warning", - }, - justif_txt_01: { - type: "decr", - elem: "all", - test: "justifiedTxt", - score: 5, - level: "AAA", - trust: "1", - top: 1, - steps: 1, - ref: "F88", - scs: "1.4.8", - dis: "15152", - result: "failed", - }, - justif_txt_02: { - type: "decr", - elem: "all", - test: "justifiedCss", - score: 5, - level: "AAA", - trust: "0.9", - top: 1, - steps: 1, - ref: "C19", - scs: "1.4.8", - dis: "14142", - result: "warning", - }, - font_02: { - type: "prop", - elem: "fontValues", - test: "fontAbsVal", - score: 3, - level: "AA", - trust: "1", - ref: "C12", - scs: "1.4.4", - dis: "15123", - result: "failed", - }, - layout_03: { - type: "decr", - elem: "all", - test: "layoutFixed", - score: 3, - level: "aa", - trust: "1", - top: 1, - steps: 1, - ref: "G146", - scs: "1.4.4,1.4.8", - dis: "15222", - result: "failed", - }, - values_02a: { - type: "decr", - elem: "all", - test: "valueAbsCss", - score: 5, - level: "AAA", - trust: "0.9", - top: 1, - steps: 1, - ref: "C24", - scs: "1.4.8", - dis: "15113", - result: "warning", - }, - values_02b: { - type: "true", - elem: "all", - test: "valueRelCss", - score: 10, - level: "aaa", - trust: "1", - ref: "C24", - scs: "1.4.8", - dis: "15113", - result: "passed", - }, - values_01a: { - type: "decr", - elem: "all", - test: "valueAbsHtml", - score: 3, - level: "AA", - trust: "0.9", - top: 1, - steps: 1, - ref: "G146", - scs: "1.4.4", - dis: "15222", - result: "warning", - }, - values_01b: { - type: "true", - elem: "all", - test: "valueRelHtml", - score: 10, - level: "aa", - trust: "0.9", - ref: "G146", - scs: "1.4.4", - dis: "15222", - result: "passed", - }, - color_02: { - type: "decr", - elem: "all", - test: "colorContrast", - score: 1, - level: "AA", - trust: "1", - top: 1, - steps: 1, - ref: "G145", - scs: "1.4.3", - dis: "15113", - result: "failed", - }, - color_01: { - type: "true", - elem: "all", - test: "colorFgBgNo", - score: 3, - level: "aa", - trust: "0.9", - ref: "F24", - scs: "1.4.3,1.4.6,1.4.8", - dis: "13113", - result: "warning", - }, - blink_02: { - type: "true", - elem: "all", - test: "cssBlink", - score: 1, - level: "A", - trust: "0.9", - ref: "F4", - scs: "2.2.2", - dis: "15152", - result: "failed", - }, - /*'ehandler_01': { - 'type': 'true', - 'elem': 'ehandler', - 'test': 'ehandMouse', - 'score': 1, - 'level': 'A', - 'trust': '1', - 'ref': 'F54', - 'scs': '2.1.1', - 'dis': '53512', - 'result': 'warning' - },*/ - ehandler_03: { - type: "true", - elem: "ehandler", - test: "ehandBoth", - score: 10, - level: "a", - trust: "0.9", - ref: "G90", - scs: "2.1.1,2.1.3", - dis: "52522", - result: "passed", - }, - ehandler_02: { - type: "prop", - elem: "ehandler", - test: "ehandBothNo", - score: 1, - level: "A", - trust: "1", - ref: "SCR20", - scs: "2.1.1,2.1.3", - dis: "53511", - result: "failed", - }, - ehandler_04: { - type: "prop", - elem: "ehandler", - test: "ehandTagNo", - score: 1, - level: "A", - trust: "0.8", - ref: "F59", - scs: "4.1.2", - dis: "43411", - result: "failed", - }, - w3c_validator_01a: { - type: "fals", - elem: "w3cValidator", - test: "w3cValidatorErrorsNo", - score: 10, - level: "a", - trust: "1", - ref: "G134", - scs: "4.1.1", - dis: "22232", - result: "passed", - }, - w3c_validator_01b: { - type: "decr", - elem: "w3cValidator", - test: "w3cValidatorErrors", - score: 1, - level: "A", - trust: "1", - top: 10, - steps: 10, - ref: "G134", - scs: "4.1.1", - dis: "22232", - result: "warning", - }, - font_01: { - type: "decr", - elem: "all", - test: "fontHtml", - score: 3, - level: "AA", - trust: "1", - top: 1, - steps: 1, - ref: "C22", - scs: "1.3.1,1.4.4,1.4.5,1.4.9", - dis: "33111", - result: "failed", - }, - layout_01a: { - type: "fals", - elem: "all", - test: "layoutElemNo", - score: 10, - level: "a", - trust: "1", - ref: "G115", - scs: "1.3.1", - dis: "34212", - result: "passed", - }, - layout_01b: { - type: "decr", - elem: "all", - test: "layoutElem", - score: 1, - level: "A", - trust: "1", - top: 2, - steps: 2, - ref: "G115", - scs: "1.3.1", - dis: "34212", - result: "failed", - }, - lang_01: { - type: "true", - elem: "all", - test: "lang", - score: 10, - level: "a", - trust: "0.8", - ref: "H57", - scs: "3.1.1", - dis: "53112", - result: "warning", - }, - lang_03: { - type: "true", - elem: "all", - test: "langNo", - score: 1, - level: "A", - trust: "1", - ref: "H57", - scs: "3.1.1", - dis: "53112", - result: "failed", - }, - lang_02: { - type: "true", - elem: "all", - test: "langCodeNo", - score: 1, - level: "A", - trust: "1", - ref: "H57", - scs: "3.1.1", - dis: "53112", - result: "failed", - }, - lang_04: { - type: "true", - elem: "all", - test: "langMatchNo", - score: 1, - level: "A", - trust: "1", - ref: "H57", - scs: "3.1.1", - dis: "53112", - result: "failed", - }, - title_02: { - type: "true", - elem: "all", - test: "titleNo", - score: 1, - level: "A", - trust: "1", - ref: "H25", - scs: "2.4.2", - dis: "52112", - result: "failed", - }, - title_03: { - type: "true", - elem: "all", - test: "titleNull", - score: 1, - level: "A", - trust: "1", - ref: "F25", - scs: "2.4.2", - dis: "33151", - result: "failed", - }, - title_06: { - type: "true", - elem: "all", - test: "titleOk", - score: 10, - level: "a", - trust: "0.5", - ref: "H25", - scs: "2.4.2", - dis: "52112", - result: "passed", - }, - title_04: { - type: "decr", - elem: "all", - test: "titleLong", - score: 10, - level: "a", - trust: "1", - top: 64, - steps: 10, - ref: "G88", - scs: "2.4.2", - dis: "42253", - result: "warning", - }, - title_05: { - type: "true", - elem: "all", - test: "titleChars", - score: 1, - level: "a", - trust: "0.5", - ref: "G88", - scs: "2.4.2", - dis: "42253", - result: "failed", - }, - title_01: { - type: "true", - elem: "all", - test: "titleVrs", - score: 7, - level: "A", - trust: "1", - ref: "H25", - scs: "2.4.2", - dis: "52112", - result: "failed", - }, - link_01: { - type: "true", - elem: "all", - test: "linkRel", - score: 10, - level: "aa", - trust: "0.9", - ref: "H59", - scs: "2.4.5,2.4.8", - dis: "55554", - result: "passed", - }, - meta_01: { - type: "true", - elem: "all", - test: "metaRefresh", - score: 1, - level: "A", - trust: "1", - ref: "F41", - scs: "2.2.1,2.2.4,3.2.5", - dis: "43353", - result: "warning", - }, - meta_02: { - type: "true", - elem: "all", - test: "metaRedir", - score: 1, - level: "A", - trust: "1", - ref: "F40", - scs: "2.2.1,2.2.4", - dis: "43353", - result: "warning", - }, - heading_01: { - type: "true", - elem: "hx", - test: "hxHasAName", - score: 10, - level: "A", - trust: "1", - ref: "H42", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - heading_02: { - type: "prop", - elem: "hx", - test: "hxWithoutAName", - score: 1, - level: "A", - trust: "1", - ref: "H42", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - aria_01: { - type: "true", - elem: "all", - test: "ariaCntxRole", - score: 10, - level: "A", - trust: "1", - ref: "ff89c9", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - aria_02: { - type: "true", - elem: "all", - test: "ariaReqElem", - score: 10, - level: "A", - trust: "1", - ref: "bc4a75", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - aria_03: { - type: "true", - elem: "all", - test: "ariaStValid", - score: 10, - level: "A", - trust: "1", - ref: "6a7281", - scs: "1.3.1,4.1.2", - dis: "43353", - result: "passed", - }, - aria_04: { - type: "fals", - elem: "all", - test: "ariaStNotValid", - score: 1, - level: "A", - trust: "1", - ref: "6a7281", - scs: "1.3.1,4.1.2", - dis: "43353", - result: "failed", - }, - aria_05: { - type: "true", - elem: "all", - test: "ariaStPermitted", - score: 10, - level: "A", - trust: "1", - ref: "5c01ea", - scs: "1.3.1,4.1.2", - dis: "43353", - result: "passed", - }, - aria_06: { - type: "fals", - elem: "all", - test: "ariaStNotPermitted", - score: 1, - level: "A", - trust: "1", - ref: "5c01ea", - scs: "1.3.1,4.1.2", - dis: "43353", - result: "failed", - }, - aria_07: { - type: "true", - elem: "all", - test: "ariaAtribDefined", - score: 10, - level: "A", - trust: "1", - ref: "5f99a7", - scs: "1.3.1,4.1.2", - dis: "43353", - result: "passed", - }, - aria_08: { - type: "fals", - elem: "all", - test: "ariaAtribNotDefined", - score: 1, - level: "A", - trust: "1", - ref: "5f99a7", - scs: "1.3.1,4.1.2", - dis: "43353", - result: "failed", - }, - aria_09: { - type: "prop", - elem: "all", - test: "ariaControlsIdNotFound", - score: 1, - level: "A", - trust: "1", - ref: "in6db8", - scs: "1.3.1,4.1.2", - dis: "43353", - result: "failed", - }, - aria_10: { - type: "true", - elem: "all", - test: "ariaControlsIdFound", - score: 10, - level: "A", - trust: "1", - ref: "in6db8", - scs: "1.3.1,4.1.2", - dis: "43353", - result: "passed", - }, - audio_video_01: { - type: "true", - elem: "all", - test: "audioAvoidsAutoPlay", - score: 10, - level: "A", - trust: "1", - ref: "80f0bf", - scs: "1.4.2", - dis: "43353", - result: "passed", - }, - audio_video_02: { - type: "fals", - elem: "all", - test: "audioAutoPlay", - score: 1, - level: "A", - trust: "1", - ref: "80f0bf", - scs: "1.4.2", - dis: "43353", - result: "failed", - }, - autocomplete_01: { - type: "true", - elem: "all", - test: "autoCmpltValid", - score: 10, - level: "A", - trust: "1", - ref: "73f2c2", - scs: "1.3.5", - dis: "43353", - result: "passed", - }, - autocomplete_02: { - type: "fals", - elem: "all", - test: "autoCmpltNotValid", - score: 1, - level: "A", - trust: "1", - ref: "73f2c2", - scs: "1.3.5", - dis: "43353", - result: "failed", - }, - button_01: { - type: "true", - elem: "button", - test: "buttonAname", - score: 10, - level: "A", - trust: "1", - ref: "97a4e1", - scs: "4.1.2", - dis: "43353", - result: "passed", - }, - button_02: { - type: "prop", - elem: "button", - test: "buttonNotAname", - score: 1, - level: "A", - trust: "1", - ref: "97a4e1", - scs: "4.1.2", - dis: "43353", - result: "failed", - }, - element_01: { - type: "true", - elem: "all", - test: "seqFocus", - score: 10, - level: "AA", - trust: "1", - ref: "oj04fd", - scs: "2.4.7", - dis: "43353", - result: "warning", - }, - element_02: { - type: "true", - elem: "all", - test: "elementDec", - score: 10, - level: "A", - trust: "1", - ref: "6cfa84", - scs: "4.1.2", - dis: "43353", - result: "passed", - }, - element_03: { - type: "fals", - elem: "all", - test: "elementNotDec", - score: 1, - level: "A", - trust: "1", - ref: "6cfa84", - scs: "4.1.2", - dis: "43353", - result: "failed", - }, - element_04: { - type: "true", - elem: "all", - test: "elementHiddenFocus", - score: 10, - level: "A", - trust: "1", - ref: "46ca7f", - scs: "4.1.2", - dis: "43353", - result: "passed", - }, - element_05: { - type: "fals", - elem: "all", - test: "elementNotHiddenFocus", - score: 1, - level: "A", - trust: "1", - ref: "46ca7f", - scs: "4.1.2", - dis: "43353", - result: "failed", - }, - element_06: { - type: "true", - elem: "all", - test: "elementLang", - score: 10, - level: "AA", - trust: "1", - ref: "H58", - scs: "3.1.2", - dis: "43353", - result: "passed", - }, - element_07: { - type: "fals", - elem: "all", - test: "elementNotLang", - score: 3, - level: "AA", - trust: "1", - ref: "H58", - scs: "3.1.2", - dis: "43353", - result: "failed", - }, - element_08: { - type: "true", - elem: "all", - test: "elementPresentChildrenNoFocus", - score: 10, - level: "A", - trust: "1", - ref: "307n5z", - scs: "4.1.2", - dis: "43353", - result: "passed", - }, - element_09: { - type: "fals", - elem: "all", - test: "elementPresentChildrenFocus", - score: 1, - level: "A", - trust: "1", - ref: "307n5z", - scs: "4.1.2", - dis: "43353", - result: "failed", - }, - element_10: { - type: "true", - elem: "all", - test: "elementRole", - score: 10, - level: "A", - trust: "1", - ref: "4e8ab6", - scs: "4.1.2,1.3.1", - dis: "43353", - result: "passed", - }, - headers_01: { - type: "true", - elem: "headers", - test: "headerAtt", - score: 10, - level: "A", - trust: "1", - ref: "H43", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - headers_02: { - type: "prop", - elem: "headers", - test: "headerAttNot", - score: 1, - level: "A", - trust: "1", - ref: "H43", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - id_01: { - type: "true", - elem: "id", - test: "idAtt", - score: 10, - level: "A", - trust: "1", - ref: "H93", - scs: "4.1.1", - dis: "43353", - result: "passed", - }, - id_02: { - type: "prop", - elem: "id", - test: "idAttNot", - score: 1, - level: "A", - trust: "1", - ref: "H93", - scs: "4.1.1", - dis: "43353", - result: "failed", - }, - iframe_02: { - type: "true", - elem: "iframeSame", - test: "iframeSameAName", - score: 10, - level: "A", - trust: "1", - ref: "4b1c6c", - scs: "4.1.2", - dis: "43353", - result: "passed", - }, - iframe_03: { - type: "prop", - elem: "iframeSame", - test: "iframeSameANameDiferent", - score: 1, - level: "A", - trust: "0.5", - ref: "4b1c6c", - scs: "4.1.2", - dis: "43353", - result: "warning", - }, - iframe_04: { - type: "true", - elem: "all", - test: "iframeNegTabIndex", - score: 10, - level: "A", - trust: "1", - ref: "G202", - scs: "2.1.1", - dis: "43353", - result: "passed", - }, - iframe_05: { - type: "fals", - elem: "all", - test: "iframeNegTabIndexNot", - score: 1, - level: "A", - trust: "1", - top: 1, - steps: 1, - ref: "G202", - scs: "2.1.1", - dis: "43353", - result: "failed", - }, - letter_01: { - type: "true", - elem: "all", - test: "letterSpacing", - score: 10, - level: "AA", - trust: "1", - ref: "24afc2", - scs: "1.4.12", - dis: "43353", - result: "passed", - }, - letter_02: { - type: "decr", - elem: "all", - test: "letterSpacingNot", - score: 3, - level: "AA", - trust: "1", - top: 1, - steps: 1, - ref: "24afc2", - scs: "1.4.12", - dis: "43353", - result: "failed", - }, - a_10: { - type: "true", - elem: "all", - test: "linkAName", - score: 10, - level: "A", - trust: "1", - ref: "G91", - scs: "4.1.2,2.4.4,2.4.9", - dis: "43353", - result: "passed", - }, - a_11: { - type: "prop", - elem: "a", - test: "linkNotAName", - score: 1, - level: "A", - trust: "1", - ref: "G91", - scs: "4.1.2,2.4.4,2.4.9", - dis: "43353", - result: "failed", - }, - a_12: { - type: "true", - elem: "all", - test: "linkIdentAName", - score: 10, - level: "A", - trust: "1", - ref: "fd3a94", - scs: "2.4.4", - dis: "43353", - result: "passed", - }, - a_13: { - type: "prop", - elem: "a", - test: "linkIdentANameNot", - score: 1, - level: "A", - trust: "0.5", - ref: "fd3a94", - scs: "2.4.4", - dis: "43353", - result: "warning", - }, - menuItem_01: { - type: "true", - elem: "menuItem", - test: "menuItemAName", - score: 10, - level: "A", - trust: "1", - ref: "m6b1q3", - scs: "4.1.2", - dis: "43353", - result: "passed", - }, - menuItem_02: { - type: "prop", - elem: "menuItem", - test: "menuItemANameNot", - score: 1, - level: "A", - trust: "1", - ref: "m6b1q3", - scs: "4.1.2", - dis: "43353", - result: "failed", - }, - meta_03: { - type: "true", - elem: "all", - test: "metaRefresh", - score: 10, - level: "AAA", - trust: "1", - ref: "G110", - scs: "2.2.4,3.2.5", - dis: "43353", - result: "passed", - }, - meta_04: { - type: "fals", - elem: "all", - test: "metaRefreshNot", - score: 5, - level: "AAA", - trust: "1", - ref: "G110", - scs: "2.2.4,3.2.5", - dis: "43353", - result: "failed", - }, - meta_05: { - type: "true", - elem: "all", - test: "metaViewport", - score: 10, - level: "AA", - trust: "1", - ref: "b4f0c3", - scs: "1.4.4", - dis: "43353", - result: "passed", - }, - object_01: { - type: "true", - elem: "object", - test: "objectAName", - score: 10, - level: "A", - trust: "1", - ref: "b4f0c3", - scs: "1.1.1", - dis: "43353", - result: "passed", - }, - object_02: { - type: "prop", - elem: "object", - test: "objectANameNot", - score: 1, - level: "A", - trust: "1", - ref: "b4f0c3", - scs: "1.1.1", - dis: "43353", - result: "failed", - }, - orientation_01: { - type: "true", - elem: "all", - test: "orientationCSS", - score: 10, - level: "AA", - trust: "1", - ref: "b33eff", - scs: "1.3.4", - dis: "43353", - result: "passed", - }, - orientation_02: { - type: "fals", - elem: "all", - test: "orientationCSSNot", - score: 3, - level: "AA", - trust: "1", - ref: "b33eff", - scs: "1.3.4", - dis: "43353", - result: "failed", - }, - role_01: { - type: "true", - elem: "all", - test: "roleValid", - score: 10, - level: "AA", - trust: "1", - ref: "674b10", - scs: "4.1.2", - dis: "43353", - result: "passed", - }, - role_02: { - type: "decr", - elem: "all", - test: "roleValidNot", - score: 5, - level: "AA", - trust: "1", - top: 1, - steps: 1, - ref: "674b10", - scs: "4.1.2", - dis: "43353", - result: "failed", - }, - scrollable_01: { - type: "true", - elem: "scrollable", - test: "scrollableAccess", - score: 10, - level: "A", - trust: "1", - ref: "G202", - scs: "2.1.1,2.1.3", - dis: "43353", - result: "passed", - }, - scrollable_02: { - type: "prop", - elem: "scrollable", - test: "scrollableAccessNot", - score: 1, - level: "A", - trust: "1", - ref: "G202", - scs: "2.1.1,2.1.3", - dis: "43353", - result: "failed", - }, - svg_01: { - type: "true", - elem: "svg", - test: "svgAName", - score: 10, - level: "A", - trust: "1", - ref: "7d6734", - scs: "1.1.1", - dis: "43353", - result: "passed", - }, - svg_02: { - type: "prop", - elem: "svg", - test: "svgNotAName", - score: 1, - level: "A", - trust: "1", - ref: "7d6734", - scs: "1.1.1", - dis: "43353", - result: "failed", - }, - table_07: { - type: "true", - elem: "all", - test: "tableHdr", - score: 10, - level: "A", - trust: "1", - ref: "d0f69e", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - table_08: { - type: "prop", - elem: "tableData", - test: "tableHdrNot", - score: 1, - level: "A", - trust: "1", - ref: "d0f69e", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - textC_01: { - type: "true", - elem: "all", - test: "textContrastH", - score: 10, - level: "AAA", - trust: "1", - ref: "G17", - scs: "1.4.6", - dis: "43353", - result: "passed", - }, - textC_02: { - type: "fals", - elem: "all", - test: "textContrastHNot", - score: 5, - level: "AAA", - trust: "1", - ref: "G17", - scs: "1.4.6", - dis: "43353", - result: "warning", - }, - video_01: { - type: "true", - elem: "all", - test: "videoAudit", - score: 10, - level: "A", - trust: "0.9", - ref: "G87", - scs: "1.2.2,1.2.4", - dis: "43353", - result: "warning", - }, - video_02: { - type: "true", - elem: "all", - test: "videoVisual", - score: 10, - level: "A", - trust: "0.9", - ref: "G8", - scs: "1.2.3,1.2.5,1.2.7", - dis: "43353", - result: "warning", - }, - label_01: { - type: "true", - elem: "all", - test: "labelAName", - score: 10, - level: "A", - trust: "1", - ref: "G208", - scs: "2.5.3", - dis: "43353", - result: "passed", - }, - label_03: { - type: "fals", - elem: "all", - test: "labelANameNot", - score: 1, - level: "A", - trust: "1", - ref: "G208", - scs: "2.5.3", - dis: "43353", - result: "failed", - }, - word_01: { - type: "true", - elem: "all", - test: "wordSpacing", - score: 10, - level: "AA", - trust: "1", - ref: "9e45ec", - scs: "1.4.12", - dis: "43353", - result: "passed", - }, - word_02: { - type: "fals", - elem: "all", - test: "wordSpacingNot", - score: 3, - level: "AA", - trust: "1", - ref: "9e45ec", - scs: "1.4.12", - dis: "43353", - result: "failed", - }, - css_02: { - type: "true", - elem: "all", - test: "overflow", - score: 10, - level: "AA", - trust: "0.5", - ref: "59br37", - scs: "1.4.4", - dis: "43353", - result: "warning", - }, - landmark_01: { - type: "true", - elem: "all", - test: "bannerTopLevel", - score: 10, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1,2.4.1", - dis: "43353", - result: "passed", - }, - landmark_02: { - type: "fals", - elem: "all", - test: "bannerNotTopLevel", - score: 3, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1,2.4.1", - dis: "43353", - result: "failed", - }, - landmark_03: { - type: "true", - elem: "all", - test: "complementaryTopLevel", - score: 10, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - landmark_04: { - type: "fals", - elem: "all", - test: "complementaryNotTopLevel", - score: 3, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - landmark_05: { - type: "true", - elem: "all", - test: "contentinfoTopLevel", - score: 10, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - landmark_06: { - type: "fals", - elem: "all", - test: "contentinfoNotTopLevel", - score: 3, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - landmark_07: { - type: "true", - elem: "all", - test: "mainTopLevel", - score: 10, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - landmark_08: { - type: "fals", - elem: "all", - test: "mainNotTopLevel", - score: 3, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - landmark_09: { - type: "true", - elem: "all", - test: "noDuplicateBanner", - score: 10, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1,2.4.1", - dis: "43353", - result: "passed", - }, - landmark_10: { - type: "fals", - elem: "all", - test: "duplicateBanner", - score: 3, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1,2.4.1", - dis: "43353", - result: "failed", - }, - landmark_11: { - type: "true", - elem: "all", - test: "noDuplicateContentinfo", - score: 10, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - landmark_12: { - type: "fals", - elem: "all", - test: "duplicateContentinfo", - score: 3, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - landmark_13: { - type: "true", - elem: "all", - test: "noDuplicateMain", - score: 10, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - landmark_14: { - type: "fals", - elem: "all", - test: "duplicateMain", - score: 3, - level: "AA", - trust: "1", - ref: "ARIA11", - scs: "1.3.1,2.4.1", - dis: "43353", - result: "failed", - }, - listitem_01: { - type: "true", - elem: "li", - test: "liSemantically", - score: 10, - level: "AA", - trust: "1", - ref: "H48", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - listitem_02: { - type: "prop", - elem: "li", - test: "liNotSemantically", - score: 3, - level: "AA", - trust: "1", - ref: "H48", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - list_02: { - type: "true", - elem: "li", - test: "listCorrectly", - score: 10, - level: "AA", - trust: "1", - ref: "H48", - scs: "1.3.1", - dis: "43353", - result: "passed", - }, - list_03: { - type: "prop", - elem: "li", - test: "listNotCorrectly", - score: 3, - level: "AA", - trust: "1", - ref: "H48", - scs: "1.3.1", - dis: "43353", - result: "failed", - }, - list_04: { - type: "true", - elem: "dd,dt", - test: "descListElement", - score: 10, - level: "AAA", - trust: "1", - ref: "H40", - scs: "3.1.3", - dis: "43353", - result: "passed", - }, - list_05: { - type: "prop", - elem: "dd,dt", - test: "notDescListElement", - score: 5, - level: "AAA", - trust: "1", - ref: "H40", - scs: "3.1.3", - dis: "43353", - result: "failed", - }, - list_06: { - type: "true", - elem: "dl", - test: "descList", - score: 10, - level: "AAA", - trust: "1", - ref: "H40", - scs: "3.1.3", - dis: "43353", - result: "passed", - }, - list_07: { - type: "prop", - elem: "dl", - test: "notDescList", - score: 5, - level: "AAA", - trust: "1", - ref: "H40", - scs: "3.1.3", - dis: "43353", - result: "failed", - }, -}; +export default { + img_01a: { + type: "fals", + elem: "img", + test: "imgAlt", + score: 10, + level: "a", + trust: "0.5", + ref: "H37", + scs: "1.1.1", + dis: "53322", + result: "passed", + }, + img_01b: { + type: "prop", + elem: "img", + test: "imgAltNo", + score: 1, + level: "A", + trust: "1", + ref: "F65", + scs: "1.1.1", + dis: "53322", + result: "failed", + }, + img_02: { + type: "prop", + elem: "img", + test: "imgAltNull", + score: 7, + level: "a", + trust: "1", + ref: "C9", + scs: "1.1.1", + dis: "41111", + result: "warning", + }, + img_03: { + type: "decr", + elem: "img", + test: "imgAltNot", + score: 1, + level: "A", + trust: "1", + top: 1, + steps: 1, + ref: "F30", + scs: "1.1.1,1.2.1", + dis: "53211", + result: "failed", + }, + img_04: { + type: "prop", + elem: "img", + test: "imgAltLong", + score: 1, + level: "a", + trust: "0.3", + ref: "H45", + scs: "1.1.1", + dis: "54153", + result: "warning", + }, + area_01a: { + type: "fals", + elem: "area", + test: "areaAltYes", + score: 10, + level: "a", + trust: "0.5", + ref: "H24", + scs: "1.1.1,2.4.4,2.4.9", + dis: "54222", + result: "passed", + }, + area_01b: { + type: "prop", + elem: "area", + test: "areaAltNo", + score: 1, + level: "A", + trust: "1", + ref: "F65", + scs: "1.1.1", + dis: "53322", + result: "failed", + }, + inp_img_01a: { + type: "fals", + elem: "inpImg", + test: "inpImgAltYes", + score: 10, + level: "a", + trust: "0.9", + ref: "H36", + scs: "1.1.1,4.1.2", + dis: "54211", + result: "passed", + }, + inp_img_01b: { + type: "prop", + elem: "inpImg", + test: "inpImgAltNo", + score: 1, + level: "A", + trust: "1", + ref: "F65", + scs: "1.1.1,4.1.2", + dis: "53322", + result: "failed", + }, + a_04: { + type: "fals", + elem: "all", + test: "a", + score: 7, + level: "AA", + trust: "1", + ref: "G125", + scs: "2.4.5", + dis: "54353", + result: "failed", + }, + a_03: { + type: "decr", + elem: "a", + test: "aImgAltNo", + score: 1, + level: "A", + trust: "1", + top: 1, + steps: 1, + ref: "F89", + scs: "2.4.4,2.4.9,4.1.2", + dis: "53322", + result: "failed", + }, + a_05: { + type: "prop", + elem: "a", + test: "aTitleMatch", + score: 1, + level: "a", + trust: "1", + ref: "H33", + scs: "2.4.4,2.4.9", + dis: "52132", + result: "failed", + }, + a_09: { + type: "decr", + elem: "a", + test: "aSameText", + score: 5, + level: "AAA", + trust: "1", + top: 1, + steps: 1, + ref: "F84", + scs: "2.4.9", + dis: "52122", + result: "warning", + }, + a_06: { + type: "decr", + elem: "a", + test: "aAdjacentSame", + score: 1, + level: "A", + trust: "1", + top: 1, + steps: 1, + ref: "H2", + scs: "1.1.1,2.4.4,2.4.9", + dis: "54353", + result: "failed", + }, + a_01a: { + type: "true", + elem: "a", + test: "aSkipFirst", + score: 10, + level: "a", + trust: "0.5", + ref: "G1", + scs: "2.4.1", + dis: "43522", + result: "warning", + }, + a_01b: { + type: "fals", + elem: "a", + test: "aSkipFirstNo", + score: 1, + level: "a", + trust: "0.5", + ref: "G1", + scs: "2.4.1", + dis: "43522", + result: "warning", + }, + a_02a: { + type: "fals", + elem: "a", + test: "aSkipNo", + score: 1, + level: "a", + trust: "0.5", + ref: "G123", + scs: "2.4.1", + dis: "43522", + result: "failed", + }, + a_02b: { + type: "true", + elem: "a", + test: "aSkip", + score: 10, + level: "a", + trust: "0.5", + ref: "G123", + scs: "2.4.1", + dis: "43522", + result: "warning", + }, + hx_01a: { + type: "fals", + elem: "all", + test: "hxNone", + score: 1, + level: "A", + trust: "1", + ref: "H42", + scs: "1.3.1", + dis: "54322", + result: "failed", + }, + hx_01b: { + type: "true", + elem: "all", + test: "hx", + score: 10, + level: "aaa", + trust: "1", + ref: "G141", + scs: "1.3.1,2.4.10", + dis: "54343", + result: "warning", + }, + hx_01c: { + type: "fals", + elem: "hx", + test: "h1", + score: 5, + level: "aaa", + trust: "1", + ref: "G141", + scs: "1.3.1,2.4.10", + dis: "54343", + result: "failed", + }, + hx_03: { + type: "prop", + elem: "hx", + test: "hxSkip", + score: 5, + level: "AAA", + trust: "1", + ref: "G141", + scs: "1.3.1,2.4.10", + dis: "54343", + result: "failed", + }, + hx_02: { + type: "true", + elem: "hx", + test: "hxNo", + score: 1, + level: "AA", + trust: "1", + ref: "G130", + scs: "2.4.6", + dis: "54253", + result: "failed", + }, + list_01: { + type: "decr", + elem: "all", + test: "liNoList", + score: 1, + level: "A", + trust: "1", + top: 3, + steps: 3, + ref: "H48", + scs: "1.3.1", + dis: "53342", + result: "failed", + }, + br_01: { + type: "decr", + elem: "all", + test: "brSec", + score: 1, + level: "a", + trust: "0.5", + top: 1, + steps: 1, + ref: "H48", + scs: "1.3.1", + dis: "53342", + result: "failed", + }, + field_02: { + type: "decr", + elem: "all", + test: "fieldNoForm", + score: 1, + level: "A", + trust: "0.5", + top: 1, + steps: 1, + ref: "H71", + scs: "1.3.1,3.3.2", + dis: "54152", + result: "warning", + }, + field_01: { + type: "true", + elem: "all", + test: "fieldLegNo", + score: 1, + level: "A", + trust: "1", + ref: "H71", + scs: "1.3.1,3.3.2", + dis: "54152", + result: "failed", + }, + label_02: { + type: "decr", + elem: "all", + test: "labelPosNo", + score: 1, + level: "A", + trust: "0.7", + top: 1, + steps: 1, + ref: "G162", + scs: "1.3.1,3.3.2", + dis: "43353", + result: "failed", + }, + input_02b: { + type: "fals", + elem: "all", + test: "inputLabel", + score: 10, + level: "a", + trust: "0.5", + ref: "H44", + scs: "1.1.1,1.3.1,3.3.2,4.1.2", + dis: "54532", + result: "passed", + }, + input_02: { + type: "prop", + elem: "label", + test: "inputLabelNo", + score: 1, + level: "a", + trust: "1", + ref: "H44", + scs: "1.1.1,1.3.1,3.3.2,4.1.2", + dis: "54532", + result: "failed", + }, + input_01: { + type: "prop", + elem: "inputLabel", + test: "inputIdTitleNo", + score: 1, + level: "A", + trust: "1", + ref: "H65", + scs: "1.1.1,1.3.1,3.3.2,4.1.2", + dis: "53122", + result: "failed", + }, + focus_01: { + type: "true", + elem: "all", + test: "focusBlur", + score: 1, + level: "a", + trust: "0.8", + ref: "F55", + scs: "2.1.1,2.4.7,3.2.1", + dis: "54142", + result: "failed", + }, + input_03: { + type: "true", + elem: "all", + test: "inputAltNo", + score: 5, + level: "a", + trust: "1", + ref: "H36", + scs: "1.1.1", + dis: "54211", + result: "failed", + }, + form_01a: { + type: "fals", + elem: "form", + test: "formSubmit", + score: 10, + level: "a", + trust: "1", + ref: "H32", + scs: "3.2.2", + dis: "21211", + result: "passed", + }, + form_01b: { + type: "prop", + elem: "form", + test: "formSubmitNo", + score: 1, + level: "A", + trust: "0.7", + ref: "H32", + scs: "3.2.2", + dis: "21211", + result: "failed", + }, + table_02: { + type: "prop", + elem: "tableData", + test: "tableDataCaption", + score: 1, + level: "A", + trust: "1", + ref: "H39", + scs: "1.3.1", + dis: "52211", + result: "failed", + }, + table_03: { + type: "prop", + elem: "table", + test: "tableCaptionSummary", + score: 5, + level: "A", + trust: "1", + ref: "H73", + scs: "1.3.1", + dis: "33152", + result: "failed", + }, + table_01: { + type: "prop", + elem: "tableLayout", + test: "tableLayoutCaption", + score: 1, + level: "A", + trust: "1", + ref: "F46", + scs: "1.3.1", + dis: "51421", + result: "warning", + }, + table_06: { + type: "decr", + elem: "tableComplex", + test: "tableComplexError", + score: 1, + level: "a", + trust: "0.8", + top: 1, + steps: 1, + ref: "H43", + scs: "1.3.1", + dis: "53211", + result: "failed", + }, + scope_01: { + type: "decr", + elem: "table", + test: "scopeNo", + score: 1, + level: "A", + trust: "1", + top: 1, + steps: 1, + ref: "H63", + scs: "1.3.1", + dis: "53353", + result: "failed", + }, + table_05a: { + type: "decr", + elem: "all", + test: "tableLayout", + score: 1, + level: "a", + trust: "1", + top: 1, + steps: 1, + ref: "H51", + scs: "1.3.1", + dis: "53352", + result: "failed", + }, + table_04: { + type: "prop", + elem: "table", + test: "tableNested", + score: 1, + level: "a", + trust: "1", + ref: "F49", + scs: "1.3.2", + dis: "53311", + result: "failed", + }, + iframe_01: { + type: "prop", + elem: "iframe", + test: "iframeTitleNo", + score: 1, + level: "A", + trust: "1", + ref: "H64", + scs: "2.4.1,4.1.2", + dis: "53222", + result: "failed", + }, + frame_01: { + type: "prop", + elem: "frame", + test: "frameTitleNo", + score: 3, + level: "A", + trust: "1", + ref: "H64", + scs: "2.4.1,4.1.2", + dis: "53222", + result: "failed", + }, + win_01: { + type: "true", + elem: "all", + test: "newWinOnLoad", + score: 3, + level: "AAA", + trust: "0.9", + ref: "F52", + scs: "3.2.5", + dis: "53454", + result: "warning", + }, + abbr_01: { + type: "true", + elem: "all", + test: "abbrNo", + score: 5, + level: "AAA", + trust: "1", + ref: "G102", + scs: "3.1.4", + dis: "42153", + result: "failed", + }, + css_01: { + type: "decr", + elem: "all", + test: "lineHeightNo", + score: 3, + level: "AA", + trust: "1", + top: 1, + steps: 1, + ref: "C21", + scs: "1.4.8,1.4.12", + dis: "15153", + result: "warning", + }, + justif_txt_01: { + type: "decr", + elem: "all", + test: "justifiedTxt", + score: 5, + level: "AAA", + trust: "1", + top: 1, + steps: 1, + ref: "F88", + scs: "1.4.8", + dis: "15152", + result: "failed", + }, + justif_txt_02: { + type: "decr", + elem: "all", + test: "justifiedCss", + score: 5, + level: "AAA", + trust: "0.9", + top: 1, + steps: 1, + ref: "C19", + scs: "1.4.8", + dis: "14142", + result: "warning", + }, + font_02: { + type: "prop", + elem: "fontValues", + test: "fontAbsVal", + score: 3, + level: "AA", + trust: "1", + ref: "C12", + scs: "1.4.4", + dis: "15123", + result: "failed", + }, + layout_03: { + type: "decr", + elem: "all", + test: "layoutFixed", + score: 3, + level: "aa", + trust: "1", + top: 1, + steps: 1, + ref: "G146", + scs: "1.4.4,1.4.8", + dis: "15222", + result: "failed", + }, + values_02a: { + type: "decr", + elem: "all", + test: "valueAbsCss", + score: 5, + level: "AAA", + trust: "0.9", + top: 1, + steps: 1, + ref: "C24", + scs: "1.4.8", + dis: "15113", + result: "warning", + }, + values_02b: { + type: "true", + elem: "all", + test: "valueRelCss", + score: 10, + level: "aaa", + trust: "1", + ref: "C24", + scs: "1.4.8", + dis: "15113", + result: "passed", + }, + values_01a: { + type: "decr", + elem: "all", + test: "valueAbsHtml", + score: 3, + level: "AA", + trust: "0.9", + top: 1, + steps: 1, + ref: "G146", + scs: "1.4.4", + dis: "15222", + result: "warning", + }, + values_01b: { + type: "true", + elem: "all", + test: "valueRelHtml", + score: 10, + level: "aa", + trust: "0.9", + ref: "G146", + scs: "1.4.4", + dis: "15222", + result: "passed", + }, + color_02: { + type: "decr", + elem: "all", + test: "colorContrast", + score: 1, + level: "AA", + trust: "1", + top: 1, + steps: 1, + ref: "G145", + scs: "1.4.3", + dis: "15113", + result: "failed", + }, + color_01: { + type: "true", + elem: "all", + test: "colorFgBgNo", + score: 3, + level: "aa", + trust: "0.9", + ref: "F24", + scs: "1.4.3,1.4.6,1.4.8", + dis: "13113", + result: "warning", + }, + blink_02: { + type: "true", + elem: "all", + test: "cssBlink", + score: 1, + level: "A", + trust: "0.9", + ref: "F4", + scs: "2.2.2", + dis: "15152", + result: "failed", + }, + /*'ehandler_01': { + 'type': 'true', + 'elem': 'ehandler', + 'test': 'ehandMouse', + 'score': 1, + 'level': 'A', + 'trust': '1', + 'ref': 'F54', + 'scs': '2.1.1', + 'dis': '53512', + 'result': 'warning' + },*/ + ehandler_03: { + type: "true", + elem: "ehandler", + test: "ehandBoth", + score: 10, + level: "a", + trust: "0.9", + ref: "G90", + scs: "2.1.1,2.1.3", + dis: "52522", + result: "passed", + }, + ehandler_02: { + type: "prop", + elem: "ehandler", + test: "ehandBothNo", + score: 1, + level: "A", + trust: "1", + ref: "SCR20", + scs: "2.1.1,2.1.3", + dis: "53511", + result: "failed", + }, + ehandler_04: { + type: "prop", + elem: "ehandler", + test: "ehandTagNo", + score: 1, + level: "A", + trust: "0.8", + ref: "F59", + scs: "4.1.2", + dis: "43411", + result: "failed", + }, + w3c_validator_01a: { + type: "fals", + elem: "w3cValidator", + test: "w3cValidatorErrorsNo", + score: 10, + level: "a", + trust: "1", + ref: "G134", + scs: "4.1.1", + dis: "22232", + result: "passed", + }, + w3c_validator_01b: { + type: "decr", + elem: "w3cValidator", + test: "w3cValidatorErrors", + score: 1, + level: "A", + trust: "1", + top: 10, + steps: 10, + ref: "G134", + scs: "4.1.1", + dis: "22232", + result: "warning", + }, + font_01: { + type: "decr", + elem: "all", + test: "fontHtml", + score: 3, + level: "AA", + trust: "1", + top: 1, + steps: 1, + ref: "C22", + scs: "1.3.1,1.4.4,1.4.5,1.4.9", + dis: "33111", + result: "failed", + }, + layout_01a: { + type: "fals", + elem: "all", + test: "layoutElemNo", + score: 10, + level: "a", + trust: "1", + ref: "G115", + scs: "1.3.1", + dis: "34212", + result: "passed", + }, + layout_01b: { + type: "decr", + elem: "all", + test: "layoutElem", + score: 1, + level: "A", + trust: "1", + top: 2, + steps: 2, + ref: "G115", + scs: "1.3.1", + dis: "34212", + result: "failed", + }, + lang_01: { + type: "true", + elem: "all", + test: "lang", + score: 10, + level: "a", + trust: "0.8", + ref: "H57", + scs: "3.1.1", + dis: "53112", + result: "warning", + }, + lang_03: { + type: "true", + elem: "all", + test: "langNo", + score: 1, + level: "A", + trust: "1", + ref: "H57", + scs: "3.1.1", + dis: "53112", + result: "failed", + }, + lang_02: { + type: "true", + elem: "all", + test: "langCodeNo", + score: 1, + level: "A", + trust: "1", + ref: "H57", + scs: "3.1.1", + dis: "53112", + result: "failed", + }, + lang_04: { + type: "true", + elem: "all", + test: "langMatchNo", + score: 1, + level: "A", + trust: "1", + ref: "H57", + scs: "3.1.1", + dis: "53112", + result: "failed", + }, + title_02: { + type: "true", + elem: "all", + test: "titleNo", + score: 1, + level: "A", + trust: "1", + ref: "H25", + scs: "2.4.2", + dis: "52112", + result: "failed", + }, + title_03: { + type: "true", + elem: "all", + test: "titleNull", + score: 1, + level: "A", + trust: "1", + ref: "F25", + scs: "2.4.2", + dis: "33151", + result: "failed", + }, + title_06: { + type: "true", + elem: "all", + test: "titleOk", + score: 10, + level: "a", + trust: "0.5", + ref: "H25", + scs: "2.4.2", + dis: "52112", + result: "passed", + }, + title_04: { + type: "decr", + elem: "all", + test: "titleLong", + score: 10, + level: "a", + trust: "1", + top: 64, + steps: 10, + ref: "G88", + scs: "2.4.2", + dis: "42253", + result: "warning", + }, + title_05: { + type: "true", + elem: "all", + test: "titleChars", + score: 1, + level: "a", + trust: "0.5", + ref: "G88", + scs: "2.4.2", + dis: "42253", + result: "failed", + }, + title_01: { + type: "true", + elem: "all", + test: "titleVrs", + score: 7, + level: "A", + trust: "1", + ref: "H25", + scs: "2.4.2", + dis: "52112", + result: "failed", + }, + link_01: { + type: "true", + elem: "all", + test: "linkRel", + score: 10, + level: "aa", + trust: "0.9", + ref: "H59", + scs: "2.4.5,2.4.8", + dis: "55554", + result: "passed", + }, + meta_01: { + type: "true", + elem: "all", + test: "metaRefresh", + score: 1, + level: "A", + trust: "1", + ref: "F41", + scs: "2.2.1,2.2.4,3.2.5", + dis: "43353", + result: "warning", + }, + meta_02: { + type: "true", + elem: "all", + test: "metaRedir", + score: 1, + level: "A", + trust: "1", + ref: "F40", + scs: "2.2.1,2.2.4", + dis: "43353", + result: "warning", + }, + heading_01: { + type: "true", + elem: "hx", + test: "hxHasAName", + score: 10, + level: "A", + trust: "1", + ref: "H42", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + heading_02: { + type: "prop", + elem: "hx", + test: "hxWithoutAName", + score: 1, + level: "A", + trust: "1", + ref: "H42", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + aria_01: { + type: "true", + elem: "all", + test: "ariaCntxRole", + score: 10, + level: "A", + trust: "1", + ref: "ff89c9", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + aria_02: { + type: "true", + elem: "all", + test: "ariaReqElem", + score: 10, + level: "A", + trust: "1", + ref: "bc4a75", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + aria_03: { + type: "true", + elem: "all", + test: "ariaStValid", + score: 10, + level: "A", + trust: "1", + ref: "6a7281", + scs: "1.3.1,4.1.2", + dis: "43353", + result: "passed", + }, + aria_04: { + type: "fals", + elem: "all", + test: "ariaStNotValid", + score: 1, + level: "A", + trust: "1", + ref: "6a7281", + scs: "1.3.1,4.1.2", + dis: "43353", + result: "failed", + }, + aria_05: { + type: "true", + elem: "all", + test: "ariaStPermitted", + score: 10, + level: "A", + trust: "1", + ref: "5c01ea", + scs: "1.3.1,4.1.2", + dis: "43353", + result: "passed", + }, + aria_06: { + type: "fals", + elem: "all", + test: "ariaStNotPermitted", + score: 1, + level: "A", + trust: "1", + ref: "5c01ea", + scs: "1.3.1,4.1.2", + dis: "43353", + result: "failed", + }, + aria_07: { + type: "true", + elem: "all", + test: "ariaAtribDefined", + score: 10, + level: "A", + trust: "1", + ref: "5f99a7", + scs: "1.3.1,4.1.2", + dis: "43353", + result: "passed", + }, + aria_08: { + type: "fals", + elem: "all", + test: "ariaAtribNotDefined", + score: 1, + level: "A", + trust: "1", + ref: "5f99a7", + scs: "1.3.1,4.1.2", + dis: "43353", + result: "failed", + }, + aria_09: { + type: "prop", + elem: "all", + test: "ariaControlsIdNotFound", + score: 1, + level: "A", + trust: "1", + ref: "in6db8", + scs: "1.3.1,4.1.2", + dis: "43353", + result: "failed", + }, + aria_10: { + type: "true", + elem: "all", + test: "ariaControlsIdFound", + score: 10, + level: "A", + trust: "1", + ref: "in6db8", + scs: "1.3.1,4.1.2", + dis: "43353", + result: "passed", + }, + audio_video_01: { + type: "true", + elem: "all", + test: "audioAvoidsAutoPlay", + score: 10, + level: "A", + trust: "1", + ref: "80f0bf", + scs: "1.4.2", + dis: "43353", + result: "passed", + }, + audio_video_02: { + type: "fals", + elem: "all", + test: "audioAutoPlay", + score: 1, + level: "A", + trust: "1", + ref: "80f0bf", + scs: "1.4.2", + dis: "43353", + result: "failed", + }, + autocomplete_01: { + type: "true", + elem: "all", + test: "autoCmpltValid", + score: 10, + level: "A", + trust: "1", + ref: "73f2c2", + scs: "1.3.5", + dis: "43353", + result: "passed", + }, + autocomplete_02: { + type: "fals", + elem: "all", + test: "autoCmpltNotValid", + score: 1, + level: "A", + trust: "1", + ref: "73f2c2", + scs: "1.3.5", + dis: "43353", + result: "failed", + }, + button_01: { + type: "true", + elem: "button", + test: "buttonAname", + score: 10, + level: "A", + trust: "1", + ref: "97a4e1", + scs: "4.1.2", + dis: "43353", + result: "passed", + }, + button_02: { + type: "prop", + elem: "button", + test: "buttonNotAname", + score: 1, + level: "A", + trust: "1", + ref: "97a4e1", + scs: "4.1.2", + dis: "43353", + result: "failed", + }, + element_01: { + type: "true", + elem: "all", + test: "seqFocus", + score: 10, + level: "AA", + trust: "1", + ref: "oj04fd", + scs: "2.4.7", + dis: "43353", + result: "warning", + }, + element_02: { + type: "true", + elem: "all", + test: "elementDec", + score: 10, + level: "A", + trust: "1", + ref: "6cfa84", + scs: "4.1.2", + dis: "43353", + result: "passed", + }, + element_03: { + type: "fals", + elem: "all", + test: "elementNotDec", + score: 1, + level: "A", + trust: "1", + ref: "6cfa84", + scs: "4.1.2", + dis: "43353", + result: "failed", + }, + element_04: { + type: "true", + elem: "all", + test: "elementHiddenFocus", + score: 10, + level: "A", + trust: "1", + ref: "46ca7f", + scs: "4.1.2", + dis: "43353", + result: "passed", + }, + element_05: { + type: "fals", + elem: "all", + test: "elementNotHiddenFocus", + score: 1, + level: "A", + trust: "1", + ref: "46ca7f", + scs: "4.1.2", + dis: "43353", + result: "failed", + }, + element_06: { + type: "true", + elem: "all", + test: "elementLang", + score: 10, + level: "AA", + trust: "1", + ref: "H58", + scs: "3.1.2", + dis: "43353", + result: "passed", + }, + element_07: { + type: "fals", + elem: "all", + test: "elementNotLang", + score: 3, + level: "AA", + trust: "1", + ref: "H58", + scs: "3.1.2", + dis: "43353", + result: "failed", + }, + element_08: { + type: "true", + elem: "all", + test: "elementPresentChildrenNoFocus", + score: 10, + level: "A", + trust: "1", + ref: "307n5z", + scs: "4.1.2", + dis: "43353", + result: "passed", + }, + element_09: { + type: "fals", + elem: "all", + test: "elementPresentChildrenFocus", + score: 1, + level: "A", + trust: "1", + ref: "307n5z", + scs: "4.1.2", + dis: "43353", + result: "failed", + }, + element_10: { + type: "true", + elem: "all", + test: "elementRole", + score: 10, + level: "A", + trust: "1", + ref: "4e8ab6", + scs: "4.1.2,1.3.1", + dis: "43353", + result: "passed", + }, + headers_01: { + type: "true", + elem: "headers", + test: "headerAtt", + score: 10, + level: "A", + trust: "1", + ref: "H43", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + headers_02: { + type: "prop", + elem: "headers", + test: "headerAttNot", + score: 1, + level: "A", + trust: "1", + ref: "H43", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + id_01: { + type: "true", + elem: "id", + test: "idAtt", + score: 10, + level: "A", + trust: "1", + ref: "H93", + scs: "4.1.1", + dis: "43353", + result: "passed", + }, + id_02: { + type: "prop", + elem: "id", + test: "idAttNot", + score: 1, + level: "A", + trust: "1", + ref: "H93", + scs: "4.1.1", + dis: "43353", + result: "failed", + }, + iframe_02: { + type: "true", + elem: "iframeSame", + test: "iframeSameAName", + score: 10, + level: "A", + trust: "1", + ref: "4b1c6c", + scs: "4.1.2", + dis: "43353", + result: "passed", + }, + iframe_03: { + type: "prop", + elem: "iframeSame", + test: "iframeSameANameDiferent", + score: 1, + level: "A", + trust: "0.5", + ref: "4b1c6c", + scs: "4.1.2", + dis: "43353", + result: "warning", + }, + iframe_04: { + type: "true", + elem: "all", + test: "iframeNegTabIndex", + score: 10, + level: "A", + trust: "1", + ref: "G202", + scs: "2.1.1", + dis: "43353", + result: "passed", + }, + iframe_05: { + type: "fals", + elem: "all", + test: "iframeNegTabIndexNot", + score: 1, + level: "A", + trust: "1", + top: 1, + steps: 1, + ref: "G202", + scs: "2.1.1", + dis: "43353", + result: "failed", + }, + letter_01: { + type: "true", + elem: "all", + test: "letterSpacing", + score: 10, + level: "AA", + trust: "1", + ref: "24afc2", + scs: "1.4.12", + dis: "43353", + result: "passed", + }, + letter_02: { + type: "decr", + elem: "all", + test: "letterSpacingNot", + score: 3, + level: "AA", + trust: "1", + top: 1, + steps: 1, + ref: "24afc2", + scs: "1.4.12", + dis: "43353", + result: "failed", + }, + a_10: { + type: "true", + elem: "all", + test: "linkAName", + score: 10, + level: "A", + trust: "1", + ref: "G91", + scs: "4.1.2,2.4.4,2.4.9", + dis: "43353", + result: "passed", + }, + a_11: { + type: "prop", + elem: "a", + test: "linkNotAName", + score: 1, + level: "A", + trust: "1", + ref: "G91", + scs: "4.1.2,2.4.4,2.4.9", + dis: "43353", + result: "failed", + }, + a_12: { + type: "true", + elem: "all", + test: "linkIdentAName", + score: 10, + level: "A", + trust: "1", + ref: "fd3a94", + scs: "2.4.4", + dis: "43353", + result: "passed", + }, + a_13: { + type: "prop", + elem: "a", + test: "linkIdentANameNot", + score: 1, + level: "A", + trust: "0.5", + ref: "fd3a94", + scs: "2.4.4", + dis: "43353", + result: "warning", + }, + menuItem_01: { + type: "true", + elem: "menuItem", + test: "menuItemAName", + score: 10, + level: "A", + trust: "1", + ref: "m6b1q3", + scs: "4.1.2", + dis: "43353", + result: "passed", + }, + menuItem_02: { + type: "prop", + elem: "menuItem", + test: "menuItemANameNot", + score: 1, + level: "A", + trust: "1", + ref: "m6b1q3", + scs: "4.1.2", + dis: "43353", + result: "failed", + }, + meta_03: { + type: "true", + elem: "all", + test: "metaRefresh", + score: 10, + level: "AAA", + trust: "1", + ref: "G110", + scs: "2.2.4,3.2.5", + dis: "43353", + result: "passed", + }, + meta_04: { + type: "fals", + elem: "all", + test: "metaRefreshNot", + score: 5, + level: "AAA", + trust: "1", + ref: "G110", + scs: "2.2.4,3.2.5", + dis: "43353", + result: "failed", + }, + meta_05: { + type: "true", + elem: "all", + test: "metaViewport", + score: 10, + level: "AA", + trust: "1", + ref: "b4f0c3", + scs: "1.4.4", + dis: "43353", + result: "passed", + }, + object_01: { + type: "true", + elem: "object", + test: "objectAName", + score: 10, + level: "A", + trust: "1", + ref: "b4f0c3", + scs: "1.1.1", + dis: "43353", + result: "passed", + }, + object_02: { + type: "prop", + elem: "object", + test: "objectANameNot", + score: 1, + level: "A", + trust: "1", + ref: "b4f0c3", + scs: "1.1.1", + dis: "43353", + result: "failed", + }, + orientation_01: { + type: "true", + elem: "all", + test: "orientationCSS", + score: 10, + level: "AA", + trust: "1", + ref: "b33eff", + scs: "1.3.4", + dis: "43353", + result: "passed", + }, + orientation_02: { + type: "fals", + elem: "all", + test: "orientationCSSNot", + score: 3, + level: "AA", + trust: "1", + ref: "b33eff", + scs: "1.3.4", + dis: "43353", + result: "failed", + }, + role_01: { + type: "true", + elem: "all", + test: "roleValid", + score: 10, + level: "AA", + trust: "1", + ref: "674b10", + scs: "4.1.2", + dis: "43353", + result: "passed", + }, + role_02: { + type: "decr", + elem: "all", + test: "roleValidNot", + score: 5, + level: "AA", + trust: "1", + top: 1, + steps: 1, + ref: "674b10", + scs: "4.1.2", + dis: "43353", + result: "failed", + }, + scrollable_01: { + type: "true", + elem: "scrollable", + test: "scrollableAccess", + score: 10, + level: "A", + trust: "1", + ref: "G202", + scs: "2.1.1,2.1.3", + dis: "43353", + result: "passed", + }, + scrollable_02: { + type: "prop", + elem: "scrollable", + test: "scrollableAccessNot", + score: 1, + level: "A", + trust: "1", + ref: "G202", + scs: "2.1.1,2.1.3", + dis: "43353", + result: "failed", + }, + svg_01: { + type: "true", + elem: "svg", + test: "svgAName", + score: 10, + level: "A", + trust: "1", + ref: "7d6734", + scs: "1.1.1", + dis: "43353", + result: "passed", + }, + svg_02: { + type: "prop", + elem: "svg", + test: "svgNotAName", + score: 1, + level: "A", + trust: "1", + ref: "7d6734", + scs: "1.1.1", + dis: "43353", + result: "failed", + }, + table_07: { + type: "true", + elem: "all", + test: "tableHdr", + score: 10, + level: "A", + trust: "1", + ref: "d0f69e", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + table_08: { + type: "prop", + elem: "tableData", + test: "tableHdrNot", + score: 1, + level: "A", + trust: "1", + ref: "d0f69e", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + textC_01: { + type: "true", + elem: "all", + test: "textContrastH", + score: 10, + level: "AAA", + trust: "1", + ref: "G17", + scs: "1.4.6", + dis: "43353", + result: "passed", + }, + textC_02: { + type: "fals", + elem: "all", + test: "textContrastHNot", + score: 5, + level: "AAA", + trust: "1", + ref: "G17", + scs: "1.4.6", + dis: "43353", + result: "warning", + }, + video_01: { + type: "true", + elem: "all", + test: "videoAudit", + score: 10, + level: "A", + trust: "0.9", + ref: "G87", + scs: "1.2.2,1.2.4", + dis: "43353", + result: "warning", + }, + video_02: { + type: "true", + elem: "all", + test: "videoVisual", + score: 10, + level: "A", + trust: "0.9", + ref: "G8", + scs: "1.2.3,1.2.5,1.2.7", + dis: "43353", + result: "warning", + }, + label_01: { + type: "true", + elem: "all", + test: "labelAName", + score: 10, + level: "A", + trust: "1", + ref: "G208", + scs: "2.5.3", + dis: "43353", + result: "passed", + }, + label_03: { + type: "fals", + elem: "all", + test: "labelANameNot", + score: 1, + level: "A", + trust: "1", + ref: "G208", + scs: "2.5.3", + dis: "43353", + result: "failed", + }, + word_01: { + type: "true", + elem: "all", + test: "wordSpacing", + score: 10, + level: "AA", + trust: "1", + ref: "9e45ec", + scs: "1.4.12", + dis: "43353", + result: "passed", + }, + word_02: { + type: "fals", + elem: "all", + test: "wordSpacingNot", + score: 3, + level: "AA", + trust: "1", + ref: "9e45ec", + scs: "1.4.12", + dis: "43353", + result: "failed", + }, + css_02: { + type: "true", + elem: "all", + test: "overflow", + score: 10, + level: "AA", + trust: "0.5", + ref: "59br37", + scs: "1.4.4", + dis: "43353", + result: "warning", + }, + landmark_01: { + type: "true", + elem: "all", + test: "bannerTopLevel", + score: 10, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1,2.4.1", + dis: "43353", + result: "passed", + }, + landmark_02: { + type: "fals", + elem: "all", + test: "bannerNotTopLevel", + score: 3, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1,2.4.1", + dis: "43353", + result: "failed", + }, + landmark_03: { + type: "true", + elem: "all", + test: "complementaryTopLevel", + score: 10, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + landmark_04: { + type: "fals", + elem: "all", + test: "complementaryNotTopLevel", + score: 3, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + landmark_05: { + type: "true", + elem: "all", + test: "contentinfoTopLevel", + score: 10, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + landmark_06: { + type: "fals", + elem: "all", + test: "contentinfoNotTopLevel", + score: 3, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + landmark_07: { + type: "true", + elem: "all", + test: "mainTopLevel", + score: 10, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + landmark_08: { + type: "fals", + elem: "all", + test: "mainNotTopLevel", + score: 3, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + landmark_09: { + type: "true", + elem: "all", + test: "noDuplicateBanner", + score: 10, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1,2.4.1", + dis: "43353", + result: "passed", + }, + landmark_10: { + type: "fals", + elem: "all", + test: "duplicateBanner", + score: 3, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1,2.4.1", + dis: "43353", + result: "failed", + }, + landmark_11: { + type: "true", + elem: "all", + test: "noDuplicateContentinfo", + score: 10, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + landmark_12: { + type: "fals", + elem: "all", + test: "duplicateContentinfo", + score: 3, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + landmark_13: { + type: "true", + elem: "all", + test: "noDuplicateMain", + score: 10, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + landmark_14: { + type: "fals", + elem: "all", + test: "duplicateMain", + score: 3, + level: "AA", + trust: "1", + ref: "ARIA11", + scs: "1.3.1,2.4.1", + dis: "43353", + result: "failed", + }, + listitem_01: { + type: "true", + elem: "li", + test: "liSemantically", + score: 10, + level: "AA", + trust: "1", + ref: "H48", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + listitem_02: { + type: "prop", + elem: "li", + test: "liNotSemantically", + score: 3, + level: "AA", + trust: "1", + ref: "H48", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + list_02: { + type: "true", + elem: "li", + test: "listCorrectly", + score: 10, + level: "AA", + trust: "1", + ref: "H48", + scs: "1.3.1", + dis: "43353", + result: "passed", + }, + list_03: { + type: "prop", + elem: "li", + test: "listNotCorrectly", + score: 3, + level: "AA", + trust: "1", + ref: "H48", + scs: "1.3.1", + dis: "43353", + result: "failed", + }, + list_04: { + type: "true", + elem: "dd,dt", + test: "descListElement", + score: 10, + level: "AAA", + trust: "1", + ref: "H40", + scs: "3.1.3", + dis: "43353", + result: "passed", + }, + list_05: { + type: "prop", + elem: "dd,dt", + test: "notDescListElement", + score: 5, + level: "AAA", + trust: "1", + ref: "H40", + scs: "3.1.3", + dis: "43353", + result: "failed", + }, + list_06: { + type: "true", + elem: "dl", + test: "descList", + score: 10, + level: "AAA", + trust: "1", + ref: "H40", + scs: "3.1.3", + dis: "43353", + result: "passed", + }, + list_07: { + type: "prop", + elem: "dl", + test: "notDescList", + score: 5, + level: "AAA", + trust: "1", + ref: "H40", + scs: "3.1.3", + dis: "43353", + result: "failed", + }, +}; diff --git a/src/evaluation/testsColors.ts b/src/evaluation/testsColors.ts index 1d5b4b97..49adc3e5 100644 --- a/src/evaluation/testsColors.ts +++ b/src/evaluation/testsColors.ts @@ -1,184 +1,184 @@ -export default { - a_01a: "Y", - a_01b: "Y", - a_02a: "R", - a_02b: "Y", - a_03: "R", - a_04: "R", - a_05: "R", - a_06: "R", - a_09: "Y", - a_10: "G", - a_11: "R", - a_12: "G", - a_13: "R", - abbr_01: "R", - akey_01: "R", - applet_01: "R", - area_01a: "G", - area_01b: "R", - aria_01: "G", - aria_02: "G", - aria_03: "G", - aria_04: "R", - aria_05: "G", - aria_06: "R", - aria_07: "G", - aria_08: "R", - aria_09: "R", - aria_10: "G", - audio_video_01: "G", - audio_video_02: "R", - autocomplete_01: "G", - autocomplete_02: "R", - blink_01: "R", - blink_02: "R", - br_01: "R", - button_01: "G", - button_02: "R", - color_01: "Y", - color_02: "R", - css_01: "Y", - css_02:"Y", - dtd_01: "R", - ehandler_01: "Y", - ehandler_02: "R", - ehandler_03: "G", - ehandler_04: "R", - embed_01: "R", - element_01: "G", - element_02: "G", - element_03: "R", - element_04: "G", - element_05: "R", - element_06: "G", - element_07: "R", - element_08: "G", - element_09: "R", - element_10: "G", - field_01: "R", - field_02: "Y", - focus_01: "R", - font_01: "R", - font_02: "R", - form_01a: "G", - form_01b: "R", - frame_01: "R", - frame_02: "R", - heading_01:"G", - heading_02:"R", - headers_01: "G", - headers_02: "R", - hx_01a: "R", - hx_01b: "Y", - hx_01c: "R", - hx_02: "R", - hx_03: "R", - id_01: "G", - id_02: "R", - iframe_01: "R", - iframe_02: "G", - iframe_03: "R", - iframe_04: "G", - iframe_05: "R", - img_01a: "G", - img_01b: "R", - img_02: "Y", - img_03: "R", - img_04: "Y", - inp_img_01a: "G", - inp_img_01b: "R", - input_01: "R", - input_02: "R", - input_02b: "G", - input_03: "R", - justif_txt_01: "R", - justif_txt_02: "Y", - label_01: "G", - label_02: "R", - label_03: "R", - landmark_01:"G", - landmark_02: "R", - landmark_03: "G", - landmark_04: "R", - landmark_05: "G", - landmark_06: "R", - landmark_07: "G", - landmark_08: "R", - landmark_09: "G", - landmark_10: "R", - landmark_11: "G", - landmark_12: "R", - landmark_13: "G", - landmark_14: "R", - lang_01: "Y", - lang_02: "R", - lang_03: "R", - lang_04: "R", - lang_05: "R", - layout_01a: "G", - layout_01b: "R", - layout_02a: "G", - layout_02b: "R", - layout_03: "R", - letter_01: "G", - letter_02: "R", - link_01: "G", - list_01: "R", - list_02: "G", - list_03: "R", - list_04: "G", - list_05: "R", - list_06: "G", - list_07: "R", - listitem_01:"G", - listitem_02: "R", - long_01: "R", - marquee_01: "Y", - menuItem_01: "G", - menuItem_02: "R", - meta_01: "Y", - meta_02: "Y", - meta_03: "G", - meta_04: "R", - meta_05: "G", - object_01: "G", - object_02: "R", - orientation_01: "G", - orientation_02: "R", - role_01: "G", - role_02: "R", - scope_01: "R", - scrollable_01: "G", - scrollable_02: "R", - svg_01: "G", - svg_02: "R", - table_01: "Y", - table_02: "R", - table_03: "R", - table_04: "R", - table_05a: "R", - table_06: "R", - table_07: "G", - table_08: "R", - textC_01: "Y", - textC_02: "Y", - title_01: "R", - title_02: "R", - title_03: "R", - title_04: "Y", - title_05: "R", - title_06: "G", - title_07: "Y", - values_01a: "Y", - values_01b: "G", - values_02a: "Y", - values_02b: "G", - video_01: "G", - video_02: "G", - w3c_validator_01a: "G", - w3c_validator_01b: "Y", - win_01: "Y", - word_01: "G", - word_02: "R", -}; +export default { + a_01a: "Y", + a_01b: "Y", + a_02a: "R", + a_02b: "Y", + a_03: "R", + a_04: "R", + a_05: "R", + a_06: "R", + a_09: "Y", + a_10: "G", + a_11: "R", + a_12: "G", + a_13: "R", + abbr_01: "R", + akey_01: "R", + applet_01: "R", + area_01a: "G", + area_01b: "R", + aria_01: "G", + aria_02: "G", + aria_03: "G", + aria_04: "R", + aria_05: "G", + aria_06: "R", + aria_07: "G", + aria_08: "R", + aria_09: "R", + aria_10: "G", + audio_video_01: "G", + audio_video_02: "R", + autocomplete_01: "G", + autocomplete_02: "R", + blink_01: "R", + blink_02: "R", + br_01: "R", + button_01: "G", + button_02: "R", + color_01: "Y", + color_02: "R", + css_01: "Y", + css_02: "Y", + dtd_01: "R", + ehandler_01: "Y", + ehandler_02: "R", + ehandler_03: "G", + ehandler_04: "R", + embed_01: "R", + element_01: "G", + element_02: "G", + element_03: "R", + element_04: "G", + element_05: "R", + element_06: "G", + element_07: "R", + element_08: "G", + element_09: "R", + element_10: "G", + field_01: "R", + field_02: "Y", + focus_01: "R", + font_01: "R", + font_02: "R", + form_01a: "G", + form_01b: "R", + frame_01: "R", + frame_02: "R", + heading_01: "G", + heading_02: "R", + headers_01: "G", + headers_02: "R", + hx_01a: "R", + hx_01b: "Y", + hx_01c: "R", + hx_02: "R", + hx_03: "R", + id_01: "G", + id_02: "R", + iframe_01: "R", + iframe_02: "G", + iframe_03: "R", + iframe_04: "G", + iframe_05: "R", + img_01a: "G", + img_01b: "R", + img_02: "Y", + img_03: "R", + img_04: "Y", + inp_img_01a: "G", + inp_img_01b: "R", + input_01: "R", + input_02: "R", + input_02b: "G", + input_03: "R", + justif_txt_01: "R", + justif_txt_02: "Y", + label_01: "G", + label_02: "R", + label_03: "R", + landmark_01: "G", + landmark_02: "R", + landmark_03: "G", + landmark_04: "R", + landmark_05: "G", + landmark_06: "R", + landmark_07: "G", + landmark_08: "R", + landmark_09: "G", + landmark_10: "R", + landmark_11: "G", + landmark_12: "R", + landmark_13: "G", + landmark_14: "R", + lang_01: "Y", + lang_02: "R", + lang_03: "R", + lang_04: "R", + lang_05: "R", + layout_01a: "G", + layout_01b: "R", + layout_02a: "G", + layout_02b: "R", + layout_03: "R", + letter_01: "G", + letter_02: "R", + link_01: "G", + list_01: "R", + list_02: "G", + list_03: "R", + list_04: "G", + list_05: "R", + list_06: "G", + list_07: "R", + listitem_01: "G", + listitem_02: "R", + long_01: "R", + marquee_01: "Y", + menuItem_01: "G", + menuItem_02: "R", + meta_01: "Y", + meta_02: "Y", + meta_03: "G", + meta_04: "R", + meta_05: "G", + object_01: "G", + object_02: "R", + orientation_01: "G", + orientation_02: "R", + role_01: "G", + role_02: "R", + scope_01: "R", + scrollable_01: "G", + scrollable_02: "R", + svg_01: "G", + svg_02: "R", + table_01: "Y", + table_02: "R", + table_03: "R", + table_04: "R", + table_05a: "R", + table_06: "R", + table_07: "G", + table_08: "R", + textC_01: "Y", + textC_02: "Y", + title_01: "R", + title_02: "R", + title_03: "R", + title_04: "Y", + title_05: "R", + title_06: "G", + title_07: "Y", + values_01a: "Y", + values_01b: "G", + values_02a: "Y", + values_02b: "G", + video_01: "G", + video_02: "G", + w3c_validator_01a: "G", + w3c_validator_01b: "Y", + win_01: "Y", + word_01: "G", + word_02: "R", +}; diff --git a/src/evaluation/xpath.ts b/src/evaluation/xpath.ts index 38757a2d..a761a416 100644 --- a/src/evaluation/xpath.ts +++ b/src/evaluation/xpath.ts @@ -1,69 +1,84 @@ const xpath: any = { - 'a': '//a[@href]', - 'aSkipFirst': '//a', - 'abbrNo': '//abbr[not(@title) or normalize-space(@title)=""]|//acronym[not(@title) or normalize-space(@title)=""]', - 'applet': '//applet', - 'area': '//area', - 'areaAltNo': '//area[not(@alt) or normalize-space(@alt)=""]', - 'blink': '//blink', - 'dl': '//dl', - 'dd,dt': '//dd,dt', - 'ehandMouse': '//*[@onmousedown]|//*[@onmouseup]|//*[@onmouseout]|//*[@onmouseover]', - 'ehandler': '//*[@onfocus]|//*[@onblur]|//*[@onkeypress]|//*[@onkeydown]|//*[@onkeyup]|//*[@onsubmit]|//*[@onreset]|//*[@onselect]|//*[@onchange]|//*[@onload]|//*[@onunload]|//*[@onclick]|//*[@ondblclick]|//*[@onmousedown]|//*[@onmouseup]|//*[@onmouseover]|//*[@onmousemove]|//*[@onmouseout]', - 'embed': '//embed', - 'fieldLegNo': '//fieldset[not(.//legend) or not(.//legend[normalize-space(.)!=""])]', - 'fieldNoForm': '//fieldset[not(ancestor::form)]', - 'fontHtml': '//b|//basefont[@*]|//body[@text or @link or @alink or @vlink]|//font[@*]|//i|//s|//strike|//u', - 'form': '//form', - 'formSubmitNo': '//form[not(.//input[@type="submit"]) and not(.//input[@type="image"]) and not(.//button[@type="submit"])]', - 'frame': '//frame', - 'frameTitleNo': '//frame[not(@title) or normalize-space(@title)=""]', - 'frameset': '//frameset', - 'hx': '//h1|//h2|//h3|//h4|//h5|//h6|//[@aria-level][@role="heading"]', - 'id': '//*[@id]', - 'iframe': '//iframe', - 'iframeTitleNo': '//iframe[not(@title) or normalize-space(@title)=""]', - 'img': '//img', - 'imgAltNo': '//img[not(@alt)]', - 'imgAltNull': '//img[normalize-space(@alt)=""]', - 'inpImg': '//input[@type="image"]', - 'inpImgAltNo': '//input[@type="image"][not(@alt)]', - 'inputAltNo': '//input[not(@type="image")][(@alt]', - 'inputLabel': '//input[@type="text"]|//input[@type="checkbox"]|//input[@type="radio"]|//input[@type="file"]|//input[@type="password"]|//textarea|//select', - 'justifiedTxt': '//*[translate(@align,"JUSTIFY","justify")="justify"]', - 'label': '//label', - 'labelForNo': '//label[not(@for) or normalize-space(@for)=""]', - 'labelTextNo': '//label[normalize-space(text())=""]', - 'lang': '//html', - 'langCodeNo': '//html', - 'langExtra': '//html', - 'langMatchNo': '//html', - 'langNo': '//html', - 'layoutAttr': '//*[@align]|//*[@hspace]|//*[@vspace]|//*[@color]|//*[@face]|//basefont[@size]|//*[@text]|//*[@link]|//*[@alink]|//*[@vlink]|//*[@bgcolor]|//*[@background]|//font[@size]', - 'layoutElem': '//blink|//center', - 'li': '//li', - 'listNotCorrectly': '//li', - 'liNoList': '//li[not(ancestor::ol) and not(ancestor::ul)]', - 'linkRel': '//link[@rel="alternate" or @rel="appendix" or @rel="bookmark" or @rel="chapter" or @rel="contents" or @rel="copyright" or @rel="glossary" or @rel="help" or @rel="index" or @rel="next" or @rel="prev" or @rel="section" or @rel="start" or @rel="subsection"]|//link[@rev="alternate" or @rev="appendix" or @rev="bookmark" or @rev="chapter" or @rev="contents" or @rev="copyright" or @rev="glossary" or @rev="help" or @rev="index" or @rev="next" or @rev="prev" or @rev="section" or @rev="start" or @rev="subsection"]', - 'longDImg': '//img[@longdesc]', - 'longDNo': '//img[normalize-space(@longdesc)="" or normalize-space(@longdesc)="#" or contains(@longdesc, " ")]', - 'marquee': '//marquee', - 'metaRedir': '//meta[translate(@http-equiv,"REFSH","refsh")="refresh"][contains(translate(@content, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "url")]', - 'metaRefresh': '//meta[translate(@http-equiv,"REFSH","refsh")="refresh"][@content > 0]', - 'newWinOnLoad': '//body[contains(@onload, "window.open") or contains(@onload, "MM_openBrWindow")]', - 'object': '//object', - 'table': '//table', - 'tableData': '//table[child::tr[th] or child::tr[td[@scope]]]', - 'tableDataCaption': '//table[child::tr[th] or child::tr[td[@scope]]][not(caption)][not(@summary)]', - 'tableLayout': '//table[not(child::tr[th]) and not(child::tr[td[@scope]])]', - 'tableLayoutCaption': '//table[not(child::tr[th]) and not(child::tr[td[@scope]])][caption or @summary]', - 'tableNested': '//table[descendant::table]', - 'titleChars': '//title', - 'titleLong': '//title', - 'titleNull': '//title', - 'titleSame': '//title', - 'titleVrs': '//title', - 'titleOk': '//title' + a: "//a[@href]", + aSkipFirst: "//a", + abbrNo: + '//abbr[not(@title) or normalize-space(@title)=""]|//acronym[not(@title) or normalize-space(@title)=""]', + applet: "//applet", + area: "//area", + areaAltNo: '//area[not(@alt) or normalize-space(@alt)=""]', + blink: "//blink", + dl: "//dl", + "dd,dt": "//dd,dt", + ehandMouse: + "//*[@onmousedown]|//*[@onmouseup]|//*[@onmouseout]|//*[@onmouseover]", + ehandler: + "//*[@onfocus]|//*[@onblur]|//*[@onkeypress]|//*[@onkeydown]|//*[@onkeyup]|//*[@onsubmit]|//*[@onreset]|//*[@onselect]|//*[@onchange]|//*[@onload]|//*[@onunload]|//*[@onclick]|//*[@ondblclick]|//*[@onmousedown]|//*[@onmouseup]|//*[@onmouseover]|//*[@onmousemove]|//*[@onmouseout]", + embed: "//embed", + fieldLegNo: + '//fieldset[not(.//legend) or not(.//legend[normalize-space(.)!=""])]', + fieldNoForm: "//fieldset[not(ancestor::form)]", + fontHtml: + "//b|//basefont[@*]|//body[@text or @link or @alink or @vlink]|//font[@*]|//i|//s|//strike|//u", + form: "//form", + formSubmitNo: + '//form[not(.//input[@type="submit"]) and not(.//input[@type="image"]) and not(.//button[@type="submit"])]', + frame: "//frame", + frameTitleNo: '//frame[not(@title) or normalize-space(@title)=""]', + frameset: "//frameset", + hx: '//h1|//h2|//h3|//h4|//h5|//h6|//[@aria-level][@role="heading"]', + id: "//*[@id]", + iframe: "//iframe", + iframeTitleNo: '//iframe[not(@title) or normalize-space(@title)=""]', + img: "//img", + imgAltNo: "//img[not(@alt)]", + imgAltNull: '//img[normalize-space(@alt)=""]', + inpImg: '//input[@type="image"]', + inpImgAltNo: '//input[@type="image"][not(@alt)]', + inputAltNo: '//input[not(@type="image")][(@alt]', + inputLabel: + '//input[@type="text"]|//input[@type="checkbox"]|//input[@type="radio"]|//input[@type="file"]|//input[@type="password"]|//textarea|//select', + justifiedTxt: '//*[translate(@align,"JUSTIFY","justify")="justify"]', + label: "//label", + labelForNo: '//label[not(@for) or normalize-space(@for)=""]', + labelTextNo: '//label[normalize-space(text())=""]', + lang: "//html", + langCodeNo: "//html", + langExtra: "//html", + langMatchNo: "//html", + langNo: "//html", + layoutAttr: + "//*[@align]|//*[@hspace]|//*[@vspace]|//*[@color]|//*[@face]|//basefont[@size]|//*[@text]|//*[@link]|//*[@alink]|//*[@vlink]|//*[@bgcolor]|//*[@background]|//font[@size]", + layoutElem: "//blink|//center", + li: "//li", + listNotCorrectly: "//li", + liNoList: "//li[not(ancestor::ol) and not(ancestor::ul)]", + linkRel: + '//link[@rel="alternate" or @rel="appendix" or @rel="bookmark" or @rel="chapter" or @rel="contents" or @rel="copyright" or @rel="glossary" or @rel="help" or @rel="index" or @rel="next" or @rel="prev" or @rel="section" or @rel="start" or @rel="subsection"]|//link[@rev="alternate" or @rev="appendix" or @rev="bookmark" or @rev="chapter" or @rev="contents" or @rev="copyright" or @rev="glossary" or @rev="help" or @rev="index" or @rev="next" or @rev="prev" or @rev="section" or @rev="start" or @rev="subsection"]', + longDImg: "//img[@longdesc]", + longDNo: + '//img[normalize-space(@longdesc)="" or normalize-space(@longdesc)="#" or contains(@longdesc, " ")]', + marquee: "//marquee", + metaRedir: + '//meta[translate(@http-equiv,"REFSH","refsh")="refresh"][contains(translate(@content, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "url")]', + metaRefresh: + '//meta[translate(@http-equiv,"REFSH","refsh")="refresh"][@content > 0]', + newWinOnLoad: + '//body[contains(@onload, "window.open") or contains(@onload, "MM_openBrWindow")]', + object: "//object", + table: "//table", + tableData: "//table[child::tr[th] or child::tr[td[@scope]]]", + tableDataCaption: + "//table[child::tr[th] or child::tr[td[@scope]]][not(caption)][not(@summary)]", + tableLayout: "//table[not(child::tr[th]) and not(child::tr[td[@scope]])]", + tableLayoutCaption: + "//table[not(child::tr[th]) and not(child::tr[td[@scope]])][caption or @summary]", + tableNested: "//table[descendant::table]", + titleChars: "//title", + titleLong: "//title", + titleNull: "//title", + titleSame: "//title", + titleVrs: "//title", + titleOk: "//title", }; export default xpath; diff --git a/src/gov-user/dto/create-gov-user.dto.ts b/src/gov-user/dto/create-gov-user.dto.ts index 22077ef8..7ec1bdde 100644 --- a/src/gov-user/dto/create-gov-user.dto.ts +++ b/src/gov-user/dto/create-gov-user.dto.ts @@ -1,8 +1,7 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsNotEmpty } from "class-validator"; export class CreateGovUserDto { - @IsNotEmpty() - ccNumber: string; - @IsNotEmpty() - name: string; - + @IsNotEmpty() + ccNumber: string; + @IsNotEmpty() + name: string; } diff --git a/src/gov-user/dto/update-gov-user.dto.ts b/src/gov-user/dto/update-gov-user.dto.ts index 83efe4c5..c402fec0 100644 --- a/src/gov-user/dto/update-gov-user.dto.ts +++ b/src/gov-user/dto/update-gov-user.dto.ts @@ -1,11 +1,11 @@ -import { PartialType } from '@nestjs/mapped-types'; -import { IsNotEmpty, IsNumber } from 'class-validator'; -import { User } from 'src/user/user.entity'; -import { CreateGovUserDto } from './create-gov-user.dto'; +import { PartialType } from "@nestjs/mapped-types"; +import { IsNotEmpty, IsNumber } from "class-validator"; +import { User } from "src/user/user.entity"; +import { CreateGovUserDto } from "./create-gov-user.dto"; export class UpdateGovUserDto extends PartialType(CreateGovUserDto) { - @IsNotEmpty() - @IsNumber() - id: number; - entities:User[]; + @IsNotEmpty() + @IsNumber() + id: number; + entities: User[]; } diff --git a/src/gov-user/entities/gov-user.entity.ts b/src/gov-user/entities/gov-user.entity.ts index 60527715..89610ce3 100644 --- a/src/gov-user/entities/gov-user.entity.ts +++ b/src/gov-user/entities/gov-user.entity.ts @@ -1,41 +1,40 @@ -import { User } from 'src/user/user.entity'; +import { User } from "src/user/user.entity"; import { - Column, - Entity, - ManyToMany, - JoinTable, - PrimaryGeneratedColumn -} from 'typeorm'; + Column, + Entity, + ManyToMany, + JoinTable, + PrimaryGeneratedColumn, +} from "typeorm"; //Utilizador do Autenticação.gov @Entity({ name: "GovUser" }) export class GovUser { + @PrimaryGeneratedColumn() + id: number; - @PrimaryGeneratedColumn() - id: number; + @Column({ type: "varchar", length: 100, nullable: false }) + name: string; - @Column({ type: 'varchar', length: 100, nullable: false }) - name: string; + @Column({ type: "varchar", nullable: true }) + ccNumber: string; - @Column({ type: 'varchar', nullable: true }) - ccNumber: string; + @ManyToMany((type) => User, (user) => user.govUsers) + @JoinTable({ + name: "UserGovUser", + inverseJoinColumn: { name: "UserId" }, + joinColumn: { name: "GovUserId" }, + }) + entities: User[]; - @ManyToMany((type) => User, (user) => user.govUsers) - @JoinTable({ - name: "UserGovUser", - inverseJoinColumn: { name: 'UserId' }, - joinColumn: { name: 'GovUserId' }, - }) - entities: User[]; + @Column({ + type: "datetime", + nullable: false, + }) + registerDate: Date; - @Column({ - type: 'datetime', - nullable: false - }) - registerDate: Date; - - @Column({ - type: 'datetime', - nullable: false - }) - lastLogin: Date; + @Column({ + type: "datetime", + nullable: false, + }) + lastLogin: Date; } diff --git a/src/gov-user/gov-user.controller.spec.ts b/src/gov-user/gov-user.controller.spec.ts index 9f9add0b..dae7ea25 100644 --- a/src/gov-user/gov-user.controller.spec.ts +++ b/src/gov-user/gov-user.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { GovUserController } from './gov-user.controller'; -import { GovUserService } from './gov-user.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { GovUserController } from "./gov-user.controller"; +import { GovUserService } from "./gov-user.service"; -describe('GovUserController', () => { +describe("GovUserController", () => { let controller: GovUserController; beforeEach(async () => { @@ -14,7 +14,7 @@ describe('GovUserController', () => { controller = module.get(GovUserController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/gov-user/gov-user.controller.ts b/src/gov-user/gov-user.controller.ts index 3cf28808..2b132237 100644 --- a/src/gov-user/gov-user.controller.ts +++ b/src/gov-user/gov-user.controller.ts @@ -1,26 +1,39 @@ -import { Controller, Get, Post, Body, Param, UseInterceptors, UseGuards } from '@nestjs/common'; -import { GovUserService } from './gov-user.service'; -import { CreateGovUserDto } from './dto/create-gov-user.dto'; -import { UpdateGovUserDto } from './dto/update-gov-user.dto'; -import { success } from 'src/lib/response'; -import { LoggingInterceptor } from 'src/log/log.interceptor'; -import { ApiBasicAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; -import { GovUser } from './entities/gov-user.entity'; -import { AuthGuard } from '@nestjs/passport'; +import { + Controller, + Get, + Post, + Body, + Param, + UseInterceptors, + UseGuards, +} from "@nestjs/common"; +import { GovUserService } from "./gov-user.service"; +import { CreateGovUserDto } from "./dto/create-gov-user.dto"; +import { UpdateGovUserDto } from "./dto/update-gov-user.dto"; +import { success } from "src/lib/response"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { + ApiBasicAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; +import { GovUser } from "./entities/gov-user.entity"; +import { AuthGuard } from "@nestjs/passport"; @ApiBasicAuth() -@ApiTags('gov-user') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller('gov-user') +@ApiTags("gov-user") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("gov-user") @UseGuards(AuthGuard("jwt-admin")) @UseInterceptors(LoggingInterceptor) export class GovUserController { - constructor(private readonly govUserService: GovUserService) { } + constructor(private readonly govUserService: GovUserService) {} - @ApiOperation({ summary: 'Create GovUser' }) + @ApiOperation({ summary: "Create GovUser" }) @ApiResponse({ status: 200, - description: 'GovUser created', + description: "GovUser created", type: GovUser, }) @Post("create") @@ -28,10 +41,10 @@ export class GovUserController { return success(await this.govUserService.create(createGovUserDto)); } - @ApiOperation({ summary: 'Find all GovUsers' }) + @ApiOperation({ summary: "Find all GovUsers" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @Get("all") @@ -39,32 +52,32 @@ export class GovUserController { return success(await this.govUserService.findAll()); } - @ApiOperation({ summary: 'Check if a specific GovUser exists' }) + @ApiOperation({ summary: "Check if a specific GovUser exists" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: Array, }) @Get("exists/:cc") - async exists(@Param('cc') cc: string) { + async exists(@Param("cc") cc: string) { return success(await this.govUserService.checkIfExists(cc)); } - @ApiOperation({ summary: 'Find a GovUser by id' }) + @ApiOperation({ summary: "Find a GovUser by id" }) @ApiResponse({ status: 200, - description: 'Success', + description: "Success", type: GovUser, }) - @Get(':id') - async findOne(@Param('id') id: string) { + @Get(":id") + async findOne(@Param("id") id: string) { return success(await this.govUserService.findOne(+id)); } - @ApiOperation({ summary: 'Update a specific GovUser' }) + @ApiOperation({ summary: "Update a specific GovUser" }) @ApiResponse({ status: 200, - description: 'The specific GovUser was updated', + description: "The specific GovUser was updated", type: GovUser, }) @Post("update") @@ -72,13 +85,13 @@ export class GovUserController { return success(await this.govUserService.update(updateGovUserDto)); } - @ApiOperation({ summary: 'Delete a specific GovUser' }) + @ApiOperation({ summary: "Delete a specific GovUser" }) @ApiResponse({ status: 200, - description: 'The specific GovUser was deleted', + description: "The specific GovUser was deleted", type: GovUser, }) - @Post('delete') + @Post("delete") async remove(@Body() updateGovUserDto: UpdateGovUserDto) { return success(await this.govUserService.remove(updateGovUserDto.id)); } diff --git a/src/gov-user/gov-user.module.ts b/src/gov-user/gov-user.module.ts index e44fbd32..05064567 100644 --- a/src/gov-user/gov-user.module.ts +++ b/src/gov-user/gov-user.module.ts @@ -1,16 +1,14 @@ -import { Module } from '@nestjs/common'; -import { GovUserService } from './gov-user.service'; -import { GovUserController } from './gov-user.controller'; -import { GovUser } from './entities/gov-user.entity'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { UserModule } from 'src/user/user.module'; +import { Module } from "@nestjs/common"; +import { GovUserService } from "./gov-user.service"; +import { GovUserController } from "./gov-user.controller"; +import { GovUser } from "./entities/gov-user.entity"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { UserModule } from "src/user/user.module"; @Module({ controllers: [GovUserController], providers: [GovUserService], exports: [GovUserService], - imports: [ - TypeOrmModule.forFeature([GovUser]), - UserModule], + imports: [TypeOrmModule.forFeature([GovUser]), UserModule], }) -export class GovUserModule { } +export class GovUserModule {} diff --git a/src/gov-user/gov-user.service.spec.ts b/src/gov-user/gov-user.service.spec.ts index 01b20a93..3b72743d 100644 --- a/src/gov-user/gov-user.service.spec.ts +++ b/src/gov-user/gov-user.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { GovUserService } from './gov-user.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { GovUserService } from "./gov-user.service"; -describe('GovUserService', () => { +describe("GovUserService", () => { let service: GovUserService; beforeEach(async () => { @@ -12,19 +12,22 @@ describe('GovUserService', () => { service = module.get(GovUserService); }); - it('should be defined', async () => { + it("should be defined", async () => { const JOSE = "Teste José"; expect(service).toBeDefined(); const initialList = await service.findAll(); - const user = await service.create({ ccNumber: "12343444", name: "Teste Manel" }); + const user = await service.create({ + ccNumber: "12343444", + name: "Teste Manel", + }); expect(user).toBeDefined(); const found = service.findOne(user.id); console.log(found); expect(found).toBeDefined(); const userUpdated = await service.update({ id: user.id, name: JOSE }); - expect(userUpdated.name).toEqual(JOSE) + expect(userUpdated.name).toEqual(JOSE); const userRemoved = await service.remove(user.id); const finalList = await service.findAll(); - expect(finalList.length).toEqual(initialList.length) + expect(finalList.length).toEqual(initialList.length); }); }); diff --git a/src/gov-user/gov-user.service.ts b/src/gov-user/gov-user.service.ts index 6a12be2d..0c2734bb 100644 --- a/src/gov-user/gov-user.service.ts +++ b/src/gov-user/gov-user.service.ts @@ -1,28 +1,33 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { User } from 'src/user/user.entity'; -import { UserService } from 'src/user/user.service'; -import { Repository } from 'typeorm'; -import { CreateGovUserDto } from './dto/create-gov-user.dto'; -import { UpdateGovUserDto } from './dto/update-gov-user.dto'; -import { GovUser } from './entities/gov-user.entity'; +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { User } from "src/user/user.entity"; +import { UserService } from "src/user/user.service"; +import { Repository } from "typeorm"; +import { CreateGovUserDto } from "./dto/create-gov-user.dto"; +import { UpdateGovUserDto } from "./dto/update-gov-user.dto"; +import { GovUser } from "./entities/gov-user.entity"; @Injectable() export class GovUserService { constructor( @InjectRepository(GovUser) private govUserRepository: Repository, - private userService:UserService){} + private userService: UserService + ) {} create(createGovUserDto: CreateGovUserDto) { return this.addToDB(createGovUserDto); } - addToDB(createGovUserDto: CreateGovUserDto){ - const newUser = this.govUserRepository.create({ registerDate: new Date(),lastLogin: new Date(),...createGovUserDto}); + addToDB(createGovUserDto: CreateGovUserDto) { + const newUser = this.govUserRepository.create({ + registerDate: new Date(), + lastLogin: new Date(), + ...createGovUserDto, + }); return this.govUserRepository.save(newUser); } - async associateUser(user:User, id:number){ + async associateUser(user: User, id: number) { const govUser = await this.findOne(id); govUser.entities.push(user); return this.govUserRepository.save(govUser); @@ -33,16 +38,25 @@ export class GovUserService { } findOne(id: number) { - return this.govUserRepository.findOne({where:{id}, relations: ["entities"]}); + return this.govUserRepository.findOne({ + where: { id }, + relations: ["entities"], + }); } findOneByCC(ccNumber: string) { console.log(ccNumber); - return this.govUserRepository.findOne({ where: { ccNumber }, relations: ["entities"] }); + return this.govUserRepository.findOne({ + where: { ccNumber }, + relations: ["entities"], + }); } updateLogin(ccNumber: string) { - return this.govUserRepository.update({ ccNumber},{lastLogin:new Date()}) + return this.govUserRepository.update( + { ccNumber }, + { lastLogin: new Date() } + ); } async checkIfExists(ccNumber: string) { @@ -54,10 +68,10 @@ export class GovUserService { const users = updateGovUserDto.entities; const entities = await Promise.all( users.map(async (user) => { - return this.userService.findById(user.UserId+""); - }), + return this.userService.findById(user.UserId + ""); + }) ); - return this.govUserRepository.save({entities, ... updateGovUserDto}); + return this.govUserRepository.save({ entities, ...updateGovUserDto }); } remove(id: number) { diff --git a/src/lib/http-exception.filter.ts b/src/lib/http-exception.filter.ts index 11cf8469..a86d7eb3 100644 --- a/src/lib/http-exception.filter.ts +++ b/src/lib/http-exception.filter.ts @@ -1,20 +1,23 @@ -import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'; -import { Request, Response } from 'express'; +import { + ExceptionFilter, + Catch, + ArgumentsHost, + HttpException, +} from "@nestjs/common"; +import { Request, Response } from "express"; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { - catch(exception: HttpException, host: ArgumentsHost) { - const ctx = host.switchToHttp(); - const response = ctx.getResponse(); - const request = ctx.getRequest(); - const status = exception.getStatus(); + catch(exception: HttpException, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const request = ctx.getRequest(); + const status = exception.getStatus(); - response - .status(status) - .json({ - statusCode: status, - timestamp: new Date().toISOString(), - path: request.url, - }); - } -} \ No newline at end of file + response.status(status).json({ + statusCode: status, + timestamp: new Date().toISOString(), + path: request.url, + }); + } +} diff --git a/src/lib/quartil.ts b/src/lib/quartil.ts index e040b7c0..2a20c66d 100644 --- a/src/lib/quartil.ts +++ b/src/lib/quartil.ts @@ -1,6 +1,6 @@ import clone from "lodash.clonedeep"; -export function calculateQuartiles(data: any): Array < any > { +export function calculateQuartiles(data: any): Array { const values = data .filter((e: any) => e !== undefined) .sort((a: number, b: number) => a - b); @@ -12,61 +12,61 @@ export function calculateQuartiles(data: any): Array < any > { q1 = values[Math.round(0.25 * (values.length + 1)) - 1]; - if(values.length % 2 === 0) { - q2 = (values[values.length / 2 - 1] + values[values.length / 2]) / 2; -} else { - q2 = values[(values.length + 1) / 2]; -} + if (values.length % 2 === 0) { + q2 = (values[values.length / 2 - 1] + values[values.length / 2]) / 2; + } else { + q2 = values[(values.length + 1) / 2]; + } -q3 = values[Math.round(0.75 * (values.length + 1)) - 1]; -q4 = values[values.length - 1]; + q3 = values[Math.round(0.75 * (values.length + 1)) - 1]; + q4 = values[values.length - 1]; -const tmp = { - q1: new Array(), - q2: new Array(), - q3: new Array(), - q4: new Array(), -}; + const tmp = { + q1: new Array(), + q2: new Array(), + q3: new Array(), + q4: new Array(), + }; -let q: string; -for (const v of values || []) { - if (v <= q1) { - q = "q1"; - } else { - if (v <= q2) { - q = "q2"; + let q: string; + for (const v of values || []) { + if (v <= q1) { + q = "q1"; } else { - if (v <= q3) { - q = "q3"; + if (v <= q2) { + q = "q2"; } else { - q = "q4"; + if (v <= q3) { + q = "q3"; + } else { + q = "q4"; + } } } - } - tmp[q].push(v); -} + tmp[q].push(v); + } -const final = new Array(); + const final = new Array(); -for (const k in tmp) { - if (k) { - const v = tmp[k]; - const sum = v.length; - if (sum > 0) { - const test = { - tot: sum, - por: Math.round((sum * 100) / values.length), - int: { - lower: v[0], - upper: v[sum - 1], - }, - }; + for (const k in tmp) { + if (k) { + const v = tmp[k]; + const sum = v.length; + if (sum > 0) { + const test = { + tot: sum, + por: Math.round((sum * 100) / values.length), + int: { + lower: v[0], + upper: v[sum - 1], + }, + }; - final.push(clone(test)); + final.push(clone(test)); + } } } -} -return final; - } \ No newline at end of file + return final; +} diff --git a/src/lib/response.ts b/src/lib/response.ts index d290cf33..74efa4c9 100644 --- a/src/lib/response.ts +++ b/src/lib/response.ts @@ -1,26 +1,26 @@ -export function success(result: any = null): any { - return { - success: 1, - message: "NO_ERROR", - errors: null, - result, - }; -} - -export function error(err: any, result: any = null): any { - return { - success: err.code, - message: err.message, - errors: err.err, - result, - }; -} - -export function accessDenied(): any { - return { - success: -1, - message: "ACCESS_DENIED", - errors: null, - result: null, - }; -} +export function success(result: any = null): any { + return { + success: 1, + message: "NO_ERROR", + errors: null, + result, + }; +} + +export function error(err: any, result: any = null): any { + return { + success: err.code, + message: err.message, + errors: err.err, + result, + }; +} + +export function accessDenied(): any { + return { + success: -1, + message: "ACCESS_DENIED", + errors: null, + result: null, + }; +} diff --git a/src/lib/security.ts b/src/lib/security.ts index e979fb4e..1fd8eeaa 100644 --- a/src/lib/security.ts +++ b/src/lib/security.ts @@ -1,20 +1,25 @@ -import * as bcrypt from 'bcrypt'; -import { createHash } from 'crypto'; - -export async function generatePasswordHash(password: string): Promise { - return bcrypt.hash(password.trim(), 10); -} - -export async function comparePasswordHash(password: string, passwordHash: string): Promise { - return await bcrypt.compare(password, passwordHash); -} - -export function createRandomUniqueHash(): string { - const current_date = (new Date()).valueOf().toString(); - const random = Math.random().toString(); - return createHash('sha256').update(current_date + random).digest('hex'); -} - -export function generateMd5Hash(content: string): string { - return createHash('md5').update(content).digest('hex'); -} \ No newline at end of file +import * as bcrypt from "bcrypt"; +import { createHash } from "crypto"; + +export async function generatePasswordHash(password: string): Promise { + return bcrypt.hash(password.trim(), 10); +} + +export async function comparePasswordHash( + password: string, + passwordHash: string +): Promise { + return await bcrypt.compare(password, passwordHash); +} + +export function createRandomUniqueHash(): string { + const current_date = new Date().valueOf().toString(); + const random = Math.random().toString(); + return createHash("sha256") + .update(current_date + random) + .digest("hex"); +} + +export function generateMd5Hash(content: string): string { + return createHash("md5").update(content).digest("hex"); +} diff --git a/src/log/dto/update-log.dto.ts b/src/log/dto/update-log.dto.ts index 378fe762..7f74c669 100644 --- a/src/log/dto/update-log.dto.ts +++ b/src/log/dto/update-log.dto.ts @@ -1,4 +1,4 @@ -import { PartialType } from '@nestjs/mapped-types'; -import { CreateLogDto } from './create-log.dto'; +import { PartialType } from "@nestjs/mapped-types"; +import { CreateLogDto } from "./create-log.dto"; export class UpdateLogDto extends PartialType(CreateLogDto) {} diff --git a/src/log/log.controller.spec.ts b/src/log/log.controller.spec.ts index b41746dd..25513555 100644 --- a/src/log/log.controller.spec.ts +++ b/src/log/log.controller.spec.ts @@ -1,8 +1,8 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { LogController } from './log.controller'; -import { LogService } from './log.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { LogController } from "./log.controller"; +import { LogService } from "./log.service"; -describe('LogController', () => { +describe("LogController", () => { let controller: LogController; beforeEach(async () => { @@ -14,7 +14,7 @@ describe('LogController', () => { controller = module.get(LogController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/log/log.controller.ts b/src/log/log.controller.ts index 0e54855b..7317bbce 100644 --- a/src/log/log.controller.ts +++ b/src/log/log.controller.ts @@ -1,17 +1,27 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete, Res, UseGuards } from '@nestjs/common'; -import { LogService } from './log.service'; -import { createReadStream } from 'fs'; -import { join } from 'path'; -import { Response } from 'express'; -import { success } from 'src/lib/response'; -import { AuthGuard } from '@nestjs/passport'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, + Res, + UseGuards, +} from "@nestjs/common"; +import { LogService } from "./log.service"; +import { createReadStream } from "fs"; +import { join } from "path"; +import { Response } from "express"; +import { success } from "src/lib/response"; +import { AuthGuard } from "@nestjs/passport"; @UseGuards(AuthGuard("jwt-admin")) -@Controller('log') +@Controller("log") export class LogController { constructor(private readonly logService: LogService) {} - @Get('error-log/:fileName') + @Get("error-log/:fileName") async getErrorLog(@Res() res: Response, @Param("fileName") fileName: string) { const path = "./error-log/" + fileName; if (path) { @@ -20,23 +30,25 @@ export class LogController { } } - @Get('error-log') + @Get("error-log") async getErrorLogList() { return success(this.logService.listErrorLog()); } - @Get('action-log') + @Get("action-log") async getActionLogList() { return success(this.logService.listActionLog()); } - @Get('action-log/:fileName') - async getActionLog(@Res() res: Response, @Param("fileName") fileName: string) { + @Get("action-log/:fileName") + async getActionLog( + @Res() res: Response, + @Param("fileName") fileName: string + ) { const path = "./action-log/" + fileName; if (path) { const file = createReadStream(join(process.cwd(), path)); file.pipe(res); } } - } diff --git a/src/log/log.interceptor.ts b/src/log/log.interceptor.ts index fd725677..895a8632 100644 --- a/src/log/log.interceptor.ts +++ b/src/log/log.interceptor.ts @@ -1,45 +1,49 @@ import { - Injectable, - NestInterceptor, - ExecutionContext, - CallHandler, - Inject, - Logger, -} from '@nestjs/common'; -import { Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; -import { WINSTON_MODULE_PROVIDER } from 'nest-winston'; + Injectable, + NestInterceptor, + ExecutionContext, + CallHandler, + Inject, + Logger, +} from "@nestjs/common"; +import { Observable } from "rxjs"; +import { tap } from "rxjs/operators"; +import { WINSTON_MODULE_PROVIDER } from "nest-winston"; @Injectable() export class LoggingInterceptor implements NestInterceptor { - constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) { } - async intercept( - context: ExecutionContext, - next: CallHandler, - ): Promise> { - const request = context.switchToHttp().getRequest(); - let user = request.user; + constructor( + @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger + ) {} + async intercept( + context: ExecutionContext, + next: CallHandler + ): Promise> { + const request = context.switchToHttp().getRequest(); + let user = request.user; - const date = new Date(); - return next.handle().pipe( - tap((data) => { - let body = JSON.stringify(request.body); - if (body.length > 400) { - body = body.substring(0, 400); - } - const logData = { - path: request.route.path, - origin: request.headers['x-forwarded-for'] || request.connection.remoteAddress, - body, - user, - }; - const dateString = date.toISOString(); - console.log(logData); - this.logger.log({ - level: 'http', - message: '"' + dateString + '"' + ':' + JSON.stringify(logData) - }); - }), - ); - } + const date = new Date(); + return next.handle().pipe( + tap((data) => { + let body = JSON.stringify(request.body); + if (body.length > 400) { + body = body.substring(0, 400); + } + const logData = { + path: request.route.path, + origin: + request.headers["x-forwarded-for"] || + request.connection.remoteAddress, + body, + user, + }; + const dateString = date.toISOString(); + console.log(logData); + this.logger.log({ + level: "http", + message: '"' + dateString + '"' + ":" + JSON.stringify(logData), + }); + }) + ); + } } diff --git a/src/log/log.module.ts b/src/log/log.module.ts index d39d46ae..5302fb23 100644 --- a/src/log/log.module.ts +++ b/src/log/log.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { LogService } from './log.service'; -import { LogController } from './log.controller'; +import { Module } from "@nestjs/common"; +import { LogService } from "./log.service"; +import { LogController } from "./log.controller"; @Module({ controllers: [LogController], - providers: [LogService] + providers: [LogService], }) export class LogModule {} diff --git a/src/log/log.service.spec.ts b/src/log/log.service.spec.ts index a2863e81..e42ba997 100644 --- a/src/log/log.service.spec.ts +++ b/src/log/log.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { LogService } from './log.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { LogService } from "./log.service"; -describe('LogService', () => { +describe("LogService", () => { let service: LogService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('LogService', () => { service = module.get(LogService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/log/log.service.ts b/src/log/log.service.ts index 97f31e07..838d80a2 100644 --- a/src/log/log.service.ts +++ b/src/log/log.service.ts @@ -1,14 +1,13 @@ -import { Injectable } from '@nestjs/common'; -var fs = require('fs'); +import { Injectable } from "@nestjs/common"; +var fs = require("fs"); @Injectable() export class LogService { - listErrorLog() { - return fs.readdirSync('./error-log/'); + return fs.readdirSync("./error-log/"); } listActionLog() { - return fs.readdirSync('./action-log/'); + return fs.readdirSync("./action-log/"); } } diff --git a/src/main.ts b/src/main.ts index fc1f7d5e..584399b8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,29 +1,29 @@ -import { NestFactory } from "@nestjs/core"; -import { AppModule } from "./app.module"; -import express from "express"; -import helmet from "helmet"; -import compression from "compression"; -import { WINSTON_MODULE_NEST_PROVIDER } from "nest-winston"; -import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger"; -import { HttpExceptionFilter } from "./lib/http-exception.filter"; - -async function bootstrap() { - const app = await NestFactory.create(AppModule, { cors: true }); - app.use(helmet()); - app.use(express.json({ limit: "50mb" })); - app.use(express.urlencoded({ limit: "50mb", extended: true })); - app.use(compression()); - app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER)); - - const config = new DocumentBuilder() - .setTitle('Monitor server') - .setDescription('The Monitor Server API description') - .setVersion('1.0') - .addTag('website') - .build(); - const document = SwaggerModule.createDocument(app, config); - SwaggerModule.setup('api', app, document); - app.useGlobalFilters(new HttpExceptionFilter()); - await app.listen(process.env.PORT || 3000); -} -bootstrap(); +import { NestFactory } from "@nestjs/core"; +import { AppModule } from "./app.module"; +import express from "express"; +import helmet from "helmet"; +import compression from "compression"; +import { WINSTON_MODULE_NEST_PROVIDER } from "nest-winston"; +import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger"; +import { HttpExceptionFilter } from "./lib/http-exception.filter"; + +async function bootstrap() { + const app = await NestFactory.create(AppModule, { cors: true }); + app.use(helmet()); + app.use(express.json({ limit: "50mb" })); + app.use(express.urlencoded({ limit: "50mb", extended: true })); + app.use(compression()); + app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER)); + + const config = new DocumentBuilder() + .setTitle("Monitor server") + .setDescription("The Monitor Server API description") + .setVersion("1.0") + .addTag("website") + .build(); + const document = SwaggerModule.createDocument(app, config); + SwaggerModule.setup("api", app, document); + app.useGlobalFilters(new HttpExceptionFilter()); + await app.listen(process.env.PORT || 3000); +} +bootstrap(); diff --git a/src/observatory/models/directory.ts b/src/observatory/models/directory.ts index d2df61a6..5772d6b9 100644 --- a/src/observatory/models/directory.ts +++ b/src/observatory/models/directory.ts @@ -1,178 +1,178 @@ -import orderBy from "lodash.orderby"; -import tests from "src/evaluation/tests"; -import { Website } from "./website"; - -export class Directory { - id: number; - rank: number; - name: string; - creationDate: Date; - websites: Array; - nPages: number; - nPagesWithoutErrors: number; - entities: Array; - declarations: number; - stamps: number; - score: number; - A: number; - AA: number; - AAA: number; - frequencies: Array; - errors: any; - recentPage: Date; - oldestPage: Date; - success: any; - - constructor(id: number, name: string, creationDate: Date) { - this.id = id; - this.rank = -1; - this.name = name; - this.creationDate = creationDate; - this.websites = new Array(); - this.nPages = 0; - this.nPagesWithoutErrors = 0; - this.entities = new Array(); - this.declarations = 0; - this.stamps = 0; - this.score = 0; - this.A = 0; - this.AA = 0; - this.AAA = 0; - this.frequencies = new Array(9).fill(0); - this.errors = {}; - this.success = {}; - } - - addWebsite(website: Website): void { - this.websites.push(website); - this.nPages += website.pages.length; - this.score += website.getScore(); - - if (website.declaration) { - this.declarations++; - } - - if (website.stamp) { - this.stamps++; - } - - this.nPagesWithoutErrors += website.AAA; - - if (website.AAA === website.pages.length) { - this.AAA++; - } else if (website.AAA + website.AA === website.pages.length) { - this.AA++; - } else if (website.AAA + website.AA + website.A === website.pages.length) { - this.A++; - } - - this.frequencies = this.frequencies.map((v: number, i: number) => { - return v + website.frequencies[i]; - }); - - const websiteErrors = website.errors; - - for (const error in websiteErrors || {}) { - if (Object.keys(this.errors).includes(error)) { - this.errors[error]["n_occurrences"] += - websiteErrors[error]["n_occurrences"]; - this.errors[error]["n_pages"] += websiteErrors[error]["n_pages"]; - this.errors[error]["n_websites"]++; - } else { - this.errors[error] = { - n_occurrences: websiteErrors[error]["n_occurrences"], - n_pages: websiteErrors[error]["n_pages"], - n_websites: 1, - }; - } - } - - const websiteSuccess = website.success; - - for (const practice in websiteSuccess || {}) { - if (Object.keys(this.success).includes(practice)) { - this.success[practice]["n_occurrences"] += - websiteSuccess[practice]["n_occurrences"]; - this.success[practice]["n_pages"] += - websiteSuccess[practice]["n_pages"]; - this.success[practice]["n_websites"]++; - } else { - this.success[practice] = { - n_occurrences: websiteSuccess[practice]["n_occurrences"], - n_pages: websiteSuccess[practice]["n_pages"], - n_websites: 1, - }; - } - } - - if (!this.recentPage) { - this.recentPage = website.recentPage; - } - - if (!this.oldestPage) { - this.oldestPage = website.oldestPage; - } - - if (website.recentPage > this.recentPage) { - this.recentPage = website.recentPage; - } else if (website.oldestPage < this.oldestPage) { - this.oldestPage = website.oldestPage; - } - - if (website.entity) { - if (website.entity.includes("@,@")) { - for (const entity of website.entity.split("@,@")) { - if (!this.entities.includes(entity.trim())) { - this.entities.push(entity.trim()); - } - } - } else if (!this.entities.includes(website.entity.trim())) { - this.entities.push(website.entity.trim()); - } - } - } - - getScore(): number { - return this.score / this.websites.length; - } - - getTopTenErrors(): any { - const errors = new Array(); - for (const key in this.errors || {}) { - errors.push({ - key, - n_occurrences: this.errors[key].n_occurrences, - n_pages: this.errors[key].n_pages, - n_websites: this.errors[key].n_websites, - }); - } - - return orderBy( - errors, - ["n_occurrences", "n_pages", "n_websites"], - ["desc", "desc", "desc"] - ).slice(0, 10); - } - - getPassedOccurrenceByWebsite(test: string): Array { - const occurrences = new Array(); - - for (const website of this.websites || []) { - if (website.success[test] && tests[test]["result"] === "passed") { - occurrences.push(website.success[test]["n_occurrences"]); - } - } - return occurrences; - } - - getErrorOccurrencesByWebsite(test: string): Array { - const occurrences = new Array(); - - for (const website of this.websites || []) { - if (website.errors[test] && tests[test]["result"] === "failed") { - occurrences.push(website.errors[test]["n_occurrences"]); - } - } - return occurrences; - } -} +import orderBy from "lodash.orderby"; +import tests from "src/evaluation/tests"; +import { Website } from "./website"; + +export class Directory { + id: number; + rank: number; + name: string; + creationDate: Date; + websites: Array; + nPages: number; + nPagesWithoutErrors: number; + entities: Array; + declarations: number; + stamps: number; + score: number; + A: number; + AA: number; + AAA: number; + frequencies: Array; + errors: any; + recentPage: Date; + oldestPage: Date; + success: any; + + constructor(id: number, name: string, creationDate: Date) { + this.id = id; + this.rank = -1; + this.name = name; + this.creationDate = creationDate; + this.websites = new Array(); + this.nPages = 0; + this.nPagesWithoutErrors = 0; + this.entities = new Array(); + this.declarations = 0; + this.stamps = 0; + this.score = 0; + this.A = 0; + this.AA = 0; + this.AAA = 0; + this.frequencies = new Array(9).fill(0); + this.errors = {}; + this.success = {}; + } + + addWebsite(website: Website): void { + this.websites.push(website); + this.nPages += website.pages.length; + this.score += website.getScore(); + + if (website.declaration) { + this.declarations++; + } + + if (website.stamp) { + this.stamps++; + } + + this.nPagesWithoutErrors += website.AAA; + + if (website.AAA === website.pages.length) { + this.AAA++; + } else if (website.AAA + website.AA === website.pages.length) { + this.AA++; + } else if (website.AAA + website.AA + website.A === website.pages.length) { + this.A++; + } + + this.frequencies = this.frequencies.map((v: number, i: number) => { + return v + website.frequencies[i]; + }); + + const websiteErrors = website.errors; + + for (const error in websiteErrors || {}) { + if (Object.keys(this.errors).includes(error)) { + this.errors[error]["n_occurrences"] += + websiteErrors[error]["n_occurrences"]; + this.errors[error]["n_pages"] += websiteErrors[error]["n_pages"]; + this.errors[error]["n_websites"]++; + } else { + this.errors[error] = { + n_occurrences: websiteErrors[error]["n_occurrences"], + n_pages: websiteErrors[error]["n_pages"], + n_websites: 1, + }; + } + } + + const websiteSuccess = website.success; + + for (const practice in websiteSuccess || {}) { + if (Object.keys(this.success).includes(practice)) { + this.success[practice]["n_occurrences"] += + websiteSuccess[practice]["n_occurrences"]; + this.success[practice]["n_pages"] += + websiteSuccess[practice]["n_pages"]; + this.success[practice]["n_websites"]++; + } else { + this.success[practice] = { + n_occurrences: websiteSuccess[practice]["n_occurrences"], + n_pages: websiteSuccess[practice]["n_pages"], + n_websites: 1, + }; + } + } + + if (!this.recentPage) { + this.recentPage = website.recentPage; + } + + if (!this.oldestPage) { + this.oldestPage = website.oldestPage; + } + + if (website.recentPage > this.recentPage) { + this.recentPage = website.recentPage; + } else if (website.oldestPage < this.oldestPage) { + this.oldestPage = website.oldestPage; + } + + if (website.entity) { + if (website.entity.includes("@,@")) { + for (const entity of website.entity.split("@,@")) { + if (!this.entities.includes(entity.trim())) { + this.entities.push(entity.trim()); + } + } + } else if (!this.entities.includes(website.entity.trim())) { + this.entities.push(website.entity.trim()); + } + } + } + + getScore(): number { + return this.score / this.websites.length; + } + + getTopTenErrors(): any { + const errors = new Array(); + for (const key in this.errors || {}) { + errors.push({ + key, + n_occurrences: this.errors[key].n_occurrences, + n_pages: this.errors[key].n_pages, + n_websites: this.errors[key].n_websites, + }); + } + + return orderBy( + errors, + ["n_occurrences", "n_pages", "n_websites"], + ["desc", "desc", "desc"] + ).slice(0, 10); + } + + getPassedOccurrenceByWebsite(test: string): Array { + const occurrences = new Array(); + + for (const website of this.websites || []) { + if (website.success[test] && tests[test]["result"] === "passed") { + occurrences.push(website.success[test]["n_occurrences"]); + } + } + return occurrences; + } + + getErrorOccurrencesByWebsite(test: string): Array { + const occurrences = new Array(); + + for (const website of this.websites || []) { + if (website.errors[test] && tests[test]["result"] === "failed") { + occurrences.push(website.errors[test]["n_occurrences"]); + } + } + return occurrences; + } +} diff --git a/src/observatory/models/evaluation.ts b/src/observatory/models/evaluation.ts index 603d7fa2..51601842 100644 --- a/src/observatory/models/evaluation.ts +++ b/src/observatory/models/evaluation.ts @@ -1,33 +1,33 @@ -export class Evaluation { - id: number; - title: string; - score: number; - errors: any; - tot: any; - A: number; - AA: number; - AAA: number; - evaluationDate: Date; - - constructor( - id: number, - title: string, - score: number, - errors: any, - tot: any, - A: number, - AA: number, - AAA: number, - evaluationDate: Date - ) { - this.id = id; - this.title = title; - this.score = parseFloat(score.toFixed(1)); - this.errors = JSON.parse(Buffer.from(errors, "base64").toString()); - this.tot = JSON.parse(Buffer.from(tot, "base64").toString()); - this.A = A; - this.AA = AA; - this.AAA = AAA; - this.evaluationDate = evaluationDate; - } -} +export class Evaluation { + id: number; + title: string; + score: number; + errors: any; + tot: any; + A: number; + AA: number; + AAA: number; + evaluationDate: Date; + + constructor( + id: number, + title: string, + score: number, + errors: any, + tot: any, + A: number, + AA: number, + AAA: number, + evaluationDate: Date + ) { + this.id = id; + this.title = title; + this.score = parseFloat(score.toFixed(1)); + this.errors = JSON.parse(Buffer.from(errors, "base64").toString()); + this.tot = JSON.parse(Buffer.from(tot, "base64").toString()); + this.A = A; + this.AA = AA; + this.AAA = AAA; + this.evaluationDate = evaluationDate; + } +} diff --git a/src/observatory/models/list-directories.ts b/src/observatory/models/list-directories.ts index f0af2ac8..7aec09f8 100644 --- a/src/observatory/models/list-directories.ts +++ b/src/observatory/models/list-directories.ts @@ -1,221 +1,221 @@ -import orderBy from "lodash.orderby"; -import tests from "src/evaluation/tests"; -import { Directory } from "./directory"; -import { Website } from "./website"; - -export class ListDirectories { - directories: Array; - nEntities: number; - nWebsites: number; - nPages: number; - nPagesWithoutErrors: number; - score: number; - A: number; - AA: number; - AAA: number; - frequencies: Array; - errors: any; - success: any; - recentPage: Date; - oldestPage: Date; - - constructor(result: any, directories: Array) { - this.directories = directories; - this.nPagesWithoutErrors = 0; - this.A = 0; - this.AA = 0; - this.AAA = 0; - this.frequencies = new Array(9).fill(0); - this.errors = {}; - this.success = {}; - - this.nEntities = result - .map((r) => r.Entity_Name) - .filter((v, i, self) => self.indexOf(v) === i).length; - - this.nWebsites = result - .map((r) => r.Website_Name) - .filter((v, i, self) => self.indexOf(v) === i).length; - - this.nPages = result - .map((r) => r.Uri) - .filter((v, i, self) => { - return self.indexOf(v) === i; - }).length; - - let score = 0; - const size = directories.length; - - for (const directory of directories || []) { - score += directory.getScore(); - this.nPagesWithoutErrors += directory.nPagesWithoutErrors; - this.A += directory.A; - this.AA += directory.AA; - this.AAA += directory.AAA; - this.frequencies = this.frequencies.map((v: number, j: number) => { - return v + directory.frequencies[j]; - }); - - const directoryErrors = directory.errors; - - for (const error in directoryErrors || {}) { - if (Object.keys(this.errors).includes(error)) { - this.errors[error]["n_occurrences"] += - directoryErrors[error]["n_occurrences"]; - this.errors[error]["n_pages"] += directoryErrors[error]["n_pages"]; - this.errors[error]["n_websites"] += - directoryErrors[error]["n_websites"]; - this.errors[error]["n_tags"]++; - } else { - this.errors[error] = { - n_occurrences: directoryErrors[error]["n_occurrences"], - n_pages: directoryErrors[error]["n_pages"], - n_websites: directoryErrors[error]["n_websites"], - n_tags: 1, - }; - } - } - - const directorySuccess = directory.success; - - for (const practice in directorySuccess || {}) { - if (Object.keys(this.success).includes(practice)) { - this.success[practice]["n_occurrences"] += - directorySuccess[practice]["n_occurrences"]; - this.success[practice]["n_pages"] += - directorySuccess[practice]["n_pages"]; - this.success[practice]["n_websites"] += - directorySuccess[practice]["n_websites"]; - this.success[practice]["n_tags"]++; - } else { - this.success[practice] = { - n_occurrences: directorySuccess[practice]["n_occurrences"], - n_pages: directorySuccess[practice]["n_pages"], - n_websites: directorySuccess[practice]["n_websites"], - n_tags: 1, - }; - } - } - - if (!this.recentPage) { - this.recentPage = directory.recentPage; - } - - if (!this.oldestPage) { - this.oldestPage = directory.oldestPage; - } - - if (directory.recentPage > this.recentPage) { - this.recentPage = directory.recentPage; - } else if (directory.oldestPage < this.oldestPage) { - this.oldestPage = directory.oldestPage; - } - } - - this.score = score / size; - } - - getScore(): number { - return this.score; - } - - getWebsites(): Array { - const websites = new Array(); - const alreadyInList = new Array(); - this.directories.map((dir: Directory) => { - dir.websites.map((w: Website) => { - if (!alreadyInList.includes(w.id)) { - w["DirectoryId"] = dir.id; - websites.push(w); - } - }); - }); - - return websites; - } - - getTopFiveErrors(): any { - const errors = new Array(); - for (const key in this.errors || {}) { - errors.push({ - key, - n_occurrences: this.errors[key].n_occurrences, - n_pages: this.errors[key].n_pages, - n_websites: this.errors[key].n_websites, - }); - } - - return orderBy( - errors, - ["n_occurrences", "n_pages", "n_websites"], - ["desc", "desc", "desc"] - ).slice(0, 5); - } - - getTopFiveBestPractices(): any { - const practices = new Array(); - for (const key in this.success || {}) { - practices.push({ - key, - n_occurrences: this.success[key].n_occurrences, - n_pages: this.success[key].n_pages, - n_websites: this.success[key].n_websites, - }); - } - - return orderBy( - practices, - ["n_occurrences", "n_pages", "n_websites"], - ["desc", "desc", "desc"] - ).slice(0, 5); - } - - getPassedAndWarningOccurrenceByDirectory(test: string): Array { - const occurrences = new Array(); - - for (const directory of this.directories || []) { - if (directory.success[test] && tests[test]["result"] !== "failed") { - occurrences.push(directory.success[test]["n_occurrences"]); - } - } - return occurrences; - } - - getPassedOccurrenceByDirectory(test: string): Array { - const occurrences = new Array(); - - for (const directory of this.directories || []) { - if (directory.success[test] && tests[test]["result"] === "passed") { - occurrences.push(directory.success[test]["n_occurrences"]); - } - } - return occurrences; - } - - getErrorOccurrenceByDirectory(test: string): Array { - const occurrences = new Array(); - - for (const directory of this.directories || []) { - if (directory.errors[test] && tests[test]["result"] === "failed") { - occurrences.push(directory.errors[test]["n_occurrences"]); - } - } - - return occurrences; - } - - getDirectory(id: number): Directory { - return this.directories.find((directory: Directory) => directory.id === id); - } - - getWebsite(directoryId: number, websiteId: number): Website { - const directory = this.directories.find( - (directory: Directory) => directory.id === directoryId - ); - const websites = directory.websites; - const website = websites.find( - (website: Website) => website.id === websiteId - ); - return website; - } -} \ No newline at end of file +import orderBy from "lodash.orderby"; +import tests from "src/evaluation/tests"; +import { Directory } from "./directory"; +import { Website } from "./website"; + +export class ListDirectories { + directories: Array; + nEntities: number; + nWebsites: number; + nPages: number; + nPagesWithoutErrors: number; + score: number; + A: number; + AA: number; + AAA: number; + frequencies: Array; + errors: any; + success: any; + recentPage: Date; + oldestPage: Date; + + constructor(result: any, directories: Array) { + this.directories = directories; + this.nPagesWithoutErrors = 0; + this.A = 0; + this.AA = 0; + this.AAA = 0; + this.frequencies = new Array(9).fill(0); + this.errors = {}; + this.success = {}; + + this.nEntities = result + .map((r) => r.Entity_Name) + .filter((v, i, self) => self.indexOf(v) === i).length; + + this.nWebsites = result + .map((r) => r.Website_Name) + .filter((v, i, self) => self.indexOf(v) === i).length; + + this.nPages = result + .map((r) => r.Uri) + .filter((v, i, self) => { + return self.indexOf(v) === i; + }).length; + + let score = 0; + const size = directories.length; + + for (const directory of directories || []) { + score += directory.getScore(); + this.nPagesWithoutErrors += directory.nPagesWithoutErrors; + this.A += directory.A; + this.AA += directory.AA; + this.AAA += directory.AAA; + this.frequencies = this.frequencies.map((v: number, j: number) => { + return v + directory.frequencies[j]; + }); + + const directoryErrors = directory.errors; + + for (const error in directoryErrors || {}) { + if (Object.keys(this.errors).includes(error)) { + this.errors[error]["n_occurrences"] += + directoryErrors[error]["n_occurrences"]; + this.errors[error]["n_pages"] += directoryErrors[error]["n_pages"]; + this.errors[error]["n_websites"] += + directoryErrors[error]["n_websites"]; + this.errors[error]["n_tags"]++; + } else { + this.errors[error] = { + n_occurrences: directoryErrors[error]["n_occurrences"], + n_pages: directoryErrors[error]["n_pages"], + n_websites: directoryErrors[error]["n_websites"], + n_tags: 1, + }; + } + } + + const directorySuccess = directory.success; + + for (const practice in directorySuccess || {}) { + if (Object.keys(this.success).includes(practice)) { + this.success[practice]["n_occurrences"] += + directorySuccess[practice]["n_occurrences"]; + this.success[practice]["n_pages"] += + directorySuccess[practice]["n_pages"]; + this.success[practice]["n_websites"] += + directorySuccess[practice]["n_websites"]; + this.success[practice]["n_tags"]++; + } else { + this.success[practice] = { + n_occurrences: directorySuccess[practice]["n_occurrences"], + n_pages: directorySuccess[practice]["n_pages"], + n_websites: directorySuccess[practice]["n_websites"], + n_tags: 1, + }; + } + } + + if (!this.recentPage) { + this.recentPage = directory.recentPage; + } + + if (!this.oldestPage) { + this.oldestPage = directory.oldestPage; + } + + if (directory.recentPage > this.recentPage) { + this.recentPage = directory.recentPage; + } else if (directory.oldestPage < this.oldestPage) { + this.oldestPage = directory.oldestPage; + } + } + + this.score = score / size; + } + + getScore(): number { + return this.score; + } + + getWebsites(): Array { + const websites = new Array(); + const alreadyInList = new Array(); + this.directories.map((dir: Directory) => { + dir.websites.map((w: Website) => { + if (!alreadyInList.includes(w.id)) { + w["DirectoryId"] = dir.id; + websites.push(w); + } + }); + }); + + return websites; + } + + getTopFiveErrors(): any { + const errors = new Array(); + for (const key in this.errors || {}) { + errors.push({ + key, + n_occurrences: this.errors[key].n_occurrences, + n_pages: this.errors[key].n_pages, + n_websites: this.errors[key].n_websites, + }); + } + + return orderBy( + errors, + ["n_occurrences", "n_pages", "n_websites"], + ["desc", "desc", "desc"] + ).slice(0, 5); + } + + getTopFiveBestPractices(): any { + const practices = new Array(); + for (const key in this.success || {}) { + practices.push({ + key, + n_occurrences: this.success[key].n_occurrences, + n_pages: this.success[key].n_pages, + n_websites: this.success[key].n_websites, + }); + } + + return orderBy( + practices, + ["n_occurrences", "n_pages", "n_websites"], + ["desc", "desc", "desc"] + ).slice(0, 5); + } + + getPassedAndWarningOccurrenceByDirectory(test: string): Array { + const occurrences = new Array(); + + for (const directory of this.directories || []) { + if (directory.success[test] && tests[test]["result"] !== "failed") { + occurrences.push(directory.success[test]["n_occurrences"]); + } + } + return occurrences; + } + + getPassedOccurrenceByDirectory(test: string): Array { + const occurrences = new Array(); + + for (const directory of this.directories || []) { + if (directory.success[test] && tests[test]["result"] === "passed") { + occurrences.push(directory.success[test]["n_occurrences"]); + } + } + return occurrences; + } + + getErrorOccurrenceByDirectory(test: string): Array { + const occurrences = new Array(); + + for (const directory of this.directories || []) { + if (directory.errors[test] && tests[test]["result"] === "failed") { + occurrences.push(directory.errors[test]["n_occurrences"]); + } + } + + return occurrences; + } + + getDirectory(id: number): Directory { + return this.directories.find((directory: Directory) => directory.id === id); + } + + getWebsite(directoryId: number, websiteId: number): Website { + const directory = this.directories.find( + (directory: Directory) => directory.id === directoryId + ); + const websites = directory.websites; + const website = websites.find( + (website: Website) => website.id === websiteId + ); + return website; + } +} diff --git a/src/observatory/models/page.ts b/src/observatory/models/page.ts index bdfd0043..240c10d1 100644 --- a/src/observatory/models/page.ts +++ b/src/observatory/models/page.ts @@ -1,19 +1,38 @@ -import { Evaluation } from './evaluation'; - -export class Page { - id: number; - uri: string; - creationDate: Date; - evaluation: Evaluation; - - constructor(id: number, uri: string, creationDate: Date) { - this.id = id; - this.uri = uri; - this.creationDate = creationDate; - } - - addEvaluation(id: number, title: string, score: number, errors: any, tot: any, - A: number, AA: number, AAA: number, evaluationDate: Date): void { - this.evaluation = new Evaluation(id, title, score, errors, tot, A, AA, AAA, evaluationDate); - } -} +import { Evaluation } from "./evaluation"; + +export class Page { + id: number; + uri: string; + creationDate: Date; + evaluation: Evaluation; + + constructor(id: number, uri: string, creationDate: Date) { + this.id = id; + this.uri = uri; + this.creationDate = creationDate; + } + + addEvaluation( + id: number, + title: string, + score: number, + errors: any, + tot: any, + A: number, + AA: number, + AAA: number, + evaluationDate: Date + ): void { + this.evaluation = new Evaluation( + id, + title, + score, + errors, + tot, + A, + AA, + AAA, + evaluationDate + ); + } +} diff --git a/src/observatory/models/website.ts b/src/observatory/models/website.ts index cdd71875..894d9cf6 100644 --- a/src/observatory/models/website.ts +++ b/src/observatory/models/website.ts @@ -1,239 +1,239 @@ -import { Page } from "./page"; -import orderBy from "lodash.orderby"; -import tests from "src/evaluation/tests"; - -export class Website { - id: number; - DirectoryId: number; - rank: number; - entity: string; - name: string; - declaration: number | null; - declarationDate: Date | null; - stamp: number | null; - stampDate: Date | null; - startingUrl: string; - creationDate: Date; - pages: Array; - calculatedScore: number; - score: number; - A: number; - AA: number; - AAA: number; - frequencies: Array; - errors: any; - recentPage: Date; - oldestPage: Date; - success: any; - - constructor( - id: number, - entity: string, - name: string, - declaration: number | null, - declarationDate: Date | null, - stamp: number | null, - stampDate: Date | null, - startingUrl: string, - creationDate: Date - ) { - this.id = id; - this.DirectoryId = -1; - this.rank = -1; - this.entity = entity; - this.name = name; - this.declaration = declaration; - this.declarationDate = declarationDate ? new Date(declarationDate) : null; - this.stamp = stamp; - this.stampDate = stampDate ? new Date(stampDate) : null; - this.startingUrl = startingUrl; - this.creationDate = creationDate; - this.pages = new Array(); - this.calculatedScore = 0; - this.score = 0; - this.A = 0; - this.AA = 0; - this.AAA = 0; - this.frequencies = new Array(9).fill(0); - this.errors = {}; - this.success = {}; - } - - addPage( - pageId: number, - uri: string, - creationDate: Date, - evaluationId: number, - title: string, - score: number, - errors: any, - tot: any, - A: number, - AA: number, - AAA: number, - evaluationDate: Date - ): void { - const page = new Page(pageId, uri, creationDate); - page.addEvaluation( - evaluationId, - title, - score, - errors, - tot, - A, - AA, - AAA, - evaluationDate - ); - this.pages.push(page); - this.score += score; - - if (A === 0) { - if (AA === 0) { - if (AAA === 0) { - this.AAA++; - } else { - this.AA++; - } - } else { - this.A++; - } - } - - const floor = Math.floor(score); - this.frequencies[floor >= 2 ? (floor === 10 ? floor - 2 : floor - 1) : 0]++; - - const pageErrors = page.evaluation.errors; - - for (const key in page.evaluation.tot.results || {}) { - const test = tests[key]["test"]; - const elem = tests[key]["elem"]; - const occurrences = - pageErrors[test] === undefined || pageErrors[test] < 1 - ? 1 - : pageErrors[test]; - const result = tests[key]["result"]; - - if (result === "failed") { - if (Object.keys(this.errors).includes(key)) { - this.errors[key]["n_occurrences"] += occurrences; - this.errors[key]["n_pages"]++; - } else { - this.errors[key] = { - n_pages: 1, - n_occurrences: occurrences, - elem, - test, - result, - }; - } - } else if (result === "passed") { - if (Object.keys(this.success).includes(key)) { - this.success[key]["n_occurrences"] += occurrences; - this.success[key]["n_pages"]++; - } else { - this.success[key] = { - n_pages: 1, - n_occurrences: occurrences, - elem, - test, - result, - }; - } - } - } - - if (!this.recentPage) { - this.recentPage = evaluationDate; - } - - if (!this.oldestPage) { - this.oldestPage = evaluationDate; - } - - if (evaluationDate > this.recentPage) { - this.recentPage = evaluationDate; - } else if (evaluationDate < this.oldestPage) { - this.oldestPage = evaluationDate; - } - } - - getScore(): number { - return this.score / this.pages.length; - } - - getAllScores(): Array { - return this.pages.map((page: Page) => page.evaluation.score); - } - - getTopTenBestPractices(): any { - const practices = new Array(); - for (const key in this.success || {}) { - practices.push({ - key, - n_occurrences: this.success[key].n_occurrences, - n_pages: this.success[key].n_pages, - }); - } - - return orderBy( - practices, - ["n_occurrences", "n_pages"], - ["desc", "desc"] - ).slice(0, 10); - } - - getTopTenErrors(): any { - const errors = new Array(); - for (const key in this.errors || {}) { - errors.push({ - key, - n_occurrences: this.errors[key].n_occurrences, - n_pages: this.errors[key].n_pages, - }); - } - - return orderBy( - errors, - ["n_occurrences", "n_pages"], - ["desc", "desc"] - ).slice(0, 10); - } - - getPassedOccurrencesByPage(test: string): Array { - const occurrences = new Array(); - for (const page of this.pages || []) { - const practice = page.evaluation.tot.elems[tests[test]["test"]]; - if ( - page.evaluation.tot.results[test] && - tests[test]["result"] === "passed" - ) { - if (!practice) { - occurrences.push(1); - } else { - occurrences.push(practice); - } - } - } - return occurrences; - } - - getErrorOccurrencesByPage(test: string): Array { - const occurrences = new Array(); - - for (const page of this.pages || []) { - const error = page.evaluation.tot.elems[tests[test]["test"]]; - if ( - page.evaluation.tot.results[test] && - tests[test]["result"] === "failed" - ) { - if (!error) { - occurrences.push(1); - } else { - occurrences.push(error); - } - } - } - return occurrences; - } -} +import { Page } from "./page"; +import orderBy from "lodash.orderby"; +import tests from "src/evaluation/tests"; + +export class Website { + id: number; + DirectoryId: number; + rank: number; + entity: string; + name: string; + declaration: number | null; + declarationDate: Date | null; + stamp: number | null; + stampDate: Date | null; + startingUrl: string; + creationDate: Date; + pages: Array; + calculatedScore: number; + score: number; + A: number; + AA: number; + AAA: number; + frequencies: Array; + errors: any; + recentPage: Date; + oldestPage: Date; + success: any; + + constructor( + id: number, + entity: string, + name: string, + declaration: number | null, + declarationDate: Date | null, + stamp: number | null, + stampDate: Date | null, + startingUrl: string, + creationDate: Date + ) { + this.id = id; + this.DirectoryId = -1; + this.rank = -1; + this.entity = entity; + this.name = name; + this.declaration = declaration; + this.declarationDate = declarationDate ? new Date(declarationDate) : null; + this.stamp = stamp; + this.stampDate = stampDate ? new Date(stampDate) : null; + this.startingUrl = startingUrl; + this.creationDate = creationDate; + this.pages = new Array(); + this.calculatedScore = 0; + this.score = 0; + this.A = 0; + this.AA = 0; + this.AAA = 0; + this.frequencies = new Array(9).fill(0); + this.errors = {}; + this.success = {}; + } + + addPage( + pageId: number, + uri: string, + creationDate: Date, + evaluationId: number, + title: string, + score: number, + errors: any, + tot: any, + A: number, + AA: number, + AAA: number, + evaluationDate: Date + ): void { + const page = new Page(pageId, uri, creationDate); + page.addEvaluation( + evaluationId, + title, + score, + errors, + tot, + A, + AA, + AAA, + evaluationDate + ); + this.pages.push(page); + this.score += score; + + if (A === 0) { + if (AA === 0) { + if (AAA === 0) { + this.AAA++; + } else { + this.AA++; + } + } else { + this.A++; + } + } + + const floor = Math.floor(score); + this.frequencies[floor >= 2 ? (floor === 10 ? floor - 2 : floor - 1) : 0]++; + + const pageErrors = page.evaluation.errors; + + for (const key in page.evaluation.tot.results || {}) { + const test = tests[key]["test"]; + const elem = tests[key]["elem"]; + const occurrences = + pageErrors[test] === undefined || pageErrors[test] < 1 + ? 1 + : pageErrors[test]; + const result = tests[key]["result"]; + + if (result === "failed") { + if (Object.keys(this.errors).includes(key)) { + this.errors[key]["n_occurrences"] += occurrences; + this.errors[key]["n_pages"]++; + } else { + this.errors[key] = { + n_pages: 1, + n_occurrences: occurrences, + elem, + test, + result, + }; + } + } else if (result === "passed") { + if (Object.keys(this.success).includes(key)) { + this.success[key]["n_occurrences"] += occurrences; + this.success[key]["n_pages"]++; + } else { + this.success[key] = { + n_pages: 1, + n_occurrences: occurrences, + elem, + test, + result, + }; + } + } + } + + if (!this.recentPage) { + this.recentPage = evaluationDate; + } + + if (!this.oldestPage) { + this.oldestPage = evaluationDate; + } + + if (evaluationDate > this.recentPage) { + this.recentPage = evaluationDate; + } else if (evaluationDate < this.oldestPage) { + this.oldestPage = evaluationDate; + } + } + + getScore(): number { + return this.score / this.pages.length; + } + + getAllScores(): Array { + return this.pages.map((page: Page) => page.evaluation.score); + } + + getTopTenBestPractices(): any { + const practices = new Array(); + for (const key in this.success || {}) { + practices.push({ + key, + n_occurrences: this.success[key].n_occurrences, + n_pages: this.success[key].n_pages, + }); + } + + return orderBy( + practices, + ["n_occurrences", "n_pages"], + ["desc", "desc"] + ).slice(0, 10); + } + + getTopTenErrors(): any { + const errors = new Array(); + for (const key in this.errors || {}) { + errors.push({ + key, + n_occurrences: this.errors[key].n_occurrences, + n_pages: this.errors[key].n_pages, + }); + } + + return orderBy( + errors, + ["n_occurrences", "n_pages"], + ["desc", "desc"] + ).slice(0, 10); + } + + getPassedOccurrencesByPage(test: string): Array { + const occurrences = new Array(); + for (const page of this.pages || []) { + const practice = page.evaluation.tot.elems[tests[test]["test"]]; + if ( + page.evaluation.tot.results[test] && + tests[test]["result"] === "passed" + ) { + if (!practice) { + occurrences.push(1); + } else { + occurrences.push(practice); + } + } + } + return occurrences; + } + + getErrorOccurrencesByPage(test: string): Array { + const occurrences = new Array(); + + for (const page of this.pages || []) { + const error = page.evaluation.tot.elems[tests[test]["test"]]; + if ( + page.evaluation.tot.results[test] && + tests[test]["result"] === "failed" + ) { + if (!error) { + occurrences.push(1); + } else { + occurrences.push(error); + } + } + } + return occurrences; + } +} diff --git a/src/observatory/observatory.controller.spec.ts b/src/observatory/observatory.controller.spec.ts index aa58a484..321f4303 100644 --- a/src/observatory/observatory.controller.spec.ts +++ b/src/observatory/observatory.controller.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ObservatoryController } from './observatory.controller'; - -describe('Observatory Controller', () => { - let controller: ObservatoryController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [ObservatoryController], - }).compile(); - - controller = module.get(ObservatoryController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { ObservatoryController } from "./observatory.controller"; + +describe("Observatory Controller", () => { + let controller: ObservatoryController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [ObservatoryController], + }).compile(); + + controller = module.get(ObservatoryController); + }); + + it("should be defined", () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/observatory/observatory.controller.ts b/src/observatory/observatory.controller.ts index bfaa49d7..e7fc8abe 100644 --- a/src/observatory/observatory.controller.ts +++ b/src/observatory/observatory.controller.ts @@ -1,58 +1,68 @@ -import { Controller, Get, Post, UseGuards, UseInterceptors } from "@nestjs/common"; -import { ObservatoryService } from "./observatory.service"; -import { success, error } from "../lib/response"; -import { AuthGuard } from "@nestjs/passport"; -import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; -import { Observatory } from "./observatory.entity"; - - -@ApiBasicAuth() -@ApiTags('observatory') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller("observatory") -@UseInterceptors(LoggingInterceptor) -export class ObservatoryController { - constructor(private readonly observatoryService: ObservatoryService) {} - - @ApiOperation({ summary: 'Get all observatory data' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Observatory, - }) - @Get('all') - async findAll(): Promise { - const data = await this.observatoryService.findAll(); - return success(data); - } - - @ApiOperation({ summary: 'Get latest observatory data' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Observatory, - }) - @Get() - async getData(): Promise { - const data = await this.observatoryService.getObservatoryData(); - return success(data); - } - - @ApiOperation({ summary: 'Generate observatory data' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("generate") - async generateData(): Promise { - try { - this.observatoryService.generateData(true); - return success(); - } catch (err) { - return error(err); - } - } -} +import { + Controller, + Get, + Post, + UseGuards, + UseInterceptors, +} from "@nestjs/common"; +import { ObservatoryService } from "./observatory.service"; +import { success, error } from "../lib/response"; +import { AuthGuard } from "@nestjs/passport"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { + ApiBasicAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; +import { Observatory } from "./observatory.entity"; + +@ApiBasicAuth() +@ApiTags("observatory") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("observatory") +@UseInterceptors(LoggingInterceptor) +export class ObservatoryController { + constructor(private readonly observatoryService: ObservatoryService) {} + + @ApiOperation({ summary: "Get all observatory data" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Observatory, + }) + @Get("all") + async findAll(): Promise { + const data = await this.observatoryService.findAll(); + return success(data); + } + + @ApiOperation({ summary: "Get latest observatory data" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Observatory, + }) + @Get() + async getData(): Promise { + const data = await this.observatoryService.getObservatoryData(); + return success(data); + } + + @ApiOperation({ summary: "Generate observatory data" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("generate") + async generateData(): Promise { + try { + this.observatoryService.generateData(true); + return success(); + } catch (err) { + return error(err); + } + } +} diff --git a/src/observatory/observatory.module.ts b/src/observatory/observatory.module.ts index 00447ef2..24872fc5 100644 --- a/src/observatory/observatory.module.ts +++ b/src/observatory/observatory.module.ts @@ -1,14 +1,14 @@ -import { Module } from '@nestjs/common'; -import { ObservatoryController } from './observatory.controller'; -import { PageModule } from '../page/page.module'; -import { Observatory } from './observatory.entity'; -import { ObservatoryService } from './observatory.service'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -@Module({ - imports: [TypeOrmModule.forFeature([Observatory])], - exports: [ObservatoryService], - controllers: [ObservatoryController], - providers: [ObservatoryService] -}) -export class ObservatoryModule {} +import { Module } from "@nestjs/common"; +import { ObservatoryController } from "./observatory.controller"; +import { PageModule } from "../page/page.module"; +import { Observatory } from "./observatory.entity"; +import { ObservatoryService } from "./observatory.service"; +import { TypeOrmModule } from "@nestjs/typeorm"; + +@Module({ + imports: [TypeOrmModule.forFeature([Observatory])], + exports: [ObservatoryService], + controllers: [ObservatoryController], + providers: [ObservatoryService], +}) +export class ObservatoryModule {} diff --git a/src/observatory/observatory.service.spec.ts b/src/observatory/observatory.service.spec.ts index 4b50d647..eb88240e 100644 --- a/src/observatory/observatory.service.spec.ts +++ b/src/observatory/observatory.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { ObservatoryService } from './observatory.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { ObservatoryService } from "./observatory.service"; -describe('ObservatoryService', () => { +describe("ObservatoryService", () => { let service: ObservatoryService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('ObservatoryService', () => { service = module.get(ObservatoryService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/observatory/observatory.service.ts b/src/observatory/observatory.service.ts index 07af2537..845f4523 100644 --- a/src/observatory/observatory.service.ts +++ b/src/observatory/observatory.service.ts @@ -45,18 +45,26 @@ export class ObservatoryService { constructor( @InjectRepository(Observatory) private readonly observatoryRepository: Repository - ) { } + ) {} async findAll(): Promise { - return this.observatoryRepository.find({ select: ["Creation_Date", "Type", "ObservatoryId"] }); + return this.observatoryRepository.find({ + select: ["Creation_Date", "Type", "ObservatoryId"], + }); } @Cron(CronExpression.EVERY_DAY_AT_1AM) async generateData(manual = false): Promise { console.log("generating data"); - console.log({ nameSpace: process.env.NAMESPACE, amsid: process.env.AMSID, intParse: parseInt(process.env.AMSID) }); + console.log({ + nameSpace: process.env.NAMESPACE, + amsid: process.env.AMSID, + intParse: parseInt(process.env.AMSID), + }); if ( - (process.env.NAMESPACE === undefined || - parseInt(process.env.AMSID) === 0) || manual) { + process.env.NAMESPACE === undefined || + parseInt(process.env.AMSID) === 0 || + manual + ) { const data = await this.getData(); const directories = new Array(); @@ -95,7 +103,6 @@ export class ObservatoryService { directories: this.getDirectories(listDirectories), }; - if (manual) { await this.observatoryRepository.delete({ Type: "manual", @@ -527,8 +534,19 @@ export class ObservatoryService { getTopFiveWebsites(listDirectories: ListDirectories): any { const websites = listDirectories .getWebsites() - .filter((value, index, array) => array.findIndex(element => element.name === value.name) === index && value.A + value.AA + value.AAA > 10) - .sort((a: Website, b: Website) => (Math.round(b.getScore() * 10) / 10) - (Math.round(a.getScore() * 10) / 10) || b.AAA - a.AAA || b.AA - a.AA || b.A - a.A) + .filter( + (value, index, array) => + array.findIndex((element) => element.name === value.name) === index && + value.A + value.AA + value.AAA > 10 + ) + .sort( + (a: Website, b: Website) => + Math.round(b.getScore() * 10) / 10 - + Math.round(a.getScore() * 10) / 10 || + b.AAA - a.AAA || + b.AA - a.AA || + b.A - a.A + ) .slice(0, 5); const topFiveWebsites = new Array(); @@ -638,7 +656,15 @@ export class ObservatoryService { let rank = 1; const directories = listDirectories.directories .slice() - .sort((a: Directory, b: Directory) => (Math.round(b.getScore() * 10) / 10) - (Math.round(a.getScore() * 10) / 10) || b.AAA - a.AAA || b.AA - a.AA || b.A - a.A || b.nPages - a.nPages) + .sort( + (a: Directory, b: Directory) => + Math.round(b.getScore() * 10) / 10 - + Math.round(a.getScore() * 10) / 10 || + b.AAA - a.AAA || + b.AA - a.AA || + b.A - a.A || + b.nPages - a.nPages + ) .map((d: Directory) => { d.rank = rank; rank++; @@ -893,9 +919,7 @@ export class ObservatoryService { n_occurrences: website.errors[key].n_occurrences, n_pages: website.errors[key].n_pages, lvl: _tests[key].level.toUpperCase(), - quartiles: calculateQuartiles( - website.getErrorOccurrencesByPage(key) - ), + quartiles: calculateQuartiles(website.getErrorOccurrencesByPage(key)), }); } } @@ -916,7 +940,6 @@ export class ObservatoryService { ): Array { let data = directories.getErrorOccurrenceByDirectory(test); return calculateQuartiles(data); - } private calculateQuartilesGlobalBestPractices( @@ -925,7 +948,6 @@ export class ObservatoryService { ): Array { let data = directories.getPassedOccurrenceByDirectory(test); return calculateQuartiles(data); - } private calculateQuartilesDirectoryErrors( diff --git a/src/page/dto/create-page-my-monitor.dto.ts b/src/page/dto/create-page-my-monitor.dto.ts index 733ca515..eaa0a3de 100644 --- a/src/page/dto/create-page-my-monitor.dto.ts +++ b/src/page/dto/create-page-my-monitor.dto.ts @@ -1,5 +1,5 @@ export class CreatePageMyMonitorDto { - website:string; - startingUrl:string; - pages:string[]; -} \ No newline at end of file + website: string; + startingUrl: string; + pages: string[]; +} diff --git a/src/page/dto/delete-page-my-monitor.dto.ts b/src/page/dto/delete-page-my-monitor.dto.ts index a2829711..98bc583c 100644 --- a/src/page/dto/delete-page-my-monitor.dto.ts +++ b/src/page/dto/delete-page-my-monitor.dto.ts @@ -1,5 +1,5 @@ export class DeletePageMyMonitorDto { - website:string; - startingUrl:string; - pagesId:number[]; -} \ No newline at end of file + website: string; + startingUrl: string; + pagesId: number[]; +} diff --git a/src/page/dto/page-create-study-monitor.dto.ts b/src/page/dto/page-create-study-monitor.dto.ts index 6fdb9741..3e19f1d6 100644 --- a/src/page/dto/page-create-study-monitor.dto.ts +++ b/src/page/dto/page-create-study-monitor.dto.ts @@ -1,6 +1,6 @@ export class PageCreateStudyMonitorDto { - tag:string; - website: string; - startingUrl: string; - pages:string; -} \ No newline at end of file + tag: string; + website: string; + startingUrl: string; + pages: string; +} diff --git a/src/page/dto/page-delete-study-monitor.dto.ts b/src/page/dto/page-delete-study-monitor.dto.ts index 7f4e5854..98aa2054 100644 --- a/src/page/dto/page-delete-study-monitor.dto.ts +++ b/src/page/dto/page-delete-study-monitor.dto.ts @@ -1,5 +1,5 @@ export class PageDeleteStudyMonitorDto { - tag:string; - website: string; - pagesId: number[]; -} \ No newline at end of file + tag: string; + website: string; + pagesId: number[]; +} diff --git a/src/page/dto/page-delete.dto.ts b/src/page/dto/page-delete.dto.ts index a3021dd7..95186206 100644 --- a/src/page/dto/page-delete.dto.ts +++ b/src/page/dto/page-delete.dto.ts @@ -1,3 +1,3 @@ export class PageDeleteDto { - pages:number[]; -} \ No newline at end of file + pages: number[]; +} diff --git a/src/page/dto/page-evaluate-study-monitor.dto.ts b/src/page/dto/page-evaluate-study-monitor.dto.ts index d6af6a6a..bf1b3b40 100644 --- a/src/page/dto/page-evaluate-study-monitor.dto.ts +++ b/src/page/dto/page-evaluate-study-monitor.dto.ts @@ -1,7 +1,5 @@ export class PageEvaluateStudyMonitorDto { - tag:string; - website: string; - url: string; - - -} \ No newline at end of file + tag: string; + website: string; + url: string; +} diff --git a/src/page/dto/page-evaluate.dto.ts b/src/page/dto/page-evaluate.dto.ts index 85d4c3eb..4a7aded9 100644 --- a/src/page/dto/page-evaluate.dto.ts +++ b/src/page/dto/page-evaluate.dto.ts @@ -1,3 +1,3 @@ export class PageEvaluateDto { - url:string; -} \ No newline at end of file + url: string; +} diff --git a/src/page/dto/page-import.dto.ts b/src/page/dto/page-import.dto.ts index d8e44f0c..6644342d 100644 --- a/src/page/dto/page-import.dto.ts +++ b/src/page/dto/page-import.dto.ts @@ -1,6 +1,6 @@ export class PageImportDto { - pageId:number; - user:string; - tag:string; - website:string; -} \ No newline at end of file + pageId: number; + user: string; + tag: string; + website: string; +} diff --git a/src/page/dto/page-list.dto.ts b/src/page/dto/page-list.dto.ts index 1d0b1e13..4e052b96 100644 --- a/src/page/dto/page-list.dto.ts +++ b/src/page/dto/page-list.dto.ts @@ -1,3 +1,3 @@ export class PageListDto { - pages:number[]//id -} \ No newline at end of file + pages: number[]; //id +} diff --git a/src/page/dto/page-update.dto.ts b/src/page/dto/page-update.dto.ts index cbb3e7b6..ace397fd 100644 --- a/src/page/dto/page-update.dto.ts +++ b/src/page/dto/page-update.dto.ts @@ -1,4 +1,4 @@ export class PageUpdateDto { - pageId:number; - checked:boolean; -} \ No newline at end of file + pageId: number; + checked: boolean; +} diff --git a/src/page/dto/page-url.dto.ts b/src/page/dto/page-url.dto.ts index 4bc29905..11c81d3e 100644 --- a/src/page/dto/page-url.dto.ts +++ b/src/page/dto/page-url.dto.ts @@ -1,3 +1,3 @@ export class PageUrlDto { - page:string//URL -} \ No newline at end of file + page: string; //URL +} diff --git a/src/page/page.controller.spec.ts b/src/page/page.controller.spec.ts index 7c61783c..e701ac87 100644 --- a/src/page/page.controller.spec.ts +++ b/src/page/page.controller.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { PageController } from './page.controller'; - -describe('Page Controller', () => { - let controller: PageController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [PageController], - }).compile(); - - controller = module.get(PageController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { PageController } from "./page.controller"; + +describe("Page Controller", () => { + let controller: PageController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [PageController], + }).compile(); + + controller = module.get(PageController); + }); + + it("should be defined", () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/page/page.controller.ts b/src/page/page.controller.ts index 46bdccc3..9c39b0dd 100644 --- a/src/page/page.controller.ts +++ b/src/page/page.controller.ts @@ -1,518 +1,558 @@ -import { - Controller, - Post, - Get, - Request, - UseGuards, - Param, - UnauthorizedException, - UseInterceptors, - Body, -} from "@nestjs/common"; -import { AuthGuard } from "@nestjs/passport"; -import { PageService } from "./page.service"; -import { success } from "../lib/response"; -import { EvaluationService } from "../evaluation/evaluation.service"; -import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiTags, ApiResponse, ApiOperation } from "@nestjs/swagger"; -import { PageUrlDto } from "./dto/page-url.dto"; -import { PageListDto } from "./dto/page-list.dto"; -import { CreatePageMyMonitorDto } from "./dto/create-page-my-monitor.dto"; -import { DeletePageMyMonitorDto } from "./dto/delete-page-my-monitor.dto"; -import { Page } from "./page.entity"; -import { PageEvaluateDto } from "./dto/page-evaluate.dto"; -import { PageEvaluateStudyMonitorDto } from "./dto/page-evaluate-study-monitor.dto"; -import { PageCreateStudyMonitorDto } from "./dto/page-create-study-monitor.dto"; -import { PageDeleteStudyMonitorDto } from "./dto/page-delete-study-monitor.dto"; -import { PageUpdateDto } from "./dto/page-update.dto"; -import { PageDeleteDto } from "./dto/page-delete.dto"; -import { PageImportDto } from "./dto/page-import.dto"; - -@ApiBasicAuth() -@ApiTags('page') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller("page") -@UseInterceptors(LoggingInterceptor) -export class PageController { - constructor( - private readonly pageService: PageService, - private readonly evaluationService: EvaluationService - ) {} - - @ApiOperation({ summary: 'Reevaluate page' }) - @ApiResponse({ - status: 200, - description: 'The evaluation request has been submited', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("reEvaluate") - async reEvaluatePage(@Body() pageUrlDto: PageUrlDto): Promise { - const page = decodeURIComponent(pageUrlDto.page); - - await this.evaluationService.increaseAMSObservatoryRequestCounter(); - - return success(await this.pageService.addPageToEvaluate(page, "10", -1)); - } - - @ApiOperation({ summary: 'Find the number of pages in observatory' }) - @ApiResponse({ - status: 200, - description: 'The number of pages in observatory', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("observatory/total") - async getNumberOfObservatoryPages(): Promise { - return success(await this.pageService.findNumberOfObservatory()); - } - - @ApiOperation({ summary: 'Reevaluate multiple pages by url' }) - @ApiResponse({ - status: 200, - description: 'The evaluation request has been submited', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("reEvaluateMulti") - async reEvaluatePages(@Request() req: any): Promise { - const pages = decodeURIComponent(req.body.pages)?.split(",") ?? []; - return success(await this.pageService.addPagesToEvaluate(pages, "10", -1)); - } - - @ApiOperation({ summary: 'Find the number of pages being evaluated by the admin' }) - @ApiResponse({ - status: 200, - description: 'The number of pages being evaluated', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("evaluationList/admin/evaluating") - async getNumberOfAdminPagesBeingEvaluated(): Promise { - return success( - await this.pageService.findAdminEvaluatingInEvaluationList() - ); - } - - @ApiOperation({ summary: 'Find the number of pages waiting for evaluation by the admin' }) - @ApiResponse({ - status: 200, - description: 'The number of pages waiting', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("evaluationList/admin/waiting") - async getNumberOfAdminPagesWaitingForEvaluation(): Promise { - return success(await this.pageService.findAdminWaitingInEvaluationList()); - } - - @ApiOperation({ summary: 'Find the number of pages that failed the evaluation by the admin' }) - @ApiResponse({ - status: 200, - description: 'The number of pages that failed the evaluation', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("evaluationList/admin/error") - async getNumberOfAdminPagesWithError(): Promise { - return success(await this.pageService.findAdminWithErrorInEvaluationList()); - } - - @ApiOperation({ summary: 'Find the number of pages being evaluated by the user' }) - @ApiResponse({ - status: 200, - description: 'The number of pages being evaluated', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("evaluationList/user/evaluating") - async getNumberOfUserPagesBeingEvaluated(): Promise { - return success(await this.pageService.findUserEvaluatingInEvaluationList()); - } - - @ApiOperation({ summary: 'Find the number of pages waiting for evaluation by the user' }) - @ApiResponse({ - status: 200, - description: 'The number of pages waiting', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("evaluationList/user/waiting") - async getNumberOfUserPagesWaitingForEvaluation(): Promise { - return success(await this.pageService.findUserWaitingInEvaluationList()); - } - - @ApiOperation({ summary: 'Find the number of pages that failed the evaluation by the user' }) - @ApiResponse({ - status: 200, - description: 'The number of pages that failed the evaluation', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("evaluationList/user/error") - async getNumberOfUserPagesWithError(): Promise { - return success(await this.pageService.findUserWithErrorInEvaluationList()); - } - - @ApiOperation({ summary: 'Delete pages from evaluation list' }) - @ApiResponse({ - status: 200, - description: 'The selected pages have been deleted from the evaluation list', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("evaluationList/error/delete") - async deleteAdminPagesWithError(@Body() pageListDto: PageListDto): Promise { - const pages = pageListDto.pages; - return success(await this.pageService.deleteAdminPagesWithError(pages)); - } - - @ApiOperation({ summary: 'Find pages with evaluation errors' }) - @ApiResponse({ - status: 200, - description: 'List of a pages with evaluation errors', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("evaluationList/error") - async getAdminPagesWithError(): Promise { - return success(await this.pageService.getAdminPagesWithError()); - } - - @ApiOperation({ summary: 'Find number of pages by search term' }) - @ApiResponse({ - status: 200, - description: 'Number of pages', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("all/count/:search") - async getAdminPageCount(@Param("search") search: string): Promise { - return success( - await this.pageService.adminCount(decodeURIComponent(search.substring(7))) - ); - } - @ApiOperation({ summary: 'Find pages by search term, sort, direction, and size' }) - @ApiResponse({ - status: 200, - description: 'List of pages', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("all/:size/:page/:sort/:direction/:search") - async getAllPages( - @Param("size") size: string, - @Param("page") page: string, - @Param("sort") sort: string, - @Param("direction") direction: string, - @Param("search") search: string - ): Promise { - console.log("pedido CHegou"); - return success( - await this.pageService.findAll( - parseInt(size), - parseInt(page), - sort.substring(5), - direction.substring(10), - decodeURIComponent(search.substring(7)) - ) - ); - } - @ApiOperation({ summary: 'Find all pages from a specific website in MyMonitor' }) - @ApiResponse({ - status: 200, - description: 'List of pages', - type: Number, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Get("myMonitor/website/:website") - async getAllMyMonitorUserWebsitePages( - @Request() req: any, - @Param("website") website: string - ): Promise { - return success( - await this.pageService.findAllFromMyMonitorUserWebsite( - req.user.userId, - website - ) - ); - } - - @ApiOperation({ summary: 'Add a page to a website in MyMonitor' }) - @ApiResponse({ - status: 200, - description: 'Page added with success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Post("myMonitor/create") - async createMyMonitorUserWebsitePages(@Request() req: any, - @Body() pageMyMonitorDto: CreatePageMyMonitorDto): Promise { - const website = pageMyMonitorDto.website; - const startingUrl = pageMyMonitorDto.startingUrl; - const uris = pageMyMonitorDto.pages; - - return success( - await this.pageService.createMyMonitorUserWebsitePages( - req.user.userId, - website, - startingUrl, - uris - ) - ); - } - - - @ApiOperation({ summary: 'Delete a page in a website in MyMonitor' }) - @ApiResponse({ - status: 200, - description: 'Page deleted with success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Post("myMonitor/remove") - async removeMyMonitorUserWebsitePages(@Request() req: any, @Body() deletePageMyMonitorDto: DeletePageMyMonitorDto): Promise { - const website = deletePageMyMonitorDto.website; - const ids = deletePageMyMonitorDto.pagesId; - return success( - await this.pageService.removeMyMonitorUserWebsitePages( - req.user.userId, - website, - ids - ) - ); - } - - @ApiOperation({ summary: 'Find pages by tag, website and user in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'List of pages', - type: Array, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("studyMonitor/tag/:tag/website/:website") - async getStudyMonitorUserTagWebsitePages( - @Request() req: any, - @Param("tag") tag: string, - @Param("website") website: string - ): Promise { - return success( - await this.pageService.findStudyMonitorUserTagWebsitePages( - req.user.userId, - tag, - website - ) - ); - } - - @ApiOperation({ summary: 'Find pages by tag, website and user in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'List of pages', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("add") - async addPages(@Request() req: any): Promise { - const websiteId = req.body.websiteId; - const uris = JSON.parse(req.body.uris).map((uri: string) => - decodeURIComponent(uri) - ); - const observatory = JSON.parse(req.body.observatory).map((uri: string) => - decodeURIComponent(uri) - ); - return success( - await this.pageService.addPages(websiteId, uris, observatory) - ); - } - - @ApiOperation({ summary: 'Evaluate page' }) - @ApiResponse({ - status: 200, - description: 'Evaluation added to evaluation queue', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("page/evaluate") - async evaluatePage(@Body() pageEvaluateDto: PageEvaluateDto): Promise { - const url = decodeURIComponent(pageEvaluateDto.url); - const page = await this.pageService.findPageFromUrl(url); - - if (page) { - await this.evaluationService.increaseAMSObservatoryRequestCounter(); - return success(await this.pageService.addPageToEvaluate(url, "10", -1)); - } else { - throw new UnauthorizedException(); - } - } - - @ApiOperation({ summary: 'Evaluate page in My Monitor' }) - @ApiResponse({ - status: 200, - description: 'Evaluation added to evaluation queue', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Post("myMonitor/evaluate") - async evaluateMyMonitorWebsitePage(@Request() req: any, @Body() pageEvaluateDto: PageEvaluateDto): Promise { - const userId = req.user.userId; - const url = decodeURIComponent(pageEvaluateDto.url); - const page = await this.pageService.findPageFromUrl(url); - const isUserPage = await this.pageService.isPageFromMyMonitorUser( - userId, - page.PageId - ); - - if (isUserPage) { - await this.evaluationService.increaseMyMonitorRequestCounter(); - return success( - await this.pageService.addPageToEvaluate(url, "01", userId) - ); - } else { - throw new UnauthorizedException(); - } - } - - @ApiOperation({ summary: 'Evaluate page in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Evaluation added to evaluation queue', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("studyMonitor/evaluate") - async evaluateStudyMonitorTagWebsitePage(@Request() req: any, @Body() pageEvaluateStudyMonitorDto:PageEvaluateStudyMonitorDto): Promise { - const userId = req.user.userId; - const tag = pageEvaluateStudyMonitorDto.tag; - const website = pageEvaluateStudyMonitorDto.website; - const url = decodeURIComponent(pageEvaluateStudyMonitorDto.url); - const page = await this.pageService.findPageFromUrl(url); - const isUserPage = await this.pageService.isPageFromStudyMonitorUser( - userId, - tag, - website, - page.PageId - ); - - if (isUserPage) { - await this.evaluationService.increaseStudyMonitorRequestCounter(); - return success( - await this.pageService.addPageToEvaluate(url, "00", userId, userId) - ); - } else { - throw new UnauthorizedException(); - } - } - - @ApiOperation({ summary: 'Create page in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Page created', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("studyMonitor/create") - async createStudyMonitorUserTagWebsitePages( - @Request() req: any, - pageCreateStudyMonitorDto: PageCreateStudyMonitorDto - ): Promise { - const tag = pageCreateStudyMonitorDto.tag; - const website = pageCreateStudyMonitorDto.website; - const startingUrl = pageCreateStudyMonitorDto.startingUrl; - const uris = JSON.parse(pageCreateStudyMonitorDto.pages).map((page) => - decodeURIComponent(page) - );//FIXME - return success( - await this.pageService.createStudyMonitorUserTagWebsitePages( - req.user.userId, - tag, - website, - startingUrl, - uris - ) - ); - } - - @ApiOperation({ summary: 'Remove page in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Page removed', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("studyMonitor/remove") - async removeStudyMonitorUserTagWebsitePages( - @Request() req: any, - pageDeleteStudyMonitorDto: PageDeleteStudyMonitorDto - ): Promise { - const tag = pageDeleteStudyMonitorDto.tag; - const website = pageDeleteStudyMonitorDto.website; - const pagesId = pageDeleteStudyMonitorDto.pagesId; - return success( - await this.pageService.removeStudyMonitorUserTagWebsitePages( - req.user.userId, - tag, - website, - pagesId - ) - ); - } - - @ApiOperation({ summary: 'Update page in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Page updated', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("update") - async update(@Body() pageUpdateDto: PageUpdateDto): Promise { - const pageId = pageUpdateDto.pageId; - const checked = pageUpdateDto.checked; - return success(await this.pageService.update(pageId, checked)); - } - - @ApiOperation({ summary: 'Delete page' }) - @ApiResponse({ - status: 200, - description: 'Page deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("delete") - async delete(@Body() pageDeleteDto: PageDeleteDto): Promise { - const pages = pageDeleteDto.pages; - return success(await this.pageService.delete(pages)); - } - - @ApiOperation({ summary: 'Import page from a my monitor or study monitor user' }) - @ApiResponse({ - status: 200, - description: 'Page imported', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("import") - async importPage(@Body() pageImportDto: PageImportDto): Promise { - const pageId = pageImportDto.pageId; - const username = pageImportDto.user; - const tag = pageImportDto.tag; - const website = pageImportDto.website; - - const type = await this.pageService.findUserType(username); - - let successImport = await this.pageService.import(pageId, type); - - if (type === "studies") { - //method to tag from selected page of studymonitor - successImport = await this.pageService.importStudy( - pageId, - username, - tag, - website - ); - } - - return success(successImport); - } -} +import { + Controller, + Post, + Get, + Request, + UseGuards, + Param, + UnauthorizedException, + UseInterceptors, + Body, +} from "@nestjs/common"; +import { AuthGuard } from "@nestjs/passport"; +import { PageService } from "./page.service"; +import { success } from "../lib/response"; +import { EvaluationService } from "../evaluation/evaluation.service"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { + ApiBasicAuth, + ApiTags, + ApiResponse, + ApiOperation, +} from "@nestjs/swagger"; +import { PageUrlDto } from "./dto/page-url.dto"; +import { PageListDto } from "./dto/page-list.dto"; +import { CreatePageMyMonitorDto } from "./dto/create-page-my-monitor.dto"; +import { DeletePageMyMonitorDto } from "./dto/delete-page-my-monitor.dto"; +import { Page } from "./page.entity"; +import { PageEvaluateDto } from "./dto/page-evaluate.dto"; +import { PageEvaluateStudyMonitorDto } from "./dto/page-evaluate-study-monitor.dto"; +import { PageCreateStudyMonitorDto } from "./dto/page-create-study-monitor.dto"; +import { PageDeleteStudyMonitorDto } from "./dto/page-delete-study-monitor.dto"; +import { PageUpdateDto } from "./dto/page-update.dto"; +import { PageDeleteDto } from "./dto/page-delete.dto"; +import { PageImportDto } from "./dto/page-import.dto"; + +@ApiBasicAuth() +@ApiTags("page") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("page") +@UseInterceptors(LoggingInterceptor) +export class PageController { + constructor( + private readonly pageService: PageService, + private readonly evaluationService: EvaluationService + ) {} + + @ApiOperation({ summary: "Reevaluate page" }) + @ApiResponse({ + status: 200, + description: "The evaluation request has been submited", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("reEvaluate") + async reEvaluatePage(@Body() pageUrlDto: PageUrlDto): Promise { + const page = decodeURIComponent(pageUrlDto.page); + + await this.evaluationService.increaseAMSObservatoryRequestCounter(); + + return success(await this.pageService.addPageToEvaluate(page, "10", -1)); + } + + @ApiOperation({ summary: "Find the number of pages in observatory" }) + @ApiResponse({ + status: 200, + description: "The number of pages in observatory", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("observatory/total") + async getNumberOfObservatoryPages(): Promise { + return success(await this.pageService.findNumberOfObservatory()); + } + + @ApiOperation({ summary: "Reevaluate multiple pages by url" }) + @ApiResponse({ + status: 200, + description: "The evaluation request has been submited", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("reEvaluateMulti") + async reEvaluatePages(@Request() req: any): Promise { + const pages = decodeURIComponent(req.body.pages)?.split(",") ?? []; + return success(await this.pageService.addPagesToEvaluate(pages, "10", -1)); + } + + @ApiOperation({ + summary: "Find the number of pages being evaluated by the admin", + }) + @ApiResponse({ + status: 200, + description: "The number of pages being evaluated", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("evaluationList/admin/evaluating") + async getNumberOfAdminPagesBeingEvaluated(): Promise { + return success( + await this.pageService.findAdminEvaluatingInEvaluationList() + ); + } + + @ApiOperation({ + summary: "Find the number of pages waiting for evaluation by the admin", + }) + @ApiResponse({ + status: 200, + description: "The number of pages waiting", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("evaluationList/admin/waiting") + async getNumberOfAdminPagesWaitingForEvaluation(): Promise { + return success(await this.pageService.findAdminWaitingInEvaluationList()); + } + + @ApiOperation({ + summary: "Find the number of pages that failed the evaluation by the admin", + }) + @ApiResponse({ + status: 200, + description: "The number of pages that failed the evaluation", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("evaluationList/admin/error") + async getNumberOfAdminPagesWithError(): Promise { + return success(await this.pageService.findAdminWithErrorInEvaluationList()); + } + + @ApiOperation({ + summary: "Find the number of pages being evaluated by the user", + }) + @ApiResponse({ + status: 200, + description: "The number of pages being evaluated", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("evaluationList/user/evaluating") + async getNumberOfUserPagesBeingEvaluated(): Promise { + return success(await this.pageService.findUserEvaluatingInEvaluationList()); + } + + @ApiOperation({ + summary: "Find the number of pages waiting for evaluation by the user", + }) + @ApiResponse({ + status: 200, + description: "The number of pages waiting", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("evaluationList/user/waiting") + async getNumberOfUserPagesWaitingForEvaluation(): Promise { + return success(await this.pageService.findUserWaitingInEvaluationList()); + } + + @ApiOperation({ + summary: "Find the number of pages that failed the evaluation by the user", + }) + @ApiResponse({ + status: 200, + description: "The number of pages that failed the evaluation", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("evaluationList/user/error") + async getNumberOfUserPagesWithError(): Promise { + return success(await this.pageService.findUserWithErrorInEvaluationList()); + } + + @ApiOperation({ summary: "Delete pages from evaluation list" }) + @ApiResponse({ + status: 200, + description: + "The selected pages have been deleted from the evaluation list", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("evaluationList/error/delete") + async deleteAdminPagesWithError( + @Body() pageListDto: PageListDto + ): Promise { + const pages = pageListDto.pages; + return success(await this.pageService.deleteAdminPagesWithError(pages)); + } + + @ApiOperation({ summary: "Find pages with evaluation errors" }) + @ApiResponse({ + status: 200, + description: "List of a pages with evaluation errors", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("evaluationList/error") + async getAdminPagesWithError(): Promise { + return success(await this.pageService.getAdminPagesWithError()); + } + + @ApiOperation({ summary: "Find number of pages by search term" }) + @ApiResponse({ + status: 200, + description: "Number of pages", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("all/count/:search") + async getAdminPageCount(@Param("search") search: string): Promise { + return success( + await this.pageService.adminCount(decodeURIComponent(search.substring(7))) + ); + } + @ApiOperation({ + summary: "Find pages by search term, sort, direction, and size", + }) + @ApiResponse({ + status: 200, + description: "List of pages", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("all/:size/:page/:sort/:direction/:search") + async getAllPages( + @Param("size") size: string, + @Param("page") page: string, + @Param("sort") sort: string, + @Param("direction") direction: string, + @Param("search") search: string + ): Promise { + console.log("pedido CHegou"); + return success( + await this.pageService.findAll( + parseInt(size), + parseInt(page), + sort.substring(5), + direction.substring(10), + decodeURIComponent(search.substring(7)) + ) + ); + } + @ApiOperation({ + summary: "Find all pages from a specific website in MyMonitor", + }) + @ApiResponse({ + status: 200, + description: "List of pages", + type: Number, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Get("myMonitor/website/:website") + async getAllMyMonitorUserWebsitePages( + @Request() req: any, + @Param("website") website: string + ): Promise { + return success( + await this.pageService.findAllFromMyMonitorUserWebsite( + req.user.userId, + website + ) + ); + } + + @ApiOperation({ summary: "Add a page to a website in MyMonitor" }) + @ApiResponse({ + status: 200, + description: "Page added with success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Post("myMonitor/create") + async createMyMonitorUserWebsitePages( + @Request() req: any, + @Body() pageMyMonitorDto: CreatePageMyMonitorDto + ): Promise { + const website = pageMyMonitorDto.website; + const startingUrl = pageMyMonitorDto.startingUrl; + const uris = pageMyMonitorDto.pages; + + return success( + await this.pageService.createMyMonitorUserWebsitePages( + req.user.userId, + website, + startingUrl, + uris + ) + ); + } + + @ApiOperation({ summary: "Delete a page in a website in MyMonitor" }) + @ApiResponse({ + status: 200, + description: "Page deleted with success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Post("myMonitor/remove") + async removeMyMonitorUserWebsitePages( + @Request() req: any, + @Body() deletePageMyMonitorDto: DeletePageMyMonitorDto + ): Promise { + const website = deletePageMyMonitorDto.website; + const ids = deletePageMyMonitorDto.pagesId; + return success( + await this.pageService.removeMyMonitorUserWebsitePages( + req.user.userId, + website, + ids + ) + ); + } + + @ApiOperation({ + summary: "Find pages by tag, website and user in Study Monitor", + }) + @ApiResponse({ + status: 200, + description: "List of pages", + type: Array, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("studyMonitor/tag/:tag/website/:website") + async getStudyMonitorUserTagWebsitePages( + @Request() req: any, + @Param("tag") tag: string, + @Param("website") website: string + ): Promise { + return success( + await this.pageService.findStudyMonitorUserTagWebsitePages( + req.user.userId, + tag, + website + ) + ); + } + + @ApiOperation({ + summary: "Find pages by tag, website and user in Study Monitor", + }) + @ApiResponse({ + status: 200, + description: "List of pages", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("add") + async addPages(@Request() req: any): Promise { + const websiteId = req.body.websiteId; + const uris = JSON.parse(req.body.uris).map((uri: string) => + decodeURIComponent(uri) + ); + const observatory = JSON.parse(req.body.observatory).map((uri: string) => + decodeURIComponent(uri) + ); + return success( + await this.pageService.addPages(websiteId, uris, observatory) + ); + } + + @ApiOperation({ summary: "Evaluate page" }) + @ApiResponse({ + status: 200, + description: "Evaluation added to evaluation queue", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("page/evaluate") + async evaluatePage(@Body() pageEvaluateDto: PageEvaluateDto): Promise { + const url = decodeURIComponent(pageEvaluateDto.url); + const page = await this.pageService.findPageFromUrl(url); + + if (page) { + await this.evaluationService.increaseAMSObservatoryRequestCounter(); + return success(await this.pageService.addPageToEvaluate(url, "10", -1)); + } else { + throw new UnauthorizedException(); + } + } + + @ApiOperation({ summary: "Evaluate page in My Monitor" }) + @ApiResponse({ + status: 200, + description: "Evaluation added to evaluation queue", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Post("myMonitor/evaluate") + async evaluateMyMonitorWebsitePage( + @Request() req: any, + @Body() pageEvaluateDto: PageEvaluateDto + ): Promise { + const userId = req.user.userId; + const url = decodeURIComponent(pageEvaluateDto.url); + const page = await this.pageService.findPageFromUrl(url); + const isUserPage = await this.pageService.isPageFromMyMonitorUser( + userId, + page.PageId + ); + + if (isUserPage) { + await this.evaluationService.increaseMyMonitorRequestCounter(); + return success( + await this.pageService.addPageToEvaluate(url, "01", userId) + ); + } else { + throw new UnauthorizedException(); + } + } + + @ApiOperation({ summary: "Evaluate page in Study Monitor" }) + @ApiResponse({ + status: 200, + description: "Evaluation added to evaluation queue", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("studyMonitor/evaluate") + async evaluateStudyMonitorTagWebsitePage( + @Request() req: any, + @Body() pageEvaluateStudyMonitorDto: PageEvaluateStudyMonitorDto + ): Promise { + const userId = req.user.userId; + const tag = pageEvaluateStudyMonitorDto.tag; + const website = pageEvaluateStudyMonitorDto.website; + const url = decodeURIComponent(pageEvaluateStudyMonitorDto.url); + const page = await this.pageService.findPageFromUrl(url); + const isUserPage = await this.pageService.isPageFromStudyMonitorUser( + userId, + tag, + website, + page.PageId + ); + + if (isUserPage) { + await this.evaluationService.increaseStudyMonitorRequestCounter(); + return success( + await this.pageService.addPageToEvaluate(url, "00", userId, userId) + ); + } else { + throw new UnauthorizedException(); + } + } + + @ApiOperation({ summary: "Create page in Study Monitor" }) + @ApiResponse({ + status: 200, + description: "Page created", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("studyMonitor/create") + async createStudyMonitorUserTagWebsitePages( + @Request() req: any, + pageCreateStudyMonitorDto: PageCreateStudyMonitorDto + ): Promise { + const tag = pageCreateStudyMonitorDto.tag; + const website = pageCreateStudyMonitorDto.website; + const startingUrl = pageCreateStudyMonitorDto.startingUrl; + const uris = JSON.parse(pageCreateStudyMonitorDto.pages).map((page) => + decodeURIComponent(page) + ); //FIXME + return success( + await this.pageService.createStudyMonitorUserTagWebsitePages( + req.user.userId, + tag, + website, + startingUrl, + uris + ) + ); + } + + @ApiOperation({ summary: "Remove page in Study Monitor" }) + @ApiResponse({ + status: 200, + description: "Page removed", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("studyMonitor/remove") + async removeStudyMonitorUserTagWebsitePages( + @Request() req: any, + pageDeleteStudyMonitorDto: PageDeleteStudyMonitorDto + ): Promise { + const tag = pageDeleteStudyMonitorDto.tag; + const website = pageDeleteStudyMonitorDto.website; + const pagesId = pageDeleteStudyMonitorDto.pagesId; + return success( + await this.pageService.removeStudyMonitorUserTagWebsitePages( + req.user.userId, + tag, + website, + pagesId + ) + ); + } + + @ApiOperation({ summary: "Update page in Study Monitor" }) + @ApiResponse({ + status: 200, + description: "Page updated", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("update") + async update(@Body() pageUpdateDto: PageUpdateDto): Promise { + const pageId = pageUpdateDto.pageId; + const checked = pageUpdateDto.checked; + return success(await this.pageService.update(pageId, checked)); + } + + @ApiOperation({ summary: "Delete page" }) + @ApiResponse({ + status: 200, + description: "Page deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("delete") + async delete(@Body() pageDeleteDto: PageDeleteDto): Promise { + const pages = pageDeleteDto.pages; + return success(await this.pageService.delete(pages)); + } + + @ApiOperation({ + summary: "Import page from a my monitor or study monitor user", + }) + @ApiResponse({ + status: 200, + description: "Page imported", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("import") + async importPage(@Body() pageImportDto: PageImportDto): Promise { + const pageId = pageImportDto.pageId; + const username = pageImportDto.user; + const tag = pageImportDto.tag; + const website = pageImportDto.website; + + const type = await this.pageService.findUserType(username); + + let successImport = await this.pageService.import(pageId, type); + + if (type === "studies") { + //method to tag from selected page of studymonitor + successImport = await this.pageService.importStudy( + pageId, + username, + tag, + website + ); + } + + return success(successImport); + } +} diff --git a/src/page/page.entity.ts b/src/page/page.entity.ts index fd6f993d..bbdb1a47 100644 --- a/src/page/page.entity.ts +++ b/src/page/page.entity.ts @@ -1,35 +1,34 @@ -import { Website } from 'src/website/website.entity'; -import { Entity, Column, PrimaryGeneratedColumn, ManyToMany } from 'typeorm'; - -@Entity('Page') -export class Page { - - @PrimaryGeneratedColumn({ - type: 'int' - }) - PageId: number; - - @Column({ - type: 'varchar', - length: 255, - nullable: false - }) - Uri: string; - - @Column({ - type: 'varchar', - length: 3, - nullable: false, - default: '000' - }) - Show_In: string; - - @Column({ - type: 'datetime', - nullable: false - }) - Creation_Date: any; - - @ManyToMany((type) => Website,(website)=>website.Pages) - Pages: Website[]; -} \ No newline at end of file +import { Website } from "src/website/website.entity"; +import { Entity, Column, PrimaryGeneratedColumn, ManyToMany } from "typeorm"; + +@Entity("Page") +export class Page { + @PrimaryGeneratedColumn({ + type: "int", + }) + PageId: number; + + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + Uri: string; + + @Column({ + type: "varchar", + length: 3, + nullable: false, + default: "000", + }) + Show_In: string; + + @Column({ + type: "datetime", + nullable: false, + }) + Creation_Date: any; + + @ManyToMany((type) => Website, (website) => website.Pages) + Pages: Website[]; +} diff --git a/src/page/page.gateway.spec.ts b/src/page/page.gateway.spec.ts index 42d1cea2..c162300f 100644 --- a/src/page/page.gateway.spec.ts +++ b/src/page/page.gateway.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { PageGateway } from './page.gateway'; +import { Test, TestingModule } from "@nestjs/testing"; +import { PageGateway } from "./page.gateway"; -describe('PageGateway', () => { +describe("PageGateway", () => { let gateway: PageGateway; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('PageGateway', () => { gateway = module.get(PageGateway); }); - it('should be defined', () => { + it("should be defined", () => { expect(gateway).toBeDefined(); }); }); diff --git a/src/page/page.module.ts b/src/page/page.module.ts index 1596811e..9c18173e 100644 --- a/src/page/page.module.ts +++ b/src/page/page.module.ts @@ -1,23 +1,23 @@ -import { Module } from "@nestjs/common"; -import { TypeOrmModule } from "@nestjs/typeorm"; -import { PageService } from "./page.service"; -import { Page } from "./page.entity"; -import { PageController } from "./page.controller"; -import { AuthModule } from "../auth/auth.module"; -import { EvaluationModule } from "../evaluation/evaluation.module"; -import { Website } from "../website/website.entity"; -import { Evaluation } from "../evaluation/evaluation.entity"; -import { AccessibilityStatementModule } from "src/accessibility-statement-module/accessibility-statement/accessibility-statement.module"; - -@Module({ - imports: [ - TypeOrmModule.forFeature([Website, Page, Evaluation]), - AuthModule, - EvaluationModule, - AccessibilityStatementModule - ], - exports: [PageService], - providers: [PageService], - controllers: [PageController], -}) -export class PageModule {} +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { PageService } from "./page.service"; +import { Page } from "./page.entity"; +import { PageController } from "./page.controller"; +import { AuthModule } from "../auth/auth.module"; +import { EvaluationModule } from "../evaluation/evaluation.module"; +import { Website } from "../website/website.entity"; +import { Evaluation } from "../evaluation/evaluation.entity"; +import { AccessibilityStatementModule } from "src/accessibility-statement-module/accessibility-statement/accessibility-statement.module"; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Website, Page, Evaluation]), + AuthModule, + EvaluationModule, + AccessibilityStatementModule, + ], + exports: [PageService], + providers: [PageService], + controllers: [PageController], +}) +export class PageModule {} diff --git a/src/page/page.service.spec.ts b/src/page/page.service.spec.ts index e7d86dbd..2c13e157 100644 --- a/src/page/page.service.spec.ts +++ b/src/page/page.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { PageService } from './page.service'; - -describe('PageService', () => { - let service: PageService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [PageService], - }).compile(); - - service = module.get(PageService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { PageService } from "./page.service"; + +describe("PageService", () => { + let service: PageService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PageService], + }).compile(); + + service = module.get(PageService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/page/page.service.ts b/src/page/page.service.ts index fdb40a8b..f6263dda 100644 --- a/src/page/page.service.ts +++ b/src/page/page.service.ts @@ -5,7 +5,6 @@ import { Website } from "../website/website.entity"; import { Page } from "./page.entity"; import { Evaluation } from "../evaluation/evaluation.entity"; - @Injectable() export class PageService { constructor( @@ -14,7 +13,8 @@ export class PageService { @InjectRepository(Page) private readonly pageRepository: Repository, @InjectDataSource() - private readonly connection: DataSource ) { } + private readonly connection: DataSource + ) {} async findUserType(username: string): Promise { if (username === "admin") { @@ -206,7 +206,6 @@ export class PageService { } async getObservatoryData(): Promise { - let data = new Array(); const directories = await this.pageRepository.query( @@ -674,10 +673,10 @@ export class PageService { return !hasError; } - convertStringToStringArray(numStr : string) : string[] { + convertStringToStringArray(numStr: string): string[] { // remove first and last character numStr = numStr.substring(1, numStr.length - 1); - return numStr.split(',').map((s) => s.substring(1, numStr.length - 1)); + return numStr.split(",").map((s) => s.substring(1, numStr.length - 1)); } async createMyMonitorUserWebsitePages( @@ -686,8 +685,8 @@ export class PageService { startingUrl: string, uris: string[] ): Promise { - let uriArray : string[] = []; - if (typeof uris === 'string') { + let uriArray: string[] = []; + if (typeof uris === "string") { uriArray = this.convertStringToStringArray(uris); } else { uriArray = uris; @@ -772,10 +771,10 @@ export class PageService { //return await this.findAllFromMyMonitorUserWebsite(userId, website); } - convertStringToNumberArray(numStr : string) : number[] { + convertStringToNumberArray(numStr: string): number[] { // remove first and last character numStr = numStr.substring(1, numStr.length - 1); - return numStr.split(',').map(Number); + return numStr.split(",").map(Number); } async removeMyMonitorUserWebsitePages( @@ -784,8 +783,8 @@ export class PageService { pagesIds: number[] ): Promise { // this should not happen, but pagesIds type is string, so it needs to be converted to number[] - let ids : number[] = []; - if (typeof pagesIds === 'string') { + let ids: number[] = []; + if (typeof pagesIds === "string") { ids = this.convertStringToNumberArray(pagesIds); } else { ids = pagesIds; @@ -847,10 +846,10 @@ export class PageService { let hasError = false; try { for (const uri of uris || []) { - const pageExists = await queryRunner.manager.findOne( - Page, - {where: {Uri: uri} , select: ["PageId", "Uri", "Creation_Date"] } - ); + const pageExists = await queryRunner.manager.findOne(Page, { + where: { Uri: uri }, + select: ["PageId", "Uri", "Creation_Date"], + }); if (pageExists) { const websitePage = await queryRunner.manager.query( diff --git a/src/stamp/dto/create-stamp.dto.ts b/src/stamp/dto/create-stamp.dto.ts index 891db2e7..1042534d 100644 --- a/src/stamp/dto/create-stamp.dto.ts +++ b/src/stamp/dto/create-stamp.dto.ts @@ -1,3 +1,3 @@ export class PageUrlDto { - websitesId:number[]; -} \ No newline at end of file + websitesId: number[]; +} diff --git a/src/stamp/stamp.controller.spec.ts b/src/stamp/stamp.controller.spec.ts index faca5015..add52eb5 100644 --- a/src/stamp/stamp.controller.spec.ts +++ b/src/stamp/stamp.controller.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { StampController } from './stamp.controller'; +import { Test, TestingModule } from "@nestjs/testing"; +import { StampController } from "./stamp.controller"; -describe('Stamp Controller', () => { +describe("Stamp Controller", () => { let controller: StampController; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('Stamp Controller', () => { controller = module.get(StampController); }); - it('should be defined', () => { + it("should be defined", () => { expect(controller).toBeDefined(); }); }); diff --git a/src/stamp/stamp.controller.ts b/src/stamp/stamp.controller.ts index c8a748fa..61ab3275 100644 --- a/src/stamp/stamp.controller.ts +++ b/src/stamp/stamp.controller.ts @@ -1,24 +1,35 @@ -import { Body, Controller, Post, Request, UseGuards, UseInterceptors } from "@nestjs/common"; +import { + Body, + Controller, + Post, + Request, + UseGuards, + UseInterceptors, +} from "@nestjs/common"; import { AuthGuard } from "@nestjs/passport"; import { StampService } from "./stamp.service"; import { success, error } from "src/lib/response"; import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiTags, ApiResponse, ApiOperation } from "@nestjs/swagger"; +import { + ApiBasicAuth, + ApiTags, + ApiResponse, + ApiOperation, +} from "@nestjs/swagger"; import { PageUrlDto } from "./dto/create-stamp.dto"; - @ApiBasicAuth() -@ApiTags('stamp') -@ApiResponse({ status: 403, description: 'Forbidden' }) +@ApiTags("stamp") +@ApiResponse({ status: 403, description: "Forbidden" }) @Controller("stamp") @UseInterceptors(LoggingInterceptor) export class StampController { constructor(private readonly stampService: StampService) {} - @ApiOperation({ summary: 'Generate digital stamp for all websites' }) + @ApiOperation({ summary: "Generate digital stamp for all websites" }) @ApiResponse({ status: 200, - description: 'The stamps were generated', + description: "The stamps were generated", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @@ -28,16 +39,18 @@ export class StampController { return errors.length === 0 ? success(true) : error(errors, false); } - @ApiOperation({ summary: 'Generate digital stamp for a specific website' }) + @ApiOperation({ summary: "Generate digital stamp for a specific website" }) @ApiResponse({ status: 200, - description: 'The stamp was generated', + description: "The stamp was generated", type: Boolean, }) @UseGuards(AuthGuard("jwt-admin")) @Post("websites") - async generateWebsiteDigitalStamp(@Body() pageUrlDto: PageUrlDto): Promise { - const websitesId =pageUrlDto.websitesId; + async generateWebsiteDigitalStamp( + @Body() pageUrlDto: PageUrlDto + ): Promise { + const websitesId = pageUrlDto.websitesId; return success( await this.stampService.generateWebsitesDigitalStamp(websitesId) ); diff --git a/src/stamp/stamp.module.ts b/src/stamp/stamp.module.ts index 09ef8a40..00c77101 100644 --- a/src/stamp/stamp.module.ts +++ b/src/stamp/stamp.module.ts @@ -1,9 +1,9 @@ -import { Module } from '@nestjs/common'; -import { StampService } from './stamp.service'; -import { StampController } from './stamp.controller'; +import { Module } from "@nestjs/common"; +import { StampService } from "./stamp.service"; +import { StampController } from "./stamp.controller"; @Module({ providers: [StampService], - controllers: [StampController] + controllers: [StampController], }) export class StampModule {} diff --git a/src/stamp/stamp.service.spec.ts b/src/stamp/stamp.service.spec.ts index 5abaf1f3..96356cd1 100644 --- a/src/stamp/stamp.service.spec.ts +++ b/src/stamp/stamp.service.spec.ts @@ -1,7 +1,7 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { StampService } from './stamp.service'; +import { Test, TestingModule } from "@nestjs/testing"; +import { StampService } from "./stamp.service"; -describe('StampService', () => { +describe("StampService", () => { let service: StampService; beforeEach(async () => { @@ -12,7 +12,7 @@ describe('StampService', () => { service = module.get(StampService); }); - it('should be defined', () => { + it("should be defined", () => { expect(service).toBeDefined(); }); }); diff --git a/src/stamp/stamp.service.ts b/src/stamp/stamp.service.ts index 72adff1b..a2f0617b 100644 --- a/src/stamp/stamp.service.ts +++ b/src/stamp/stamp.service.ts @@ -8,7 +8,8 @@ import { InjectDataSource } from "@nestjs/typeorm"; export class StampService { constructor( @InjectDataSource() - private readonly connection: DataSource) { } + private readonly connection: DataSource + ) {} async generateAllWebsitesDigitalStamp(): Promise { const websites = await this.connection.query(` SELECT DISTINCT diff --git a/src/tag/dto/create-tag-study.dto.ts b/src/tag/dto/create-tag-study.dto.ts index 8ba09fbe..c51f3cb0 100644 --- a/src/tag/dto/create-tag-study.dto.ts +++ b/src/tag/dto/create-tag-study.dto.ts @@ -1,6 +1,6 @@ export class CreateTagStudyDto { - user_tag_name:string; - userId:number; - type:string; - tagsId:number[]; -} \ No newline at end of file + user_tag_name: string; + userId: number; + type: string; + tagsId: number[]; +} diff --git a/src/tag/dto/create-tag.dto.ts b/src/tag/dto/create-tag.dto.ts index 9a3ff794..733f0949 100644 --- a/src/tag/dto/create-tag.dto.ts +++ b/src/tag/dto/create-tag.dto.ts @@ -1,5 +1,5 @@ export class CreateTagDto { - directories:number[]; - websites:number[]; - name:string; -} \ No newline at end of file + directories: number[]; + websites: number[]; + name: string; +} diff --git a/src/tag/dto/delete-tag-bulk.dto.ts b/src/tag/dto/delete-tag-bulk.dto.ts index 4418c88a..073a4adc 100644 --- a/src/tag/dto/delete-tag-bulk.dto.ts +++ b/src/tag/dto/delete-tag-bulk.dto.ts @@ -1,3 +1,3 @@ export class DeleteTagBulkDto { - tagsId:number[]; -} \ No newline at end of file + tagsId: number[]; +} diff --git a/src/tag/dto/delete-tag-study.dto.ts b/src/tag/dto/delete-tag-study.dto.ts index c0b990d9..804db268 100644 --- a/src/tag/dto/delete-tag-study.dto.ts +++ b/src/tag/dto/delete-tag-study.dto.ts @@ -1,3 +1,3 @@ export class DeleteTagStudyDto { - tagsId:number[]; -} \ No newline at end of file + tagsId: number[]; +} diff --git a/src/tag/dto/delete-tag.dto.ts b/src/tag/dto/delete-tag.dto.ts index 5b615849..9e5ad93d 100644 --- a/src/tag/dto/delete-tag.dto.ts +++ b/src/tag/dto/delete-tag.dto.ts @@ -1,3 +1,3 @@ export class DeleteTagDto { - tagId:number; -} \ No newline at end of file + tagId: number; +} diff --git a/src/tag/dto/import-tag.dto.ts b/src/tag/dto/import-tag.dto.ts index fdaaf953..b19619ab 100644 --- a/src/tag/dto/import-tag.dto.ts +++ b/src/tag/dto/import-tag.dto.ts @@ -1,4 +1,4 @@ export class ImportTagDto { - tagId:number; - tagName:string; -} \ No newline at end of file + tagId: number; + tagName: string; +} diff --git a/src/tag/dto/tag-reevalute.dto.ts b/src/tag/dto/tag-reevalute.dto.ts index 9f829954..87eb859c 100644 --- a/src/tag/dto/tag-reevalute.dto.ts +++ b/src/tag/dto/tag-reevalute.dto.ts @@ -1,4 +1,4 @@ export class TagReEvaluateDto { - tagsId:number[]; - option:string; -} \ No newline at end of file + tagsId: number[]; + option: string; +} diff --git a/src/tag/dto/update-tag.dto.ts b/src/tag/dto/update-tag.dto.ts index 98d97ea4..f39ba4a1 100644 --- a/src/tag/dto/update-tag.dto.ts +++ b/src/tag/dto/update-tag.dto.ts @@ -2,7 +2,7 @@ import { PartialType } from "@nestjs/mapped-types"; import { CreateTagDto } from "./create-tag.dto"; export class UpdateTagDto extends PartialType(CreateTagDto) { - defaultDirectories: number[]; - defaultWebsites: number[]; - tagId:number; -} \ No newline at end of file + defaultDirectories: number[]; + defaultWebsites: number[]; + tagId: number; +} diff --git a/src/tag/tag.controller.spec.ts b/src/tag/tag.controller.spec.ts index 399b2131..b3fecb67 100644 --- a/src/tag/tag.controller.spec.ts +++ b/src/tag/tag.controller.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { TagController } from './tag.controller'; - -describe('Tag Controller', () => { - let controller: TagController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [TagController], - }).compile(); - - controller = module.get(TagController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { TagController } from "./tag.controller"; + +describe("Tag Controller", () => { + let controller: TagController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [TagController], + }).compile(); + + controller = module.get(TagController); + }); + + it("should be defined", () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/tag/tag.controller.ts b/src/tag/tag.controller.ts index 35fa2180..31e266b5 100644 --- a/src/tag/tag.controller.ts +++ b/src/tag/tag.controller.ts @@ -1,439 +1,456 @@ -import { - Controller, - InternalServerErrorException, - Post, - Get, - Request, - Param, - UseGuards, - UseInterceptors, - Body, -} from "@nestjs/common"; -import { AuthGuard } from "@nestjs/passport"; -import { TagService } from "./tag.service"; -import { Tag } from "./tag.entity"; -import { success } from "../lib/response"; -import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiTags, ApiResponse, ApiOperation } from "@nestjs/swagger"; -import { TagReEvaluateDto } from "./dto/tag-reevalute.dto"; -import { CreateTagDto } from "./dto/create-tag.dto"; -import { UpdateTagDto } from "./dto/update-tag.dto"; -import { DeleteTagDto } from "./dto/delete-tag.dto"; -import { DeleteTagBulkDto } from "./dto/delete-tag-bulk.dto"; -import { CreateTagStudyDto } from "./dto/create-tag-study.dto"; -import { DeleteTagStudyDto } from "./dto/delete-tag-study.dto"; -import { ImportTagDto } from "./dto/import-tag.dto"; - -@ApiBasicAuth() -@ApiTags('tag') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller("tag") -@UseInterceptors(LoggingInterceptor) -export class TagController { - constructor(private readonly tagService: TagService) {} - - @ApiOperation({ summary: 'Reevaluate all pages from a tag' }) - @ApiResponse({ - status: 200, - description: 'The evaluation request has been submited', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("reEvaluate") - async reEvaluateWebsitePages(@Body() tagReEvaluateDto: TagReEvaluateDto): Promise { - const tagsId = tagReEvaluateDto.tagsId; - const option = tagReEvaluateDto.option; - - return success(await this.tagService.addPagesToEvaluate(tagsId, option)); - } - - @ApiOperation({ summary: 'Create a new tag' }) - @ApiResponse({ - status: 200, - description: 'The tag was created', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("create") - async createOfficialTag(@Body() createTagDto: CreateTagDto): Promise { - const tag = new Tag(); - tag.Name = createTagDto.name; - tag.Creation_Date = new Date(); - - const directories = createTagDto.directories; - const websites = createTagDto.websites; - - const createSuccess = await this.tagService.createOne( - tag, - directories, - websites - ); - - if (!createSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Update a specific tag' }) - @ApiResponse({ - status: 200, - description: 'The tag was updated', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("update") - async updateOfficialTag(@Body() updateTagDto: UpdateTagDto): Promise { - const tagId = updateTagDto.tagId; - const name = updateTagDto.name; - const defaultDirectories = updateTagDto.defaultDirectories; - const directories = updateTagDto.directories; - const defaultWebsites = updateTagDto.defaultWebsites; - const websites = updateTagDto.websites; - - const updateSuccess = await this.tagService.update( - tagId, - name, - defaultDirectories, - directories, - defaultWebsites, - websites - ); - - if (!updateSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Delete a specific tag' }) - @ApiResponse({ - status: 200, - description: 'The tag was deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("delete") - async deleteOfficialTag(@Body() deleteTagDto: DeleteTagDto): Promise { - const tagId = deleteTagDto.tagId; - - const deleteSuccess = await this.tagService.delete(tagId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Delete a list of tags' }) - @ApiResponse({ - status: 200, - description: 'The tags were deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("deleteBulk") - async deleteBulkOfficialTags(@Body() deleteTagBulkDto: DeleteTagBulkDto): Promise { - const tagsId = deleteTagBulkDto.tagsId; - - const deleteSuccess = await this.tagService.deleteBulk(tagsId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Delete all pages from a specific tag' }) - @ApiResponse({ - status: 200, - description: 'The pages were deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("pages/deleteBulk") - async deleteBulkOfficialTagsPages(@Body() deleteTagBulkDto: DeleteTagBulkDto): Promise { - const tagsId = deleteTagBulkDto.tagsId; - - const deleteSuccess = await this.tagService.pagesDeleteBulk(tagsId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Create study monitor tag' }) - @ApiResponse({ - status: 200, - description: 'The study monitor tag was created', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("user/create") - async createStudyMonitorUserTag(@Body() createTagStudyDto: CreateTagStudyDto): Promise { - const tag = new Tag(); - tag.Name = createTagStudyDto.user_tag_name; - tag.UserId = createTagStudyDto.userId; - tag.Creation_Date = new Date(); - - const type = createTagStudyDto.type; - const tagsId = createTagStudyDto.tagsId; - - const createSuccess = await this.tagService.createUserTag( - tag, - type, - tagsId - ); - - if (!createSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - - @ApiOperation({ summary: 'Delete study monitor tag' }) - @ApiResponse({ - status: 200, - description: 'The study monitor tag was deleted', - type: Array, - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("user/remove") - async removeStudyMonitorUserTag(@Request() req: any, deleteTagStudyDto: DeleteTagStudyDto): Promise { - const tagsId = deleteTagStudyDto.tagsId; - - const removeSuccess = await this.tagService.removeUserTag(tagsId); - - if (!removeSuccess) { - throw new InternalServerErrorException(); - } - - return success( - await this.tagService.findAllFromStudyMonitorUser(req.user.userId) - ); - } - - @ApiOperation({ summary: 'Import tag to AMS' }) - @ApiResponse({ - status: 200, - description: 'The tag was imported', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("import") - async importTag(@Body() importTagDto: ImportTagDto): Promise { - const tagId = importTagDto.tagId; - const tagName = importTagDto.tagName; - - return success(await this.tagService.import(tagId, tagName)); - } - - @ApiOperation({ summary: 'Check if tag exists by name' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("exists/:tagName") - async checkIfTagNameExists( - @Param("tagName") tagName: string - ): Promise { - return success(!!(await this.tagService.findByOfficialTagName(tagName))); - } - - @ApiOperation({ summary: 'Find all tags' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("all") - async getAllTags(): Promise { - return success(await this.tagService.findAll()); - } - @ApiOperation({ summary: 'Find websites from a specific user tag study monitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get(":tag/user/:user/websites/study") - async getUserTagWebsites( - @Param("tag") tag: string, - @Param("user") user: string - ): Promise { - const websites = await this.tagService.findAllUserTagWebsites(tag, user); - - for (const website of websites || []) { - website["imported"] = await this.tagService.verifyUpdateWebsiteAdmin( - website.WebsiteId - ); - - const websiteAdmin = await this.tagService.websiteExistsInAdmin( - website.WebsiteId - ); - website["hasWebsite"] = websiteAdmin.length === 1; - website["webName"] = undefined; - - if (websiteAdmin.length === 1) { - website["webName"] = websiteAdmin[0].Name; - } - } - - return success(websites); - } - - @ApiOperation({ summary: 'Find websites from a specific user tag' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get(":tag/user/:user/websites") - async getTagWebsites( - @Param("tag") tag: string, - @Param("user") user: string - ): Promise { - return success(await this.tagService.findAllUserTagWebsites(tag, user)); - } - - @ApiOperation({ summary: 'Find pages from a specific user tag' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get(":tag/website/:website/user/:user/pages") - async getUserWebsitePages( - @Param("tag") tag: string, - @Param("website") website: string, - @Param("user") user: string - ): Promise { - return success( - await this.tagService.findAllUserWebsitePages(tag, website, user) - ); - } - - @ApiOperation({ summary: 'Find a specific tag by name' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get(":tag/websites/pages") - async getListOfTagWebsitePages(@Param("tag") tag: string): Promise { - return success(await this.tagService.findAllWebsitePages(tag)); - } - - @ApiOperation({ summary: 'Find a specific tag by id' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt")) - @Get("info/:tagId") - async getTagInfo(@Param("tagId") tagId: number): Promise { - return success(await this.tagService.findInfo(tagId)); - } - - @ApiOperation({ summary: 'Find all AMS tags' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt")) - @Get("allOfficial") - async getAllOfficialTags(): Promise { - return success(await this.tagService.findAllOfficial()); - } - - @ApiOperation({ summary: 'Find the number of study monitor tags' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("studyMonitor/total") - async getNumberOfStudyMonitorUsers(): Promise { - return success(await this.tagService.findNumberOfStudyMonitor()); - } - - @ApiOperation({ summary: 'Find the number observatory tags' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("observatory/total") - async getNumberOfObservatoryTags(): Promise { - return success(await this.tagService.findNumberOfObservatory()); - } - - @ApiOperation({ summary: 'Find all study monitor tags from a specific user' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("studyMonitor") - async getStudyMonitorUserTags(@Request() req: any): Promise { - return success( - await this.tagService.findAllFromStudyMonitorUser(req.user.userId) - ); - } - - @ApiOperation({ summary: 'Find tag data from a specific tag' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("studyMonitor/:tag/data") - async getStudyMonitorUserTagData( - @Request() req: any, - @Param("tag") tag: string - ): Promise { - return success( - await this.tagService.findStudyMonitorUserTagData(req.user.userId, tag) - ); - } - - @ApiOperation({ summary: 'Find tag data from a specific tag and website' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("studyMonitor/:tag/website/:website/data") - async getStudyMonitorUserTagWebsitesPagesData( - @Request() req: any, - @Param("tag") tag: string, - @Param("website") website: string - ): Promise { - return success( - await this.tagService.findStudyMonitorUserTagWebsitesPagesData( - req.user.userId, - tag, - website - ) - ); - } -} +import { + Controller, + InternalServerErrorException, + Post, + Get, + Request, + Param, + UseGuards, + UseInterceptors, + Body, +} from "@nestjs/common"; +import { AuthGuard } from "@nestjs/passport"; +import { TagService } from "./tag.service"; +import { Tag } from "./tag.entity"; +import { success } from "../lib/response"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { + ApiBasicAuth, + ApiTags, + ApiResponse, + ApiOperation, +} from "@nestjs/swagger"; +import { TagReEvaluateDto } from "./dto/tag-reevalute.dto"; +import { CreateTagDto } from "./dto/create-tag.dto"; +import { UpdateTagDto } from "./dto/update-tag.dto"; +import { DeleteTagDto } from "./dto/delete-tag.dto"; +import { DeleteTagBulkDto } from "./dto/delete-tag-bulk.dto"; +import { CreateTagStudyDto } from "./dto/create-tag-study.dto"; +import { DeleteTagStudyDto } from "./dto/delete-tag-study.dto"; +import { ImportTagDto } from "./dto/import-tag.dto"; + +@ApiBasicAuth() +@ApiTags("tag") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("tag") +@UseInterceptors(LoggingInterceptor) +export class TagController { + constructor(private readonly tagService: TagService) {} + + @ApiOperation({ summary: "Reevaluate all pages from a tag" }) + @ApiResponse({ + status: 200, + description: "The evaluation request has been submited", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("reEvaluate") + async reEvaluateWebsitePages( + @Body() tagReEvaluateDto: TagReEvaluateDto + ): Promise { + const tagsId = tagReEvaluateDto.tagsId; + const option = tagReEvaluateDto.option; + + return success(await this.tagService.addPagesToEvaluate(tagsId, option)); + } + + @ApiOperation({ summary: "Create a new tag" }) + @ApiResponse({ + status: 200, + description: "The tag was created", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("create") + async createOfficialTag(@Body() createTagDto: CreateTagDto): Promise { + const tag = new Tag(); + tag.Name = createTagDto.name; + tag.Creation_Date = new Date(); + + const directories = createTagDto.directories; + const websites = createTagDto.websites; + + const createSuccess = await this.tagService.createOne( + tag, + directories, + websites + ); + + if (!createSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Update a specific tag" }) + @ApiResponse({ + status: 200, + description: "The tag was updated", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("update") + async updateOfficialTag(@Body() updateTagDto: UpdateTagDto): Promise { + const tagId = updateTagDto.tagId; + const name = updateTagDto.name; + const defaultDirectories = updateTagDto.defaultDirectories; + const directories = updateTagDto.directories; + const defaultWebsites = updateTagDto.defaultWebsites; + const websites = updateTagDto.websites; + + const updateSuccess = await this.tagService.update( + tagId, + name, + defaultDirectories, + directories, + defaultWebsites, + websites + ); + + if (!updateSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Delete a specific tag" }) + @ApiResponse({ + status: 200, + description: "The tag was deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("delete") + async deleteOfficialTag(@Body() deleteTagDto: DeleteTagDto): Promise { + const tagId = deleteTagDto.tagId; + + const deleteSuccess = await this.tagService.delete(tagId); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Delete a list of tags" }) + @ApiResponse({ + status: 200, + description: "The tags were deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("deleteBulk") + async deleteBulkOfficialTags( + @Body() deleteTagBulkDto: DeleteTagBulkDto + ): Promise { + const tagsId = deleteTagBulkDto.tagsId; + + const deleteSuccess = await this.tagService.deleteBulk(tagsId); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Delete all pages from a specific tag" }) + @ApiResponse({ + status: 200, + description: "The pages were deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("pages/deleteBulk") + async deleteBulkOfficialTagsPages( + @Body() deleteTagBulkDto: DeleteTagBulkDto + ): Promise { + const tagsId = deleteTagBulkDto.tagsId; + + const deleteSuccess = await this.tagService.pagesDeleteBulk(tagsId); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Create study monitor tag" }) + @ApiResponse({ + status: 200, + description: "The study monitor tag was created", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("user/create") + async createStudyMonitorUserTag( + @Body() createTagStudyDto: CreateTagStudyDto + ): Promise { + const tag = new Tag(); + tag.Name = createTagStudyDto.user_tag_name; + tag.UserId = createTagStudyDto.userId; + tag.Creation_Date = new Date(); + + const type = createTagStudyDto.type; + const tagsId = createTagStudyDto.tagsId; + + const createSuccess = await this.tagService.createUserTag( + tag, + type, + tagsId + ); + + if (!createSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Delete study monitor tag" }) + @ApiResponse({ + status: 200, + description: "The study monitor tag was deleted", + type: Array, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("user/remove") + async removeStudyMonitorUserTag( + @Request() req: any, + deleteTagStudyDto: DeleteTagStudyDto + ): Promise { + const tagsId = deleteTagStudyDto.tagsId; + + const removeSuccess = await this.tagService.removeUserTag(tagsId); + + if (!removeSuccess) { + throw new InternalServerErrorException(); + } + + return success( + await this.tagService.findAllFromStudyMonitorUser(req.user.userId) + ); + } + + @ApiOperation({ summary: "Import tag to AMS" }) + @ApiResponse({ + status: 200, + description: "The tag was imported", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("import") + async importTag(@Body() importTagDto: ImportTagDto): Promise { + const tagId = importTagDto.tagId; + const tagName = importTagDto.tagName; + + return success(await this.tagService.import(tagId, tagName)); + } + + @ApiOperation({ summary: "Check if tag exists by name" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("exists/:tagName") + async checkIfTagNameExists( + @Param("tagName") tagName: string + ): Promise { + return success(!!(await this.tagService.findByOfficialTagName(tagName))); + } + + @ApiOperation({ summary: "Find all tags" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("all") + async getAllTags(): Promise { + return success(await this.tagService.findAll()); + } + @ApiOperation({ + summary: "Find websites from a specific user tag study monitor", + }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get(":tag/user/:user/websites/study") + async getUserTagWebsites( + @Param("tag") tag: string, + @Param("user") user: string + ): Promise { + const websites = await this.tagService.findAllUserTagWebsites(tag, user); + + for (const website of websites || []) { + website["imported"] = await this.tagService.verifyUpdateWebsiteAdmin( + website.WebsiteId + ); + + const websiteAdmin = await this.tagService.websiteExistsInAdmin( + website.WebsiteId + ); + website["hasWebsite"] = websiteAdmin.length === 1; + website["webName"] = undefined; + + if (websiteAdmin.length === 1) { + website["webName"] = websiteAdmin[0].Name; + } + } + + return success(websites); + } + + @ApiOperation({ summary: "Find websites from a specific user tag" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get(":tag/user/:user/websites") + async getTagWebsites( + @Param("tag") tag: string, + @Param("user") user: string + ): Promise { + return success(await this.tagService.findAllUserTagWebsites(tag, user)); + } + + @ApiOperation({ summary: "Find pages from a specific user tag" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get(":tag/website/:website/user/:user/pages") + async getUserWebsitePages( + @Param("tag") tag: string, + @Param("website") website: string, + @Param("user") user: string + ): Promise { + return success( + await this.tagService.findAllUserWebsitePages(tag, website, user) + ); + } + + @ApiOperation({ summary: "Find a specific tag by name" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get(":tag/websites/pages") + async getListOfTagWebsitePages(@Param("tag") tag: string): Promise { + return success(await this.tagService.findAllWebsitePages(tag)); + } + + @ApiOperation({ summary: "Find a specific tag by id" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt")) + @Get("info/:tagId") + async getTagInfo(@Param("tagId") tagId: number): Promise { + return success(await this.tagService.findInfo(tagId)); + } + + @ApiOperation({ summary: "Find all AMS tags" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt")) + @Get("allOfficial") + async getAllOfficialTags(): Promise { + return success(await this.tagService.findAllOfficial()); + } + + @ApiOperation({ summary: "Find the number of study monitor tags" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("studyMonitor/total") + async getNumberOfStudyMonitorUsers(): Promise { + return success(await this.tagService.findNumberOfStudyMonitor()); + } + + @ApiOperation({ summary: "Find the number observatory tags" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("observatory/total") + async getNumberOfObservatoryTags(): Promise { + return success(await this.tagService.findNumberOfObservatory()); + } + + @ApiOperation({ summary: "Find all study monitor tags from a specific user" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("studyMonitor") + async getStudyMonitorUserTags(@Request() req: any): Promise { + return success( + await this.tagService.findAllFromStudyMonitorUser(req.user.userId) + ); + } + + @ApiOperation({ summary: "Find tag data from a specific tag" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("studyMonitor/:tag/data") + async getStudyMonitorUserTagData( + @Request() req: any, + @Param("tag") tag: string + ): Promise { + return success( + await this.tagService.findStudyMonitorUserTagData(req.user.userId, tag) + ); + } + + @ApiOperation({ summary: "Find tag data from a specific tag and website" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("studyMonitor/:tag/website/:website/data") + async getStudyMonitorUserTagWebsitesPagesData( + @Request() req: any, + @Param("tag") tag: string, + @Param("website") website: string + ): Promise { + return success( + await this.tagService.findStudyMonitorUserTagWebsitesPagesData( + req.user.userId, + tag, + website + ) + ); + } +} diff --git a/src/tag/tag.entity.ts b/src/tag/tag.entity.ts index f6de0ac9..7335ecfa 100644 --- a/src/tag/tag.entity.ts +++ b/src/tag/tag.entity.ts @@ -1,48 +1,48 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - JoinTable, - ManyToMany, -} from "typeorm"; -import { Directory } from "../directory/directory.entity"; -import { Website } from "../website/website.entity"; - -@Entity("Tag") -export class Tag { - @PrimaryGeneratedColumn({ - type: "int", - }) - TagId: number; - - @Column({ - type: "int", - nullable: true, - }) - UserId: number; - - @Column({ - type: "varchar", - length: 255, - nullable: false, - }) - Name: string; - - @Column({ - type: "datetime", - nullable: false, - }) - Creation_Date: any; - - @ManyToMany((type) => Directory) - @JoinTable() - Directories: Directory[]; - - @ManyToMany((type) => Website, website => website.Tags) - @JoinTable({ - name: "TagWebsite", - joinColumns: [{ name: "TagId" }], - inverseJoinColumns: [{ name: "WebsiteId" }] - }) - Websites: Website[]; -} +import { + Entity, + Column, + PrimaryGeneratedColumn, + JoinTable, + ManyToMany, +} from "typeorm"; +import { Directory } from "../directory/directory.entity"; +import { Website } from "../website/website.entity"; + +@Entity("Tag") +export class Tag { + @PrimaryGeneratedColumn({ + type: "int", + }) + TagId: number; + + @Column({ + type: "int", + nullable: true, + }) + UserId: number; + + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + Name: string; + + @Column({ + type: "datetime", + nullable: false, + }) + Creation_Date: any; + + @ManyToMany((type) => Directory) + @JoinTable() + Directories: Directory[]; + + @ManyToMany((type) => Website, (website) => website.Tags) + @JoinTable({ + name: "TagWebsite", + joinColumns: [{ name: "TagId" }], + inverseJoinColumns: [{ name: "WebsiteId" }], + }) + Websites: Website[]; +} diff --git a/src/tag/tag.module.ts b/src/tag/tag.module.ts index 17ade8b7..e6e3a763 100644 --- a/src/tag/tag.module.ts +++ b/src/tag/tag.module.ts @@ -1,13 +1,13 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { TagService } from './tag.service'; -import { Tag } from './tag.entity'; -import { TagController } from './tag.controller'; - -@Module({ - imports: [TypeOrmModule.forFeature([Tag])], - exports: [TagService], - providers: [TagService], - controllers: [TagController] -}) -export class TagModule {} +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { TagService } from "./tag.service"; +import { Tag } from "./tag.entity"; +import { TagController } from "./tag.controller"; + +@Module({ + imports: [TypeOrmModule.forFeature([Tag])], + exports: [TagService], + providers: [TagService], + controllers: [TagController], +}) +export class TagModule {} diff --git a/src/tag/tag.service.spec.ts b/src/tag/tag.service.spec.ts index bbc3acc4..9d56e877 100644 --- a/src/tag/tag.service.spec.ts +++ b/src/tag/tag.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { TagService } from './tag.service'; - -describe('TagService', () => { - let service: TagService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [TagService], - }).compile(); - - service = module.get(TagService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { TagService } from "./tag.service"; + +describe("TagService", () => { + let service: TagService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [TagService], + }).compile(); + + service = module.get(TagService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/tag/tag.service.ts b/src/tag/tag.service.ts index a2f49275..bd717027 100644 --- a/src/tag/tag.service.ts +++ b/src/tag/tag.service.ts @@ -1,1043 +1,1040 @@ -import { Injectable, InternalServerErrorException } from "@nestjs/common"; -import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; -import { DataSource, Repository, IsNull, In } from "typeorm"; -import { Tag } from "./tag.entity"; -import { Website } from "../website/website.entity"; - -@Injectable() -export class TagService { - constructor( - @InjectRepository(Tag) - private readonly tagRepository: Repository, - @InjectDataSource() - private readonly connection: DataSource ) {} - - async addPagesToEvaluate(tagsId: number[], option: string): Promise { - const pages = await this.tagRepository.query( - ` - SELECT - p.PageId, - p.Uri - FROM - TagWebsite as tw, - Website as w, - WebsitePage as wp, - Page as p - WHERE - tw.TagId IN (?) AND - w.WebsiteId = tw.WebsiteId AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE ? - `, - [tagsId, option === "all" ? "1__" : "1_1"] - ); - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - let error = false; - try { - for (const page of pages || []) { - try { - const pageEval = await queryRunner.manager.query( - `SELECT * FROM Evaluation_List WHERE PageId = ? AND UserId = -1 AND Url = ? AND Show_To = ? LIMIT 1`, - [page.PageId, page.Uri, "10"] - ); - if (pageEval.length > 0) { - await queryRunner.manager.query( - `UPDATE Evaluation_List SET Error = NULL, Is_Evaluating = 0 WHERE EvaluationListId = ?`, - [pageEval[0].EvaluationListId] - ); - } else { - await queryRunner.manager.query( - `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, - [page.PageId, -1, page.Uri, "10", new Date()] - ); - } - } catch (_) {} - } - - await queryRunner.manager.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "AMS/Observatory"`, - [pages.length] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.log(err); - error = true; - } finally { - await queryRunner.release(); - } - - return !error; - } - - async findByTagName(tagName: string): Promise { - const tag = await this.tagRepository.findOne({ where: { Name: tagName } }); - return tag; - } - - async findByOfficialTagName(tagName: string): Promise { - const tag = await this.tagRepository.findOne({ - where: { Name: tagName, UserId: IsNull() }, - }); - return tag; - } - - async findInfo(tagId: number): Promise { - const tags = await this.tagRepository.query( - `SELECT t.*, u.Username FROM Tag as t LEFT OUTER JOIN User as u ON u.UserId = t.UserId WHERE TagId = ? LIMIT 1`, - [tagId] - ); - - if (tags) { - const tag = tags[0]; - - tag.directories = await this.tagRepository.query( - `SELECT d.* - FROM - DirectoryTag as dt, - Directory as d - WHERE - dt.TagId = ? AND - d.DirectoryId = dt.DirectoryId`, - [tagId] - ); - - tag.websites = await this.tagRepository.query( - `SELECT w.* - FROM - TagWebsite as tw, - Website as w - WHERE - tw.TagId = ? AND - w.WebsiteId = tw.WebsiteId`, - [tagId] - ); - - return tag; - } else { - throw new InternalServerErrorException(); - } - } - - async findAll(): Promise { - const tags = await this.tagRepository.query(`SELECT - t.*, - COUNT(distinct tw.WebsiteId) as Websites - FROM - Tag as t - LEFT OUTER JOIN TagWebsite as tw ON tw.TagId = t.TagId - WHERE - t.UserId IS NULL - GROUP BY t.TagId`); - - return tags; - } - - async findAllOfficial(): Promise { - return this.tagRepository.find({ where: { UserId: IsNull() } }); - } - - async findNumberOfStudyMonitor(): Promise { - return ( - await this.tagRepository.query( - `SELECT COUNT(t.TagId) as Tags FROM Tag as t, User as u WHERE u.Type = "studies" AND t.UserId = u.UserId` - ) - )[0].Tags; - } - - async findNumberOfObservatory(): Promise { - return ( - await this.tagRepository.query(` - SELECT - COUNT(distinct t.TagId) as Tags - FROM - Directory as d, - DirectoryTag as dt, - Tag as t - WHERE - d.Show_in_Observatory = 1 AND - dt.DirectoryId = d.DirectoryId AND - t.TagId = dt.TagId - `) - )[0].Tags; - } - - async findAllFromStudyMonitorUser(userId: number): Promise { - const tags = await this.tagRepository.query( - `SELECT - distinct t.*, - COUNT(distinct tw.WebsiteId) as Websites, - COUNT(distinct wp.PageId) as Pages - FROM - Tag as t - LEFT OUTER JOIN TagWebsite as tw ON tw.TagId = t.TagId - LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = tw.WebsiteId - WHERE - t.UserId = ? - GROUP BY t.TagId`, - [userId] - ); - - return tags; - } - - async findStudyMonitorUserTagData(userId: number, tag: string): Promise { - const pages = await this.tagRepository.query( - `SELECT - w.WebsiteId, - w.Name, - w.StartingUrl, - p.Uri, - e.Score, - e.Tot, - e.Errors, - e.A, - e.AA, - e.AAA, - e.Evaluation_Date - FROM - Page as p, - Tag as t, - TagWebsite as tw, - Website as w, - WebsitePage as wp, - Evaluation as e - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - e.PageId = p.PageId AND - e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND StudyUserId = w.UserId);`, - [tag, userId, userId] - ); - - return pages; - } - - async findStudyMonitorUserTagWebsitesPagesData( - userId: number, - tag: string, - website: string - ): Promise { - const pages = await this.tagRepository.query( - `SELECT - distinct p.*, - e.Score, - e.Errors, - e.Tot, - e.A, - e.AA, - e.AAA, - e.Evaluation_Date - FROM - Page as p, - Tag as t, - TagWebsite as tw, - Website as w, - WebsitePage as wp, - Evaluation as e - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.Name = ? AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - e.PageId = p.PageId AND - e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND StudyUserId = w.UserId);`, - [tag, userId, website, userId] - ); - - return pages; - } - - async getUserId(username: string): Promise { - return ( - await this.tagRepository.query( - "SELECT * FROM User WHERE Username = ? LIMIT 1", - [username] - ) - )[0].UserId; - } - - async findAllUserWebsitePages( - tag: string, - website: string, - user: string - ): Promise { - const userId = await this.getUserId(user); - - const websiteExists = await this.tagRepository.query( - `SELECT * FROM Website WHERE UserId = ? AND Name = ? LIMIT 1`, - [userId, website] - ); - - if (tag !== "null") { - if (websiteExists) { - const pages = await this.tagRepository.query( - `SELECT - distinct p.*, - e.Score, - e.A, - e.AA, - e.AAA, - e.Evaluation_Date - FROM - Page as p, - Tag as t, - TagWebsite as tw, - Website as w, - WebsitePage as wp, - Evaluation as e - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.Name = ? AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - e.PageId = p.PageId AND - e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId)`, - [tag, userId, website, userId] - ); - - return pages; - } - } else { - if (websiteExists) { - const pages = await this.tagRepository.query( - `SELECT - distinct p.*, - e.Score, - e.A, - e.AA, - e.AAA, - e.Errors, - e.Evaluation_Date - FROM - Page as p, - Website as w, - WebsitePage as wp, - Evaluation as e - WHERE - w.Name = ? AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - e.PageId = p.PageId AND - p.Show_In LIKE '_1_' AND - e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId)`, - [website, userId] - ); - - return pages; - } - } - } - - async findAllWebsitePages(tag: string): Promise { - - const websites = await this.tagRepository.query( - ` - SELECT - w.WebsiteId, - p.*, - e.A, - e.AA, - e.AAA, - e.Score, - e.Errors, - e.Tot, - e.Evaluation_Date - FROM - Tag as t, - TagWebsite as tw, - Website as w, - WebsitePage as wp, - Page as p - LEFT OUTER JOIN Evaluation e ON e.PageId = p.PageId AND e.Show_To LIKE "1_" AND e.Evaluation_Date = ( - SELECT Evaluation_Date FROM Evaluation - WHERE PageId = p.PageId AND Show_To LIKE "1_" - ORDER BY Evaluation_Date DESC LIMIT 1 - ) - WHERE - t.Name = ? AND - t.UserId IS NULL AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE "1__" - GROUP BY w.WebsiteId, p.PageId, e.A, e.AA, e.AAA, e.Score, e.Errors, e.Tot, e.Evaluation_Date`, - [tag] - ); - - return websites; //.filter((w) => w.Score !== null); - } - - async createOne( - tag: Tag, - directories: number[], - websites: number[] - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const insertTag = await queryRunner.manager.save(tag); - - for (const directoryId of directories || []) { - await queryRunner.manager.query( - `INSERT INTO DirectoryTag (DirectoryId, TagId) VALUES (?, ?)`, - [directoryId, insertTag.TagId] - ); - } - - for (const websiteId of websites || []) { - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, - [insertTag.TagId, websiteId] - ); - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async createDirectory( - tag: Tag, - tags: number[], - method: string - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const insertTag = await queryRunner.manager.save(tag); - - let websites = new Array(); - if (tags.length > 0) { - if (method === "cross") { - websites = await queryRunner.manager.query( - `SELECT WebsiteId - FROM - TagWebsite - WHERE - TagId IN (?) - GROUP BY - WebsiteId - HAVING - COUNT(WebsiteId) = ?`, - [tags, tags.length] - ); - } else if (method === "join") { - websites = await queryRunner.manager.query( - `SELECT DISTINCT WebsiteId - FROM - TagWebsite - WHERE - TagId IN (?)`, - [tags] - ); - } - } else { - const tagId = tags[0]; - websites = await queryRunner.manager.query( - `SELECT WebsiteId FROM TagWebsite WHERE TagId = ?`, - [tagId] - ); - } - - for (const website of websites || []) { - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, - [insertTag.TagId, website.WebsiteId] - ); - } - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async createUserTag(tag: Tag, type: string, tagsId: number[]): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - if (type === "official" || type === "user") { - const insertTag = await queryRunner.manager.save(tag); - - if (type === "official") { - let websites = null; - if (tagsId.length > 1) { - websites = await queryRunner.manager.query( - `SELECT w.Name, w.WebsiteId, w.StartingUrl - FROM - TagWebsite as tw - LEFT OUTER JOIN Website as w ON w.WebsiteId = tw.WebsiteId - WHERE - tw.TagId IN (?) - GROUP BY - w.Name, w.WebsiteId, w.StartingUrl - HAVING - COUNT(tw.WebsiteId) = ?`, - [tagsId, tagsId.length] - ); - } else { - websites = await queryRunner.manager.query( - `SELECT w.Name, w.WebsiteId, w.StartingUrl - FROM - TagWebsite as tw - LEFT OUTER JOIN Website as w ON w.WebsiteId = tw.WebsiteId - WHERE - tw.TagId = ? - GROUP BY - w.Name, w.WebsiteId, w.StartingUrl`, - [tagsId[0]] - ); - } - - for (const website of websites || []) { - const newWebsite = new Website(); - newWebsite.Name = website.Name; - newWebsite.StartingUrl = website.StartingUrl; - newWebsite.UserId = tag.UserId; - newWebsite.Creation_Date = tag.Creation_Date; - const insertWebsite = await queryRunner.manager.save(newWebsite); - - const pages = await queryRunner.manager.query( - `SELECT wp.* FROM WebsitePage as wp, Page as p WHERE wp.WebsiteId = ? AND p.PageId = wp.PageId AND p.Show_In LIKE "1_1"`, - [website.WebsiteId] - ); - - for (const page of pages || []) { - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, - [insertWebsite.WebsiteId, page.PageId] - ); - } - - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, - [insertTag.TagId, insertWebsite.WebsiteId] - ); - } - } - - await queryRunner.commitTransaction(); - } else { - hasError = true; - } - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async update( - tagId: number, - name: string, - defaultDirectories: number[], - directories: number[], - defaultWebsites: number[], - websites: number[] - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.update(Tag, { TagId: tagId }, { Name: name }); - - for (const id of defaultDirectories || []) { - if (!directories.includes(id)) { - await queryRunner.manager.query( - `DELETE FROM DirectoryTag WHERE DirectoryId = ? AND TagId = ?`, - [id, tagId] - ); - } - } - - for (const id of directories || []) { - if (!defaultDirectories.includes(id)) { - await queryRunner.manager.query( - `INSERT INTO DirectoryTag (DirectoryId, TagId) VALUES (?, ?)`, - [id, tagId] - ); - } - } - - for (const id of defaultWebsites || []) { - if (!websites.includes(id)) { - await queryRunner.manager.query( - `DELETE FROM TagWebsite WHERE TagId = ? AND WebsiteId = ?`, - [tagId, id] - ); - } - } - - for (const id of websites || []) { - if (!defaultWebsites.includes(id)) { - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, - [tagId, id] - ); - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async delete(tagId: number): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.delete(Tag, { TagId: tagId }); - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async deleteBulk(tagsId: Array): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.delete(Tag, { TagId: In(tagsId) }); - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async pagesDeleteBulk(tagsId: Array): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const websites = await queryRunner.manager.query( - ` - SELECT * FROM TagWebsite WHERE TagId IN (?) - `, - [tagsId] - ); - - const pages = await queryRunner.manager.query( - ` - SELECT - PageId - FROM - WebsitePage - WHERE - WebsiteId IN (?) - `, - [websites.map((w) => w.WebsiteId)] - ); - - await queryRunner.manager.query( - ` - DELETE FROM - Page - WHERE - PageId IN (?) - `, - [pages.map((p) => p.PageId)] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async removeUserTag(tagsId: number[]): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - for (const id of tagsId || []) { - const relations = await queryRunner.manager.query( - `SELECT * FROM TagWebsite WHERE TagId = ? AND WebsiteId <> -1`, - [id] - ); - if (relations.length > 0) { - const websitesId = relations.map((tw) => tw.WebsiteId); - await queryRunner.manager.delete(Website, { - WebsiteId: In(websitesId), - }); - } - } - - await queryRunner.manager.delete(Tag, { TagId: In(tagsId) }); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async findAllUserTagWebsites(tag: string, user: string): Promise { - - if (user === "admin") { - const websites = await this.tagRepository.query( - `SELECT w.*, u.Username as User, COUNT(distinct p.PageId) as Pages, COUNT(distinct e.PageId) as Evaluated_Pages - FROM - Website as w - LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId - LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE "1__" - LEFT OUTER JOIN Evaluation as e ON e.PageId = p.PageId - LEFT OUTER JOIN User as u ON u.UserId = w.UserId, - Tag as t, - TagWebsite as tw - WHERE - t.Name = ? AND - t.UserId IS NULL AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId - GROUP BY w.WebsiteId`, - [tag] - ); - - return websites; - } else { - const websites = await this.tagRepository.query( - `SELECT w.*, e.Long_Name as Entity, u.Username as User - FROM - User as u, - Tag as t, - TagWebsite as tw, - EntityWebsite as ew - LEFT OUTER JOIN Website as w ON w.WebsiteId = ew.WebsiteId - LEFT OUTER JOIN Entity as e ON e.EntityId = ew.EntityId - WHERE - t.Name = ? AND - u.Username = ? AND - t.UserId = u.UserId AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId - GROUP BY w.WebsiteId, w.StartingUrl`, - [tag, user] - ); - - return websites; - } - } - - async verifyUpdateWebsiteAdmin(websiteId: number): Promise { - - const studyP = await this.tagRepository.query( - `SELECT p.PageId - FROM - Page as p, - WebsitePage as wp, - Website as w - WHERE - w.WebsiteId = ? AND - wp.WebsiteId = w.WebsiteId AND - wp.PageId = p.PageId AND - p.Show_In LIKE '0%'`, - [websiteId] - ); - - return studyP.length === 0; - } - - async websiteExistsInAdmin(websiteId: number): Promise { - - const websites = await this.tagRepository.query( - `SELECT - w2.* - FROM - Website as w, - Website as w2 - WHERE - w.WebsiteId = ? AND - w2.StartingUrl = w.StartingUrl AND - w2.WebsiteId != w.WebsiteId`, - [websiteId] - ); - - return websites; - } - - async import(tagId: number, tagName: string): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const websites = await queryRunner.manager.query( - `SELECT tw.*, w.Name FROM TagWebsite as tw, Website as w WHERE tw.TagId = ? AND w.WebsiteId = tw.WebsiteId`, - [tagId] - ); - - if (websites.length > 0) { - const date = new Date() - .toISOString() - .replace(/T/, " ") - .replace(/\..+/, ""); - const insertTag = await queryRunner.manager.query( - `INSERT INTO Tag (Name, Creation_Date) - VALUES (?, ?)`, - [tagName, date] - ); - - for (const website of websites || []) { - const websiteId = await this.importWebsite( - queryRunner, - website.WebsiteId, - website.Name - ); - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, - [insertTag.insertId, websiteId] - ); - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - console.error(err); - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - private async importWebsite( - queryRunner: any, - websiteId: number, - websiteName: string - ): Promise { - let returnWebsiteId = websiteId; - - const website = await queryRunner.manager.query( - `SELECT distinct w.* - FROM - Website as w - WHERE - w.WebsiteId = ?`, - [websiteId] - ); - - const webDate = website[0].Creation_Date.toISOString() - .replace(/T/, " ") - .replace(/\..+/, ""); - - const pages = await queryRunner.manager.query( - `SELECT p.* - FROM - Page as p, - Website as w, - WebsitePage as wp - WHERE - w.WebsiteId = ? AND - wp.WebsiteId = w.WebsiteId AND - wp.PageId = p.PageId`, - [websiteId] - ); - - const websiteP = ( - await queryRunner.manager.query( - `SELECT distinct w.* - FROM - Website as w, - User as u - WHERE - w.StartingUrl = ? AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type = "monitor")) - LIMIT 1 - `, - [website[0].StartingUrl] - ) - )[0]; - - const websiteUrl = website[0].StartingUrl; - - if (website.length > 0) { - if (websiteP) { - for (const page of pages || []) { - if (page.Show_In[0] === "0") { - await this.importPage(queryRunner, page.PageId); - try { - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, - [websiteP.WebsiteId, page.PageId] - ); - } catch (err) { - // ignore - don't know why - } - } - } - await queryRunner.manager.query( - `UPDATE Website SET Creation_Date = ? WHERE WebsiteId = ?`, - [webDate, websiteP.WebsiteId] - ); - } else { - const insertWebsite = await queryRunner.manager.query( - `INSERT INTO Website (Name, StartingUrl, Creation_Date) VALUES (?, ?)`, - [websiteName, websiteUrl, webDate] - ); - returnWebsiteId = insertWebsite.insertId; - - for (const page of pages || []) { - if (page.Show_In[0] === "0") { - await this.importPage(queryRunner, page.PageId); - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES ("${website.insertId}", "${page.PageId}")`, - [website.WebsiteId, page.PageId] - ); - } - } - } - } - - return returnWebsiteId; - } - - private async importPage(queryRunner: any, pageId: number): Promise { - const page = await queryRunner.manager.query( - `SELECT Show_In FROM Page WHERE PageId = ? LIMIT 1`, - [pageId] - ); - - if (page.length > 0) { - const show = "1" + page[0].Show_In[1] + page[0].Show_In[2]; - await queryRunner.manager.query( - `UPDATE Page SET Show_In = ? WHERE PageId = ?`, - [show, pageId] - ); - - const evaluation = await queryRunner.manager.query( - `SELECT e.EvaluationId, e.Show_To FROM Evaluation as e WHERE e.PageId = ? AND e.Show_To LIKE "_1" ORDER BY e.Evaluation_Date DESC LIMIT 1`, - [pageId] - ); - - const evalId = evaluation[0].EvaluationId; - const showTo = evaluation[0].Show_To; - - if (evaluation.length > 0) { - const newShowTo = "1" + showTo[1]; - await queryRunner.manager.query( - `UPDATE Evaluation SET Show_To = ? WHERE EvaluationId = ?`, - [newShowTo, evalId] - ); - } - } - } -} +import { Injectable, InternalServerErrorException } from "@nestjs/common"; +import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; +import { DataSource, Repository, IsNull, In } from "typeorm"; +import { Tag } from "./tag.entity"; +import { Website } from "../website/website.entity"; + +@Injectable() +export class TagService { + constructor( + @InjectRepository(Tag) + private readonly tagRepository: Repository, + @InjectDataSource() + private readonly connection: DataSource + ) {} + + async addPagesToEvaluate(tagsId: number[], option: string): Promise { + const pages = await this.tagRepository.query( + ` + SELECT + p.PageId, + p.Uri + FROM + TagWebsite as tw, + Website as w, + WebsitePage as wp, + Page as p + WHERE + tw.TagId IN (?) AND + w.WebsiteId = tw.WebsiteId AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE ? + `, + [tagsId, option === "all" ? "1__" : "1_1"] + ); + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + let error = false; + try { + for (const page of pages || []) { + try { + const pageEval = await queryRunner.manager.query( + `SELECT * FROM Evaluation_List WHERE PageId = ? AND UserId = -1 AND Url = ? AND Show_To = ? LIMIT 1`, + [page.PageId, page.Uri, "10"] + ); + if (pageEval.length > 0) { + await queryRunner.manager.query( + `UPDATE Evaluation_List SET Error = NULL, Is_Evaluating = 0 WHERE EvaluationListId = ?`, + [pageEval[0].EvaluationListId] + ); + } else { + await queryRunner.manager.query( + `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, + [page.PageId, -1, page.Uri, "10", new Date()] + ); + } + } catch (_) {} + } + + await queryRunner.manager.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "AMS/Observatory"`, + [pages.length] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.log(err); + error = true; + } finally { + await queryRunner.release(); + } + + return !error; + } + + async findByTagName(tagName: string): Promise { + const tag = await this.tagRepository.findOne({ where: { Name: tagName } }); + return tag; + } + + async findByOfficialTagName(tagName: string): Promise { + const tag = await this.tagRepository.findOne({ + where: { Name: tagName, UserId: IsNull() }, + }); + return tag; + } + + async findInfo(tagId: number): Promise { + const tags = await this.tagRepository.query( + `SELECT t.*, u.Username FROM Tag as t LEFT OUTER JOIN User as u ON u.UserId = t.UserId WHERE TagId = ? LIMIT 1`, + [tagId] + ); + + if (tags) { + const tag = tags[0]; + + tag.directories = await this.tagRepository.query( + `SELECT d.* + FROM + DirectoryTag as dt, + Directory as d + WHERE + dt.TagId = ? AND + d.DirectoryId = dt.DirectoryId`, + [tagId] + ); + + tag.websites = await this.tagRepository.query( + `SELECT w.* + FROM + TagWebsite as tw, + Website as w + WHERE + tw.TagId = ? AND + w.WebsiteId = tw.WebsiteId`, + [tagId] + ); + + return tag; + } else { + throw new InternalServerErrorException(); + } + } + + async findAll(): Promise { + const tags = await this.tagRepository.query(`SELECT + t.*, + COUNT(distinct tw.WebsiteId) as Websites + FROM + Tag as t + LEFT OUTER JOIN TagWebsite as tw ON tw.TagId = t.TagId + WHERE + t.UserId IS NULL + GROUP BY t.TagId`); + + return tags; + } + + async findAllOfficial(): Promise { + return this.tagRepository.find({ where: { UserId: IsNull() } }); + } + + async findNumberOfStudyMonitor(): Promise { + return ( + await this.tagRepository.query( + `SELECT COUNT(t.TagId) as Tags FROM Tag as t, User as u WHERE u.Type = "studies" AND t.UserId = u.UserId` + ) + )[0].Tags; + } + + async findNumberOfObservatory(): Promise { + return ( + await this.tagRepository.query(` + SELECT + COUNT(distinct t.TagId) as Tags + FROM + Directory as d, + DirectoryTag as dt, + Tag as t + WHERE + d.Show_in_Observatory = 1 AND + dt.DirectoryId = d.DirectoryId AND + t.TagId = dt.TagId + `) + )[0].Tags; + } + + async findAllFromStudyMonitorUser(userId: number): Promise { + const tags = await this.tagRepository.query( + `SELECT + distinct t.*, + COUNT(distinct tw.WebsiteId) as Websites, + COUNT(distinct wp.PageId) as Pages + FROM + Tag as t + LEFT OUTER JOIN TagWebsite as tw ON tw.TagId = t.TagId + LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = tw.WebsiteId + WHERE + t.UserId = ? + GROUP BY t.TagId`, + [userId] + ); + + return tags; + } + + async findStudyMonitorUserTagData(userId: number, tag: string): Promise { + const pages = await this.tagRepository.query( + `SELECT + w.WebsiteId, + w.Name, + w.StartingUrl, + p.Uri, + e.Score, + e.Tot, + e.Errors, + e.A, + e.AA, + e.AAA, + e.Evaluation_Date + FROM + Page as p, + Tag as t, + TagWebsite as tw, + Website as w, + WebsitePage as wp, + Evaluation as e + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + e.PageId = p.PageId AND + e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND StudyUserId = w.UserId);`, + [tag, userId, userId] + ); + + return pages; + } + + async findStudyMonitorUserTagWebsitesPagesData( + userId: number, + tag: string, + website: string + ): Promise { + const pages = await this.tagRepository.query( + `SELECT + distinct p.*, + e.Score, + e.Errors, + e.Tot, + e.A, + e.AA, + e.AAA, + e.Evaluation_Date + FROM + Page as p, + Tag as t, + TagWebsite as tw, + Website as w, + WebsitePage as wp, + Evaluation as e + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.Name = ? AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + e.PageId = p.PageId AND + e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND StudyUserId = w.UserId);`, + [tag, userId, website, userId] + ); + + return pages; + } + + async getUserId(username: string): Promise { + return ( + await this.tagRepository.query( + "SELECT * FROM User WHERE Username = ? LIMIT 1", + [username] + ) + )[0].UserId; + } + + async findAllUserWebsitePages( + tag: string, + website: string, + user: string + ): Promise { + const userId = await this.getUserId(user); + + const websiteExists = await this.tagRepository.query( + `SELECT * FROM Website WHERE UserId = ? AND Name = ? LIMIT 1`, + [userId, website] + ); + + if (tag !== "null") { + if (websiteExists) { + const pages = await this.tagRepository.query( + `SELECT + distinct p.*, + e.Score, + e.A, + e.AA, + e.AAA, + e.Evaluation_Date + FROM + Page as p, + Tag as t, + TagWebsite as tw, + Website as w, + WebsitePage as wp, + Evaluation as e + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.Name = ? AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + e.PageId = p.PageId AND + e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId)`, + [tag, userId, website, userId] + ); + + return pages; + } + } else { + if (websiteExists) { + const pages = await this.tagRepository.query( + `SELECT + distinct p.*, + e.Score, + e.A, + e.AA, + e.AAA, + e.Errors, + e.Evaluation_Date + FROM + Page as p, + Website as w, + WebsitePage as wp, + Evaluation as e + WHERE + w.Name = ? AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + e.PageId = p.PageId AND + p.Show_In LIKE '_1_' AND + e.Evaluation_Date IN (SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId)`, + [website, userId] + ); + + return pages; + } + } + } + + async findAllWebsitePages(tag: string): Promise { + const websites = await this.tagRepository.query( + ` + SELECT + w.WebsiteId, + p.*, + e.A, + e.AA, + e.AAA, + e.Score, + e.Errors, + e.Tot, + e.Evaluation_Date + FROM + Tag as t, + TagWebsite as tw, + Website as w, + WebsitePage as wp, + Page as p + LEFT OUTER JOIN Evaluation e ON e.PageId = p.PageId AND e.Show_To LIKE "1_" AND e.Evaluation_Date = ( + SELECT Evaluation_Date FROM Evaluation + WHERE PageId = p.PageId AND Show_To LIKE "1_" + ORDER BY Evaluation_Date DESC LIMIT 1 + ) + WHERE + t.Name = ? AND + t.UserId IS NULL AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE "1__" + GROUP BY w.WebsiteId, p.PageId, e.A, e.AA, e.AAA, e.Score, e.Errors, e.Tot, e.Evaluation_Date`, + [tag] + ); + + return websites; //.filter((w) => w.Score !== null); + } + + async createOne( + tag: Tag, + directories: number[], + websites: number[] + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const insertTag = await queryRunner.manager.save(tag); + + for (const directoryId of directories || []) { + await queryRunner.manager.query( + `INSERT INTO DirectoryTag (DirectoryId, TagId) VALUES (?, ?)`, + [directoryId, insertTag.TagId] + ); + } + + for (const websiteId of websites || []) { + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, + [insertTag.TagId, websiteId] + ); + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async createDirectory( + tag: Tag, + tags: number[], + method: string + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const insertTag = await queryRunner.manager.save(tag); + + let websites = new Array(); + if (tags.length > 0) { + if (method === "cross") { + websites = await queryRunner.manager.query( + `SELECT WebsiteId + FROM + TagWebsite + WHERE + TagId IN (?) + GROUP BY + WebsiteId + HAVING + COUNT(WebsiteId) = ?`, + [tags, tags.length] + ); + } else if (method === "join") { + websites = await queryRunner.manager.query( + `SELECT DISTINCT WebsiteId + FROM + TagWebsite + WHERE + TagId IN (?)`, + [tags] + ); + } + } else { + const tagId = tags[0]; + websites = await queryRunner.manager.query( + `SELECT WebsiteId FROM TagWebsite WHERE TagId = ?`, + [tagId] + ); + } + + for (const website of websites || []) { + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, + [insertTag.TagId, website.WebsiteId] + ); + } + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async createUserTag(tag: Tag, type: string, tagsId: number[]): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + if (type === "official" || type === "user") { + const insertTag = await queryRunner.manager.save(tag); + + if (type === "official") { + let websites = null; + if (tagsId.length > 1) { + websites = await queryRunner.manager.query( + `SELECT w.Name, w.WebsiteId, w.StartingUrl + FROM + TagWebsite as tw + LEFT OUTER JOIN Website as w ON w.WebsiteId = tw.WebsiteId + WHERE + tw.TagId IN (?) + GROUP BY + w.Name, w.WebsiteId, w.StartingUrl + HAVING + COUNT(tw.WebsiteId) = ?`, + [tagsId, tagsId.length] + ); + } else { + websites = await queryRunner.manager.query( + `SELECT w.Name, w.WebsiteId, w.StartingUrl + FROM + TagWebsite as tw + LEFT OUTER JOIN Website as w ON w.WebsiteId = tw.WebsiteId + WHERE + tw.TagId = ? + GROUP BY + w.Name, w.WebsiteId, w.StartingUrl`, + [tagsId[0]] + ); + } + + for (const website of websites || []) { + const newWebsite = new Website(); + newWebsite.Name = website.Name; + newWebsite.StartingUrl = website.StartingUrl; + newWebsite.UserId = tag.UserId; + newWebsite.Creation_Date = tag.Creation_Date; + const insertWebsite = await queryRunner.manager.save(newWebsite); + + const pages = await queryRunner.manager.query( + `SELECT wp.* FROM WebsitePage as wp, Page as p WHERE wp.WebsiteId = ? AND p.PageId = wp.PageId AND p.Show_In LIKE "1_1"`, + [website.WebsiteId] + ); + + for (const page of pages || []) { + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, + [insertWebsite.WebsiteId, page.PageId] + ); + } + + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, + [insertTag.TagId, insertWebsite.WebsiteId] + ); + } + } + + await queryRunner.commitTransaction(); + } else { + hasError = true; + } + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async update( + tagId: number, + name: string, + defaultDirectories: number[], + directories: number[], + defaultWebsites: number[], + websites: number[] + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.update(Tag, { TagId: tagId }, { Name: name }); + + for (const id of defaultDirectories || []) { + if (!directories.includes(id)) { + await queryRunner.manager.query( + `DELETE FROM DirectoryTag WHERE DirectoryId = ? AND TagId = ?`, + [id, tagId] + ); + } + } + + for (const id of directories || []) { + if (!defaultDirectories.includes(id)) { + await queryRunner.manager.query( + `INSERT INTO DirectoryTag (DirectoryId, TagId) VALUES (?, ?)`, + [id, tagId] + ); + } + } + + for (const id of defaultWebsites || []) { + if (!websites.includes(id)) { + await queryRunner.manager.query( + `DELETE FROM TagWebsite WHERE TagId = ? AND WebsiteId = ?`, + [tagId, id] + ); + } + } + + for (const id of websites || []) { + if (!defaultWebsites.includes(id)) { + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, + [tagId, id] + ); + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async delete(tagId: number): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.delete(Tag, { TagId: tagId }); + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async deleteBulk(tagsId: Array): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.delete(Tag, { TagId: In(tagsId) }); + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async pagesDeleteBulk(tagsId: Array): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const websites = await queryRunner.manager.query( + ` + SELECT * FROM TagWebsite WHERE TagId IN (?) + `, + [tagsId] + ); + + const pages = await queryRunner.manager.query( + ` + SELECT + PageId + FROM + WebsitePage + WHERE + WebsiteId IN (?) + `, + [websites.map((w) => w.WebsiteId)] + ); + + await queryRunner.manager.query( + ` + DELETE FROM + Page + WHERE + PageId IN (?) + `, + [pages.map((p) => p.PageId)] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async removeUserTag(tagsId: number[]): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + for (const id of tagsId || []) { + const relations = await queryRunner.manager.query( + `SELECT * FROM TagWebsite WHERE TagId = ? AND WebsiteId <> -1`, + [id] + ); + if (relations.length > 0) { + const websitesId = relations.map((tw) => tw.WebsiteId); + await queryRunner.manager.delete(Website, { + WebsiteId: In(websitesId), + }); + } + } + + await queryRunner.manager.delete(Tag, { TagId: In(tagsId) }); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async findAllUserTagWebsites(tag: string, user: string): Promise { + if (user === "admin") { + const websites = await this.tagRepository.query( + `SELECT w.*, u.Username as User, COUNT(distinct p.PageId) as Pages, COUNT(distinct e.PageId) as Evaluated_Pages + FROM + Website as w + LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId + LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE "1__" + LEFT OUTER JOIN Evaluation as e ON e.PageId = p.PageId + LEFT OUTER JOIN User as u ON u.UserId = w.UserId, + Tag as t, + TagWebsite as tw + WHERE + t.Name = ? AND + t.UserId IS NULL AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId + GROUP BY w.WebsiteId`, + [tag] + ); + + return websites; + } else { + const websites = await this.tagRepository.query( + `SELECT w.*, e.Long_Name as Entity, u.Username as User + FROM + User as u, + Tag as t, + TagWebsite as tw, + EntityWebsite as ew + LEFT OUTER JOIN Website as w ON w.WebsiteId = ew.WebsiteId + LEFT OUTER JOIN Entity as e ON e.EntityId = ew.EntityId + WHERE + t.Name = ? AND + u.Username = ? AND + t.UserId = u.UserId AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId + GROUP BY w.WebsiteId, w.StartingUrl`, + [tag, user] + ); + + return websites; + } + } + + async verifyUpdateWebsiteAdmin(websiteId: number): Promise { + const studyP = await this.tagRepository.query( + `SELECT p.PageId + FROM + Page as p, + WebsitePage as wp, + Website as w + WHERE + w.WebsiteId = ? AND + wp.WebsiteId = w.WebsiteId AND + wp.PageId = p.PageId AND + p.Show_In LIKE '0%'`, + [websiteId] + ); + + return studyP.length === 0; + } + + async websiteExistsInAdmin(websiteId: number): Promise { + const websites = await this.tagRepository.query( + `SELECT + w2.* + FROM + Website as w, + Website as w2 + WHERE + w.WebsiteId = ? AND + w2.StartingUrl = w.StartingUrl AND + w2.WebsiteId != w.WebsiteId`, + [websiteId] + ); + + return websites; + } + + async import(tagId: number, tagName: string): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const websites = await queryRunner.manager.query( + `SELECT tw.*, w.Name FROM TagWebsite as tw, Website as w WHERE tw.TagId = ? AND w.WebsiteId = tw.WebsiteId`, + [tagId] + ); + + if (websites.length > 0) { + const date = new Date() + .toISOString() + .replace(/T/, " ") + .replace(/\..+/, ""); + const insertTag = await queryRunner.manager.query( + `INSERT INTO Tag (Name, Creation_Date) + VALUES (?, ?)`, + [tagName, date] + ); + + for (const website of websites || []) { + const websiteId = await this.importWebsite( + queryRunner, + website.WebsiteId, + website.Name + ); + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, + [insertTag.insertId, websiteId] + ); + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + console.error(err); + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + private async importWebsite( + queryRunner: any, + websiteId: number, + websiteName: string + ): Promise { + let returnWebsiteId = websiteId; + + const website = await queryRunner.manager.query( + `SELECT distinct w.* + FROM + Website as w + WHERE + w.WebsiteId = ?`, + [websiteId] + ); + + const webDate = website[0].Creation_Date.toISOString() + .replace(/T/, " ") + .replace(/\..+/, ""); + + const pages = await queryRunner.manager.query( + `SELECT p.* + FROM + Page as p, + Website as w, + WebsitePage as wp + WHERE + w.WebsiteId = ? AND + wp.WebsiteId = w.WebsiteId AND + wp.PageId = p.PageId`, + [websiteId] + ); + + const websiteP = ( + await queryRunner.manager.query( + `SELECT distinct w.* + FROM + Website as w, + User as u + WHERE + w.StartingUrl = ? AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type = "monitor")) + LIMIT 1 + `, + [website[0].StartingUrl] + ) + )[0]; + + const websiteUrl = website[0].StartingUrl; + + if (website.length > 0) { + if (websiteP) { + for (const page of pages || []) { + if (page.Show_In[0] === "0") { + await this.importPage(queryRunner, page.PageId); + try { + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, + [websiteP.WebsiteId, page.PageId] + ); + } catch (err) { + // ignore - don't know why + } + } + } + await queryRunner.manager.query( + `UPDATE Website SET Creation_Date = ? WHERE WebsiteId = ?`, + [webDate, websiteP.WebsiteId] + ); + } else { + const insertWebsite = await queryRunner.manager.query( + `INSERT INTO Website (Name, StartingUrl, Creation_Date) VALUES (?, ?)`, + [websiteName, websiteUrl, webDate] + ); + returnWebsiteId = insertWebsite.insertId; + + for (const page of pages || []) { + if (page.Show_In[0] === "0") { + await this.importPage(queryRunner, page.PageId); + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES ("${website.insertId}", "${page.PageId}")`, + [website.WebsiteId, page.PageId] + ); + } + } + } + } + + return returnWebsiteId; + } + + private async importPage(queryRunner: any, pageId: number): Promise { + const page = await queryRunner.manager.query( + `SELECT Show_In FROM Page WHERE PageId = ? LIMIT 1`, + [pageId] + ); + + if (page.length > 0) { + const show = "1" + page[0].Show_In[1] + page[0].Show_In[2]; + await queryRunner.manager.query( + `UPDATE Page SET Show_In = ? WHERE PageId = ?`, + [show, pageId] + ); + + const evaluation = await queryRunner.manager.query( + `SELECT e.EvaluationId, e.Show_To FROM Evaluation as e WHERE e.PageId = ? AND e.Show_To LIKE "_1" ORDER BY e.Evaluation_Date DESC LIMIT 1`, + [pageId] + ); + + const evalId = evaluation[0].EvaluationId; + const showTo = evaluation[0].Show_To; + + if (evaluation.length > 0) { + const newShowTo = "1" + showTo[1]; + await queryRunner.manager.query( + `UPDATE Evaluation SET Show_To = ? WHERE EvaluationId = ?`, + [newShowTo, evalId] + ); + } + } + } +} diff --git a/src/user/dto/create-user.dto.ts b/src/user/dto/create-user.dto.ts index 712162f9..cd12fd9c 100644 --- a/src/user/dto/create-user.dto.ts +++ b/src/user/dto/create-user.dto.ts @@ -1,10 +1,10 @@ export class CreateUserDto { - password:string; - username:string; - names:string; - emails:string; - type:string; - tags:string[]; - websites:string[]; - transfer:any; -} \ No newline at end of file + password: string; + username: string; + names: string; + emails: string; + type: string; + tags: string[]; + websites: string[]; + transfer: any; +} diff --git a/src/user/dto/delete-user.dto.ts b/src/user/dto/delete-user.dto.ts index c8f73179..34f41127 100644 --- a/src/user/dto/delete-user.dto.ts +++ b/src/user/dto/delete-user.dto.ts @@ -1,4 +1,4 @@ export class DeleteUserDto { - userId:number; - app:string; -} \ No newline at end of file + userId: number; + app: string; +} diff --git a/src/user/dto/update-user.dto.ts b/src/user/dto/update-user.dto.ts index f4d32c11..1abb395b 100644 --- a/src/user/dto/update-user.dto.ts +++ b/src/user/dto/update-user.dto.ts @@ -1,14 +1,14 @@ export class UpdateUserDto { - password:string; - username:string; - names:string; - emails:string; - type:string; - tags:string[]; - websites:number[]; - transfer:any; - userId:number; - confirmPassword:string; - app:string; - defaultWebsites:number[]; -} \ No newline at end of file + password: string; + username: string; + names: string; + emails: string; + type: string; + tags: string[]; + websites: number[]; + transfer: any; + userId: number; + confirmPassword: string; + app: string; + defaultWebsites: number[]; +} diff --git a/src/user/user.controller.spec.ts b/src/user/user.controller.spec.ts index b2af3462..ff5fd987 100644 --- a/src/user/user.controller.spec.ts +++ b/src/user/user.controller.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { UserController } from './user.controller'; - -describe('User Controller', () => { - let controller: UserController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [UserController], - }).compile(); - - controller = module.get(UserController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { UserController } from "./user.controller"; + +describe("User Controller", () => { + let controller: UserController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [UserController], + }).compile(); + + controller = module.get(UserController); + }); + + it("should be defined", () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 23e57fe3..4914b228 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -1,362 +1,367 @@ -import { - Controller, - InternalServerErrorException, - Post, - Get, - Request, - Param, - UseGuards, - UnauthorizedException, - UseInterceptors, - Body, -} from "@nestjs/common"; -import { AuthGuard } from "@nestjs/passport"; -import { UserService } from "./user.service"; -import { User } from "./user.entity"; -import { generatePasswordHash, createRandomUniqueHash } from "../lib/security"; -import { success } from "../lib/response"; -import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiTags, ApiResponse, ApiOperation } from "@nestjs/swagger"; -import { CreateUserDto } from "./dto/create-user.dto"; -import { UpdateUserDto } from "./dto/update-user.dto"; -import { DeleteUserDto } from "./dto/delete-user.dto"; - -@ApiBasicAuth() -@ApiTags('tag') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller("user") -@UseInterceptors(LoggingInterceptor) -export class UserController { - constructor(private readonly userService: UserService) {} - - @ApiOperation({ summary: 'Change user password' }) - @ApiResponse({ - status: 200, - description: 'The password was changed', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt")) - @Post("changePassword") - async changeUserPassword(@Request() req: any): Promise { - if (!this.passwordValidator(req.body.newPassword)) { - throw new InternalServerErrorException(); - } - - const password = req.body.password; - const newPassword = req.body.newPassword; - const confirmNewPassword = req.body.confirmPassword; - - if (newPassword !== confirmNewPassword) { - throw new UnauthorizedException(); - } - - return success( - !!(await this.userService.changePassword( - req.user.userId, - password, - newPassword - )) - ); - } - - private passwordValidator(password: string): boolean { - const isShort = password.length < 8 || password.length === 0; - - const hasUpperCase = password.toLowerCase() !== password; - - const hasLowerCase = password.toUpperCase() !== password; - - const specialFormat = /[ `!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/; - const hasSpecial = specialFormat.test(password); - - const numberFormat = /\d/g; - const hasNumber = numberFormat.test(password); - - if ( - isShort || - !hasUpperCase || - !hasLowerCase || - !hasNumber || - !hasSpecial - ) { - return false; - } - - return true; - } - - - @ApiOperation({ summary: 'Create user' }) - @ApiResponse({ - status: 200, - description: 'A new user was created', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("create") - async createUser(@Body() createUserDto: CreateUserDto): Promise { - if (!this.passwordValidator(createUserDto.password)) { - throw new InternalServerErrorException(); - } - - const user = new User(); - user.Username = createUserDto.username; - user.Password = await generatePasswordHash(createUserDto.password); - user.Names = createUserDto.names; - user.Emails = createUserDto.emails; - user.Type = createUserDto.type; - user.Register_Date = new Date(); - user.Unique_Hash = createRandomUniqueHash(); - - const tags = createUserDto.tags; - const websites = createUserDto.websites; - const transfer = !!createUserDto.transfer; - - const createSuccess = await this.userService.createOne( - user, - tags, - websites, - transfer - ); - if (!createSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Update user' }) - @ApiResponse({ - status: 200, - description: 'The user was updated', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("update") - async updateUser(@Body() updateUserDto: UpdateUserDto): Promise { - const userId = updateUserDto.userId; - const password = updateUserDto.password; - const confirmPassword = updateUserDto.confirmPassword;//FIXME - - if (password && confirmPassword && !this.passwordValidator(password)) { - throw new InternalServerErrorException(); - } - - if (password !== confirmPassword) { - return success(false); - } - - const names = updateUserDto.names; - const emails = updateUserDto.emails; - const app = updateUserDto.app; - - const websites = this.convertToNumberArray(updateUserDto.websites); - const defaultWebsites = this.convertToNumberArray(updateUserDto.defaultWebsites); - const transfer = !!updateUserDto.transfer; - - const updateSuccess = await this.userService.update( - userId, - password, - names, - emails, - app, - defaultWebsites, - websites, - transfer - ); - if (!updateSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - private convertToNumberArray(str: any): number[] { - if (typeof str === "string") { - // remove first and last character - str = str.substring(1, str.length - 1); - return str.split(",").map((x) => +x); - } else { - return str; - } - } - - @ApiOperation({ summary: 'Delete user' }) - @ApiResponse({ - status: 200, - description: 'The user was deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("delete") - async deleteUser(@Body() deleteUserDto: DeleteUserDto): Promise { - const userId = deleteUserDto.userId; - const app = deleteUserDto.app; - - const deleteSuccess = await this.userService.delete(userId, app); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Find user by id' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("get/:id") - getUser(@Param("id") id: string): Promise { - return this.userService.findById(id); - } - - @ApiOperation({ summary: 'Find user info by id' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("info/:userId") - async getUserInfo(@Param("userId") userId: number): Promise { - return success(await this.userService.findInfo(userId)); - } - - @ApiOperation({ summary: 'Check if user exists by id' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("exists/:username") - async checkIfUsernameExists( - @Param("username") username: string - ): Promise { - return success(!!(await this.userService.findByUsername(username))); - } - - @ApiOperation({ summary: 'Find all users AMS' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("all") - async getAllNonAdminUsers(): Promise { - return success(await this.userService.findAll()); - } - - - @ApiOperation({ summary: 'Find all users MyMonitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("myMonitor") - async getAllMyMonitorUsers(): Promise { - return success(await this.userService.findAllFromMyMonitor()); - } - - @ApiOperation({ summary: 'Find total users Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("studyMonitor/total") - async getNumberOfStudyMonitorUsers(): Promise { - return success(await this.userService.findNumberOfStudyMonitor()); - } - - @ApiOperation({ summary: 'Find total users My Monitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("myMonitor/total") - async getNumberOfMyMonitorUsers(): Promise { - return success(await this.userService.findNumberOfMyMonitor()); - } - - @ApiOperation({ summary: 'Check if tag name exists' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("tag/nameExists/:name") - async checkIfUserTagNameExists( - @Request() req: any, - @Param("name") name: string - ): Promise { - if (name) { - return success( - !!(await this.userService.findStudyMonitorUserTagByName( - req.user.userId, - name - )) - ); - } else { - return success(false); - } - } - - @ApiOperation({ summary: 'Find user type' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("type/:user") - async getUserType(@Param("user") user: string): Promise { - if (user) { - return success(await this.userService.findType(user)); - } else { - return success(null); - } - } - - @ApiOperation({ summary: 'Find websites by user' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("websites/:user") - async getListOfUserWebsites(@Param("user") user: string): Promise { - if (user) { - return success(await this.userService.findAllWebsites(user)); - } else { - throw new InternalServerErrorException(); - } - } - - @ApiOperation({ summary: 'Find tags by user' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("tags/:user") - async getListOfUserTags(@Param("user") user: string): Promise { - if (user) { - return success(await this.userService.findAllTags(user)); - } else { - throw new InternalServerErrorException(); - } - } -} +import { + Controller, + InternalServerErrorException, + Post, + Get, + Request, + Param, + UseGuards, + UnauthorizedException, + UseInterceptors, + Body, +} from "@nestjs/common"; +import { AuthGuard } from "@nestjs/passport"; +import { UserService } from "./user.service"; +import { User } from "./user.entity"; +import { generatePasswordHash, createRandomUniqueHash } from "../lib/security"; +import { success } from "../lib/response"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { + ApiBasicAuth, + ApiTags, + ApiResponse, + ApiOperation, +} from "@nestjs/swagger"; +import { CreateUserDto } from "./dto/create-user.dto"; +import { UpdateUserDto } from "./dto/update-user.dto"; +import { DeleteUserDto } from "./dto/delete-user.dto"; + +@ApiBasicAuth() +@ApiTags("tag") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("user") +@UseInterceptors(LoggingInterceptor) +export class UserController { + constructor(private readonly userService: UserService) {} + + @ApiOperation({ summary: "Change user password" }) + @ApiResponse({ + status: 200, + description: "The password was changed", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt")) + @Post("changePassword") + async changeUserPassword(@Request() req: any): Promise { + if (!this.passwordValidator(req.body.newPassword)) { + throw new InternalServerErrorException(); + } + + const password = req.body.password; + const newPassword = req.body.newPassword; + const confirmNewPassword = req.body.confirmPassword; + + if (newPassword !== confirmNewPassword) { + throw new UnauthorizedException(); + } + + return success( + !!(await this.userService.changePassword( + req.user.userId, + password, + newPassword + )) + ); + } + + private passwordValidator(password: string): boolean { + const isShort = password.length < 8 || password.length === 0; + + const hasUpperCase = password.toLowerCase() !== password; + + const hasLowerCase = password.toUpperCase() !== password; + + const specialFormat = /[ `!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/; + const hasSpecial = specialFormat.test(password); + + const numberFormat = /\d/g; + const hasNumber = numberFormat.test(password); + + if ( + isShort || + !hasUpperCase || + !hasLowerCase || + !hasNumber || + !hasSpecial + ) { + return false; + } + + return true; + } + + @ApiOperation({ summary: "Create user" }) + @ApiResponse({ + status: 200, + description: "A new user was created", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("create") + async createUser(@Body() createUserDto: CreateUserDto): Promise { + if (!this.passwordValidator(createUserDto.password)) { + throw new InternalServerErrorException(); + } + + const user = new User(); + user.Username = createUserDto.username; + user.Password = await generatePasswordHash(createUserDto.password); + user.Names = createUserDto.names; + user.Emails = createUserDto.emails; + user.Type = createUserDto.type; + user.Register_Date = new Date(); + user.Unique_Hash = createRandomUniqueHash(); + + const tags = createUserDto.tags; + const websites = createUserDto.websites; + const transfer = !!createUserDto.transfer; + + const createSuccess = await this.userService.createOne( + user, + tags, + websites, + transfer + ); + if (!createSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Update user" }) + @ApiResponse({ + status: 200, + description: "The user was updated", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("update") + async updateUser(@Body() updateUserDto: UpdateUserDto): Promise { + const userId = updateUserDto.userId; + const password = updateUserDto.password; + const confirmPassword = updateUserDto.confirmPassword; //FIXME + + if (password && confirmPassword && !this.passwordValidator(password)) { + throw new InternalServerErrorException(); + } + + if (password !== confirmPassword) { + return success(false); + } + + const names = updateUserDto.names; + const emails = updateUserDto.emails; + const app = updateUserDto.app; + + const websites = this.convertToNumberArray(updateUserDto.websites); + const defaultWebsites = this.convertToNumberArray( + updateUserDto.defaultWebsites + ); + const transfer = !!updateUserDto.transfer; + + const updateSuccess = await this.userService.update( + userId, + password, + names, + emails, + app, + defaultWebsites, + websites, + transfer + ); + if (!updateSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + private convertToNumberArray(str: any): number[] { + if (typeof str === "string") { + // remove first and last character + str = str.substring(1, str.length - 1); + return str.split(",").map((x) => +x); + } else { + return str; + } + } + + @ApiOperation({ summary: "Delete user" }) + @ApiResponse({ + status: 200, + description: "The user was deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("delete") + async deleteUser(@Body() deleteUserDto: DeleteUserDto): Promise { + const userId = deleteUserDto.userId; + const app = deleteUserDto.app; + + const deleteSuccess = await this.userService.delete(userId, app); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Find user by id" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("get/:id") + getUser(@Param("id") id: string): Promise { + return this.userService.findById(id); + } + + @ApiOperation({ summary: "Find user info by id" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("info/:userId") + async getUserInfo(@Param("userId") userId: number): Promise { + return success(await this.userService.findInfo(userId)); + } + + @ApiOperation({ summary: "Check if user exists by id" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("exists/:username") + async checkIfUsernameExists( + @Param("username") username: string + ): Promise { + return success(!!(await this.userService.findByUsername(username))); + } + + @ApiOperation({ summary: "Find all users AMS" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("all") + async getAllNonAdminUsers(): Promise { + return success(await this.userService.findAll()); + } + + @ApiOperation({ summary: "Find all users MyMonitor" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("myMonitor") + async getAllMyMonitorUsers(): Promise { + return success(await this.userService.findAllFromMyMonitor()); + } + + @ApiOperation({ summary: "Find total users Study Monitor" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("studyMonitor/total") + async getNumberOfStudyMonitorUsers(): Promise { + return success(await this.userService.findNumberOfStudyMonitor()); + } + + @ApiOperation({ summary: "Find total users My Monitor" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("myMonitor/total") + async getNumberOfMyMonitorUsers(): Promise { + return success(await this.userService.findNumberOfMyMonitor()); + } + + @ApiOperation({ summary: "Check if tag name exists" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("tag/nameExists/:name") + async checkIfUserTagNameExists( + @Request() req: any, + @Param("name") name: string + ): Promise { + if (name) { + return success( + !!(await this.userService.findStudyMonitorUserTagByName( + req.user.userId, + name + )) + ); + } else { + return success(false); + } + } + + @ApiOperation({ summary: "Find user type" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("type/:user") + async getUserType(@Param("user") user: string): Promise { + if (user) { + return success(await this.userService.findType(user)); + } else { + return success(null); + } + } + + @ApiOperation({ summary: "Find websites by user" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("websites/:user") + async getListOfUserWebsites(@Param("user") user: string): Promise { + if (user) { + return success(await this.userService.findAllWebsites(user)); + } else { + throw new InternalServerErrorException(); + } + } + + @ApiOperation({ summary: "Find tags by user" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("tags/:user") + async getListOfUserTags(@Param("user") user: string): Promise { + if (user) { + return success(await this.userService.findAllTags(user)); + } else { + throw new InternalServerErrorException(); + } + } +} diff --git a/src/user/user.entity.ts b/src/user/user.entity.ts index ab811cbc..0d5516da 100644 --- a/src/user/user.entity.ts +++ b/src/user/user.entity.ts @@ -1,69 +1,68 @@ -import { GovUser } from 'src/gov-user/entities/gov-user.entity'; -import { Entity, Column, PrimaryGeneratedColumn, ManyToMany } from 'typeorm'; - -@Entity('User') -export class User { - - @PrimaryGeneratedColumn({ - type: 'int' - }) - UserId: number; - - @Column({ - type: 'varchar', - length: 255, - unique: true, - nullable: false - }) - Username: string; - - @Column({ - type: 'varchar', - length: 255, - nullable: false - }) - Password: string; - - @Column({ - type: 'varchar', - length: 45, - nullable: false - }) - Type: string; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Names: string; - - @Column({ - type: 'varchar', - length: 255, - nullable: true - }) - Emails: string; - - @Column({ - type: 'datetime', - nullable: false - }) - Register_Date: any; - - @Column({ - type: 'datetime', - nullable: true - }) - Last_Login: any; - - @Column({ - type: 'varchar', - length: 255, - nullable: false - }) - Unique_Hash: string; - - @ManyToMany((type) => GovUser, (govUser) => govUser.entities) - govUsers: User[]; -} \ No newline at end of file +import { GovUser } from "src/gov-user/entities/gov-user.entity"; +import { Entity, Column, PrimaryGeneratedColumn, ManyToMany } from "typeorm"; + +@Entity("User") +export class User { + @PrimaryGeneratedColumn({ + type: "int", + }) + UserId: number; + + @Column({ + type: "varchar", + length: 255, + unique: true, + nullable: false, + }) + Username: string; + + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + Password: string; + + @Column({ + type: "varchar", + length: 45, + nullable: false, + }) + Type: string; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Names: string; + + @Column({ + type: "varchar", + length: 255, + nullable: true, + }) + Emails: string; + + @Column({ + type: "datetime", + nullable: false, + }) + Register_Date: any; + + @Column({ + type: "datetime", + nullable: true, + }) + Last_Login: any; + + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + Unique_Hash: string; + + @ManyToMany((type) => GovUser, (govUser) => govUser.entities) + govUsers: User[]; +} diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 2e272e30..dada3ae7 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -1,14 +1,14 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { UserService } from './user.service'; -import { UserController } from './user.controller'; -import { User } from './user.entity'; -import { Tag } from '../tag/tag.entity'; - -@Module({ - imports: [TypeOrmModule.forFeature([User, Tag])], - exports: [UserService], - providers: [UserService], - controllers: [UserController] -}) -export class UserModule {} +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { UserService } from "./user.service"; +import { UserController } from "./user.controller"; +import { User } from "./user.entity"; +import { Tag } from "../tag/tag.entity"; + +@Module({ + imports: [TypeOrmModule.forFeature([User, Tag])], + exports: [UserService], + providers: [UserService], + controllers: [UserController], +}) +export class UserModule {} diff --git a/src/user/user.service.spec.ts b/src/user/user.service.spec.ts index 2cdfb800..b7433eaf 100644 --- a/src/user/user.service.spec.ts +++ b/src/user/user.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { UserService } from './user.service'; - -describe('UserService', () => { - let service: UserService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [UserService], - }).compile(); - - service = module.get(UserService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { UserService } from "./user.service"; + +describe("UserService", () => { + let service: UserService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [UserService], + }).compile(); + + service = module.get(UserService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 0aacab3f..343e5953 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -1,521 +1,520 @@ -import { - Injectable, - UnauthorizedException, - InternalServerErrorException, -} from "@nestjs/common"; -import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; -import { Repository, In, DataSource } from "typeorm"; -import { User } from "./user.entity"; -import { Tag } from "../tag/tag.entity"; -import { Website } from "../website/website.entity"; -import { comparePasswordHash, generatePasswordHash } from "../lib/security"; - -@Injectable() -export class UserService { - constructor( - @InjectRepository(User) - private readonly userRepository: Repository, - @InjectRepository(Tag) - private readonly tagRepository: Repository, - @InjectDataSource() - private readonly connection: DataSource ) { } - - async changePassword( - userId: number, - password: string, - newPassword: string - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const user = await this.userRepository.findOne({ - where: { UserId: userId }, - }); - if (user && (await comparePasswordHash(password, user.Password))) { - const newPasswordHash = await generatePasswordHash(newPassword); - await queryRunner.manager.update( - User, - { UserId: userId }, - { Password: newPasswordHash } - ); - } else { - hasError = true; - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - console.log(err); - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - if (hasError) { - throw new UnauthorizedException(); - } - - return true; - } - - async update( - userId: number, - password: string, - names: string, - emails: string, - app: string, - defaultWebsites: number[], - websites: number[], - transfer: boolean - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.update( - User, - { UserId: userId }, - { Names: names, Emails: emails } - ); - - if (password && password !== "null") { - await queryRunner.manager.update( - User, - { UserId: userId }, - { Password: await generatePasswordHash(password) } - ); - } - - if (app === "monitor") { - for (const id of defaultWebsites || []) { - if (!websites.includes(id)) { - await queryRunner.manager.query( - ` - UPDATE - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - SET - p.Show_In = "101", - e.Show_To = "10" - WHERE - w.WebsiteId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In = "111" AND - e.PageId = p.PageId`, - [id] - ); - - await queryRunner.manager.query( - ` - UPDATE - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - SET - p.Show_In = "100", - e.Show_To = "10" - WHERE - w.WebsiteId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In = "110" AND - e.PageId = p.PageId`, - [id] - ); - - await queryRunner.manager.query( - ` - UPDATE - Website as w, - WebsitePage as wp, - Page as p, - Evaluation as e - SET - p.Show_In = "000", - e.Show_To = "10" - WHERE - w.WebsiteId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In = "010" AND - e.PageId = p.PageId`, - [id] - ); - - await queryRunner.manager.update( - Website, - { WebsiteId: id }, - { UserId: null } - ); - } - } - - for (const id of websites || []) { - if (!defaultWebsites.includes(id)) { - await queryRunner.manager.update( - Website, - { WebsiteId: id }, - { UserId: userId } - ); - - if (transfer) { - await queryRunner.manager.query( - `UPDATE Website as w, WebsitePage as wp, Page as p, Evaluation as e SET p.Show_In = "111", e.Show_To = "11" - WHERE - w.WebsiteId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In = "101" AND - e.PageId = p.PageId`, - [id] - ); - } - } - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - console.log(err); - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async delete(userId: number, app: string): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - if (app === "monitor") { - await queryRunner.manager.query( - ` - UPDATE - Website as w, - WebsitePage as wp, - Page as p - SET - p.Show_In = "101" - WHERE - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE "111"`, - [userId] - ); - - await queryRunner.manager.query( - ` - UPDATE - Website as w, - WebsitePage as wp, - Page as p - SET - p.Show_In = "100" - WHERE - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In = "110"`, - [userId] - ); - - await queryRunner.manager.query( - ` - UPDATE - Website as w, - WebsitePage as wp, - Page as p - SET - p.Show_In = "000" - WHERE - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In = "100"`, - [userId] - ); - - await queryRunner.manager.query( - `UPDATE Website SET UserId = NULL WHERE UserId = ?`, - [userId] - ); - } else { - await queryRunner.manager.query( - `DELETE FROM Tag WHERE UserId = ? AND TagId <> 0`, - [userId] - ); - await queryRunner.manager.query( - `DELETE FROM Website WHERE UserId = ? AND WebsiteId <> 0`, - [userId] - ); - } - - await queryRunner.manager.query(`DELETE FROM User WHERE UserId = ?`, [ - userId, - ]); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - console.log(err); - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async findAll(): Promise { - const users = await this.userRepository.query(` - SELECT - u.UserId, u.Username, u.Type, u.Register_Date, u.Last_Login, - COUNT(distinct w.WebsiteId) as Websites - FROM User as u - LEFT OUTER JOIN Website as w ON w.UserId = u.UserId - GROUP BY u.UserId`); - - return users; - } - - async findAllFromMyMonitor(): Promise { - return this.userRepository.find({ - select: ["UserId", "Username", "Type", "Register_Date", "Last_Login"], - where: { Type: "monitor" }, - }); - } - - async findInfo(userId: number): Promise { - const user = await this.userRepository.findOne({ - where: { UserId: userId }, - }); - - if (user) { - if (user.Type === "monitor") { - user["websites"] = await this.userRepository.query( - `SELECT * FROM Website WHERE UserId = ?`, - [userId] - ); - } - - delete user.Password; - delete user.Unique_Hash; - - return user; - } else { - throw new InternalServerErrorException(); - } - } - - findById(id: string): Promise { - return this.userRepository.findOne({ where: { UserId: +id } }); - } - - findByUsername(username: string): Promise { - return this.userRepository.findOne({ where: { Username:username } }); - } - - findNumberOfStudyMonitor(): Promise { - return this.userRepository.count({ where:{Type: "studies"} }); - } - - findNumberOfMyMonitor(): Promise { - return this.userRepository.count({ where: {Type: "monitor" }}); - } - - async findStudyMonitorUserTagByName( - userId: number, - name: string - ): Promise { - return await this.tagRepository.findOne({ - where: { Name: name, UserId: userId }, - }); - } - - async createOne( - user: User, - tags: string[], - websites: string[], - transfer: boolean - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const insertUser = await queryRunner.manager.save(user); - - if (user.Type === "monitor" && websites.length > 0) { - await queryRunner.manager.update( - Website, - { WebsiteId: In(websites) }, - { UserId: insertUser.UserId } - ); - - if (transfer) { - await queryRunner.manager.query( - `UPDATE Website as w, WebsitePage as wp, Page as p, Evaluation as e - SET - p.Show_In = "111", - e.Show_To = "11" - WHERE - w.WebsiteId IN (?) AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE "101" AND - e.PageId = p.PageId`, - [websites] - ); - } - } else if (user.Type === "studies" && tags.length > 0) { - const copyTags = await queryRunner.manager.query( - `SELECT * FROM Tag WHERE TagId IN (?)`, - [tags] - ); - for (const tag of copyTags || []) { - // Create user tag - const newTag = new Tag(); - newTag.Name = tag.Name; - newTag.UserId = insertUser.UserId; - newTag.Creation_Date = new Date(); - - const insertTag = await queryRunner.manager.save(newTag); - - // Create user tag websites - const copyWebsites = await queryRunner.manager.query( - ` - SELECT w.* - FROM - TagWebsite as tw, - Website as w - WHERE - tw.TagId = ? AND - w.WebsiteId = tw.WebsiteId - `, - [tag.TagId] - ); - - for (const website of copyWebsites || []) { - const newWebsite = new Website(); - newWebsite.Name = website.Name; - newWebsite.StartingUrl = website.StaringUrl; - newWebsite.UserId = insertUser.UserId; - newWebsite.Creation_Date = new Date(); - - const insertWebsite = await queryRunner.manager.save(newWebsite); - - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, - [insertTag.TagId, insertWebsite.WebsiteId] - ); - - // Create user tag website pages connection - const pages = await queryRunner.manager.query( - `SELECT * FROM WebsitePage WHERE WebsiteId = ?`, - [website[0].WebsiteId] - ); - - for (const page of pages || []) { - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, - [insertWebsite.WebsiteId, page.PageId] - ); - } - } - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - console.log(err); - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async findType(username: string): Promise { - if (username === "admin") { - return "nimda"; - } - - const user = await this.userRepository.findOne({ - where: { Username: username }, - }); - - if (user) { - return user.Type; - } else { - return null; - } - } - - async findAllWebsites(user: string): Promise { - - const websites = await this.userRepository.query( - `SELECT w.*, e.Short_Name as Entity, e.Long_Name as Entity2, u.Username as User - FROM - User as u, - EntityWebsite as ew - LEFT OUTER JOIN Website as w ON w.WebsiteId = ew.WebsiteId - LEFT OUTER JOIN Entity as e ON e.EntityId = ew.EntityId - WHERE - u.Username = ? AND - w.UserId = u.UserId - GROUP BY w.WebsiteId, w.StartingUrl`, - [user] - ); - - return websites; - } - - async findAllTags(user: string): Promise { - - const tags = await this.userRepository.query( - `SELECT t.*, COUNT(distinct tw.WebsiteId) as Websites, u.Username as User - FROM - User as u, - Tag as t - LEFT OUTER JOIN TagWebsite as tw ON tw.TagId = t.TagId - WHERE - u.Username = ? AND - t.UserId = u.UserId - GROUP BY t.TagId`, - [user] - ); - - return tags; - } -} +import { + Injectable, + UnauthorizedException, + InternalServerErrorException, +} from "@nestjs/common"; +import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; +import { Repository, In, DataSource } from "typeorm"; +import { User } from "./user.entity"; +import { Tag } from "../tag/tag.entity"; +import { Website } from "../website/website.entity"; +import { comparePasswordHash, generatePasswordHash } from "../lib/security"; + +@Injectable() +export class UserService { + constructor( + @InjectRepository(User) + private readonly userRepository: Repository, + @InjectRepository(Tag) + private readonly tagRepository: Repository, + @InjectDataSource() + private readonly connection: DataSource + ) {} + + async changePassword( + userId: number, + password: string, + newPassword: string + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const user = await this.userRepository.findOne({ + where: { UserId: userId }, + }); + if (user && (await comparePasswordHash(password, user.Password))) { + const newPasswordHash = await generatePasswordHash(newPassword); + await queryRunner.manager.update( + User, + { UserId: userId }, + { Password: newPasswordHash } + ); + } else { + hasError = true; + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + console.log(err); + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + if (hasError) { + throw new UnauthorizedException(); + } + + return true; + } + + async update( + userId: number, + password: string, + names: string, + emails: string, + app: string, + defaultWebsites: number[], + websites: number[], + transfer: boolean + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.update( + User, + { UserId: userId }, + { Names: names, Emails: emails } + ); + + if (password && password !== "null") { + await queryRunner.manager.update( + User, + { UserId: userId }, + { Password: await generatePasswordHash(password) } + ); + } + + if (app === "monitor") { + for (const id of defaultWebsites || []) { + if (!websites.includes(id)) { + await queryRunner.manager.query( + ` + UPDATE + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + SET + p.Show_In = "101", + e.Show_To = "10" + WHERE + w.WebsiteId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In = "111" AND + e.PageId = p.PageId`, + [id] + ); + + await queryRunner.manager.query( + ` + UPDATE + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + SET + p.Show_In = "100", + e.Show_To = "10" + WHERE + w.WebsiteId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In = "110" AND + e.PageId = p.PageId`, + [id] + ); + + await queryRunner.manager.query( + ` + UPDATE + Website as w, + WebsitePage as wp, + Page as p, + Evaluation as e + SET + p.Show_In = "000", + e.Show_To = "10" + WHERE + w.WebsiteId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In = "010" AND + e.PageId = p.PageId`, + [id] + ); + + await queryRunner.manager.update( + Website, + { WebsiteId: id }, + { UserId: null } + ); + } + } + + for (const id of websites || []) { + if (!defaultWebsites.includes(id)) { + await queryRunner.manager.update( + Website, + { WebsiteId: id }, + { UserId: userId } + ); + + if (transfer) { + await queryRunner.manager.query( + `UPDATE Website as w, WebsitePage as wp, Page as p, Evaluation as e SET p.Show_In = "111", e.Show_To = "11" + WHERE + w.WebsiteId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In = "101" AND + e.PageId = p.PageId`, + [id] + ); + } + } + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + console.log(err); + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async delete(userId: number, app: string): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + if (app === "monitor") { + await queryRunner.manager.query( + ` + UPDATE + Website as w, + WebsitePage as wp, + Page as p + SET + p.Show_In = "101" + WHERE + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE "111"`, + [userId] + ); + + await queryRunner.manager.query( + ` + UPDATE + Website as w, + WebsitePage as wp, + Page as p + SET + p.Show_In = "100" + WHERE + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In = "110"`, + [userId] + ); + + await queryRunner.manager.query( + ` + UPDATE + Website as w, + WebsitePage as wp, + Page as p + SET + p.Show_In = "000" + WHERE + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In = "100"`, + [userId] + ); + + await queryRunner.manager.query( + `UPDATE Website SET UserId = NULL WHERE UserId = ?`, + [userId] + ); + } else { + await queryRunner.manager.query( + `DELETE FROM Tag WHERE UserId = ? AND TagId <> 0`, + [userId] + ); + await queryRunner.manager.query( + `DELETE FROM Website WHERE UserId = ? AND WebsiteId <> 0`, + [userId] + ); + } + + await queryRunner.manager.query(`DELETE FROM User WHERE UserId = ?`, [ + userId, + ]); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + console.log(err); + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async findAll(): Promise { + const users = await this.userRepository.query(` + SELECT + u.UserId, u.Username, u.Type, u.Register_Date, u.Last_Login, + COUNT(distinct w.WebsiteId) as Websites + FROM User as u + LEFT OUTER JOIN Website as w ON w.UserId = u.UserId + GROUP BY u.UserId`); + + return users; + } + + async findAllFromMyMonitor(): Promise { + return this.userRepository.find({ + select: ["UserId", "Username", "Type", "Register_Date", "Last_Login"], + where: { Type: "monitor" }, + }); + } + + async findInfo(userId: number): Promise { + const user = await this.userRepository.findOne({ + where: { UserId: userId }, + }); + + if (user) { + if (user.Type === "monitor") { + user["websites"] = await this.userRepository.query( + `SELECT * FROM Website WHERE UserId = ?`, + [userId] + ); + } + + delete user.Password; + delete user.Unique_Hash; + + return user; + } else { + throw new InternalServerErrorException(); + } + } + + findById(id: string): Promise { + return this.userRepository.findOne({ where: { UserId: +id } }); + } + + findByUsername(username: string): Promise { + return this.userRepository.findOne({ where: { Username: username } }); + } + + findNumberOfStudyMonitor(): Promise { + return this.userRepository.count({ where: { Type: "studies" } }); + } + + findNumberOfMyMonitor(): Promise { + return this.userRepository.count({ where: { Type: "monitor" } }); + } + + async findStudyMonitorUserTagByName( + userId: number, + name: string + ): Promise { + return await this.tagRepository.findOne({ + where: { Name: name, UserId: userId }, + }); + } + + async createOne( + user: User, + tags: string[], + websites: string[], + transfer: boolean + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const insertUser = await queryRunner.manager.save(user); + + if (user.Type === "monitor" && websites.length > 0) { + await queryRunner.manager.update( + Website, + { WebsiteId: In(websites) }, + { UserId: insertUser.UserId } + ); + + if (transfer) { + await queryRunner.manager.query( + `UPDATE Website as w, WebsitePage as wp, Page as p, Evaluation as e + SET + p.Show_In = "111", + e.Show_To = "11" + WHERE + w.WebsiteId IN (?) AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE "101" AND + e.PageId = p.PageId`, + [websites] + ); + } + } else if (user.Type === "studies" && tags.length > 0) { + const copyTags = await queryRunner.manager.query( + `SELECT * FROM Tag WHERE TagId IN (?)`, + [tags] + ); + for (const tag of copyTags || []) { + // Create user tag + const newTag = new Tag(); + newTag.Name = tag.Name; + newTag.UserId = insertUser.UserId; + newTag.Creation_Date = new Date(); + + const insertTag = await queryRunner.manager.save(newTag); + + // Create user tag websites + const copyWebsites = await queryRunner.manager.query( + ` + SELECT w.* + FROM + TagWebsite as tw, + Website as w + WHERE + tw.TagId = ? AND + w.WebsiteId = tw.WebsiteId + `, + [tag.TagId] + ); + + for (const website of copyWebsites || []) { + const newWebsite = new Website(); + newWebsite.Name = website.Name; + newWebsite.StartingUrl = website.StaringUrl; + newWebsite.UserId = insertUser.UserId; + newWebsite.Creation_Date = new Date(); + + const insertWebsite = await queryRunner.manager.save(newWebsite); + + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, + [insertTag.TagId, insertWebsite.WebsiteId] + ); + + // Create user tag website pages connection + const pages = await queryRunner.manager.query( + `SELECT * FROM WebsitePage WHERE WebsiteId = ?`, + [website[0].WebsiteId] + ); + + for (const page of pages || []) { + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, + [insertWebsite.WebsiteId, page.PageId] + ); + } + } + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + console.log(err); + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async findType(username: string): Promise { + if (username === "admin") { + return "nimda"; + } + + const user = await this.userRepository.findOne({ + where: { Username: username }, + }); + + if (user) { + return user.Type; + } else { + return null; + } + } + + async findAllWebsites(user: string): Promise { + const websites = await this.userRepository.query( + `SELECT w.*, e.Short_Name as Entity, e.Long_Name as Entity2, u.Username as User + FROM + User as u, + EntityWebsite as ew + LEFT OUTER JOIN Website as w ON w.WebsiteId = ew.WebsiteId + LEFT OUTER JOIN Entity as e ON e.EntityId = ew.EntityId + WHERE + u.Username = ? AND + w.UserId = u.UserId + GROUP BY w.WebsiteId, w.StartingUrl`, + [user] + ); + + return websites; + } + + async findAllTags(user: string): Promise { + const tags = await this.userRepository.query( + `SELECT t.*, COUNT(distinct tw.WebsiteId) as Websites, u.Username as User + FROM + User as u, + Tag as t + LEFT OUTER JOIN TagWebsite as tw ON tw.TagId = t.TagId + WHERE + u.Username = ? AND + t.UserId = u.UserId + GROUP BY t.TagId`, + [user] + ); + + return tags; + } +} diff --git a/src/website/dto/create-website.dto.ts b/src/website/dto/create-website.dto.ts index b4acfec9..a9c3c2ab 100644 --- a/src/website/dto/create-website.dto.ts +++ b/src/website/dto/create-website.dto.ts @@ -1,27 +1,27 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsNotEmpty } from "class-validator"; export class CreateWebsiteDto { - websiteId: number; + websiteId: number; - @IsNotEmpty() - userId: number; + @IsNotEmpty() + userId: number; - @IsNotEmpty() - name: string; + @IsNotEmpty() + name: string; - @IsNotEmpty() - startingUrl: string; + @IsNotEmpty() + startingUrl: string; - declaration: number; + declaration: number; - declaration_Update_Date: any; + declaration_Update_Date: any; - stamp: number; + stamp: number; - stamp_Update_Date: any; + stamp_Update_Date: any; - creation_Date: any; + creation_Date: any; - entities: string[]; + entities: string[]; - tags: string[]; -} \ No newline at end of file + tags: string[]; +} diff --git a/src/website/dto/delete-bulk-website.dto.ts b/src/website/dto/delete-bulk-website.dto.ts index c69aeae6..a63cf697 100644 --- a/src/website/dto/delete-bulk-website.dto.ts +++ b/src/website/dto/delete-bulk-website.dto.ts @@ -1,4 +1,3 @@ export class DeleteBulkWebsiteDto { - - websitesId: number[]; -} \ No newline at end of file + websitesId: number[]; +} diff --git a/src/website/dto/delete-website.dto.ts b/src/website/dto/delete-website.dto.ts index 31cedd41..59eb4af9 100644 --- a/src/website/dto/delete-website.dto.ts +++ b/src/website/dto/delete-website.dto.ts @@ -1,4 +1,3 @@ export class DeleteWebsiteDto { - - websiteId: number; -} \ No newline at end of file + websiteId: number; +} diff --git a/src/website/dto/import-website-my-monitor.dto.ts b/src/website/dto/import-website-my-monitor.dto.ts index 122ab5b3..82e3da49 100644 --- a/src/website/dto/import-website-my-monitor.dto.ts +++ b/src/website/dto/import-website-my-monitor.dto.ts @@ -1,6 +1,6 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsNotEmpty } from "class-validator"; export class ImportWebsiteMyMonitorDto { - @IsNotEmpty() - websiteId: number; - newWebsiteName: string -} \ No newline at end of file + @IsNotEmpty() + websiteId: number; + newWebsiteName: string; +} diff --git a/src/website/dto/update-observatory-pages.dto.ts b/src/website/dto/update-observatory-pages.dto.ts index 5e756707..051db4bd 100644 --- a/src/website/dto/update-observatory-pages.dto.ts +++ b/src/website/dto/update-observatory-pages.dto.ts @@ -1,13 +1,10 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsNotEmpty } from "class-validator"; export class UpdateObservatoryPages { - @IsNotEmpty() - pages: ObservatoryPage[]; - + @IsNotEmpty() + pages: ObservatoryPage[]; } export class ObservatoryPage { - id:number; - inObservatory:boolean; - + id: number; + inObservatory: boolean; } - diff --git a/src/website/dto/update-website.dto.ts b/src/website/dto/update-website.dto.ts index 22d2d96f..337b4490 100644 --- a/src/website/dto/update-website.dto.ts +++ b/src/website/dto/update-website.dto.ts @@ -1,38 +1,37 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsNotEmpty } from "class-validator"; export class UpdateWebsiteDto { - @IsNotEmpty() - websiteId: number; + @IsNotEmpty() + websiteId: number; - @IsNotEmpty() - userId: number; + @IsNotEmpty() + userId: number; - @IsNotEmpty() - oldUserId: number; + @IsNotEmpty() + oldUserId: number; - @IsNotEmpty() - name: string; + @IsNotEmpty() + name: string; - @IsNotEmpty() - startingUrl: string; + @IsNotEmpty() + startingUrl: string; - declaration: number; + declaration: number; - stamp: number; + stamp: number; - declarationUpdateDate: any; + declarationUpdateDate: any; - stampUpdateDate: any; + stampUpdateDate: any; + creation_Date: any; - creation_Date: any; + entities: number[]; - entities: number[]; + tags: number[]; - tags: number[]; + transfer: boolean; - transfer: boolean; + defaultEntities: number[]; - defaultEntities: number[]; - - defaultTags: number[]; -} \ No newline at end of file + defaultTags: number[]; +} diff --git a/src/website/dto/website-my-monitor.dto.ts b/src/website/dto/website-my-monitor.dto.ts index 93690bda..53b28178 100644 --- a/src/website/dto/website-my-monitor.dto.ts +++ b/src/website/dto/website-my-monitor.dto.ts @@ -1,6 +1,6 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsNotEmpty } from "class-validator"; export class WebsiteMyMonitorDto { - @IsNotEmpty() - website: string; - userId: number; -} \ No newline at end of file + @IsNotEmpty() + website: string; + userId: number; +} diff --git a/src/website/dto/websites-id.dto.ts b/src/website/dto/websites-id.dto.ts index 01a81ad9..8f0e0c62 100644 --- a/src/website/dto/websites-id.dto.ts +++ b/src/website/dto/websites-id.dto.ts @@ -1,9 +1,8 @@ -import { IsNotEmpty } from 'class-validator'; +import { IsNotEmpty } from "class-validator"; export class WebsitesIdDto { - @IsNotEmpty() - websitesId: number[]; + @IsNotEmpty() + websitesId: number[]; - @IsNotEmpty() - option: string; - -} \ No newline at end of file + @IsNotEmpty() + option: string; +} diff --git a/src/website/website.controller.spec.ts b/src/website/website.controller.spec.ts index 64c10d5b..e266b4c4 100644 --- a/src/website/website.controller.spec.ts +++ b/src/website/website.controller.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { WebsiteController } from './website.controller'; - -describe('Website Controller', () => { - let controller: WebsiteController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [WebsiteController], - }).compile(); - - controller = module.get(WebsiteController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { WebsiteController } from "./website.controller"; + +describe("Website Controller", () => { + let controller: WebsiteController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [WebsiteController], + }).compile(); + + controller = module.get(WebsiteController); + }); + + it("should be defined", () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/website/website.controller.ts b/src/website/website.controller.ts index 25fda69a..3fd655c7 100644 --- a/src/website/website.controller.ts +++ b/src/website/website.controller.ts @@ -1,672 +1,726 @@ -import { - Controller, - InternalServerErrorException, - Request, - Get, - Post, - UseGuards, - Param, - UseInterceptors, - Body, - Delete, -} from "@nestjs/common"; -import { AuthGuard } from "@nestjs/passport"; -import { WebsiteService } from "./website.service"; -import { Website } from "./website.entity"; -import { success } from "../lib/response"; -import { LoggingInterceptor } from "src/log/log.interceptor"; -import { ApiBasicAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger"; -import { WebsitesIdDto } from "./dto/websites-id.dto"; -import { CreateWebsiteDto } from "./dto/create-website.dto"; -import { UpdateWebsiteDto } from "./dto/update-website.dto"; -import { UpdateObservatoryPages } from "./dto/update-observatory-pages.dto"; -import { DeleteWebsiteDto } from "./dto/delete-website.dto"; -import { DeleteBulkWebsiteDto } from "./dto/delete-bulk-website.dto"; -import { ImportWebsiteMyMonitorDto } from "./dto/import-website-my-monitor.dto"; -import { Page } from "src/page/page.entity"; -import { WebsiteMyMonitorDto } from "./dto/website-my-monitor.dto"; - -@ApiBasicAuth() -@ApiTags('website') -@ApiResponse({ status: 403, description: 'Forbidden' }) -@Controller("website") -@UseInterceptors(LoggingInterceptor) -export class WebsiteController { - constructor(private readonly websiteService: WebsiteService) {} - - @ApiOperation({ summary: 'Reevaluate all pages from website' }) - @ApiResponse({ - status: 200, - description: 'The evaluation request has been submited', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("accessibility-statement/update") - async accessibilityStatementUpdate(): Promise { - return success( - await this.websiteService.findAccessiblityStatements()); - } - - - @UseGuards(AuthGuard("jwt-admin")) - @Post("accessibility-statement/update/:id") - async accessibilityStatementUpdateById(@Param('id') id: number): Promise { - await this.websiteService.updateAStatement(id); - return success(true); - } - - @UseGuards(AuthGuard("jwt-admin")) - @Post("reEvaluate") - async reEvaluateWebsitePages(@Body() websitesIdDto: WebsitesIdDto): Promise { - return success( - await this.websiteService.addPagesToEvaluate(websitesIdDto.websitesId, websitesIdDto.option) - ); - } - - @ApiOperation({ summary: 'Create website' }) - @ApiResponse({ - status: 200, - description: 'The website has been created', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("create") - async createWebsite(@Body() websiteDto: CreateWebsiteDto): Promise { - - const createSuccess = await this.websiteService.createOne( - websiteDto, - websiteDto.entities, - websiteDto.tags - ); - if (!createSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - - @ApiOperation({ summary: 'Update website' }) - @ApiResponse({ - status: 200, - description: 'The website has been updated', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("update") - async updateWebsite(@Body() updateWebsiteDto: UpdateWebsiteDto): Promise { - - const updateSuccess = await this.websiteService.update( - updateWebsiteDto - ); - if (!updateSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Update pages in the observatory' }) - @ApiResponse({ - status: 200, - description: 'The pages in the observatory have been updated', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("pages/updateObservatory") - async updateWebsitePagesObservatory(@Body() updateObservatoryPages: UpdateObservatoryPages): Promise { - return success( - await this.websiteService.updatePagesObservatory(updateObservatoryPages) - ); - } - - @ApiOperation({ summary: 'Delete websites' }) - @ApiResponse({ - status: 200, - description: 'The website list has been deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("deleteBulk") - async deleteWebsites(@Body() deleteBulkWebsiteDto: DeleteBulkWebsiteDto): Promise { - const deleteSuccess = await this.websiteService.deleteBulk(deleteBulkWebsiteDto.websitesId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Delete website' }) - @ApiResponse({ - status: 200, - description: 'The website has been deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post('delete') - async deleteWebsite(@Body() deleteWebsiteDto: DeleteWebsiteDto): Promise { - - const deleteSuccess = await this.websiteService.delete(deleteWebsiteDto.websiteId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Finds a website, by the starting URL, from the current user' }) - @ApiResponse({ - status: 200, - description: 'The website has been found', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Get("myMonitor/url/:website") - async getMyMonitorUserWebsiteDomain( - @Request() req: any, - @Param("website") website: string - ): Promise { - return success( - await this.websiteService.findMyMonitorUserWebsiteStartingUrl( - req.user.userId, - website - ) - ); - } - - @ApiOperation({ summary: 'Deletes all pages from a list of websites' }) - @ApiResponse({ - status: 200, - description: 'The selected pages have been deleted', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("pages/deleteBulk") - async deleteWebsitesaPages(@Body() deleteBulkWebsiteDto: DeleteBulkWebsiteDto): Promise { - const deleteSuccess = await this.websiteService.pagesDeleteBulk(deleteBulkWebsiteDto.websitesId); - if (!deleteSuccess) { - throw new InternalServerErrorException(); - } - - return success(true); - } - - @ApiOperation({ summary: 'Imports a website from MyMonitor' }) - @ApiResponse({ - status: 200, - description: 'The selected website has been imported', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Post("import") - async importWebsiteFromMyMonitor(@Body() importWebsiteMyMonitorDto: ImportWebsiteMyMonitorDto): Promise { - const websiteId = importWebsiteMyMonitorDto.websiteId; - const websiteName = importWebsiteMyMonitorDto.newWebsiteName; - - return success(await this.websiteService.import(websiteId, websiteName)); - } - - @ApiOperation({ summary: 'Calculates the number of websites in AMS filtered by search string' }) - @ApiResponse({ - status: 200, - description: ' The number of websites in AMS filtered by search string', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("all/count/:search") - async getAdminWebsiteCount(@Param("search") search: string): Promise { - return success( - await this.websiteService.adminCount( - decodeURIComponent(search.substring(7)) - ) - ); - } - - @ApiOperation({ summary: 'Finds websites in AMS filtered by search string, size, sort and direction' }) - @ApiResponse({ - status: 200, - description: ' The websites in AMS filtered by search string, size, sort and direction', - type: Array, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("all/:size/:page/:sort/:direction/:search") - async getAllWebsites( - @Param("size") size: string, - @Param("page") page: string, - @Param("sort") sort: string, - @Param("direction") direction: string, - @Param("search") search: string - ): Promise { - return success( - await this.websiteService.findAll( - parseInt(size), - parseInt(page), - sort.substring(5), - direction.substring(10), - decodeURIComponent(search.substring(7)) - ) - ); - } - - @ApiOperation({ summary: 'Find website information by id' }) - @ApiResponse({ - status: 200, - description: ' The specific website information', - type: Website, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("info/:websiteId") - async getWebsiteInfo(@Param("websiteId") websiteId: number): Promise { - return success(await this.websiteService.findInfo(websiteId)); - } - - @ApiOperation({ summary: 'Find website by user and name' }) - @ApiResponse({ - status: 200, - description: ' The specific website', - type: Website, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get(":website/user/:user/pages") - async getAllWebsiteDomains( - @Param("website") website: string, - @Param("user") user: string - ): Promise { - const websiteId = await this.websiteService.getIdFromUserAndName( - user, - website - ); - - return success(await this.websiteService.findAllPages(websiteId)); - } - - @ApiOperation({ summary: 'Finds all website data to build a csv' }) - @ApiResponse({ - status: 200, - description: ' All the webiste data', - type: Website, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("csv") - async getAllWebsiteCSVData(): Promise { - return success(await this.websiteService.getAllWebsiteDataCSV()); - } - - @ApiOperation({ summary: 'Finds all pages from a website by id' }) - @ApiResponse({ - status: 200, - description: ' All pages from the specific website', - type: Array, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("pages/:websiteId") - async getAllWebsitePages( - @Param("websiteId") websiteId: number - ): Promise { - return success(await this.websiteService.findAllPages(websiteId)); - } - - @ApiOperation({ summary: 'Finds all websites excluding Study Monitor websites' }) - @ApiResponse({ - status: 200, - description: 'The list of websites', - type: Array, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("official") - async getAllOfficialWebsites(): Promise { - return success(await this.websiteService.findAllOfficial()); - } - - @ApiOperation({ summary: 'Finds all websites without user' }) - @ApiResponse({ - status: 200, - description: 'The list of websites', - type: Array, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("withoutUser") - async getWebsitesWithoutUser(): Promise { - return success(await this.websiteService.findAllWithoutUser()); - } - - @ApiOperation({ summary: 'Finds all websites without entity' }) - @ApiResponse({ - status: 200, - description: 'The list of websites', - type: Array, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("withoutEntity") - async getWebsitesWithoutEntity(): Promise { - return success(await this.websiteService.findAllWithoutEntity()); - } - - @ApiOperation({ summary: 'Finds the number of websites in study monitor' }) - @ApiResponse({ - status: 200, - description: 'The number of websites', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("studyMonitor/total") - async getNumberOfStudyMonitorWebsites(): Promise { - return success(await this.websiteService.findNumberOfStudyMonitor()); - } - - @ApiOperation({ summary: 'Finds the number of websites in my monitor' }) - @ApiResponse({ - status: 200, - description: 'The number of websites', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("myMonitor/total") - async getNumberOfMyMonitorWebsites(): Promise { - return success(await this.websiteService.findNumberOfMyMonitor()); - } - - @ApiOperation({ summary: 'Finds the number of websites in observatory' }) - @ApiResponse({ - status: 200, - description: 'The number of websites', - type: Number, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("observatory/total") - async getNumberOfObservatoryWebsites(): Promise { - return success(await this.websiteService.findNumberOfObservatory()); - } - - @ApiOperation({ summary: 'Check if website exists by name' }) - @ApiResponse({ - status: 200, - description: 'The specific website', - type: Website, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("exists/:name") - async checkIfWebsiteExists(@Param("name") name: string): Promise { - return success(!!(await this.websiteService.findByOfficialName(name))); - } - - @ApiOperation({ summary: 'Check if website exists by starting url' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-admin")) - @Get("exists/url/:url") - async checkIfWebsiteUrlExists(@Param("url") url: string): Promise { - return success( - !!(await this.websiteService.existsUrl(decodeURIComponent(url))) - ); - } - - @ApiOperation({ summary: 'Check if website is in observatory' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Post("isInObservatory") - async checkIfIsInObservatory(websiteMyMonitorDto: WebsiteMyMonitorDto): Promise { - return success( - await this.websiteService.isInObservatory( - websiteMyMonitorDto.userId, - websiteMyMonitorDto.website - ) - ); - } - - @ApiOperation({ summary: 'Transfers observatory pages from a specific website to a specific user' }) - @ApiResponse({ - status: 200, - description: 'The transfer was a success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Post("transferObservatoryPages") - async transferObservatoryPages(@Request() req: any, @Body() websiteMyMonitorDto: WebsiteMyMonitorDto): Promise { - return success( - await this.websiteService.transferObservatoryPages( - req.user.userId, - websiteMyMonitorDto.website - ) - ); - } - - @ApiOperation({ summary: 'Finds all websites from a specific user' }) - @ApiResponse({ - status: 200, - description: 'The list of websites', - type: Array, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Get("myMonitor") - async getMyMonitorUserWebsites(@Request() req: any): Promise { - return success( - await this.websiteService.findAllFromMyMonitorUser(req.user.userId) - ); - } - - @ApiOperation({ summary: 'Reevalute all pages from a specific website in My Monitor' }) - @ApiResponse({ - status: 200, - description: 'The page evaluation was submited', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-monitor")) - @Post("myMonitor/reEvaluate") - async reEvaluateMyMonitorUserWebsitePages(websiteMyMonitorDto: WebsiteMyMonitorDto): Promise { - const userId = websiteMyMonitorDto.userId; - const website = websiteMyMonitorDto.website; - - return success( - await this.websiteService.reEvaluateMyMonitorWebsite(userId, website) - ); - } - - @ApiOperation({ summary: 'Reevalute all pages from a specific website in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'The page evaluation was submited', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("studyMonitor/reEvaluate") - async reEvaluateStudyMonitorUserTagWebsitePages( - @Request() req: any - ): Promise { - const userId = req.user.userId; - const tag = req.body.tag; - const website = req.body.website; - - return success( - await this.websiteService.reEvaluateStudyMonitorWebsite( - userId, - tag, - website - ) - ); - } - - @ApiOperation({ summary: 'Find all websites from a specific user and tag in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'The website list', - type: Array, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("studyMonitor/tag/:tag") - async getStudyMonitorUserTagWebsites( - @Request() req: any, - @Param("tag") tag: string - ): Promise { - const userId = req.user.userId; - return success( - await this.websiteService.findAllFromStudyMonitorUserTag(userId, tag) - ); - } - - @ApiOperation({ summary: 'Find all websites from a specific user and tag in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'The website list', - type: Array, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("studyMonitor/otherTags/:tag") - async getStudyMonitorUserOtherTagsWebsites( - @Request() req: any, - @Param("tag") tag: string - ): Promise { - const userId = req.user.userId; - return success( - await this.websiteService.findAllFromStudyMonitorUserOtherTagsWebsites( - userId, - tag - ) - ); - } - - @ApiOperation({ summary: 'Find all websites from a specific user and tag in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'The website list', - type: Array, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("studyMonitor/tag/:tag/website/nameExists/:website") - async checkIfStudyMonitorUserTagWebsiteNameExists( - @Request() req: any, - @Param("tag") tag: string, - @Param("website") website: string - ): Promise { - const userId = req.user.userId; - return success( - !!(await this.websiteService.findStudyMonitorUserTagWebsiteByName( - userId, - tag, - website - )) - ); - } - - @ApiOperation({ summary: 'Check if website exists in specific tag in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Array, - }) - @UseGuards(AuthGuard("jwt-study")) - @Get("studyMonitor/tag/:tag/websiteExists/:startingUrl") - async checkIfStudyMonitorUserTagWebsiteExists( - @Request() req: any, - @Param("tag") tag: string, - @Param("startingUrl") startingUrl: string - ): Promise { - const userId = req.user.userId; - return success( - !!(await this.websiteService.findStudyMonitorUserTagWebsiteByStartingUrl( - userId, - tag, - startingUrl - )) - ); - } - - - @ApiOperation({ summary: 'Link a website to a tag in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Array, - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("studyMonitor/link") - async linkStudyMonitorUserTagWebsite(@Request() req: any): Promise { - const userId = req.user.userId; - const tag = req.body.tag; - const websitesId = JSON.parse(req.body.websitesId); - - const linkSuccess = - await this.websiteService.linkStudyMonitorUserTagWebsite( - userId, - tag, - websitesId - ); - if (!linkSuccess) { - throw new InternalServerErrorException(); - } - - return success( - await this.websiteService.findAllFromStudyMonitorUserTag(userId, tag) - ); - } - - @ApiOperation({ summary: 'Create a website in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Website - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("studyMonitor/create") - async createStudyMonitorUserTagWebsite(@Request() req: any): Promise { - const userId = req.user.userId; - const tag = req.body.tag; - const websiteName = req.body.name; - const startingUrl = decodeURIComponent(req.body.startingUrl); - const pages = JSON.parse(req.body.pages).map((page: string) => - decodeURIComponent(page) - ); - - const createSuccess = - await this.websiteService.createStudyMonitorUserTagWebsite( - userId, - tag, - websiteName, - startingUrl, - pages - ); - if (!createSuccess) { - throw new InternalServerErrorException(); - } - - return success( - await this.websiteService.findAllFromStudyMonitorUserTag(userId, tag) - ); - } - - @ApiOperation({ summary: 'Remove a website to a tag in Study Monitor' }) - @ApiResponse({ - status: 200, - description: 'Success', - type: Boolean, - }) - @UseGuards(AuthGuard("jwt-study")) - @Post("studyMonitor/remove") - async removeStudyMonitorUserTagWebsite(@Request() req: any): Promise { - const userId = req.user.userId; - const tag = req.body.tag; - const websitesId = JSON.parse(req.body.websitesId); - - const removeSuccess = - await this.websiteService.removeStudyMonitorUserTagWebsite( - userId, - tag, - websitesId - ); - if (!removeSuccess) { - throw new InternalServerErrorException(); - } - - return success( - await this.websiteService.findAllFromStudyMonitorUserTag(userId, tag) - ); - } -} +import { + Controller, + InternalServerErrorException, + Request, + Get, + Post, + UseGuards, + Param, + UseInterceptors, + Body, + Delete, +} from "@nestjs/common"; +import { AuthGuard } from "@nestjs/passport"; +import { WebsiteService } from "./website.service"; +import { Website } from "./website.entity"; +import { success } from "../lib/response"; +import { LoggingInterceptor } from "src/log/log.interceptor"; +import { + ApiBasicAuth, + ApiOperation, + ApiResponse, + ApiTags, +} from "@nestjs/swagger"; +import { WebsitesIdDto } from "./dto/websites-id.dto"; +import { CreateWebsiteDto } from "./dto/create-website.dto"; +import { UpdateWebsiteDto } from "./dto/update-website.dto"; +import { UpdateObservatoryPages } from "./dto/update-observatory-pages.dto"; +import { DeleteWebsiteDto } from "./dto/delete-website.dto"; +import { DeleteBulkWebsiteDto } from "./dto/delete-bulk-website.dto"; +import { ImportWebsiteMyMonitorDto } from "./dto/import-website-my-monitor.dto"; +import { Page } from "src/page/page.entity"; +import { WebsiteMyMonitorDto } from "./dto/website-my-monitor.dto"; + +@ApiBasicAuth() +@ApiTags("website") +@ApiResponse({ status: 403, description: "Forbidden" }) +@Controller("website") +@UseInterceptors(LoggingInterceptor) +export class WebsiteController { + constructor(private readonly websiteService: WebsiteService) {} + + @ApiOperation({ summary: "Reevaluate all pages from website" }) + @ApiResponse({ + status: 200, + description: "The evaluation request has been submited", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("accessibility-statement/update") + async accessibilityStatementUpdate(): Promise { + return success(await this.websiteService.findAccessiblityStatements()); + } + + @UseGuards(AuthGuard("jwt-admin")) + @Post("accessibility-statement/update/:id") + async accessibilityStatementUpdateById( + @Param("id") id: number + ): Promise { + await this.websiteService.updateAStatement(id); + return success(true); + } + + @UseGuards(AuthGuard("jwt-admin")) + @Post("reEvaluate") + async reEvaluateWebsitePages( + @Body() websitesIdDto: WebsitesIdDto + ): Promise { + return success( + await this.websiteService.addPagesToEvaluate( + websitesIdDto.websitesId, + websitesIdDto.option + ) + ); + } + + @ApiOperation({ summary: "Create website" }) + @ApiResponse({ + status: 200, + description: "The website has been created", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("create") + async createWebsite(@Body() websiteDto: CreateWebsiteDto): Promise { + const createSuccess = await this.websiteService.createOne( + websiteDto, + websiteDto.entities, + websiteDto.tags + ); + if (!createSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Update website" }) + @ApiResponse({ + status: 200, + description: "The website has been updated", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("update") + async updateWebsite( + @Body() updateWebsiteDto: UpdateWebsiteDto + ): Promise { + const updateSuccess = await this.websiteService.update(updateWebsiteDto); + if (!updateSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Update pages in the observatory" }) + @ApiResponse({ + status: 200, + description: "The pages in the observatory have been updated", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("pages/updateObservatory") + async updateWebsitePagesObservatory( + @Body() updateObservatoryPages: UpdateObservatoryPages + ): Promise { + return success( + await this.websiteService.updatePagesObservatory(updateObservatoryPages) + ); + } + + @ApiOperation({ summary: "Delete websites" }) + @ApiResponse({ + status: 200, + description: "The website list has been deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("deleteBulk") + async deleteWebsites( + @Body() deleteBulkWebsiteDto: DeleteBulkWebsiteDto + ): Promise { + const deleteSuccess = await this.websiteService.deleteBulk( + deleteBulkWebsiteDto.websitesId + ); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Delete website" }) + @ApiResponse({ + status: 200, + description: "The website has been deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("delete") + async deleteWebsite( + @Body() deleteWebsiteDto: DeleteWebsiteDto + ): Promise { + const deleteSuccess = await this.websiteService.delete( + deleteWebsiteDto.websiteId + ); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ + summary: "Finds a website, by the starting URL, from the current user", + }) + @ApiResponse({ + status: 200, + description: "The website has been found", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Get("myMonitor/url/:website") + async getMyMonitorUserWebsiteDomain( + @Request() req: any, + @Param("website") website: string + ): Promise { + return success( + await this.websiteService.findMyMonitorUserWebsiteStartingUrl( + req.user.userId, + website + ) + ); + } + + @ApiOperation({ summary: "Deletes all pages from a list of websites" }) + @ApiResponse({ + status: 200, + description: "The selected pages have been deleted", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("pages/deleteBulk") + async deleteWebsitesaPages( + @Body() deleteBulkWebsiteDto: DeleteBulkWebsiteDto + ): Promise { + const deleteSuccess = await this.websiteService.pagesDeleteBulk( + deleteBulkWebsiteDto.websitesId + ); + if (!deleteSuccess) { + throw new InternalServerErrorException(); + } + + return success(true); + } + + @ApiOperation({ summary: "Imports a website from MyMonitor" }) + @ApiResponse({ + status: 200, + description: "The selected website has been imported", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Post("import") + async importWebsiteFromMyMonitor( + @Body() importWebsiteMyMonitorDto: ImportWebsiteMyMonitorDto + ): Promise { + const websiteId = importWebsiteMyMonitorDto.websiteId; + const websiteName = importWebsiteMyMonitorDto.newWebsiteName; + + return success(await this.websiteService.import(websiteId, websiteName)); + } + + @ApiOperation({ + summary: + "Calculates the number of websites in AMS filtered by search string", + }) + @ApiResponse({ + status: 200, + description: " The number of websites in AMS filtered by search string", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("all/count/:search") + async getAdminWebsiteCount(@Param("search") search: string): Promise { + return success( + await this.websiteService.adminCount( + decodeURIComponent(search.substring(7)) + ) + ); + } + + @ApiOperation({ + summary: + "Finds websites in AMS filtered by search string, size, sort and direction", + }) + @ApiResponse({ + status: 200, + description: + " The websites in AMS filtered by search string, size, sort and direction", + type: Array, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("all/:size/:page/:sort/:direction/:search") + async getAllWebsites( + @Param("size") size: string, + @Param("page") page: string, + @Param("sort") sort: string, + @Param("direction") direction: string, + @Param("search") search: string + ): Promise { + return success( + await this.websiteService.findAll( + parseInt(size), + parseInt(page), + sort.substring(5), + direction.substring(10), + decodeURIComponent(search.substring(7)) + ) + ); + } + + @ApiOperation({ summary: "Find website information by id" }) + @ApiResponse({ + status: 200, + description: " The specific website information", + type: Website, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("info/:websiteId") + async getWebsiteInfo(@Param("websiteId") websiteId: number): Promise { + return success(await this.websiteService.findInfo(websiteId)); + } + + @ApiOperation({ summary: "Find website by user and name" }) + @ApiResponse({ + status: 200, + description: " The specific website", + type: Website, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get(":website/user/:user/pages") + async getAllWebsiteDomains( + @Param("website") website: string, + @Param("user") user: string + ): Promise { + const websiteId = await this.websiteService.getIdFromUserAndName( + user, + website + ); + + return success(await this.websiteService.findAllPages(websiteId)); + } + + @ApiOperation({ summary: "Finds all website data to build a csv" }) + @ApiResponse({ + status: 200, + description: " All the webiste data", + type: Website, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("csv") + async getAllWebsiteCSVData(): Promise { + return success(await this.websiteService.getAllWebsiteDataCSV()); + } + + @ApiOperation({ summary: "Finds all pages from a website by id" }) + @ApiResponse({ + status: 200, + description: " All pages from the specific website", + type: Array, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("pages/:websiteId") + async getAllWebsitePages( + @Param("websiteId") websiteId: number + ): Promise { + return success(await this.websiteService.findAllPages(websiteId)); + } + + @ApiOperation({ + summary: "Finds all websites excluding Study Monitor websites", + }) + @ApiResponse({ + status: 200, + description: "The list of websites", + type: Array, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("official") + async getAllOfficialWebsites(): Promise { + return success(await this.websiteService.findAllOfficial()); + } + + @ApiOperation({ summary: "Finds all websites without user" }) + @ApiResponse({ + status: 200, + description: "The list of websites", + type: Array, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("withoutUser") + async getWebsitesWithoutUser(): Promise { + return success(await this.websiteService.findAllWithoutUser()); + } + + @ApiOperation({ summary: "Finds all websites without entity" }) + @ApiResponse({ + status: 200, + description: "The list of websites", + type: Array, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("withoutEntity") + async getWebsitesWithoutEntity(): Promise { + return success(await this.websiteService.findAllWithoutEntity()); + } + + @ApiOperation({ summary: "Finds the number of websites in study monitor" }) + @ApiResponse({ + status: 200, + description: "The number of websites", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("studyMonitor/total") + async getNumberOfStudyMonitorWebsites(): Promise { + return success(await this.websiteService.findNumberOfStudyMonitor()); + } + + @ApiOperation({ summary: "Finds the number of websites in my monitor" }) + @ApiResponse({ + status: 200, + description: "The number of websites", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("myMonitor/total") + async getNumberOfMyMonitorWebsites(): Promise { + return success(await this.websiteService.findNumberOfMyMonitor()); + } + + @ApiOperation({ summary: "Finds the number of websites in observatory" }) + @ApiResponse({ + status: 200, + description: "The number of websites", + type: Number, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("observatory/total") + async getNumberOfObservatoryWebsites(): Promise { + return success(await this.websiteService.findNumberOfObservatory()); + } + + @ApiOperation({ summary: "Check if website exists by name" }) + @ApiResponse({ + status: 200, + description: "The specific website", + type: Website, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("exists/:name") + async checkIfWebsiteExists(@Param("name") name: string): Promise { + return success(!!(await this.websiteService.findByOfficialName(name))); + } + + @ApiOperation({ summary: "Check if website exists by starting url" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-admin")) + @Get("exists/url/:url") + async checkIfWebsiteUrlExists(@Param("url") url: string): Promise { + return success( + !!(await this.websiteService.existsUrl(decodeURIComponent(url))) + ); + } + + @ApiOperation({ summary: "Check if website is in observatory" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Post("isInObservatory") + async checkIfIsInObservatory( + websiteMyMonitorDto: WebsiteMyMonitorDto + ): Promise { + return success( + await this.websiteService.isInObservatory( + websiteMyMonitorDto.userId, + websiteMyMonitorDto.website + ) + ); + } + + @ApiOperation({ + summary: + "Transfers observatory pages from a specific website to a specific user", + }) + @ApiResponse({ + status: 200, + description: "The transfer was a success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Post("transferObservatoryPages") + async transferObservatoryPages( + @Request() req: any, + @Body() websiteMyMonitorDto: WebsiteMyMonitorDto + ): Promise { + return success( + await this.websiteService.transferObservatoryPages( + req.user.userId, + websiteMyMonitorDto.website + ) + ); + } + + @ApiOperation({ summary: "Finds all websites from a specific user" }) + @ApiResponse({ + status: 200, + description: "The list of websites", + type: Array, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Get("myMonitor") + async getMyMonitorUserWebsites(@Request() req: any): Promise { + return success( + await this.websiteService.findAllFromMyMonitorUser(req.user.userId) + ); + } + + @ApiOperation({ + summary: "Reevalute all pages from a specific website in My Monitor", + }) + @ApiResponse({ + status: 200, + description: "The page evaluation was submited", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-monitor")) + @Post("myMonitor/reEvaluate") + async reEvaluateMyMonitorUserWebsitePages( + websiteMyMonitorDto: WebsiteMyMonitorDto + ): Promise { + const userId = websiteMyMonitorDto.userId; + const website = websiteMyMonitorDto.website; + + return success( + await this.websiteService.reEvaluateMyMonitorWebsite(userId, website) + ); + } + + @ApiOperation({ + summary: "Reevalute all pages from a specific website in Study Monitor", + }) + @ApiResponse({ + status: 200, + description: "The page evaluation was submited", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("studyMonitor/reEvaluate") + async reEvaluateStudyMonitorUserTagWebsitePages( + @Request() req: any + ): Promise { + const userId = req.user.userId; + const tag = req.body.tag; + const website = req.body.website; + + return success( + await this.websiteService.reEvaluateStudyMonitorWebsite( + userId, + tag, + website + ) + ); + } + + @ApiOperation({ + summary: "Find all websites from a specific user and tag in Study Monitor", + }) + @ApiResponse({ + status: 200, + description: "The website list", + type: Array, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("studyMonitor/tag/:tag") + async getStudyMonitorUserTagWebsites( + @Request() req: any, + @Param("tag") tag: string + ): Promise { + const userId = req.user.userId; + return success( + await this.websiteService.findAllFromStudyMonitorUserTag(userId, tag) + ); + } + + @ApiOperation({ + summary: "Find all websites from a specific user and tag in Study Monitor", + }) + @ApiResponse({ + status: 200, + description: "The website list", + type: Array, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("studyMonitor/otherTags/:tag") + async getStudyMonitorUserOtherTagsWebsites( + @Request() req: any, + @Param("tag") tag: string + ): Promise { + const userId = req.user.userId; + return success( + await this.websiteService.findAllFromStudyMonitorUserOtherTagsWebsites( + userId, + tag + ) + ); + } + + @ApiOperation({ + summary: "Find all websites from a specific user and tag in Study Monitor", + }) + @ApiResponse({ + status: 200, + description: "The website list", + type: Array, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("studyMonitor/tag/:tag/website/nameExists/:website") + async checkIfStudyMonitorUserTagWebsiteNameExists( + @Request() req: any, + @Param("tag") tag: string, + @Param("website") website: string + ): Promise { + const userId = req.user.userId; + return success( + !!(await this.websiteService.findStudyMonitorUserTagWebsiteByName( + userId, + tag, + website + )) + ); + } + + @ApiOperation({ + summary: "Check if website exists in specific tag in Study Monitor", + }) + @ApiResponse({ + status: 200, + description: "Success", + type: Array, + }) + @UseGuards(AuthGuard("jwt-study")) + @Get("studyMonitor/tag/:tag/websiteExists/:startingUrl") + async checkIfStudyMonitorUserTagWebsiteExists( + @Request() req: any, + @Param("tag") tag: string, + @Param("startingUrl") startingUrl: string + ): Promise { + const userId = req.user.userId; + return success( + !!(await this.websiteService.findStudyMonitorUserTagWebsiteByStartingUrl( + userId, + tag, + startingUrl + )) + ); + } + + @ApiOperation({ summary: "Link a website to a tag in Study Monitor" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Array, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("studyMonitor/link") + async linkStudyMonitorUserTagWebsite(@Request() req: any): Promise { + const userId = req.user.userId; + const tag = req.body.tag; + const websitesId = JSON.parse(req.body.websitesId); + + const linkSuccess = + await this.websiteService.linkStudyMonitorUserTagWebsite( + userId, + tag, + websitesId + ); + if (!linkSuccess) { + throw new InternalServerErrorException(); + } + + return success( + await this.websiteService.findAllFromStudyMonitorUserTag(userId, tag) + ); + } + + @ApiOperation({ summary: "Create a website in Study Monitor" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Website, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("studyMonitor/create") + async createStudyMonitorUserTagWebsite(@Request() req: any): Promise { + const userId = req.user.userId; + const tag = req.body.tag; + const websiteName = req.body.name; + const startingUrl = decodeURIComponent(req.body.startingUrl); + const pages = JSON.parse(req.body.pages).map((page: string) => + decodeURIComponent(page) + ); + + const createSuccess = + await this.websiteService.createStudyMonitorUserTagWebsite( + userId, + tag, + websiteName, + startingUrl, + pages + ); + if (!createSuccess) { + throw new InternalServerErrorException(); + } + + return success( + await this.websiteService.findAllFromStudyMonitorUserTag(userId, tag) + ); + } + + @ApiOperation({ summary: "Remove a website to a tag in Study Monitor" }) + @ApiResponse({ + status: 200, + description: "Success", + type: Boolean, + }) + @UseGuards(AuthGuard("jwt-study")) + @Post("studyMonitor/remove") + async removeStudyMonitorUserTagWebsite(@Request() req: any): Promise { + const userId = req.user.userId; + const tag = req.body.tag; + const websitesId = JSON.parse(req.body.websitesId); + + const removeSuccess = + await this.websiteService.removeStudyMonitorUserTagWebsite( + userId, + tag, + websitesId + ); + if (!removeSuccess) { + throw new InternalServerErrorException(); + } + + return success( + await this.websiteService.findAllFromStudyMonitorUserTag(userId, tag) + ); + } +} diff --git a/src/website/website.entity.ts b/src/website/website.entity.ts index d8a88e0d..ce3ca6bf 100644 --- a/src/website/website.entity.ts +++ b/src/website/website.entity.ts @@ -1,88 +1,88 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - JoinTable, - ManyToMany, - OneToMany -} from "typeorm"; -import { Tag } from "../tag/tag.entity"; -import { EntityTable } from "../entity/entity.entity"; -import { Page } from "src/page/page.entity"; -import { AccessibilityStatement } from "src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity"; - -@Entity("Website") -export class Website { - @PrimaryGeneratedColumn({ - type: "int", - }) - WebsiteId: number; - - @Column({ - type: "int", - nullable: true, - }) - UserId: number; - - @Column({ - type: "varchar", - length: 255, - nullable: false, - }) - Name: string; - - @Column({ - type: "varchar", - length: 255, - nullable: false, - }) - StartingUrl: string; - - @Column({ - type: "int", - nullable: true, - }) - Declaration: number; - - @Column({ - type: "datetime", - nullable: true, - }) - Declaration_Update_Date: any; - - @Column({ - type: "int", - nullable: true, - }) - Stamp: number; - - @Column({ - type: "datetime", - nullable: true, - }) - Stamp_Update_Date: any; - - @Column({ - type: "datetime", - nullable: false, - }) - Creation_Date: any; - - @ManyToMany((type) => Tag,tag=>tag.Websites) - Tags: Tag[]; - - @ManyToMany((type) => EntityTable) - @JoinTable() - Entities: EntityTable[]; - - @JoinTable({ - name: 'WebsitePage', - joinColumn: { name: 'WebsiteId' }, - inverseJoinColumn: { name: 'PageId' } - }) - @ManyToMany((type) => Page, (page) => page.Pages) - Pages: Page[]; - - @OneToMany(type => AccessibilityStatement, (as) => as.Website) - AStatements: AccessibilityStatement[]; -} +import { + Entity, + Column, + PrimaryGeneratedColumn, + JoinTable, + ManyToMany, + OneToMany, +} from "typeorm"; +import { Tag } from "../tag/tag.entity"; +import { EntityTable } from "../entity/entity.entity"; +import { Page } from "src/page/page.entity"; +import { AccessibilityStatement } from "src/accessibility-statement-module/accessibility-statement/entities/accessibility-statement.entity"; + +@Entity("Website") +export class Website { + @PrimaryGeneratedColumn({ + type: "int", + }) + WebsiteId: number; + + @Column({ + type: "int", + nullable: true, + }) + UserId: number; + + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + Name: string; + + @Column({ + type: "varchar", + length: 255, + nullable: false, + }) + StartingUrl: string; + + @Column({ + type: "int", + nullable: true, + }) + Declaration: number; + + @Column({ + type: "datetime", + nullable: true, + }) + Declaration_Update_Date: any; + + @Column({ + type: "int", + nullable: true, + }) + Stamp: number; + + @Column({ + type: "datetime", + nullable: true, + }) + Stamp_Update_Date: any; + + @Column({ + type: "datetime", + nullable: false, + }) + Creation_Date: any; + + @ManyToMany((type) => Tag, (tag) => tag.Websites) + Tags: Tag[]; + + @ManyToMany((type) => EntityTable) + @JoinTable() + Entities: EntityTable[]; + + @JoinTable({ + name: "WebsitePage", + joinColumn: { name: "WebsiteId" }, + inverseJoinColumn: { name: "PageId" }, + }) + @ManyToMany((type) => Page, (page) => page.Pages) + Pages: Page[]; + + @OneToMany((type) => AccessibilityStatement, (as) => as.Website) + AStatements: AccessibilityStatement[]; +} diff --git a/src/website/website.module.ts b/src/website/website.module.ts index 2233585c..018cef9f 100644 --- a/src/website/website.module.ts +++ b/src/website/website.module.ts @@ -1,19 +1,23 @@ -import { Module } from "@nestjs/common"; -import { TypeOrmModule } from "@nestjs/typeorm"; -import { WebsiteService } from "./website.service"; -import { Website } from "./website.entity"; -import { Tag } from "../tag/tag.entity"; -import { Page } from "../page/page.entity"; -import { WebsiteController } from "./website.controller"; -import { EvaluationModule } from "../evaluation/evaluation.module"; -import { AccessibilityStatementModule } from "src/accessibility-statement-module/accessibility-statement/accessibility-statement.module"; -import { CollectionDateModule } from "src/accessibility-statement-module/collection-date/collection-date.module"; - -@Module({ - imports: [TypeOrmModule.forFeature([Tag, Website, Page]), EvaluationModule, - AccessibilityStatementModule,CollectionDateModule], - exports: [WebsiteService], - providers: [WebsiteService], - controllers: [WebsiteController], -}) -export class WebsiteModule { } +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { WebsiteService } from "./website.service"; +import { Website } from "./website.entity"; +import { Tag } from "../tag/tag.entity"; +import { Page } from "../page/page.entity"; +import { WebsiteController } from "./website.controller"; +import { EvaluationModule } from "../evaluation/evaluation.module"; +import { AccessibilityStatementModule } from "src/accessibility-statement-module/accessibility-statement/accessibility-statement.module"; +import { CollectionDateModule } from "src/accessibility-statement-module/collection-date/collection-date.module"; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Tag, Website, Page]), + EvaluationModule, + AccessibilityStatementModule, + CollectionDateModule, + ], + exports: [WebsiteService], + providers: [WebsiteService], + controllers: [WebsiteController], +}) +export class WebsiteModule {} diff --git a/src/website/website.service.spec.ts b/src/website/website.service.spec.ts index c492e1b8..340951c2 100644 --- a/src/website/website.service.spec.ts +++ b/src/website/website.service.spec.ts @@ -1,18 +1,18 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { WebsiteService } from './website.service'; - -describe('WebsiteService', () => { - let service: WebsiteService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [WebsiteService], - }).compile(); - - service = module.get(WebsiteService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { WebsiteService } from "./website.service"; + +describe("WebsiteService", () => { + let service: WebsiteService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [WebsiteService], + }).compile(); + + service = module.get(WebsiteService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/website/website.service.ts b/src/website/website.service.ts index f55e72f6..62bd3ec2 100644 --- a/src/website/website.service.ts +++ b/src/website/website.service.ts @@ -1,1623 +1,1644 @@ -import { Injectable, InternalServerErrorException } from "@nestjs/common"; -import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; -import { DataSource, IsNull, Repository } from "typeorm"; -import { Page } from "../page/page.entity"; -import { EvaluationService } from "../evaluation/evaluation.service"; -import { AccessibilityStatementService } from "src/accessibility-statement-module/accessibility-statement/accessibility-statement.service"; -import { CollectionDateService } from "src/accessibility-statement-module/collection-date/collection-date.service"; -import { Tag } from "../tag/tag.entity"; -import { CreateWebsiteDto } from "./dto/create-website.dto"; -import { UpdateObservatoryPages } from "./dto/update-observatory-pages.dto"; -import { UpdateWebsiteDto } from "./dto/update-website.dto"; -import { Website } from "./website.entity"; - -@Injectable() -export class WebsiteService { - constructor( - @InjectRepository(Website) - private readonly websiteRepository: Repository, - private evaluationService: EvaluationService, - private readonly accessibilityStatementService: AccessibilityStatementService, - private readonly collectionDateService: CollectionDateService, - @InjectRepository(Tag) - private readonly tagRepository: Repository, - @InjectRepository(Page) - private readonly pageRepository: Repository, - @InjectDataSource() - private readonly connection: DataSource) { } - - async findAccessiblityStatements(): Promise { - const websites = await this.websiteRepository.find({relations:["Pages"]}); - await this.collectionDateService.create(); - for (const website of websites) { - const id = website.WebsiteId; - const pages = website.Pages; - await this.findAccessiblityStatementsInPageList(pages, website); - } - } - - async updateAStatement(WebsiteId:number): Promise { - const website = await this.websiteRepository.findOne({ where:{WebsiteId}, relations: ["Pages"] }); - if(website){ - const pages = website.Pages; - await this.findAccessiblityStatementsInPageList(pages, website);} - } - - async findAccessiblityStatementsInPageList(pages:Page[], website:Website): Promise { - for(const page of pages){ - const id = page.PageId; - const evaluation = await this.evaluationService.getLastEvaluationByPage(id); - if (evaluation) { - const rawHtml = Buffer.from(evaluation.Pagecode, "base64").toString(); - await this.accessibilityStatementService.createIfExist(rawHtml, website, page.Uri); - } - } -} - async getAllWebsiteDataCSV(): Promise { - const websites = await this.websiteRepository.find({ relations: ["Tags"] }); - return await Promise.all(websites.map(async (website) => { - const id = website.WebsiteId; - const pages = await this.findAllPages(id); - website["numberOfPages"] = pages.length; - website["averagePoints"] = this.averagePointsPageEvaluation(pages); - return website; - })); - } - private averagePointsPageEvaluation(pages) { - const totalPoints = pages.reduce((total, page) => { return total + (+page.Score) }, 0); - return totalPoints / pages.length; - } - - - async addPagesToEvaluate( - websitesId: number[], - option: string - ): Promise { - const pages = await this.websiteRepository.query( - ` - SELECT - p.PageId, - p.Uri - FROM - WebsitePage as wp, - Page as p - WHERE - wp.WebsiteId IN (?) AND - p.PageId = wp.PageId AND - p.Show_In LIKE ?`, - [websitesId, option === "all" ? "1__" : "1_1"] - ); - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - let error = false; - try { - for (const page of pages || []) { - try { - const pageEval = await queryRunner.manager.query( - `SELECT * FROM Evaluation_List WHERE PageId = ? AND UserId = -1 AND Url = ? AND Show_To = ? LIMIT 1`, - [page.PageId, page.Uri, "10"] - ); - if (pageEval.length > 0) { - await queryRunner.manager.query( - `UPDATE Evaluation_List SET Error = NULL, Is_Evaluating = 0 WHERE EvaluationListId = ?`, - [pageEval[0].EvaluationListId] - ); - } else { - await queryRunner.manager.query( - `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, - [page.PageId, -1, page.Uri, "10", new Date()] - ); - } - } catch (_) { } - } - - await queryRunner.manager.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "AMS/Observatory"`, - [pages.length] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.log(err); - error = true; - } finally { - await queryRunner.release(); - } - - return !error; - } - - async adminCount(search: string): Promise { - const count = await this.websiteRepository.query( - `SELECT COUNT(w.WebsiteId) as Count - FROM - Website as w - LEFT OUTER JOIN User as u ON u.UserId = w.UserId - WHERE - w.Name LIKE ? AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies'))`, - [search.trim() !== "" ? `%${search.trim()}%` : "%"] - ); - - return count[0].Count; - } - - async getIdFromUserAndName(user: string, name: string): Promise { - const website = await this.websiteRepository.query( - ` - SELECT w.* FROM Website as w, User as u - WHERE - w.Name LIKE ? AND - ((w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) OR - w.UserId IS NOT NULL AND (u.UserId = w.UserId AND u.Username LIKE ?)) - LIMIT 1 - `, - [name, user] - ); - return website[0].WebsiteId; - } - - async findAll( - size: number, - page: number, - sort: string, - direction: string, - search: string - ): Promise { - if (!direction.trim()) { - const websites = await this.websiteRepository.query( - ` - SELECT - w.*, - u.Username as User, u.Type as Type, - COUNT(distinct p.PageId) as Pages, - COUNT(distinct e.PageId) as Evaluated_Pages - FROM - Website as w - LEFT OUTER JOIN User as u ON u.UserId = w.UserId - LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId - LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE "1__" - LEFT OUTER JOIN Evaluation as e ON e.PageId = p.PageId - WHERE - (w.Name LIKE ? OR w.StartingUrl LIKE ?) AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) - GROUP BY w.WebsiteId - LIMIT ? OFFSET ?`, - [ - search.trim() !== "" ? `%${search.trim()}%` : "%", - search.trim() !== "" ? `%${search.trim()}%` : "%", - size, - page * size, - ] - ); - - /* - LEFT OUTER JOIN Evaluation as e2 ON e.PageId = p.PageId AND e2.Evaluation_Date = ( - SELECT Evaluation_Date FROM Evaluation - WHERE PageId = p.PageId - ORDER BY Evaluation_Date DESC LIMIT 1 - ) - */ - return websites; - } else { - let order = ""; - switch (sort) { - case "Name": - order = "w.Name"; - break; - case "StartingUrl": - order = "w.StartingUrl"; - break; - case "Pages": - order = "Pages"; - break; - case "Creation_Date": - order = "w.Creation_Date"; - break; - } - - const websites = await this.websiteRepository.query( - ` - SELECT - w.*, - u.Username as User, u.Type as Type, - COUNT(distinct p.PageId) as Pages, - COUNT(distinct e.PageId) as Evaluated_Pages - FROM - Website as w - LEFT OUTER JOIN User as u ON u.UserId = w.UserId - LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId - LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE "1__" - LEFT OUTER JOIN Evaluation as e ON e.PageId = p.PageId - WHERE - (w.Name LIKE ? OR w.StartingUrl LIKE ?) AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) - GROUP BY w.WebsiteId - ORDER BY ${order} ${direction.toUpperCase()} - LIMIT ? OFFSET ?`, - [ - search.trim() !== "" ? `%${search.trim()}%` : "%", - search.trim() !== "" ? `%${search.trim()}%` : "%", - size, - page * size, - ] - ); - return websites; - } - } - - async findInfo(websiteId: number): Promise { - const websites = await this.websiteRepository.query( - `SELECT w.*, u.Username as User, e.Long_Name as Entity, COUNT(distinct wp.PageId) as Pages - FROM - Website as w - LEFT OUTER JOIN User as u ON u.UserId = w.UserId - LEFT OUTER JOIN EntityWebsite as ew ON ew.WebsiteId = w.WebsiteId - LEFT OUTER JOIN Entity as e ON e.EntityId = ew.EntityId - LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId - WHERE - w.WebsiteId = ? - GROUP BY w.WebsiteId, w.StartingUrl - LIMIT 1`, - [websiteId] - ); - - if (websites) { - const website = websites[0]; - - website.tags = await this.websiteRepository.query( - `SELECT t.* FROM Tag as t, TagWebsite as tw WHERE tw.WebsiteId = ? AND t.TagId = tw.TagId`, - [websiteId] - ); - - website.entities = await this.websiteRepository.query( - `SELECT e.* FROM Entity as e, EntityWebsite as ew WHERE ew.WebsiteId = ? AND e.EntityId = ew.EntityId`, - [websiteId] - ); - return website; - } else { - throw new InternalServerErrorException(); - } - } - - async findUserType(username: string): Promise { - if (username === "admin") { - return "nimda"; - } - - const user = await this.websiteRepository.query( - `SELECT * FROM User WHERE Username = ? LIMIT 1`, - [username] - ); - - if (user) { - return user[0].Type; - } else { - return null; - } - } - - async findAllPages(websiteId: number): Promise { - const pages = await this.websiteRepository.query( - `SELECT - distinct p.*, - e.Score, - e.A, - e.AA, - e.AAA, - e.Tot, - e.Errors, - e.Element_Count, - e.Tag_Count, - e.Evaluation_Date, - el.EvaluationListId, el.Error, el.Is_Evaluating - FROM - WebsitePage as wp, - Page as p - LEFT OUTER JOIN Evaluation_List as el ON el.PageId = p.PageId AND el.UserId = -1 - LEFT OUTER JOIN Evaluation as e ON e.PageId = p.PageId AND e.Show_To LIKE "1_" AND e.Evaluation_Date IN ( - SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND Show_To LIKE "1_" - ) - WHERE - wp.WebsiteId = ? AND - p.PageId = wp.PageId AND - p.Show_In LIKE "1__"`, - [websiteId] - ); - - return pages; - } - - async findAllOfficial(): Promise { - const websites = await this.websiteRepository.query(`SELECT distinct w.* - FROM - Website as w, - User as u - WHERE - w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')`); - return websites; - } - - async findByOfficialName(name: string): Promise { - const website = await this.websiteRepository.findOne({ - where: { Name:name, UserId: IsNull() }, - }); - return website; - /*if (website && website.Name !== name) { - return undefined; - } else { - return website; - }*/ - } - - async existsUrl(url: string): Promise { - return ( - ( - await this.websiteRepository.query( - `SELECT w.* - FROM - Website as w, - User as u - WHERE - w.StartingUrl = ? AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) - LIMIT 1`, - [url] - ) - ).length > 0 - ); - } - - async findAllWithoutUser(): Promise { - const websites = await this.websiteRepository.query( - `SELECT * FROM Website WHERE UserId IS NULL` - ); - return websites; - } - /** - * - * SELECT distinct w.* - FROM - User as u , - EntityWebsite as ew - LEFT OUTER JOIN Website as ew ON w.WebsiteId = ew.WebsiteId - WHERE - ew.EntityId IS NULL AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) - */ - async findAllWithoutEntity(): Promise { - const websites = await this.websiteRepository.query(`SELECT distinct w.* - FROM - User as u , - EntityWebsite as ew - LEFT OUTER JOIN Website as ew ON w.WebsiteId = ew.WebsiteId - WHERE - ew.EntityId IS NULL AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies'))`); - return websites; //TODO: fix - } - - async findAllFromMyMonitorUser(userId: number): Promise { - const websites = await this.websiteRepository.query( - `SELECT w.*, COUNT(distinct p.PageId) as Pages - FROM - Website as w - LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId - LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE '_1%' - WHERE - w.UserId = ? - GROUP BY w.WebsiteId, w.StartingUrl`, - [userId] - ); - return websites; - } - - async isInObservatory(userId: number, website: string): Promise { - - const tags = await this.websiteRepository.query( - ` - SELECT t.* - FROM - Directory as d, - DirectoryTag as dt, - Tag as t, - TagWebsite as tw, - Website as w - WHERE - w.UserId = ? AND - w.Name = ? AND - tw.WebsiteId = w.WebsiteId AND - t.TagId = tw.TagId AND - t.UserId IS NULL AND - dt.TagId = t.TagId AND - d.DirectoryId = dt.DirectoryId AND - d.Show_In_Observatory = 1 - `, - [userId, website] - ); - - return tags.length > 0; - } - - async transferObservatoryPages( - userId: number, - website: string - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - let error = false; - try { - const pages = await queryRunner.manager.query( - ` - SELECT - p.* - FROM - Directory as dir, - DirectoryTag as dt, - Tag as t, - TagWebsite as tw, - Website as w, - WebsitePage as wp, - Page as p - WHERE - w.UserId = ? AND - w.Name = ? AND - tw.WebsiteId = w.WebsiteId AND - t.TagId = tw.TagId AND - t.UserId IS NULL AND - dt.TagId = t.TagId AND - dir.DirectoryId = dt.DirectoryId AND - dir.Show_In_Observatory = 1 AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId and - p.Show_In LIKE "_01" - `, - [userId, website] - ); - - for (const page of pages || []) { - const evaluation = await queryRunner.manager.query( - ` - SELECT * - FROM - Evaluation - WHERE - PageId = ? AND - Show_To LIKE "1_" - ORDER BY Evaluation_Date DESC LIMIT 1 - `, - [page.PageId] - ); - if (evaluation.length > 0) { - await queryRunner.manager.query( - `UPDATE Page SET Show_In = ? WHERE PageId = ?`, - [page.Show_In[0] + "1" + page.Show_In[2], page.PageId] - ); - await queryRunner.manager.query( - `UPDATE Evaluation SET Show_To = ? WHERE EvaluationId = ?`, - [evaluation[0].Show_To[0] + "1", evaluation[0].EvaluationId] - ); - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.log(err); - error = true; - } finally { - await queryRunner.release(); - } - - return !error; - } - - async reEvaluateMyMonitorWebsite( - userId: number, - websiteName: string - ): Promise { - const website = await this.websiteRepository.findOne({ - where: { UserId: userId, Name: websiteName }, - }); - if (!website) { - throw new InternalServerErrorException(); - } - - - const pages = await this.websiteRepository.query( - `SELECT - distinct p.* - FROM - Page as p, - Website as w, - WebsitePage as wp - WHERE - w.Name = ? AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId AND - p.Show_In LIKE '_1_'`, - [website.Name, website.UserId] - ); - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - let error = false; - try { - for (const page of pages || []) { - try { - await queryRunner.manager.query( - `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, - [page.PageId, userId, page.Uri, "01", new Date()] - ); - } catch (_) { } - } - - await queryRunner.manager.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "MyMonitor"`, - [pages.length] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.log(err); - error = true; - } finally { - await queryRunner.release(); - } - - return !error; - } - - async reEvaluateStudyMonitorWebsite( - userId: number, - tag: string, - website: string - ): Promise { - const websiteExists = await this.websiteRepository.query( - `SELECT * FROM Website WHERE UserId = ? AND Name = ? LIMIT 1`, - [userId, website] - ); - - if (!websiteExists) { - throw new InternalServerErrorException(); - } - - const pages = await this.websiteRepository.query( - `SELECT - distinct p.* - FROM - Page as p, - Tag as t, - TagWebsite as tw, - Website as w, - WebsitePage as wp - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.Name = ? AND - w.UserId = ? AND - wp.WebsiteId = w.WebsiteId AND - p.PageId = wp.PageId`, - [tag, userId, website, userId] - ); - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - - await queryRunner.startTransaction(); - - let error = false; - try { - for (const page of pages || []) { - try { - await queryRunner.manager.query( - `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date, StudyUserId) VALUES (?, ?, ?, ?, ?, ?)`, - [page.PageId, userId, page.Uri, "00", new Date(), userId] - ); - } catch (_) { } - } - - await queryRunner.manager.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "StudyMonitor"`, - [pages.length] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - console.log(err); - error = true; - } finally { - await queryRunner.release(); - } - - return !error; - } - - async findAllFromStudyMonitorUserTag( - userId: number, - tagName: string - ): Promise { - const tag = await this.tagRepository.findOne({ - where: { UserId: userId, Name: tagName }, - }); - if (tag) { - return await this.websiteRepository.query( - `SELECT - w.WebsiteId, - w.Name, - w.StartingUrl, - COUNT(distinct p.PageId) as Pages, - AVG(e.Score) as Score - FROM - Tag as t, - TagWebsite as tw, - Website as w - LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId - LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId - LEFT OUTER JOIN Evaluation as e ON e.StudyUserId = ? AND e.Evaluation_Date IN ( - SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND StudyUserId = e.StudyUserId - ) - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.UserId = ? - GROUP BY w.WebsiteId, w.StartingUrl`, - [userId, tagName, userId, userId] - ); - } else { - throw new InternalServerErrorException(); - } - } - - async findAllFromStudyMonitorUserOtherTagsWebsites( - userId: number, - tagName: string - ): Promise { - const websites = await this.websiteRepository.query( - `SELECT - distinct w.*, - t.Name as TagName - FROM - Tag as t, - TagWebsite as tw, - Website as w - WHERE - t.Name != ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.UserId = ? AND - w.Name NOT IN ( - SELECT - w2.Name - FROM - Tag as t2, - TagWebsite as tw2, - Website as w2 - WHERE - t2.Name = ? AND - t2.UserId = ? AND - tw2.TagId = t2.TagId AND - w2.WebsiteId = tw2.WebsiteId AND - w2.UserId = ? - ) AND - w.StartingUrl NOT IN ( - SELECT - w2.StartingUrl - FROM - Tag as t2, - TagWebsite as tw2, - Website as w2 - WHERE - t2.Name = ? AND - t2.UserId = ? AND - tw2.TagId = t2.TagId AND - w2.WebsiteId = tw2.WebsiteId AND - w2.UserId = ? - )`, - [ - tagName, - userId, - userId, - tagName, - userId, - userId, - tagName, - userId, - userId, - ] - ); - - return websites; - } - - async findStudyMonitorUserTagWebsiteByName( - userId: number, - tag: string, - websiteName: string - ): Promise { - const website = await this.websiteRepository.query( - `SELECT * FROM - Tag as t, - TagWebsite as tw, - Website as w - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.UserId = ? AND - w.Name = ? - LIMIT 1`, - [tag, userId, userId, websiteName] - ); - - return website[0]; - } - - async findStudyMonitorUserTagWebsiteByStartingUrl( - userId: number, - tag: string, - startingUrl: string - ): Promise { - const website = await this.websiteRepository.query( - `SELECT * FROM - Tag as t, - TagWebsite as tw, - Website as w - WHERE - t.Name = ? AND - t.UserId = ? AND - tw.TagId = t.TagId AND - w.WebsiteId = tw.WebsiteId AND - w.UserId = ? AND - w.StartingUrl = ? - LIMIT 1`, - [tag, userId, userId, startingUrl] - ); - - return website[0]; - } - - async linkStudyMonitorUserTagWebsite( - userId: number, - tag: string, - websitesId: number[] - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - for (const id of websitesId || []) { - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) - SELECT TagId, ? FROM Tag WHERE Name = ? AND UserId = ?`, - [id, tag, userId] - ); - } - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async createStudyMonitorUserTagWebsite( - userId: number, - tag: string, - websiteName: string, - startingUrl: string, - pages: string[] - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const newWebsite = new Website(); - newWebsite.UserId = userId; - newWebsite.Name = websiteName; - newWebsite.StartingUrl = startingUrl; - newWebsite.Creation_Date = new Date(); - - const insertWebsite = await queryRunner.manager.save(newWebsite); - - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) SELECT TagId, ? FROM Tag WHERE Name = ?`, - [insertWebsite.WebsiteId, tag] - ); - - for (const url of pages || []) { - const page = await queryRunner.manager.findOne(Page, { - where: { Uri: url }, - }); - if (page) { - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, - [insertWebsite.WebsiteId, page.PageId] - ); - await queryRunner.manager.query( - `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date, StudyUserId) VALUES (?, ?, ?, ?, ?, ?)`, - [page.PageId, userId, page.Uri, "00", page.Creation_Date, userId] - ); - } else { - //const evaluation = await this.evaluationService.evaluateUrl(url); - - const newPage = new Page(); - newPage.Uri = url; - newPage.Show_In = "000"; - newPage.Creation_Date = newWebsite.Creation_Date; - - const insertPage = await queryRunner.manager.save(newPage); - - //await this.evaluationService.savePageEvaluation(queryRunner, insertPage.PageId, evaluation, '01'); - - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, - [insertWebsite.WebsiteId, insertPage.PageId] - ); - - const existingWebsite = await queryRunner.manager.query( - `SELECT distinct w.WebsiteId, w.StartingUrl - FROM - User as u, - Website as w - WHERE - w.StartingUrl = ? AND - ( - w.UserId IS NULL OR - ( - u.UserId = w.UserId AND - u.Type = 'monitor' - ) - ) - LIMIT 1`, - [startingUrl] - ); - - if (existingWebsite.length > 0) { - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, - [existingWebsite[0].WebsiteId, newPage.PageId] - ); - } - - await queryRunner.manager.query( - `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, - [ - insertPage.PageId, - userId, - insertPage.Uri, - "00", - insertPage.Creation_Date, - ] - ); - } - } - - await queryRunner.manager.query( - `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "StudyMonitor"`, - [pages.length] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async removeStudyMonitorUserTagWebsite( - userId: number, - tag: string, - websitesId: number[] - ): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - for (const id of websitesId || []) { - const relations = await queryRunner.manager.query( - `SELECT tw.* FROM TagWebsite as tw, Website as w - WHERE - tw.WebsiteId = ? AND - tw.TagId <> -1 AND - w.WebsiteId = tw.WebsiteId AND - w.UserId = ?`, - [id, userId] - ); - - if (relations) { - await queryRunner.manager.query( - ` - DELETE tw FROM Tag as t, TagWebsite as tw - WHERE - t.Name = ? AND - tw.TagId = t.TagId AND - tw.WebsiteId = ?`, - [tag, id] - ); - } else { - await queryRunner.manager.delete(Website, { WebsiteId: id }); - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async findNumberOfStudyMonitor(): Promise { - return ( - await this.websiteRepository.query( - `SELECT COUNT(w.WebsiteId) as Websites FROM Website as w, User as u WHERE u.Type = "studies" AND w.UserId = u.UserId` - ) - )[0].Websites; - } - - async findNumberOfMyMonitor(): Promise { - return ( - await this.websiteRepository.query( - `SELECT COUNT(w.WebsiteId) as Websites FROM Website as w, User as u WHERE u.Type = "monitor" AND w.UserId = u.UserId` - ) - )[0].Websites; - } - - async findNumberOfObservatory(): Promise { - /*const manager = getManager(); - return ( - await manager.query(` - SELECT - COUNT(distinct w.WebsiteId) as Websites - FROM - Directory as d, - DirectoryTag as dt, - TagWebsite as tw, - Website as w - WHERE - d.Show_in_Observatory = 1 AND - dt.DirectoryId = d.DirectoryId AND - tw.TagId = dt.TagId AND - w.WebsiteId = tw.WebsiteId`) - )[0].Websites;*/ - - const data = ( - await this.websiteRepository.query( - "SELECT * FROM Observatory ORDER BY Creation_Date DESC LIMIT 1" - ) - )[0].Global_Statistics; - const dataPrint = await this.connection.query( - `SELECT - COUNT(distinct w.WebsiteId) as Websites - FROM - Directory as d, - DirectoryTag as dt, - TagWebsite as tw, - Website as w - WHERE - d.Show_in_Observatory = 1 AND - dt.DirectoryId = d.DirectoryId AND - tw.TagId = dt.TagId AND - w.WebsiteId = tw.WebsiteId`); - console.log(dataPrint[0].Websites); - const parsedData = JSON.parse(data); - return parsedData.nWebsites; - } - - async createOne( - websiteDto: CreateWebsiteDto, - entities: string[], - tags: string[] - ): Promise { - const website = new Website(); - website.Name = websiteDto.name; - website.UserId = websiteDto.userId; - website.Declaration = websiteDto.declaration; - website.Declaration_Update_Date = websiteDto.declaration_Update_Date; - website.Stamp = websiteDto.stamp; - website.Stamp_Update_Date = websiteDto.stamp_Update_Date; - website.Creation_Date = new Date(); - - website.Creation_Date = new Date(); - website.StartingUrl = decodeURIComponent(websiteDto.startingUrl); - - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const insertWebsite = await queryRunner.manager.save(website); - - for (const entity of entities || []) { - await queryRunner.manager.query( - `INSERT INTO EntityWebsite (EntityId, WebsiteId) VALUES (?, ?)`, - [entity, insertWebsite.WebsiteId] - ); - } - - for (const tag of tags || []) { - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, - [tag, insertWebsite.WebsiteId] - ); - } - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async update( - updateWebsiteDto: UpdateWebsiteDto - ): Promise { - const oldUserId = updateWebsiteDto.oldUserId; - const userId = updateWebsiteDto.userId; - const transfer = updateWebsiteDto.transfer; - const websiteId = updateWebsiteDto.websiteId; - const entities = updateWebsiteDto.entities; - const defaultEntities = updateWebsiteDto.defaultEntities; - const defaultTags = updateWebsiteDto.defaultTags; - const tags = updateWebsiteDto.tags; - updateWebsiteDto.startingUrl = decodeURIComponent(updateWebsiteDto.startingUrl); - - const queryRunner = this.connection.createQueryRunner(); - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.update( - Website, - { WebsiteId:websiteId }, - { - UserId:userId, - Name: updateWebsiteDto.name, - StartingUrl: updateWebsiteDto.startingUrl, - Declaration: updateWebsiteDto.declaration, - Declaration_Update_Date: updateWebsiteDto.declarationUpdateDate, - Stamp: updateWebsiteDto.stamp, - Stamp_Update_Date: updateWebsiteDto.stampUpdateDate, - } - ); - if (oldUserId === null && userId !== null) { - if (transfer) { - await queryRunner.manager.query( - ` - UPDATE - WebsitePage as wp, - Page as p, - Evaluation as e - SET - p.Show_In = "111", - e.Show_To = "11" - WHERE - wp.WebsiteId = ? AND - p.PageId = wp.PageId AND - p.Show_In LIKE "101" AND - e.PageId = p.PageId`, - [websiteId] - ); - } - } else if ( - (oldUserId !== null && userId !== null && oldUserId !== userId) || - (oldUserId !== null && userId === null) - ) { - if (!transfer || (oldUserId && !userId)) { - await queryRunner.manager.query( - ` - UPDATE - WebsitePage as wp, - Page as p, - Evaluation as e - SET - p.Show_In = "101", - e.Show_To = "10" - WHERE - wp.WebsiteId = ? AND - p.PageId = wp.PageId AND - p.Show_In = "111" AND - e.PageId = p.PageId`, - [websiteId] - ); - } - - await queryRunner.manager.query( - ` - UPDATE - WebsitePage as wp, - Page as p, - Evaluation as e - SET - p.Show_In = "100", - e.Show_To = "10" - WHERE - wp.WebsiteId = ? AND - p.PageId = wp.PageId AND - p.Show_In = "110" AND - e.PageId = p.PageId`, - [websiteId] - ); - - await queryRunner.manager.query( - ` - UPDATE - WebsitePage as wp, - Page as p, - Evaluation as e - SET - p.Show_In = "000", - e.Show_To = "10" - WHERE - wp.WebsiteId = ? AND - p.PageId = wp.PageId AND - p.Show_In = "010" AND - e.PageId = p.PageId`, - [websiteId] - ); - } - - for (const id of defaultEntities || []) { - if (!entities.includes(id)) { - await queryRunner.manager.query( - `DELETE FROM EntityWebsite WHERE EntityId = ? AND WebsiteId = ?`, - [id, websiteId] - ); - } - } - - for (const id of entities || []) { - if (!defaultEntities.includes(id)) { - await queryRunner.manager.query( - `INSERT INTO EntityWebsite (EntityId, WebsiteId) VALUES (?, ?)`, - [id, websiteId] - ); - } - } - - for (const id of defaultTags || []) { - if (!tags.includes(id)) { - await queryRunner.manager.query( - `DELETE FROM TagWebsite WHERE TagId = ? AND WebsiteId = ?`, - [id, websiteId] - ); - } - } - - for (const id of tags || []) { - if (!defaultTags.includes(id)) { - await queryRunner.manager.query( - `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, - [id, websiteId] - ); - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async findMyMonitorUserWebsiteStartingUrl( - userId: number, - websiteName: string - ): Promise { - const website = await this.websiteRepository.query( - `SELECT w.StartingUrl FROM - Website as w - WHERE - w.UserId = ? AND - w.Name = ? - LIMIT 1`, - [userId, websiteName] - ); - - return website ? website[0].StartingUrl : null; - } - - async updatePagesObservatory(updateObservatoryPages: UpdateObservatoryPages): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - - let hasError = false; - try { - for (const observatoryPage of updateObservatoryPages.pages || []) { - let show = null; - const id = observatoryPage.id; - const page = await this.pageRepository.findOne({where:{PageId:id}}); - - if (!observatoryPage.inObservatory) { - show = page.Show_In[0] + page.Show_In[2] + "0"; - } else { - show = page.Show_In[0] + page.Show_In[2] + "1"; - } - - await queryRunner.manager.update( - Page, - { PageId: page.PageId }, - { Show_In: show } - ); - } - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return !hasError; - } - - async delete(websiteId: number): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.query( - `DELETE FROM TagWebsite WHERE WebsiteId = ? AND TagId <> 0`, - [websiteId] - ); - - const pages = await queryRunner.manager.query( - ` - SELECT - wp.PageId - FROM - WebsitePage as wp - WHERE - wp.WebsiteId = ? - `, - [websiteId] - ); - - if (pages.length > 0) { - await queryRunner.manager.query( - ` - DELETE FROM - Page - WHERE - PageId IN (?) - `, - [pages.map((p) => p.PageId)] - ); - } - - await queryRunner.manager.query( - //`UPDATE Website SET UserId = NULL, EntityId = NULL, Deleted = 1 WHERE WebsiteId = ?`, - `DELETE FROM Website WHERE WebsiteId = ?`, - [websiteId] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return websiteId; - } - - async deleteBulk(websitesId: Array): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - await queryRunner.manager.query( - `DELETE FROM TagWebsite WHERE WebsiteId IN (?) AND TagId <> 0`, - [websitesId] - ); - - const pages = await queryRunner.manager.query( - ` - SELECT - wp.PageId - FROM - WebsitePage as wp - WHERE - wp.WebsiteId IN (?) - `, - [websitesId] - ); - if (pages.length > 0) { - await queryRunner.manager.query( - ` - DELETE FROM - Page - WHERE - PageId IN (?) - `, - [pages.map((p) => p.PageId)] - ); - } - - await queryRunner.manager.query( - //`UPDATE Website SET UserId = NULL, EntityId = NULL, Deleted = 1 WHERE WebsiteId = ?`, - `DELETE FROM Website WHERE WebsiteId IN (?)`, - [websitesId] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return websitesId; - } - - async pagesDeleteBulk(websitesId: Array): Promise { - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const pages = await queryRunner.manager.query( - ` - SELECT - PageId - FROM - WebsitePage - WHERE - WebsiteId IN (?) - `, - [websitesId] - ); - - await queryRunner.manager.query( - ` - DELETE FROM - Page - WHERE - PageId IN (?) - `, - [pages.map((p) => p.PageId)] - ); - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return websitesId; - } - - async import(websiteId: number, newWebsiteName: string): Promise { - let returnWebsiteId = websiteId; - const queryRunner = this.connection.createQueryRunner(); - - await queryRunner.connect(); - await queryRunner.startTransaction(); - - let hasError = false; - try { - const website = await queryRunner.manager.query( - `SELECT * - FROM - Website as w - WHERE - w.WebsiteId = ?`, - [websiteId] - ); - - const webDate = website[0].Creation_Date.toISOString() - .replace(/T/, " ") - .replace(/\..+/, ""); - - const pages = await queryRunner.manager.query( - `SELECT p.* - FROM - Page as p, - Website as w, - WebsitePage as wp - WHERE - wp.WebsiteId = w.WebsiteId AND - wp.PageId = p.PageId - w.WebsiteId = ? AND`, - [websiteId] - ); - - const websiteP = ( - await queryRunner.manager.query( - `SELECT distinct w.* - FROM - Website as w, - User as u - WHERE - w.StartingUrl = ? AND - (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type = "monitor")) - LIMIT 1 - `, - [website[0].StartingUrl] - ) - )[0]; - - const websiteUrl = website[0].StartingUrl; - - if (website.length > 0) { - if (websiteP) { - for (const page of pages || []) { - if (page.Show_In[0] === "0") { - await this.importPage(queryRunner, page.PageId); - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, - [websiteP.WebsiteId, page.PageId] - ); - } - } - - await queryRunner.manager.query( - `UPDATE Website SET Creation_Date = ? WHERE WebsiteId = ?`, - [webDate, websiteP.WebsiteId] - ); - } else { - const insertWebsite = await queryRunner.manager.query( - `INSERT INTO Website (Name, StartingUrl, Creation_Date) VALUES (?, ?, ?)`, - [newWebsiteName, websiteUrl, webDate] - ); - returnWebsiteId = insertWebsite.WebsiteId; - - for (const page of pages || []) { - if (page.Show_In[0] === "0") { - await this.importPage(queryRunner, page.PageId); - await queryRunner.manager.query( - `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?,?)`, - [website.WebsiteId, page.PageId] - ); - } - } - } - } - - await queryRunner.commitTransaction(); - } catch (err) { - console.log(err); - // since we have errors lets rollback the changes we made - await queryRunner.rollbackTransaction(); - hasError = true; - } finally { - // you need to release a queryRunner which was manually instantiated - await queryRunner.release(); - } - - return returnWebsiteId; - } - - private async importPage(queryRunner: any, pageId: number): Promise { - const page = await queryRunner.manager.query( - `SELECT Show_In FROM Page WHERE PageId = ? LIMIT 1`, - [pageId] - ); - - if (page.length > 0) { - const show = "1" + page[0].Show_In[1] + page[0].Show_In[2]; - await queryRunner.manager.query( - `UPDATE Page SET Show_In = ? WHERE PageId = ?`, - [show, pageId] - ); - - const evaluation = await queryRunner.manager.query( - `SELECT e.EvaluationId, e.Show_To FROM Evaluation as e WHERE e.PageId = ? AND e.Show_To LIKE "_1" ORDER BY e.Evaluation_Date DESC LIMIT 1`, - [pageId] - ); - - const evalId = evaluation[0].EvaluationId; - const showTo = evaluation[0].Show_To; - - if (evaluation.length > 0) { - const newShowTo = "1" + showTo[1]; - await queryRunner.manager.query( - `UPDATE Evaluation SET Show_To = ? WHERE EvaluationId = ?`, - [newShowTo, evalId] - ); - } - } - } -} +import { Injectable, InternalServerErrorException } from "@nestjs/common"; +import { InjectDataSource, InjectRepository } from "@nestjs/typeorm"; +import { DataSource, IsNull, Repository } from "typeorm"; +import { Page } from "../page/page.entity"; +import { EvaluationService } from "../evaluation/evaluation.service"; +import { AccessibilityStatementService } from "src/accessibility-statement-module/accessibility-statement/accessibility-statement.service"; +import { CollectionDateService } from "src/accessibility-statement-module/collection-date/collection-date.service"; +import { Tag } from "../tag/tag.entity"; +import { CreateWebsiteDto } from "./dto/create-website.dto"; +import { UpdateObservatoryPages } from "./dto/update-observatory-pages.dto"; +import { UpdateWebsiteDto } from "./dto/update-website.dto"; +import { Website } from "./website.entity"; + +@Injectable() +export class WebsiteService { + constructor( + @InjectRepository(Website) + private readonly websiteRepository: Repository, + private evaluationService: EvaluationService, + private readonly accessibilityStatementService: AccessibilityStatementService, + private readonly collectionDateService: CollectionDateService, + @InjectRepository(Tag) + private readonly tagRepository: Repository, + @InjectRepository(Page) + private readonly pageRepository: Repository, + @InjectDataSource() + private readonly connection: DataSource + ) {} + + async findAccessiblityStatements(): Promise { + const websites = await this.websiteRepository.find({ + relations: ["Pages"], + }); + await this.collectionDateService.create(); + for (const website of websites) { + const id = website.WebsiteId; + const pages = website.Pages; + await this.findAccessiblityStatementsInPageList(pages, website); + } + } + + async updateAStatement(WebsiteId: number): Promise { + const website = await this.websiteRepository.findOne({ + where: { WebsiteId }, + relations: ["Pages"], + }); + if (website) { + const pages = website.Pages; + await this.findAccessiblityStatementsInPageList(pages, website); + } + } + + async findAccessiblityStatementsInPageList( + pages: Page[], + website: Website + ): Promise { + for (const page of pages) { + const id = page.PageId; + const evaluation = await this.evaluationService.getLastEvaluationByPage( + id + ); + if (evaluation) { + const rawHtml = Buffer.from(evaluation.Pagecode, "base64").toString(); + await this.accessibilityStatementService.createIfExist( + rawHtml, + website, + page.Uri + ); + } + } + } + async getAllWebsiteDataCSV(): Promise { + const websites = await this.websiteRepository.find({ relations: ["Tags"] }); + return await Promise.all( + websites.map(async (website) => { + const id = website.WebsiteId; + const pages = await this.findAllPages(id); + website["numberOfPages"] = pages.length; + website["averagePoints"] = this.averagePointsPageEvaluation(pages); + return website; + }) + ); + } + private averagePointsPageEvaluation(pages) { + const totalPoints = pages.reduce((total, page) => { + return total + +page.Score; + }, 0); + return totalPoints / pages.length; + } + + async addPagesToEvaluate( + websitesId: number[], + option: string + ): Promise { + const pages = await this.websiteRepository.query( + ` + SELECT + p.PageId, + p.Uri + FROM + WebsitePage as wp, + Page as p + WHERE + wp.WebsiteId IN (?) AND + p.PageId = wp.PageId AND + p.Show_In LIKE ?`, + [websitesId, option === "all" ? "1__" : "1_1"] + ); + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + let error = false; + try { + for (const page of pages || []) { + try { + const pageEval = await queryRunner.manager.query( + `SELECT * FROM Evaluation_List WHERE PageId = ? AND UserId = -1 AND Url = ? AND Show_To = ? LIMIT 1`, + [page.PageId, page.Uri, "10"] + ); + if (pageEval.length > 0) { + await queryRunner.manager.query( + `UPDATE Evaluation_List SET Error = NULL, Is_Evaluating = 0 WHERE EvaluationListId = ?`, + [pageEval[0].EvaluationListId] + ); + } else { + await queryRunner.manager.query( + `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, + [page.PageId, -1, page.Uri, "10", new Date()] + ); + } + } catch (_) {} + } + + await queryRunner.manager.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "AMS/Observatory"`, + [pages.length] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.log(err); + error = true; + } finally { + await queryRunner.release(); + } + + return !error; + } + + async adminCount(search: string): Promise { + const count = await this.websiteRepository.query( + `SELECT COUNT(w.WebsiteId) as Count + FROM + Website as w + LEFT OUTER JOIN User as u ON u.UserId = w.UserId + WHERE + w.Name LIKE ? AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies'))`, + [search.trim() !== "" ? `%${search.trim()}%` : "%"] + ); + + return count[0].Count; + } + + async getIdFromUserAndName(user: string, name: string): Promise { + const website = await this.websiteRepository.query( + ` + SELECT w.* FROM Website as w, User as u + WHERE + w.Name LIKE ? AND + ((w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) OR + w.UserId IS NOT NULL AND (u.UserId = w.UserId AND u.Username LIKE ?)) + LIMIT 1 + `, + [name, user] + ); + return website[0].WebsiteId; + } + + async findAll( + size: number, + page: number, + sort: string, + direction: string, + search: string + ): Promise { + if (!direction.trim()) { + const websites = await this.websiteRepository.query( + ` + SELECT + w.*, + u.Username as User, u.Type as Type, + COUNT(distinct p.PageId) as Pages, + COUNT(distinct e.PageId) as Evaluated_Pages + FROM + Website as w + LEFT OUTER JOIN User as u ON u.UserId = w.UserId + LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId + LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE "1__" + LEFT OUTER JOIN Evaluation as e ON e.PageId = p.PageId + WHERE + (w.Name LIKE ? OR w.StartingUrl LIKE ?) AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) + GROUP BY w.WebsiteId + LIMIT ? OFFSET ?`, + [ + search.trim() !== "" ? `%${search.trim()}%` : "%", + search.trim() !== "" ? `%${search.trim()}%` : "%", + size, + page * size, + ] + ); + + /* + LEFT OUTER JOIN Evaluation as e2 ON e.PageId = p.PageId AND e2.Evaluation_Date = ( + SELECT Evaluation_Date FROM Evaluation + WHERE PageId = p.PageId + ORDER BY Evaluation_Date DESC LIMIT 1 + ) + */ + return websites; + } else { + let order = ""; + switch (sort) { + case "Name": + order = "w.Name"; + break; + case "StartingUrl": + order = "w.StartingUrl"; + break; + case "Pages": + order = "Pages"; + break; + case "Creation_Date": + order = "w.Creation_Date"; + break; + } + + const websites = await this.websiteRepository.query( + ` + SELECT + w.*, + u.Username as User, u.Type as Type, + COUNT(distinct p.PageId) as Pages, + COUNT(distinct e.PageId) as Evaluated_Pages + FROM + Website as w + LEFT OUTER JOIN User as u ON u.UserId = w.UserId + LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId + LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE "1__" + LEFT OUTER JOIN Evaluation as e ON e.PageId = p.PageId + WHERE + (w.Name LIKE ? OR w.StartingUrl LIKE ?) AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) + GROUP BY w.WebsiteId + ORDER BY ${order} ${direction.toUpperCase()} + LIMIT ? OFFSET ?`, + [ + search.trim() !== "" ? `%${search.trim()}%` : "%", + search.trim() !== "" ? `%${search.trim()}%` : "%", + size, + page * size, + ] + ); + return websites; + } + } + + async findInfo(websiteId: number): Promise { + const websites = await this.websiteRepository.query( + `SELECT w.*, u.Username as User, e.Long_Name as Entity, COUNT(distinct wp.PageId) as Pages + FROM + Website as w + LEFT OUTER JOIN User as u ON u.UserId = w.UserId + LEFT OUTER JOIN EntityWebsite as ew ON ew.WebsiteId = w.WebsiteId + LEFT OUTER JOIN Entity as e ON e.EntityId = ew.EntityId + LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId + WHERE + w.WebsiteId = ? + GROUP BY w.WebsiteId, w.StartingUrl + LIMIT 1`, + [websiteId] + ); + + if (websites) { + const website = websites[0]; + + website.tags = await this.websiteRepository.query( + `SELECT t.* FROM Tag as t, TagWebsite as tw WHERE tw.WebsiteId = ? AND t.TagId = tw.TagId`, + [websiteId] + ); + + website.entities = await this.websiteRepository.query( + `SELECT e.* FROM Entity as e, EntityWebsite as ew WHERE ew.WebsiteId = ? AND e.EntityId = ew.EntityId`, + [websiteId] + ); + return website; + } else { + throw new InternalServerErrorException(); + } + } + + async findUserType(username: string): Promise { + if (username === "admin") { + return "nimda"; + } + + const user = await this.websiteRepository.query( + `SELECT * FROM User WHERE Username = ? LIMIT 1`, + [username] + ); + + if (user) { + return user[0].Type; + } else { + return null; + } + } + + async findAllPages(websiteId: number): Promise { + const pages = await this.websiteRepository.query( + `SELECT + distinct p.*, + e.Score, + e.A, + e.AA, + e.AAA, + e.Tot, + e.Errors, + e.Element_Count, + e.Tag_Count, + e.Evaluation_Date, + el.EvaluationListId, el.Error, el.Is_Evaluating + FROM + WebsitePage as wp, + Page as p + LEFT OUTER JOIN Evaluation_List as el ON el.PageId = p.PageId AND el.UserId = -1 + LEFT OUTER JOIN Evaluation as e ON e.PageId = p.PageId AND e.Show_To LIKE "1_" AND e.Evaluation_Date IN ( + SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND Show_To LIKE "1_" + ) + WHERE + wp.WebsiteId = ? AND + p.PageId = wp.PageId AND + p.Show_In LIKE "1__"`, + [websiteId] + ); + + return pages; + } + + async findAllOfficial(): Promise { + const websites = await this.websiteRepository.query(`SELECT distinct w.* + FROM + Website as w, + User as u + WHERE + w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')`); + return websites; + } + + async findByOfficialName(name: string): Promise { + const website = await this.websiteRepository.findOne({ + where: { Name: name, UserId: IsNull() }, + }); + return website; + /*if (website && website.Name !== name) { + return undefined; + } else { + return website; + }*/ + } + + async existsUrl(url: string): Promise { + return ( + ( + await this.websiteRepository.query( + `SELECT w.* + FROM + Website as w, + User as u + WHERE + w.StartingUrl = ? AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) + LIMIT 1`, + [url] + ) + ).length > 0 + ); + } + + async findAllWithoutUser(): Promise { + const websites = await this.websiteRepository.query( + `SELECT * FROM Website WHERE UserId IS NULL` + ); + return websites; + } + /** + * + * SELECT distinct w.* + FROM + User as u , + EntityWebsite as ew + LEFT OUTER JOIN Website as ew ON w.WebsiteId = ew.WebsiteId + WHERE + ew.EntityId IS NULL AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies')) + */ + async findAllWithoutEntity(): Promise { + const websites = await this.websiteRepository.query(`SELECT distinct w.* + FROM + User as u , + EntityWebsite as ew + LEFT OUTER JOIN Website as ew ON w.WebsiteId = ew.WebsiteId + WHERE + ew.EntityId IS NULL AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type != 'studies'))`); + return websites; //TODO: fix + } + + async findAllFromMyMonitorUser(userId: number): Promise { + const websites = await this.websiteRepository.query( + `SELECT w.*, COUNT(distinct p.PageId) as Pages + FROM + Website as w + LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId + LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId AND p.Show_In LIKE '_1%' + WHERE + w.UserId = ? + GROUP BY w.WebsiteId, w.StartingUrl`, + [userId] + ); + return websites; + } + + async isInObservatory(userId: number, website: string): Promise { + const tags = await this.websiteRepository.query( + ` + SELECT t.* + FROM + Directory as d, + DirectoryTag as dt, + Tag as t, + TagWebsite as tw, + Website as w + WHERE + w.UserId = ? AND + w.Name = ? AND + tw.WebsiteId = w.WebsiteId AND + t.TagId = tw.TagId AND + t.UserId IS NULL AND + dt.TagId = t.TagId AND + d.DirectoryId = dt.DirectoryId AND + d.Show_In_Observatory = 1 + `, + [userId, website] + ); + + return tags.length > 0; + } + + async transferObservatoryPages( + userId: number, + website: string + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + let error = false; + try { + const pages = await queryRunner.manager.query( + ` + SELECT + p.* + FROM + Directory as dir, + DirectoryTag as dt, + Tag as t, + TagWebsite as tw, + Website as w, + WebsitePage as wp, + Page as p + WHERE + w.UserId = ? AND + w.Name = ? AND + tw.WebsiteId = w.WebsiteId AND + t.TagId = tw.TagId AND + t.UserId IS NULL AND + dt.TagId = t.TagId AND + dir.DirectoryId = dt.DirectoryId AND + dir.Show_In_Observatory = 1 AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId and + p.Show_In LIKE "_01" + `, + [userId, website] + ); + + for (const page of pages || []) { + const evaluation = await queryRunner.manager.query( + ` + SELECT * + FROM + Evaluation + WHERE + PageId = ? AND + Show_To LIKE "1_" + ORDER BY Evaluation_Date DESC LIMIT 1 + `, + [page.PageId] + ); + if (evaluation.length > 0) { + await queryRunner.manager.query( + `UPDATE Page SET Show_In = ? WHERE PageId = ?`, + [page.Show_In[0] + "1" + page.Show_In[2], page.PageId] + ); + await queryRunner.manager.query( + `UPDATE Evaluation SET Show_To = ? WHERE EvaluationId = ?`, + [evaluation[0].Show_To[0] + "1", evaluation[0].EvaluationId] + ); + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.log(err); + error = true; + } finally { + await queryRunner.release(); + } + + return !error; + } + + async reEvaluateMyMonitorWebsite( + userId: number, + websiteName: string + ): Promise { + const website = await this.websiteRepository.findOne({ + where: { UserId: userId, Name: websiteName }, + }); + if (!website) { + throw new InternalServerErrorException(); + } + + const pages = await this.websiteRepository.query( + `SELECT + distinct p.* + FROM + Page as p, + Website as w, + WebsitePage as wp + WHERE + w.Name = ? AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId AND + p.Show_In LIKE '_1_'`, + [website.Name, website.UserId] + ); + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + let error = false; + try { + for (const page of pages || []) { + try { + await queryRunner.manager.query( + `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, + [page.PageId, userId, page.Uri, "01", new Date()] + ); + } catch (_) {} + } + + await queryRunner.manager.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "MyMonitor"`, + [pages.length] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.log(err); + error = true; + } finally { + await queryRunner.release(); + } + + return !error; + } + + async reEvaluateStudyMonitorWebsite( + userId: number, + tag: string, + website: string + ): Promise { + const websiteExists = await this.websiteRepository.query( + `SELECT * FROM Website WHERE UserId = ? AND Name = ? LIMIT 1`, + [userId, website] + ); + + if (!websiteExists) { + throw new InternalServerErrorException(); + } + + const pages = await this.websiteRepository.query( + `SELECT + distinct p.* + FROM + Page as p, + Tag as t, + TagWebsite as tw, + Website as w, + WebsitePage as wp + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.Name = ? AND + w.UserId = ? AND + wp.WebsiteId = w.WebsiteId AND + p.PageId = wp.PageId`, + [tag, userId, website, userId] + ); + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + + await queryRunner.startTransaction(); + + let error = false; + try { + for (const page of pages || []) { + try { + await queryRunner.manager.query( + `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date, StudyUserId) VALUES (?, ?, ?, ?, ?, ?)`, + [page.PageId, userId, page.Uri, "00", new Date(), userId] + ); + } catch (_) {} + } + + await queryRunner.manager.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "StudyMonitor"`, + [pages.length] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + console.log(err); + error = true; + } finally { + await queryRunner.release(); + } + + return !error; + } + + async findAllFromStudyMonitorUserTag( + userId: number, + tagName: string + ): Promise { + const tag = await this.tagRepository.findOne({ + where: { UserId: userId, Name: tagName }, + }); + if (tag) { + return await this.websiteRepository.query( + `SELECT + w.WebsiteId, + w.Name, + w.StartingUrl, + COUNT(distinct p.PageId) as Pages, + AVG(e.Score) as Score + FROM + Tag as t, + TagWebsite as tw, + Website as w + LEFT OUTER JOIN WebsitePage as wp ON wp.WebsiteId = w.WebsiteId + LEFT OUTER JOIN Page as p ON p.PageId = wp.PageId + LEFT OUTER JOIN Evaluation as e ON e.StudyUserId = ? AND e.Evaluation_Date IN ( + SELECT max(Evaluation_Date) FROM Evaluation WHERE PageId = p.PageId AND StudyUserId = e.StudyUserId + ) + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.UserId = ? + GROUP BY w.WebsiteId, w.StartingUrl`, + [userId, tagName, userId, userId] + ); + } else { + throw new InternalServerErrorException(); + } + } + + async findAllFromStudyMonitorUserOtherTagsWebsites( + userId: number, + tagName: string + ): Promise { + const websites = await this.websiteRepository.query( + `SELECT + distinct w.*, + t.Name as TagName + FROM + Tag as t, + TagWebsite as tw, + Website as w + WHERE + t.Name != ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.UserId = ? AND + w.Name NOT IN ( + SELECT + w2.Name + FROM + Tag as t2, + TagWebsite as tw2, + Website as w2 + WHERE + t2.Name = ? AND + t2.UserId = ? AND + tw2.TagId = t2.TagId AND + w2.WebsiteId = tw2.WebsiteId AND + w2.UserId = ? + ) AND + w.StartingUrl NOT IN ( + SELECT + w2.StartingUrl + FROM + Tag as t2, + TagWebsite as tw2, + Website as w2 + WHERE + t2.Name = ? AND + t2.UserId = ? AND + tw2.TagId = t2.TagId AND + w2.WebsiteId = tw2.WebsiteId AND + w2.UserId = ? + )`, + [ + tagName, + userId, + userId, + tagName, + userId, + userId, + tagName, + userId, + userId, + ] + ); + + return websites; + } + + async findStudyMonitorUserTagWebsiteByName( + userId: number, + tag: string, + websiteName: string + ): Promise { + const website = await this.websiteRepository.query( + `SELECT * FROM + Tag as t, + TagWebsite as tw, + Website as w + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.UserId = ? AND + w.Name = ? + LIMIT 1`, + [tag, userId, userId, websiteName] + ); + + return website[0]; + } + + async findStudyMonitorUserTagWebsiteByStartingUrl( + userId: number, + tag: string, + startingUrl: string + ): Promise { + const website = await this.websiteRepository.query( + `SELECT * FROM + Tag as t, + TagWebsite as tw, + Website as w + WHERE + t.Name = ? AND + t.UserId = ? AND + tw.TagId = t.TagId AND + w.WebsiteId = tw.WebsiteId AND + w.UserId = ? AND + w.StartingUrl = ? + LIMIT 1`, + [tag, userId, userId, startingUrl] + ); + + return website[0]; + } + + async linkStudyMonitorUserTagWebsite( + userId: number, + tag: string, + websitesId: number[] + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + for (const id of websitesId || []) { + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) + SELECT TagId, ? FROM Tag WHERE Name = ? AND UserId = ?`, + [id, tag, userId] + ); + } + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async createStudyMonitorUserTagWebsite( + userId: number, + tag: string, + websiteName: string, + startingUrl: string, + pages: string[] + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const newWebsite = new Website(); + newWebsite.UserId = userId; + newWebsite.Name = websiteName; + newWebsite.StartingUrl = startingUrl; + newWebsite.Creation_Date = new Date(); + + const insertWebsite = await queryRunner.manager.save(newWebsite); + + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) SELECT TagId, ? FROM Tag WHERE Name = ?`, + [insertWebsite.WebsiteId, tag] + ); + + for (const url of pages || []) { + const page = await queryRunner.manager.findOne(Page, { + where: { Uri: url }, + }); + if (page) { + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, + [insertWebsite.WebsiteId, page.PageId] + ); + await queryRunner.manager.query( + `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date, StudyUserId) VALUES (?, ?, ?, ?, ?, ?)`, + [page.PageId, userId, page.Uri, "00", page.Creation_Date, userId] + ); + } else { + //const evaluation = await this.evaluationService.evaluateUrl(url); + + const newPage = new Page(); + newPage.Uri = url; + newPage.Show_In = "000"; + newPage.Creation_Date = newWebsite.Creation_Date; + + const insertPage = await queryRunner.manager.save(newPage); + + //await this.evaluationService.savePageEvaluation(queryRunner, insertPage.PageId, evaluation, '01'); + + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, + [insertWebsite.WebsiteId, insertPage.PageId] + ); + + const existingWebsite = await queryRunner.manager.query( + `SELECT distinct w.WebsiteId, w.StartingUrl + FROM + User as u, + Website as w + WHERE + w.StartingUrl = ? AND + ( + w.UserId IS NULL OR + ( + u.UserId = w.UserId AND + u.Type = 'monitor' + ) + ) + LIMIT 1`, + [startingUrl] + ); + + if (existingWebsite.length > 0) { + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, + [existingWebsite[0].WebsiteId, newPage.PageId] + ); + } + + await queryRunner.manager.query( + `INSERT INTO Evaluation_List (PageId, UserId, Url, Show_To, Creation_Date) VALUES (?, ?, ?, ?, ?)`, + [ + insertPage.PageId, + userId, + insertPage.Uri, + "00", + insertPage.Creation_Date, + ] + ); + } + } + + await queryRunner.manager.query( + `UPDATE Evaluation_Request_Counter SET Counter = Counter + ?, Last_Request = NOW() WHERE Application = "StudyMonitor"`, + [pages.length] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async removeStudyMonitorUserTagWebsite( + userId: number, + tag: string, + websitesId: number[] + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + for (const id of websitesId || []) { + const relations = await queryRunner.manager.query( + `SELECT tw.* FROM TagWebsite as tw, Website as w + WHERE + tw.WebsiteId = ? AND + tw.TagId <> -1 AND + w.WebsiteId = tw.WebsiteId AND + w.UserId = ?`, + [id, userId] + ); + + if (relations) { + await queryRunner.manager.query( + ` + DELETE tw FROM Tag as t, TagWebsite as tw + WHERE + t.Name = ? AND + tw.TagId = t.TagId AND + tw.WebsiteId = ?`, + [tag, id] + ); + } else { + await queryRunner.manager.delete(Website, { WebsiteId: id }); + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async findNumberOfStudyMonitor(): Promise { + return ( + await this.websiteRepository.query( + `SELECT COUNT(w.WebsiteId) as Websites FROM Website as w, User as u WHERE u.Type = "studies" AND w.UserId = u.UserId` + ) + )[0].Websites; + } + + async findNumberOfMyMonitor(): Promise { + return ( + await this.websiteRepository.query( + `SELECT COUNT(w.WebsiteId) as Websites FROM Website as w, User as u WHERE u.Type = "monitor" AND w.UserId = u.UserId` + ) + )[0].Websites; + } + + async findNumberOfObservatory(): Promise { + /*const manager = getManager(); + return ( + await manager.query(` + SELECT + COUNT(distinct w.WebsiteId) as Websites + FROM + Directory as d, + DirectoryTag as dt, + TagWebsite as tw, + Website as w + WHERE + d.Show_in_Observatory = 1 AND + dt.DirectoryId = d.DirectoryId AND + tw.TagId = dt.TagId AND + w.WebsiteId = tw.WebsiteId`) + )[0].Websites;*/ + + const data = ( + await this.websiteRepository.query( + "SELECT * FROM Observatory ORDER BY Creation_Date DESC LIMIT 1" + ) + )[0].Global_Statistics; + const dataPrint = await this.connection.query( + `SELECT + COUNT(distinct w.WebsiteId) as Websites + FROM + Directory as d, + DirectoryTag as dt, + TagWebsite as tw, + Website as w + WHERE + d.Show_in_Observatory = 1 AND + dt.DirectoryId = d.DirectoryId AND + tw.TagId = dt.TagId AND + w.WebsiteId = tw.WebsiteId` + ); + console.log(dataPrint[0].Websites); + const parsedData = JSON.parse(data); + return parsedData.nWebsites; + } + + async createOne( + websiteDto: CreateWebsiteDto, + entities: string[], + tags: string[] + ): Promise { + const website = new Website(); + website.Name = websiteDto.name; + website.UserId = websiteDto.userId; + website.Declaration = websiteDto.declaration; + website.Declaration_Update_Date = websiteDto.declaration_Update_Date; + website.Stamp = websiteDto.stamp; + website.Stamp_Update_Date = websiteDto.stamp_Update_Date; + website.Creation_Date = new Date(); + + website.Creation_Date = new Date(); + website.StartingUrl = decodeURIComponent(websiteDto.startingUrl); + + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const insertWebsite = await queryRunner.manager.save(website); + + for (const entity of entities || []) { + await queryRunner.manager.query( + `INSERT INTO EntityWebsite (EntityId, WebsiteId) VALUES (?, ?)`, + [entity, insertWebsite.WebsiteId] + ); + } + + for (const tag of tags || []) { + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, + [tag, insertWebsite.WebsiteId] + ); + } + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async update(updateWebsiteDto: UpdateWebsiteDto): Promise { + const oldUserId = updateWebsiteDto.oldUserId; + const userId = updateWebsiteDto.userId; + const transfer = updateWebsiteDto.transfer; + const websiteId = updateWebsiteDto.websiteId; + const entities = updateWebsiteDto.entities; + const defaultEntities = updateWebsiteDto.defaultEntities; + const defaultTags = updateWebsiteDto.defaultTags; + const tags = updateWebsiteDto.tags; + updateWebsiteDto.startingUrl = decodeURIComponent( + updateWebsiteDto.startingUrl + ); + + const queryRunner = this.connection.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.update( + Website, + { WebsiteId: websiteId }, + { + UserId: userId, + Name: updateWebsiteDto.name, + StartingUrl: updateWebsiteDto.startingUrl, + Declaration: updateWebsiteDto.declaration, + Declaration_Update_Date: updateWebsiteDto.declarationUpdateDate, + Stamp: updateWebsiteDto.stamp, + Stamp_Update_Date: updateWebsiteDto.stampUpdateDate, + } + ); + if (oldUserId === null && userId !== null) { + if (transfer) { + await queryRunner.manager.query( + ` + UPDATE + WebsitePage as wp, + Page as p, + Evaluation as e + SET + p.Show_In = "111", + e.Show_To = "11" + WHERE + wp.WebsiteId = ? AND + p.PageId = wp.PageId AND + p.Show_In LIKE "101" AND + e.PageId = p.PageId`, + [websiteId] + ); + } + } else if ( + (oldUserId !== null && userId !== null && oldUserId !== userId) || + (oldUserId !== null && userId === null) + ) { + if (!transfer || (oldUserId && !userId)) { + await queryRunner.manager.query( + ` + UPDATE + WebsitePage as wp, + Page as p, + Evaluation as e + SET + p.Show_In = "101", + e.Show_To = "10" + WHERE + wp.WebsiteId = ? AND + p.PageId = wp.PageId AND + p.Show_In = "111" AND + e.PageId = p.PageId`, + [websiteId] + ); + } + + await queryRunner.manager.query( + ` + UPDATE + WebsitePage as wp, + Page as p, + Evaluation as e + SET + p.Show_In = "100", + e.Show_To = "10" + WHERE + wp.WebsiteId = ? AND + p.PageId = wp.PageId AND + p.Show_In = "110" AND + e.PageId = p.PageId`, + [websiteId] + ); + + await queryRunner.manager.query( + ` + UPDATE + WebsitePage as wp, + Page as p, + Evaluation as e + SET + p.Show_In = "000", + e.Show_To = "10" + WHERE + wp.WebsiteId = ? AND + p.PageId = wp.PageId AND + p.Show_In = "010" AND + e.PageId = p.PageId`, + [websiteId] + ); + } + + for (const id of defaultEntities || []) { + if (!entities.includes(id)) { + await queryRunner.manager.query( + `DELETE FROM EntityWebsite WHERE EntityId = ? AND WebsiteId = ?`, + [id, websiteId] + ); + } + } + + for (const id of entities || []) { + if (!defaultEntities.includes(id)) { + await queryRunner.manager.query( + `INSERT INTO EntityWebsite (EntityId, WebsiteId) VALUES (?, ?)`, + [id, websiteId] + ); + } + } + + for (const id of defaultTags || []) { + if (!tags.includes(id)) { + await queryRunner.manager.query( + `DELETE FROM TagWebsite WHERE TagId = ? AND WebsiteId = ?`, + [id, websiteId] + ); + } + } + + for (const id of tags || []) { + if (!defaultTags.includes(id)) { + await queryRunner.manager.query( + `INSERT INTO TagWebsite (TagId, WebsiteId) VALUES (?, ?)`, + [id, websiteId] + ); + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async findMyMonitorUserWebsiteStartingUrl( + userId: number, + websiteName: string + ): Promise { + const website = await this.websiteRepository.query( + `SELECT w.StartingUrl FROM + Website as w + WHERE + w.UserId = ? AND + w.Name = ? + LIMIT 1`, + [userId, websiteName] + ); + + return website ? website[0].StartingUrl : null; + } + + async updatePagesObservatory( + updateObservatoryPages: UpdateObservatoryPages + ): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + for (const observatoryPage of updateObservatoryPages.pages || []) { + let show = null; + const id = observatoryPage.id; + const page = await this.pageRepository.findOne({ + where: { PageId: id }, + }); + + if (!observatoryPage.inObservatory) { + show = page.Show_In[0] + page.Show_In[2] + "0"; + } else { + show = page.Show_In[0] + page.Show_In[2] + "1"; + } + + await queryRunner.manager.update( + Page, + { PageId: page.PageId }, + { Show_In: show } + ); + } + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return !hasError; + } + + async delete(websiteId: number): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.query( + `DELETE FROM TagWebsite WHERE WebsiteId = ? AND TagId <> 0`, + [websiteId] + ); + + const pages = await queryRunner.manager.query( + ` + SELECT + wp.PageId + FROM + WebsitePage as wp + WHERE + wp.WebsiteId = ? + `, + [websiteId] + ); + + if (pages.length > 0) { + await queryRunner.manager.query( + ` + DELETE FROM + Page + WHERE + PageId IN (?) + `, + [pages.map((p) => p.PageId)] + ); + } + + await queryRunner.manager.query( + //`UPDATE Website SET UserId = NULL, EntityId = NULL, Deleted = 1 WHERE WebsiteId = ?`, + `DELETE FROM Website WHERE WebsiteId = ?`, + [websiteId] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return websiteId; + } + + async deleteBulk(websitesId: Array): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + await queryRunner.manager.query( + `DELETE FROM TagWebsite WHERE WebsiteId IN (?) AND TagId <> 0`, + [websitesId] + ); + + const pages = await queryRunner.manager.query( + ` + SELECT + wp.PageId + FROM + WebsitePage as wp + WHERE + wp.WebsiteId IN (?) + `, + [websitesId] + ); + if (pages.length > 0) { + await queryRunner.manager.query( + ` + DELETE FROM + Page + WHERE + PageId IN (?) + `, + [pages.map((p) => p.PageId)] + ); + } + + await queryRunner.manager.query( + //`UPDATE Website SET UserId = NULL, EntityId = NULL, Deleted = 1 WHERE WebsiteId = ?`, + `DELETE FROM Website WHERE WebsiteId IN (?)`, + [websitesId] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return websitesId; + } + + async pagesDeleteBulk(websitesId: Array): Promise { + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const pages = await queryRunner.manager.query( + ` + SELECT + PageId + FROM + WebsitePage + WHERE + WebsiteId IN (?) + `, + [websitesId] + ); + + await queryRunner.manager.query( + ` + DELETE FROM + Page + WHERE + PageId IN (?) + `, + [pages.map((p) => p.PageId)] + ); + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return websitesId; + } + + async import(websiteId: number, newWebsiteName: string): Promise { + let returnWebsiteId = websiteId; + const queryRunner = this.connection.createQueryRunner(); + + await queryRunner.connect(); + await queryRunner.startTransaction(); + + let hasError = false; + try { + const website = await queryRunner.manager.query( + `SELECT * + FROM + Website as w + WHERE + w.WebsiteId = ?`, + [websiteId] + ); + + const webDate = website[0].Creation_Date.toISOString() + .replace(/T/, " ") + .replace(/\..+/, ""); + + const pages = await queryRunner.manager.query( + `SELECT p.* + FROM + Page as p, + Website as w, + WebsitePage as wp + WHERE + wp.WebsiteId = w.WebsiteId AND + wp.PageId = p.PageId + w.WebsiteId = ? AND`, + [websiteId] + ); + + const websiteP = ( + await queryRunner.manager.query( + `SELECT distinct w.* + FROM + Website as w, + User as u + WHERE + w.StartingUrl = ? AND + (w.UserId IS NULL OR (u.UserId = w.UserId AND u.Type = "monitor")) + LIMIT 1 + `, + [website[0].StartingUrl] + ) + )[0]; + + const websiteUrl = website[0].StartingUrl; + + if (website.length > 0) { + if (websiteP) { + for (const page of pages || []) { + if (page.Show_In[0] === "0") { + await this.importPage(queryRunner, page.PageId); + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?, ?)`, + [websiteP.WebsiteId, page.PageId] + ); + } + } + + await queryRunner.manager.query( + `UPDATE Website SET Creation_Date = ? WHERE WebsiteId = ?`, + [webDate, websiteP.WebsiteId] + ); + } else { + const insertWebsite = await queryRunner.manager.query( + `INSERT INTO Website (Name, StartingUrl, Creation_Date) VALUES (?, ?, ?)`, + [newWebsiteName, websiteUrl, webDate] + ); + returnWebsiteId = insertWebsite.WebsiteId; + + for (const page of pages || []) { + if (page.Show_In[0] === "0") { + await this.importPage(queryRunner, page.PageId); + await queryRunner.manager.query( + `INSERT INTO WebsitePage (WebsiteId, PageId) VALUES (?,?)`, + [website.WebsiteId, page.PageId] + ); + } + } + } + } + + await queryRunner.commitTransaction(); + } catch (err) { + console.log(err); + // since we have errors lets rollback the changes we made + await queryRunner.rollbackTransaction(); + hasError = true; + } finally { + // you need to release a queryRunner which was manually instantiated + await queryRunner.release(); + } + + return returnWebsiteId; + } + + private async importPage(queryRunner: any, pageId: number): Promise { + const page = await queryRunner.manager.query( + `SELECT Show_In FROM Page WHERE PageId = ? LIMIT 1`, + [pageId] + ); + + if (page.length > 0) { + const show = "1" + page[0].Show_In[1] + page[0].Show_In[2]; + await queryRunner.manager.query( + `UPDATE Page SET Show_In = ? WHERE PageId = ?`, + [show, pageId] + ); + + const evaluation = await queryRunner.manager.query( + `SELECT e.EvaluationId, e.Show_To FROM Evaluation as e WHERE e.PageId = ? AND e.Show_To LIKE "_1" ORDER BY e.Evaluation_Date DESC LIMIT 1`, + [pageId] + ); + + const evalId = evaluation[0].EvaluationId; + const showTo = evaluation[0].Show_To; + + if (evaluation.length > 0) { + const newShowTo = "1" + showTo[1]; + await queryRunner.manager.query( + `UPDATE Evaluation SET Show_To = ? WHERE EvaluationId = ?`, + [newShowTo, evalId] + ); + } + } + } +} diff --git a/test/app.e2e-spec.ts b/test/app.e2e-spec.ts index 8c6434f6..05db0a79 100644 --- a/test/app.e2e-spec.ts +++ b/test/app.e2e-spec.ts @@ -1,24 +1,24 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import * as request from 'supertest'; -import { AppModule } from './../src/app.module'; - -describe('AppController (e2e)', () => { - let app: INestApplication; - - beforeEach(async () => { - const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = moduleFixture.createNestApplication(); - await app.init(); - }); - - it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); - }); -}); +import { Test, TestingModule } from "@nestjs/testing"; +import { INestApplication } from "@nestjs/common"; +import * as request from "supertest"; +import { AppModule } from "./../src/app.module"; + +describe("AppController (e2e)", () => { + let app: INestApplication; + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + await app.init(); + }); + + it("/ (GET)", () => { + return request(app.getHttpServer()) + .get("/") + .expect(200) + .expect("Hello World!"); + }); +}); diff --git a/test/website.e2e-spec.ts b/test/website.e2e-spec.ts index 8bb23bb8..5a449dd4 100644 --- a/test/website.e2e-spec.ts +++ b/test/website.e2e-spec.ts @@ -1,48 +1,48 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { INestApplication } from '@nestjs/common'; -import * as request from 'supertest'; -import { AuthGuard } from '@nestjs/passport'; -import { WebsiteModule } from 'src/website/website.module'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { readFileSync } from 'fs'; +import { Test, TestingModule } from "@nestjs/testing"; +import { INestApplication } from "@nestjs/common"; +import * as request from "supertest"; +import { AuthGuard } from "@nestjs/passport"; +import { WebsiteModule } from "src/website/website.module"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { readFileSync } from "fs"; -describe('WebsiteController (e2e)', () => { +describe("WebsiteController (e2e)", () => { let app: INestApplication; - const CREATE_WEBSITE = '/website/create';//post - const UPDATE_WEBSITE = '/website/update';//post - const DELETE_BULK_WEBSITE = '/website/deleteBulk';//post - const REEVALUTE_WEBSITE = '/website/reEvaluate';//post - const UPDATE_OBSERVATORY_PAGES_WEBSITE = '/website/pages/updateObservatory';//post - const DELETE_WEBSITE = '/website/';//delete :id - const MYMONITOR_WEBSITE_DOMANIN = "/website/myMonitor/url/";//get :website - const DELETE_PAGES_WEBSITE = "/website/pages/deleteBulk";// post - const IMPORT_WEBSITE = "website/import";//post - const ADMIN_COUNT_WEBSITE = "website/all/count/"//get :search - const ADMIN_ALL_WEBSITES = "website/all/"//get :size/:page/:sort/:diretion/:search - const WEBSITE_INFO = "website/info/"//get :websiteId - const WEBSITE_USER_NAME ="website/";//get :website/user/:user/pages - const WEBSITE_CSV = "website/csv";//get - const PAGES_WEBSITE = "website/pages/";//get :websiteId - const OFICIAL_WEBSITE = "website/oficial";//get - const WITHOUT_USER_WEBSITE = "website/withoutUser"//get - const WITHOUT_ENTITY_WEBSITE = "website/withoutEntity"//get - const STUDY_MONITOR_TOTAL_WEBSITES = "website/studyMonitor/total";//get - const MY_MONITOR_TOTAL_WEBSITES = "website/myMonitor/total";//get - const OBSERVATORY_TOTAL_WEBSITES = "website/observatory/total";//get - const WEBSITE_EXISTS_NAME = "website/exists";//get :name - const WEBSITE_EXISTS_URL = "website/exists/url";//get :url - const WEBSITE_IN_OBSERVATORY = "website/isInObservatory";//post - const WEBSITE_TRANSFER_OBSERVATORY = "website/tranferObservatoryPages";//post - const WEBSITE_MY_MONITOR = "website/myMonitor";//get - const WEBSITE_MY_MONITOR_REEVALUATE = "website/myMonitor/reEvalute";//post - const WEBSITE_STUDY_MONITOR_REEVALUATE = "website/studyMonitor/reEvalute";//post - const WEBSITE_TAG = "website/studyMonitor/tag/";//get :tag - const WEBSITE_OTHER_TAG = "website/studyMonitor/otherTags/";//get :tag - const WEBSITE_TAG_EXISTS_NAME = "website/studyMonitor/tag/";//get :tag/website/nameExists/:website - const WEBSITE_TAG_EXISTS_URL = "website/studyMonitor/tag/";//get :tag/websiteExists/:startingUrl - const WEBSITE_STUDY_MONITOR_LINK = "website/studyMonitor/link";//post - const WEBSITE_STUDY_MONITOR_CREATE = "website/studyMonitor/create";//post - const WEBSITE_STUDY_MONITOR_REMOVE = "website/studyMonitor/remove"//post + const CREATE_WEBSITE = "/website/create"; //post + const UPDATE_WEBSITE = "/website/update"; //post + const DELETE_BULK_WEBSITE = "/website/deleteBulk"; //post + const REEVALUTE_WEBSITE = "/website/reEvaluate"; //post + const UPDATE_OBSERVATORY_PAGES_WEBSITE = "/website/pages/updateObservatory"; //post + const DELETE_WEBSITE = "/website/"; //delete :id + const MYMONITOR_WEBSITE_DOMANIN = "/website/myMonitor/url/"; //get :website + const DELETE_PAGES_WEBSITE = "/website/pages/deleteBulk"; // post + const IMPORT_WEBSITE = "website/import"; //post + const ADMIN_COUNT_WEBSITE = "website/all/count/"; //get :search + const ADMIN_ALL_WEBSITES = "website/all/"; //get :size/:page/:sort/:diretion/:search + const WEBSITE_INFO = "website/info/"; //get :websiteId + const WEBSITE_USER_NAME = "website/"; //get :website/user/:user/pages + const WEBSITE_CSV = "website/csv"; //get + const PAGES_WEBSITE = "website/pages/"; //get :websiteId + const OFICIAL_WEBSITE = "website/oficial"; //get + const WITHOUT_USER_WEBSITE = "website/withoutUser"; //get + const WITHOUT_ENTITY_WEBSITE = "website/withoutEntity"; //get + const STUDY_MONITOR_TOTAL_WEBSITES = "website/studyMonitor/total"; //get + const MY_MONITOR_TOTAL_WEBSITES = "website/myMonitor/total"; //get + const OBSERVATORY_TOTAL_WEBSITES = "website/observatory/total"; //get + const WEBSITE_EXISTS_NAME = "website/exists"; //get :name + const WEBSITE_EXISTS_URL = "website/exists/url"; //get :url + const WEBSITE_IN_OBSERVATORY = "website/isInObservatory"; //post + const WEBSITE_TRANSFER_OBSERVATORY = "website/tranferObservatoryPages"; //post + const WEBSITE_MY_MONITOR = "website/myMonitor"; //get + const WEBSITE_MY_MONITOR_REEVALUATE = "website/myMonitor/reEvalute"; //post + const WEBSITE_STUDY_MONITOR_REEVALUATE = "website/studyMonitor/reEvalute"; //post + const WEBSITE_TAG = "website/studyMonitor/tag/"; //get :tag + const WEBSITE_OTHER_TAG = "website/studyMonitor/otherTags/"; //get :tag + const WEBSITE_TAG_EXISTS_NAME = "website/studyMonitor/tag/"; //get :tag/website/nameExists/:website + const WEBSITE_TAG_EXISTS_URL = "website/studyMonitor/tag/"; //get :tag/websiteExists/:startingUrl + const WEBSITE_STUDY_MONITOR_LINK = "website/studyMonitor/link"; //post + const WEBSITE_STUDY_MONITOR_CREATE = "website/studyMonitor/create"; //post + const WEBSITE_STUDY_MONITOR_REMOVE = "website/studyMonitor/remove"; //post const databaseConfig = JSON.parse( readFileSync("../monitor_db.json").toString() @@ -50,7 +50,8 @@ describe('WebsiteController (e2e)', () => { beforeEach(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ - imports: [WebsiteModule, + imports: [ + WebsiteModule, TypeOrmModule.forRoot({ type: "mysql", host: databaseConfig.host, @@ -61,58 +62,53 @@ describe('WebsiteController (e2e)', () => { entities: [__dirname + "/**/*.entity{.ts,.js}"], synchronize: true, }), - ], - }).overrideGuard(AuthGuard("jwt-admin")) + ], + }) + .overrideGuard(AuthGuard("jwt-admin")) .useValue({ canActivate: () => true }) .overrideGuard(AuthGuard("jwt-monitor")) .useValue({ canActivate: () => true }) .overrideGuard(AuthGuard("jwt-study")) - .useValue({ canActivate: () => true }) + .useValue({ canActivate: () => true }) .compile(); - /** - * https://medium.com/@salmon.3e/integration-testing-with-nestjs-and-typeorm-2ac3f77e7628 - */ + /** + * https://medium.com/@salmon.3e/integration-testing-with-nestjs-and-typeorm-2ac3f77e7628 + */ app = moduleFixture.createNestApplication(); await app.init(); }); - - it('/POST'+CREATE_WEBSITE , async () => { - const createWebsiteDto = - { + it("/POST" + CREATE_WEBSITE, async () => { + const createWebsiteDto = { userId: 1, name: "Sapo", startingUrl: "https://www.sapo.pt/", entities: [], - tags: [] - } + tags: [], + }; const website = await request(app.getHttpServer()) .post(CREATE_WEBSITE) .send(createWebsiteDto) - .expect(200) + .expect(200); const websiteInfo = await request(app.getHttpServer()) - .get(WEBSITE_INFO+website.id) + .get(WEBSITE_INFO + website.id) .send(createWebsiteDto) - .expect(200) - - + .expect(200); }); - - it('/POST' + CREATE_WEBSITE, async () => { - const createWebsiteDto = - { + it("/POST" + CREATE_WEBSITE, async () => { + const createWebsiteDto = { userId: 1, name: "Acessibilidade", startingUrl: "https://www.acessibilidade.gov.pt/", entities: [], - tags: [] - } + tags: [], + }; const website = await request(app.getHttpServer()) .post(CREATE_WEBSITE) .send(createWebsiteDto) - .expect(200) + .expect(200); }); });