Skip to content
Snippets Groups Projects
Commit c507f536 authored by Antonin COQUET's avatar Antonin COQUET Committed by Hugo SUBTIL
Browse files

feat: add newsletter subscription

parent 0d2e5996
Branches
Tags
2 merge requests!96release V1.10.0,!62Dev
...@@ -3,8 +3,8 @@ import { getModelToken } from '@nestjs/mongoose'; ...@@ -3,8 +3,8 @@ import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
import { ConfigurationModule } from '../configuration/configuration.module'; import { ConfigurationModule } from '../configuration/configuration.module';
import { MailerService } from '../mailer/mailer.service'; import { MailerService } from '../mailer/mailer.service';
import { CreateStructureDto } from '../structures/dto/create-structure.dto'; import { NewsletterSubscription } from '../newsletter/newsletter-subscription.schema';
import { structureDto } from '../structures/dto/structure.dto'; import { NewsletterService } from '../newsletter/newsletter.service';
import { Structure } from '../structures/schemas/structure.schema'; import { Structure } from '../structures/schemas/structure.schema';
import { StructuresService } from '../structures/services/structures.service'; import { StructuresService } from '../structures/services/structures.service';
import { User } from '../users/schemas/user.schema'; import { User } from '../users/schemas/user.schema';
...@@ -21,11 +21,16 @@ describe('AdminController', () => { ...@@ -21,11 +21,16 @@ describe('AdminController', () => {
providers: [ providers: [
UsersService, UsersService,
StructuresService, StructuresService,
NewsletterService,
MailerService, MailerService,
{ {
provide: getModelToken('User'), provide: getModelToken('User'),
useValue: User, useValue: User,
}, },
{
provide: getModelToken('NewsletterSubscription'),
useValue: NewsletterSubscription,
},
{ {
provide: getModelToken('Structure'), provide: getModelToken('Structure'),
useValue: Structure, useValue: Structure,
......
...@@ -2,6 +2,7 @@ import { Body, Delete, Param } from '@nestjs/common'; ...@@ -2,6 +2,7 @@ import { Body, Delete, Param } from '@nestjs/common';
import { Controller, Get, Post, UseGuards } from '@nestjs/common'; import { Controller, Get, Post, UseGuards } from '@nestjs/common';
import { ApiOperation, ApiParam } from '@nestjs/swagger'; import { ApiOperation, ApiParam } from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { NewsletterService } from '../newsletter/newsletter.service';
import { StructuresService } from '../structures/services/structures.service'; import { StructuresService } from '../structures/services/structures.service';
import { Roles } from '../users/decorators/roles.decorator'; import { Roles } from '../users/decorators/roles.decorator';
import { RolesGuard } from '../users/guards/roles.guard'; import { RolesGuard } from '../users/guards/roles.guard';
...@@ -10,7 +11,11 @@ import { PendingStructureDto } from './dto/pending-structure.dto'; ...@@ -10,7 +11,11 @@ import { PendingStructureDto } from './dto/pending-structure.dto';
@Controller('admin') @Controller('admin')
export class AdminController { export class AdminController {
constructor(private usersService: UsersService, private structuresService: StructuresService) {} constructor(
private usersService: UsersService,
private structuresService: StructuresService,
private newsletterService: NewsletterService
) {}
@UseGuards(JwtAuthGuard, RolesGuard) @UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin') @Roles('admin')
...@@ -96,4 +101,21 @@ export class AdminController { ...@@ -96,4 +101,21 @@ export class AdminController {
return this.usersService.searchUsers(searchString.searchString); return this.usersService.searchUsers(searchString.searchString);
else return this.usersService.findAll(); else return this.usersService.findAll();
} }
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Post('searchNewsletterSubscriptions')
public async getNewsletterSubscriptions(@Body() searchString: { searchString: string }) {
if (searchString && searchString.searchString.length > 0)
return this.newsletterService.searchNewsletterSubscription(searchString.searchString);
else return this.newsletterService.findAll();
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Delete('newsletterSubscription/:email')
@ApiParam({ name: 'email', type: String, required: true })
public async unsubscribeUserFromNewsletter(@Param() params) {
return await this.newsletterService.deleteOneEmail(params.email);
}
} }
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { NewsletterModule } from '../newsletter/newsletter.module';
import { StructuresModule } from '../structures/structures.module'; import { StructuresModule } from '../structures/structures.module';
import { UsersModule } from '../users/users.module'; import { UsersModule } from '../users/users.module';
import { AdminController } from './admin.controller'; import { AdminController } from './admin.controller';
import { AdminService } from './admin.service'; import { AdminService } from './admin.service';
@Module({ @Module({
imports: [UsersModule, StructuresModule], imports: [UsersModule, StructuresModule, NewsletterModule],
controllers: [AdminController], controllers: [AdminController],
providers: [AdminService], providers: [AdminService],
}) })
......
...@@ -12,6 +12,7 @@ import { TclModule } from './tcl/tcl.module'; ...@@ -12,6 +12,7 @@ import { TclModule } from './tcl/tcl.module';
import { AdminModule } from './admin/admin.module'; import { AdminModule } from './admin/admin.module';
import { PostsModule } from './posts/posts.module'; import { PostsModule } from './posts/posts.module';
import { TempUserModule } from './temp-user/temp-user.module'; import { TempUserModule } from './temp-user/temp-user.module';
import { NewsletterModule } from './newsletter/newsletter.module';
@Module({ @Module({
imports: [ imports: [
ConfigurationModule, ConfigurationModule,
...@@ -28,6 +29,7 @@ import { TempUserModule } from './temp-user/temp-user.module'; ...@@ -28,6 +29,7 @@ import { TempUserModule } from './temp-user/temp-user.module';
AdminModule, AdminModule,
PostsModule, PostsModule,
TempUserModule, TempUserModule,
NewsletterModule
], ],
controllers: [AppController], controllers: [AppController],
}) })
......
import { Document } from 'mongoose';
export interface INewsletterSubscription extends Document {
email: string;
}
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
export type NewsletterSubscriptionDocument = NewsletterSubscription & Document;
@Schema({ timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' } })
export class NewsletterSubscription {
@Prop({ required: true })
email: string;
}
export const NewsletterSubscriptionSchema = SchemaFactory.createForClass(NewsletterSubscription);
import { HttpModule } from '@nestjs/common';
import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { ConfigurationModule } from '../configuration/configuration.module';
import { NewsletterSubscription } from './newsletter-subscription.schema';
import { NewsletterController } from './newsletter.controller';
import { NewsletterService } from './newsletter.service';
describe('NewsletterController', () => {
let controller: NewsletterController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [ConfigurationModule, HttpModule],
providers: [
NewsletterService,
{
provide: getModelToken('NewsletterSubscription'),
useValue: NewsletterSubscription,
},
],
controllers: [NewsletterController],
}).compile();
controller = module.get<NewsletterController>(NewsletterController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
it('should subscribe user', async () => {
const result = { email: 'email@test.com' };
jest.spyOn(controller, 'newsletterSubscribe').mockImplementation(async (): Promise<{ email }> => result);
const email = { email: 'email@test.com' };
expect(await controller.newsletterSubscribe(email)).toBe(result);
});
it('should unsubscribe user', async () => {
const result = { email: 'email@test.com' };
jest.spyOn(controller, 'newsletterUnsubscribe').mockImplementation(async (): Promise<{ email }> => result);
const email = { email: 'email@test.com' };
expect(await controller.newsletterUnsubscribe(email)).toBe(result);
});
});
import { Body, Controller, Post } from '@nestjs/common';
import { NewsletterService } from './newsletter.service';
@Controller('newsletter')
export class NewsletterController {
constructor(private newsletterService: NewsletterService) {}
@Post('subscribe')
public async newsletterSubscribe(@Body() email: { email: string }) {
return this.newsletterService.newsletterSubscribe(email.email);
}
@Post('unsubscribe')
public async newsletterUnsubscribe(@Body() email: { email: string }) {
return this.newsletterService.newsletterUnsubscribe(email.email);
}
}
import { HttpModule, Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { NewsletterService } from './newsletter.service';
import { NewsletterController } from './newsletter.controller';
import { NewsletterSubscription, NewsletterSubscriptionSchema } from './newsletter-subscription.schema';
@Module({
imports: [
MongooseModule.forFeature([{ name: NewsletterSubscription.name, schema: NewsletterSubscriptionSchema }]),
HttpModule,
],
providers: [NewsletterService],
exports: [NewsletterService],
controllers: [NewsletterController],
})
export class NewsletterModule {}
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, Types } from 'mongoose';
import { INewsletterSubscription } from './interface/newsletter-subscription.interface';
import { NewsletterSubscription } from './newsletter-subscription.schema';
@Injectable()
export class NewsletterService {
constructor(
@InjectModel(NewsletterSubscription.name) private newsletterSubscriptionModel: Model<INewsletterSubscription>
) {}
public async newsletterSubscribe(email: string): Promise<NewsletterSubscription> {
const existingEmail = await this.findOne(email);
if (existingEmail) {
throw new HttpException('Email already exists', HttpStatus.BAD_REQUEST);
}
const createSubscription = new this.newsletterSubscriptionModel({ email: email });
createSubscription.save();
return await this.findOne(email);
}
public async newsletterUnsubscribe(email: string): Promise<NewsletterSubscription> {
const subscription = await this.newsletterSubscriptionModel.findOne({ email: email }).exec();
if (!subscription) {
throw new HttpException('Invalid email', HttpStatus.BAD_REQUEST);
}
return subscription.deleteOne();
}
public async findOne(mail: string): Promise<NewsletterSubscription | undefined> {
return this.newsletterSubscriptionModel.findOne({ email: mail }).exec();
}
public async searchNewsletterSubscription(searchString: string) {
return this.newsletterSubscriptionModel.find({ email: new RegExp(searchString, 'i') }).exec();
}
public async deleteOneEmail(mail: string): Promise<NewsletterSubscription | undefined> {
const subscription = await this.newsletterSubscriptionModel.findOne({ email: mail }).exec();
if (!subscription) {
throw new HttpException('Invalid email', HttpStatus.BAD_REQUEST);
}
return subscription.deleteOne();
}
public async findAll(): Promise<NewsletterSubscription[]> {
return await this.newsletterSubscriptionModel.find().exec();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment