added some token usage, has errors

This commit is contained in:
OkaykOrhmn 2025-07-23 16:45:04 +03:30
parent d2e3063094
commit f3d0659c39
4 changed files with 108 additions and 140 deletions

View File

@ -1,9 +1,11 @@
import { Injectable, NotFoundException } from '@nestjs/common'; import { Injectable, InternalServerErrorException, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { Answer } from './entity/answer.entity'; import { Answer } from './entity/answer.entity';
import { CreateAnswerDto } from './dto/create-answer.dto'; import { CreateAnswerDto } from './dto/create-answer.dto';
import { UpdateAnswerDto } from './dto/update-answer.dto'; import { UpdateAnswerDto } from './dto/update-answer.dto';
import { CreateAttachmentDto } from '../attachment/dto/create_attachment.dto';
import { Attachment } from '../attachment/entity/attachment.entity';
@Injectable() @Injectable()
export class AnswerService { export class AnswerService {
@ -12,13 +14,15 @@ export class AnswerService {
private readonly answerRepository: Repository<Answer>, private readonly answerRepository: Repository<Answer>,
) {} ) {}
async create(data: CreateAnswerDto): Promise<Answer> { async create(data: CreateAnswerDto, token: any): Promise<Answer> {
try { if (!token || !token.sub) {
const answer = this.answerRepository.create({ ...data }); throw new InternalServerErrorException('Failed to extract sub from token');
return await this.answerRepository.save(answer);
} catch (error) {
throw new Error(`Failed to create answer: ${error.message}`);
} }
const answer = this.answerRepository.create({
...data,
participantId: token.sub, // token.sub is userId, but we want participantId ?!
});
return await this.answerRepository.save(answer);
} }
async findAll( page = 1, limit = 10 ): Promise<{ async findAll( page = 1, limit = 10 ): Promise<{

View File

@ -14,47 +14,17 @@ export class AttachmentService {
private readonly attachmentRepository: Repository<Attachment>, private readonly attachmentRepository: Repository<Attachment>,
) {} ) {}
async create(data: CreateAttachmentDto): Promise<Attachment> { async create(data: CreateAttachmentDto, token: any): Promise<Attachment> {
try { // Extract sub from decoded token
// Here we send a sample request, in final implementation, there'll be no need for that, we'll get the decoded token if (!token || !token.sub) {
const authResponse = await axios.post( throw new InternalServerErrorException('Failed to extract sub from token');
'https://auth.didvan.com/realms/didvan/protocol/openid-connect/token',
new URLSearchParams({
client_id: 'didvan-app',
username: 'bob',
password: 'developer_password',
grant_type: 'password',
}),
{
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
},
);
// Decode the access token to extract the 'sub' claim
const token = authResponse.data.access_token;
const decodedToken: any = decode(token);
if (!decodedToken || !decodedToken.sub) {
throw new InternalServerErrorException('Failed to decode token or extract sub');
} }
// Create the attachment with ownerId set to token.sub
// Create the attachment with ownerId set to sub
const attachment = this.attachmentRepository.create({ const attachment = this.attachmentRepository.create({
...data, ...data,
ownerId: decodedToken.sub, // Set ownerId to the token's sub ownerId: token.sub, // Set ownerId to the token's sub
metadata: data.metadata
? { entries: data.metadata.entries }
: { entries: [] },
status: data.status || 'active',
}); });
// Save the attachment to the database
return await this.attachmentRepository.save(attachment); return await this.attachmentRepository.save(attachment);
} catch (error) {
throw new InternalServerErrorException(`Failed to create attachment: ${error.message}`);
}
} }
async findAll( async findAll(

View File

@ -23,7 +23,7 @@ export class FormResultController {
} }
@Get(':id') @Get(':id')
async findOne( async findOne( // just gets the data in database
@Param('id', new ParseUUIDPipe()) id: string, @Param('id', new ParseUUIDPipe()) id: string,
): Promise<FormResult | null> { ): Promise<FormResult | null> {
return this.formResultService.findById(id); return this.formResultService.findById(id);
@ -44,10 +44,10 @@ export class FormResultController {
return this.formResultService.remove(id); return this.formResultService.remove(id);
} }
// @Get('form/:formId/statistics') @Get(':id/refresh')
// async getFormStatistics( async getFormStatistics( // updates data in database and then returns
// @Param('formId', new ParseUUIDPipe()) formId: string, @Param('formId', new ParseUUIDPipe()) formId: string,
// ): Promise<FormResult> { ): Promise<FormResult> {
// return this.formResultService.getFormStatistics(formId); return this.formResultService.getFormStatistics(formId);
// } }
} }

View File

@ -1,12 +1,14 @@
import { Injectable, NotFoundException } from '@nestjs/common'; import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { FormResult } from './entity/formResult.entity'; import { FormResult } from './entity/formResult.entity';
import { CreateFormResultDto } from './dto/create-formResult.dto'; import { CreateFormResultDto } from './dto/create-formResult.dto';
import { UpdateFormResultDto } from './dto/update-formResult.dto'; import { UpdateFormResultDto } from './dto/update-formResult.dto';
import { Answer } from 'src/answer/entity/answer.entity'; import { Answer } from 'src/answer/entity/answer.entity';
import { Question } from '../question/entity/question.entity'; import { Question } from '../question/entity/question.entity';
import { Form } from '../form/entity/form.entity'; import { Form } from '../form/entity/form.entity';
import { FormSection } from '../formSection/entity/formSection.entity';
import { FormPage } from '../formPage/entity/formPage.entity';
import { Repository, In } from 'typeorm';
@Injectable() @Injectable()
export class FormResultService { export class FormResultService {
@ -19,6 +21,15 @@ export class FormResultService {
private readonly questionRepository: Repository<Question>, private readonly questionRepository: Repository<Question>,
@InjectRepository(Answer) @InjectRepository(Answer)
private readonly answerRepository: Repository<Answer>, private readonly answerRepository: Repository<Answer>,
@InjectRepository(Form)
@InjectRepository(FormPage)
private readonly formPageRepository: Repository<FormPage>,
@InjectRepository(FormSection)
private readonly formSectionRepository: Repository<FormSection>,
@InjectRepository(Question)
@InjectRepository(Answer)
@InjectRepository(FormResult)
private readonly formResultRepository: Repository<FormResult>,
) {} ) {}
async create(data: CreateFormResultDto): Promise<FormResult> { async create(data: CreateFormResultDto): Promise<FormResult> {
@ -94,90 +105,73 @@ export class FormResultService {
throw new NotFoundException(`FormResult with ID "${id}" not found`); throw new NotFoundException(`FormResult with ID "${id}" not found`);
} }
} }
//
// async getFormStatistics(formId: string): Promise<FormResult> { async getFormStatistics(formId: string): Promise<FormResult> {
// // 1. Find the Form entity // 1. Find the Form entity
// const form = await this.formRepository.findOne({ where: { id: formId } }); const form = await this.formRepository.findOne({ where: { id: formId } });
// if (!form) { if (!form) {
// throw new NotFoundException(`Form with ID "${formId}" not found`); throw new NotFoundException(`Form with ID "${formId}" not found`);
// } }
//
// // 2. Compute numQuestions // 2. Compute numQuestions
// const numQuestions = await this.questionRepository.count({ const pageIds = form.pageIds || [];
// where: { const formPages = await this.formPageRepository.find({ where: { id: In(pageIds) } });
// formSection: { const formSectionIds = formPages.flatMap(page => page.formSectionIds || []);
// formPage: { const formSections = await this.formSectionRepository.find({ where: { id: In(formSectionIds) } });
// form: { id: formId }, const questionIds = formSections.flatMap(section => section.questionIds || []);
// }, const numQuestions = questionIds.length;
// },
// }, // 3. Compute numParticipants (distinct participantId from answers)
// }); const numParticipantsResult = await this.answerRepository
// .createQueryBuilder('answer')
// // 3. Compute numParticipants .select('COUNT(DISTINCT answer.participantId)', 'count')
// const numParticipantsResult = await this.answerRepository .where('answer.questionId IN (:...questionIds)', { questionIds: questionIds.length ? questionIds : ['none'] }) // Handle empty questionIds
// .createQueryBuilder('answer') .getRawOne();
// .select('COUNT(DISTINCT answer.participantId)', 'count') const numParticipants = numParticipantsResult ? Number(numParticipantsResult.count) : 0;
// .innerJoin('answer.question', 'question')
// .innerJoin('question.formSection', 'formSection') // 4. Compute numAnswers
// .innerJoin('formSection.formPage', 'formPage') const numAnswers = await this.answerRepository.count({
// .where('formPage.formId = :formId', { formId }) where: { questionId: In(questionIds.length ? questionIds : ['none']) }, // Handle empty questionIds
// .getRawOne(); });
// const numParticipants = numParticipantsResult ? Number(numParticipantsResult.count) : 0;
// // 5. Compute numCompleteParticipants (participants who answered all questions)
// // 4. Compute numAnswers const subQuery = this.answerRepository
// const numAnswers = await this.answerRepository.count({ .createQueryBuilder('answer')
// where: { .select('answer.participantId')
// question: { .where('answer.questionId IN (:...questionIds)', { questionIds: questionIds.length ? questionIds : ['none'] }) // Handle empty questionIds
// formSection: { .groupBy('answer.participantId')
// formPage: { .having('COUNT(DISTINCT answer.questionId) = :numQuestions', { numQuestions: numQuestions || 1 }); // Avoid division by zero
// form: { id: formId },
// }, const numCompleteParticipantsResult = await this.answerRepository.manager
// }, .createQueryBuilder()
// }, .select('COUNT(*)', 'count')
// }, .from(`(${subQuery.getQuery()})`, 'subquery')
// }); .setParameters(subQuery.getParameters())
// .getRawOne();
// // 5. Compute numCompleteParticipants const numCompleteParticipants = numCompleteParticipantsResult ? Number(numCompleteParticipantsResult.count) : 0;
// const subQuery = this.answerRepository
// .createQueryBuilder('answer') // 6. Find or create FormResult for the Form
// .select('answer.participantId') let formResult = await this.formResultRepository.findOne({ where: { formId } });
// .innerJoin('answer.question', 'question') if (!formResult) {
// .innerJoin('question.formSection', 'formSection') formResult = this.formResultRepository.create({
// .innerJoin('formSection.formPage', 'formPage') formId, // Link to Form via formId
// .where('formPage.formId = :formId', { formId }) numQuestions,
// .groupBy('answer.participantId') numParticipants,
// .having('COUNT(DISTINCT answer.questionId) = :numQuestions', { numQuestions }); numAnswers,
// numComplete: numCompleteParticipants,
// const numCompleteParticipantsResult = await this.answerRepository.manager opinions: [], // Initialize as empty or compute if needed
// .createQueryBuilder() status: 'active',
// .select('COUNT(*)', 'count') });
// .from(`(${subQuery.getQuery()})`, 'subquery') } else {
// .setParameters(subQuery.getParameters()) formResult.numQuestions = numQuestions;
// .getRawOne(); formResult.numParticipants = numParticipants;
// const numCompleteParticipants = numCompleteParticipantsResult ? Number(numCompleteParticipantsResult.count) : 0; formResult.numAnswers = numAnswers;
// formResult.numComplete = numCompleteParticipants;
// // 6. Find or create FormResult for the Form // Preserve existing opinions or update if needed
// let formResult = await this.formResultRepo.findOne({ where: { form: { id: formId } }, relations: ['form'] }); }
// if (!formResult) {
// formResult = this.formResultRepo.create({ // 7. Save and return the FormResult
// form, // Link to the Form entity return await this.formResultRepository.save(formResult);
// numQuestions, }
// numParticipants,
// numAnswers,
// numComplete: numCompleteParticipants,
// opinions: [], // Initialize as empty or compute if needed
// status: 'active',
// });
// } else {
// formResult.numQuestions = numQuestions;
// formResult.numParticipants = numParticipants;
// formResult.numAnswers = numAnswers;
// formResult.numComplete = numCompleteParticipants;
// // Preserve existing opinions or update if needed
// }
//
// // 7. Save and return the FormResult
// return await this.formResultRepo.save(formResult);
// }
} }