diff --git a/src/admin/admin.controller.spec.ts b/src/admin/admin.controller.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0b8ca9028651014a25b02e06c12425dee70ab800
--- /dev/null
+++ b/src/admin/admin.controller.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { AdminController } from './admin.controller';
+
+describe('AdminController', () => {
+  let controller: AdminController;
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      controllers: [AdminController],
+    }).compile();
+
+    controller = module.get<AdminController>(AdminController);
+  });
+
+  it('should be defined', () => {
+    expect(controller).toBeDefined();
+  });
+});
diff --git a/src/admin/admin.controller.ts b/src/admin/admin.controller.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5dc32d88222999fdd011ae76aae56cc548da3627
--- /dev/null
+++ b/src/admin/admin.controller.ts
@@ -0,0 +1,45 @@
+import { Body } from '@nestjs/common';
+import { Controller, Get, Post, UseGuards } from '@nestjs/common';
+import { ApiOperation } from '@nestjs/swagger';
+import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { Roles } from '../users/decorators/roles.decorator';
+import { RolesGuard } from '../users/guards/roles.guard';
+import { UsersService } from '../users/users.service';
+import { PendingStructureDto } from './dto/pending-structure.dto';
+
+@Controller('admin')
+export class AdminController {
+  constructor(private usersService: UsersService) {}
+
+  @UseGuards(JwtAuthGuard, RolesGuard)
+  @Roles('admin')
+  @Get('pendingStructures')
+  @ApiOperation({ description: 'Get pending structre for validation' })
+  public getPendingAttachments(): Promise<PendingStructureDto[]> {
+    return this.usersService.getPendingStructures();
+  }
+
+  @UseGuards(JwtAuthGuard, RolesGuard)
+  @Roles('admin')
+  @Post('validatePendingStructure')
+  @ApiOperation({ description: 'Validate structure ownership' })
+  public validatePendingStructure(@Body() pendingStructureDto: PendingStructureDto) {
+    return this.usersService.validatePendingStructure(
+      pendingStructureDto.userEmail,
+      pendingStructureDto.structureId,
+      true
+    );
+  }
+
+  @UseGuards(JwtAuthGuard, RolesGuard)
+  @Roles('admin')
+  @Post('rejectPendingStructure')
+  @ApiOperation({ description: 'Refuse structure ownership' })
+  public refusePendingStructure(@Body() pendingStructureDto: PendingStructureDto) {
+    return this.usersService.validatePendingStructure(
+      pendingStructureDto.userEmail,
+      pendingStructureDto.structureId,
+      false
+    );
+  }
+}
diff --git a/src/admin/admin.module.ts b/src/admin/admin.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3376e00f618f654dbdb6213a2cfd48ddb8e99cb2
--- /dev/null
+++ b/src/admin/admin.module.ts
@@ -0,0 +1,12 @@
+import { Module } from '@nestjs/common';
+import { UsersModule } from '../users/users.module';
+import { UsersService } from '../users/users.service';
+import { AdminController } from './admin.controller';
+import { AdminService } from './admin.service';
+
+@Module({
+  imports: [UsersModule],
+  controllers: [AdminController],
+  providers: [AdminService],
+})
+export class AdminModule {}
diff --git a/src/admin/admin.service.spec.ts b/src/admin/admin.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5e5e153df03a8437915bb59ff2861c9366e40f02
--- /dev/null
+++ b/src/admin/admin.service.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { AdminService } from './admin.service';
+
+describe('AdminService', () => {
+  let service: AdminService;
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      providers: [AdminService],
+    }).compile();
+
+    service = module.get<AdminService>(AdminService);
+  });
+
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+});
diff --git a/src/admin/admin.service.ts b/src/admin/admin.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..796f9fd1a19a12cbc184a3364dbebe88e2165365
--- /dev/null
+++ b/src/admin/admin.service.ts
@@ -0,0 +1,4 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class AdminService {}
diff --git a/src/admin/dto/pending-structure.dto.ts b/src/admin/dto/pending-structure.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..04936833a26fea61d590dac33f3f682492f7c9dc
--- /dev/null
+++ b/src/admin/dto/pending-structure.dto.ts
@@ -0,0 +1,14 @@
+import { ApiProperty } from '@nestjs/swagger';
+import { IsEmail, IsNotEmpty, IsNumber } from 'class-validator';
+
+export class PendingStructureDto {
+  @IsNotEmpty()
+  @IsEmail()
+  @ApiProperty({ type: String })
+  readonly userEmail: string;
+
+  @IsNotEmpty()
+  @IsNumber()
+  @ApiProperty({ type: Number })
+  readonly structureId: number;
+}
diff --git a/src/app.module.ts b/src/app.module.ts
index d3a7ebdbbc56ff9f03b326d78405b5cb81008137..0d49be79613c4a4a01487ac0ab4110fe19006ba7 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -8,6 +8,7 @@ import { AuthModule } from './auth/auth.module';
 import { UsersModule } from './users/users.module';
 import { MailerModule } from './mailer/mailer.module';
 import { TclModule } from './tcl/tcl.module';
+import { AdminModule } from './admin/admin.module';
 @Module({
   imports: [
     ConfigurationModule,
@@ -20,6 +21,7 @@ import { TclModule } from './tcl/tcl.module';
     UsersModule,
     MailerModule,
     TclModule,
+    AdminModule,
   ],
   controllers: [AppController],
 })
diff --git a/src/auth/auth.controller.spec.ts b/src/auth/auth.controller.spec.ts
index 819bebe40d056c7a9315d71c309bd092e61e17d5..52a4184107d34402e9bdd97e8d5e9dfd27209fb4 100644
--- a/src/auth/auth.controller.spec.ts
+++ b/src/auth/auth.controller.spec.ts
@@ -4,7 +4,7 @@ import { PassportModule } from '@nestjs/passport';
 import { Test, TestingModule } from '@nestjs/testing';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerModule } from '../mailer/mailer.module';
-import { User } from '../users/user.schema';
+import { User } from '../users/schemas/user.schema';
 import { UsersService } from '../users/users.service';
 import { AuthController } from './auth.controller';
 import { AuthService } from './auth.service';
diff --git a/src/auth/auth.service.spec.ts b/src/auth/auth.service.spec.ts
index 0582053c0ba31e3b72bc38e036442121a5e58ab1..2e85b13e99460b761605d520d20d936392dc2d9c 100644
--- a/src/auth/auth.service.spec.ts
+++ b/src/auth/auth.service.spec.ts
@@ -5,7 +5,7 @@ import { PassportModule } from '@nestjs/passport';
 import { Test, TestingModule } from '@nestjs/testing';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerModule } from '../mailer/mailer.module';
-import { User } from '../users/user.schema';
+import { User } from '../users/schemas/user.schema';
 import { UsersService } from '../users/users.service';
 import { AuthService } from './auth.service';
 import { LoginDto } from './login-dto';
diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts
index 2719b0ba95e55f801e744ed89c98f11effeca726..54b820141ed6bd7776f8911e8c679893d6b4c20b 100644
--- a/src/auth/auth.service.ts
+++ b/src/auth/auth.service.ts
@@ -2,9 +2,8 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
 import { UsersService } from '../users/users.service';
 import { JwtService } from '@nestjs/jwt';
 import { LoginDto } from './login-dto';
-import { CreateUserDto } from '../users/create-user.dto';
 import { DateTime } from 'luxon';
-import { User } from '../users/user.schema';
+import { User } from '../users/schemas/user.schema';
 
 @Injectable()
 export class AuthService {
@@ -34,10 +33,10 @@ export class AuthService {
     };
   }
 
-  private _createToken({ email }: CreateUserDto): any {
+  private _createToken(user: User): any {
     const local = DateTime.local().setZone('Europe/Paris');
     return {
-      accessToken: this.jwtService.sign({ email }),
+      accessToken: this.jwtService.sign({ email: user.email, role: user.role }),
       expiresAt: local.plus({ days: 1 }),
     };
   }
diff --git a/src/configuration/config.ts b/src/configuration/config.ts
index b6d29acca6ec81c264ea73c4c482790a914a3c36..00bbfff6d98d45181cad4ed3e58d048e1467a3a5 100644
--- a/src/configuration/config.ts
+++ b/src/configuration/config.ts
@@ -21,5 +21,13 @@ export const config = {
       ejs: 'resetPassword.ejs',
       json: 'resetPassword.json',
     },
+    adminStructureClaim: {
+      ejs: 'adminStructureClaim.ejs',
+      json: 'adminStructureClaim.json',
+    },
+    structureClaimValidation: {
+      ejs: 'structureClaimValidation.ejs',
+      json: 'structureClaimValidation.json',
+    },
   },
 };
diff --git a/src/mailer/mail-templates/adminStructureClaim.ejs b/src/mailer/mail-templates/adminStructureClaim.ejs
new file mode 100644
index 0000000000000000000000000000000000000000..12ba539835a44a9a609bd7d1937d45ec48e09474
--- /dev/null
+++ b/src/mailer/mail-templates/adminStructureClaim.ejs
@@ -0,0 +1,6 @@
+Bonjour<br />
+<br />
+Une nouvelle structure a été revendiquée. Pour valider ou refuser la demande, merci de vous rendre sur
+<a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/admin">ce lien</a>.
+<br />
+Ce mail est un mail automatique. Merci de ne pas y répondre.
diff --git a/src/mailer/mail-templates/adminStructureClaim.json b/src/mailer/mail-templates/adminStructureClaim.json
new file mode 100644
index 0000000000000000000000000000000000000000..bad53f08f4c0debbe28b988b65f37b6a3902ddb2
--- /dev/null
+++ b/src/mailer/mail-templates/adminStructureClaim.json
@@ -0,0 +1,3 @@
+{
+  "subject": "Nouvelle demande de revendication de structure"
+}
diff --git a/src/mailer/mail-templates/structureClaimValidation.ejs b/src/mailer/mail-templates/structureClaimValidation.ejs
new file mode 100644
index 0000000000000000000000000000000000000000..eca79ec7fe230a7dd947880ee5795c57cd1647cc
--- /dev/null
+++ b/src/mailer/mail-templates/structureClaimValidation.ejs
@@ -0,0 +1,6 @@
+Bonjour<br />
+<br />
+La demande de rattachement de structure a votre compte a été <strong><%= status %></strong>.
+<br />
+<br />
+Ce mail est un mail automatique. Merci de ne pas y répondre.
diff --git a/src/mailer/mail-templates/structureClaimValidation.json b/src/mailer/mail-templates/structureClaimValidation.json
new file mode 100644
index 0000000000000000000000000000000000000000..bdcb607dc59c9beed42c21a607287be19c06e217
--- /dev/null
+++ b/src/mailer/mail-templates/structureClaimValidation.json
@@ -0,0 +1,3 @@
+{
+  "subject": "Votre demande de rattachement, Réseau des Acteurs de la Médiation Numérique de la Métropole de Lyon"
+}
diff --git a/src/structures/structures.controller.ts b/src/structures/structures.controller.ts
index eaa5722913675e3d639e7cae7944486e24097b22..cce9d59b0e76e601fc080358c1ba1bfe03e872a5 100644
--- a/src/structures/structures.controller.ts
+++ b/src/structures/structures.controller.ts
@@ -1,5 +1,5 @@
 import { Body, Controller, Get, Param, ParseIntPipe, Post, Put, Query } from '@nestjs/common';
-import { User } from '../users/user.schema';
+import { User } from '../users/schemas/user.schema';
 import { UsersService } from '../users/users.service';
 import { CreateStructureDto } from './dto/create-structure.dto';
 import { QueryStructure } from './dto/query-structure.dto';
@@ -22,7 +22,8 @@ export class StructuresController {
   }
 
   @Put(':id')
-  public async update(@Param('id') id: number, @Body() body: structureDto) {
+  //TODO: protect, only structure owner can edit it
+  public async update(@Param('id') id: number, @Body() body: structureDto): Promise<Structure> {
     return this.structureService.update(id, body);
   }
 
@@ -37,7 +38,7 @@ export class StructuresController {
   }
 
   @Post(':id/claim')
-  public async claim(@Param('id', new ParseIntPipe()) idStructure: number, @Body() user: User) {
+  public async claim(@Param('id', new ParseIntPipe()) idStructure: number, @Body() user: User): Promise<number[]> {
     return this.userService.updateStructureLinked(user.email, idStructure);
   }
 
diff --git a/src/structures/structures.service.ts b/src/structures/structures.service.ts
index 85d241a5f62339cbdd2768667f286ad75dd2ec46..e1cb232eed112e76dc63e370017564cef63471ba 100644
--- a/src/structures/structures.service.ts
+++ b/src/structures/structures.service.ts
@@ -26,6 +26,7 @@ export class StructuresService {
     createdStructure.save();
     user.structuresLink.push(createdStructure.id);
     user.save();
+
     return createdStructure;
   }
 
@@ -116,13 +117,11 @@ export class StructuresService {
     });
   }
 
-  public async isClaimed(idStructure): Promise<boolean> {
-    const users = await this.userService.findAll();
-    users.forEach((user) => {
-      if (user.structuresLink.includes(idStructure)) {
-        return true;
-      }
-    });
+  public async isClaimed(structureId: number): Promise<boolean> {
+    const isStructureClaimed = await this.userService.isStructureClaimed(structureId.toString());
+    if (isStructureClaimed) {
+      return true;
+    }
     return false;
   }
 
diff --git a/src/users/decorators/roles.decorator.ts b/src/users/decorators/roles.decorator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b0376727cc30742bda0e26d1e498c4f36fd4be02
--- /dev/null
+++ b/src/users/decorators/roles.decorator.ts
@@ -0,0 +1,3 @@
+import { SetMetadata } from '@nestjs/common';
+
+export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
diff --git a/src/users/change-email.dto.ts b/src/users/dto/change-email.dto.ts
similarity index 100%
rename from src/users/change-email.dto.ts
rename to src/users/dto/change-email.dto.ts
diff --git a/src/users/change-password.dto.ts b/src/users/dto/change-password.dto.ts
similarity index 100%
rename from src/users/change-password.dto.ts
rename to src/users/dto/change-password.dto.ts
diff --git a/src/users/create-user.dto.ts b/src/users/dto/create-user.dto.ts
similarity index 89%
rename from src/users/create-user.dto.ts
rename to src/users/dto/create-user.dto.ts
index acb92be7f354d6a6afc05b729a4e6c0da247f6f3..34297e1cae9c8ac7634be3311347a8fa316abb12 100644
--- a/src/users/create-user.dto.ts
+++ b/src/users/dto/create-user.dto.ts
@@ -14,5 +14,5 @@ export class CreateUserDto {
 
   @IsArray()
   @IsOptional()
-  structuresLink?: Array<number>;
+  pendingStructuresLink?: Array<number>;
 }
diff --git a/src/users/reset-password-apply.dto.ts b/src/users/dto/reset-password-apply.dto.ts
similarity index 100%
rename from src/users/reset-password-apply.dto.ts
rename to src/users/dto/reset-password-apply.dto.ts
diff --git a/src/users/reset-password.dto.ts b/src/users/dto/reset-password.dto.ts
similarity index 100%
rename from src/users/reset-password.dto.ts
rename to src/users/dto/reset-password.dto.ts
diff --git a/src/users/guards/roles.guard.ts b/src/users/guards/roles.guard.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2ad8873575a0458ca5f15ffa6568f6af8767cbdd
--- /dev/null
+++ b/src/users/guards/roles.guard.ts
@@ -0,0 +1,33 @@
+import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
+import { Reflector } from '@nestjs/core';
+import { UserRole } from '../enum/user-role.enum';
+
+@Injectable()
+export class RolesGuard implements CanActivate {
+  constructor(private reflector: Reflector) {}
+
+  canActivate(context: ExecutionContext): boolean {
+    const roles = this.reflector.get<string[]>('roles', context.getHandler());
+    if (!roles) {
+      return true;
+    }
+    const request = context.switchToHttp().getRequest();
+    const user = request.user;
+    return this.matchRoles(user.role, roles[0]);
+  }
+
+  /**
+   * Return true if user is admin or if the requested role match the user role.
+   * @param userRole user role from request
+   * @param expectedRole role requested by the endpoint
+   */
+  private matchRoles(userRole: number, expectedRole: string): boolean {
+    if (userRole === UserRole.admin) {
+      return true;
+    } else if (userRole === UserRole[expectedRole]) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+}
diff --git a/src/users/user.interface.ts b/src/users/interfaces/user.interface.ts
similarity index 90%
rename from src/users/user.interface.ts
rename to src/users/interfaces/user.interface.ts
index d235abc515217700995b46e9fa21a851af6ac2f8..243b6057b04185acfadae85a87863f0eb37f6dad 100644
--- a/src/users/user.interface.ts
+++ b/src/users/interfaces/user.interface.ts
@@ -11,4 +11,5 @@ export interface IUser extends Document {
   changeEmailToken: string;
   newEmail: string;
   structuresLink: number[];
+  pendingStructuresLink: number[];
 }
diff --git a/src/users/user.schema.ts b/src/users/schemas/user.schema.ts
similarity index 85%
rename from src/users/user.schema.ts
rename to src/users/schemas/user.schema.ts
index 490f7b424b14c5c756aa30a65ce0d84805f903b8..7e019777ac5a768bf84eb00259b2337fb910d791 100644
--- a/src/users/user.schema.ts
+++ b/src/users/schemas/user.schema.ts
@@ -1,5 +1,5 @@
 import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
-import { UserRole } from './enum/user-role.enum';
+import { UserRole } from '../enum/user-role.enum';
 @Schema()
 export class User {
   @Prop({ required: true })
@@ -28,6 +28,9 @@ export class User {
 
   @Prop({ default: null })
   structuresLink: number[];
+
+  @Prop({ default: null })
+  pendingStructuresLink: number[];
 }
 
 export const UserSchema = SchemaFactory.createForClass(User);
diff --git a/src/users/users.controller.spec.ts b/src/users/users.controller.spec.ts
index 714006debf399341880614d0a8e280e93bbadb7c..7dd57ee72fcb1a6243abc0c94b7351825843f492 100644
--- a/src/users/users.controller.spec.ts
+++ b/src/users/users.controller.spec.ts
@@ -3,7 +3,7 @@ import { getModelToken } from '@nestjs/mongoose';
 import { Test, TestingModule } from '@nestjs/testing';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerService } from '../mailer/mailer.service';
-import { User } from './user.schema';
+import { User } from './schemas/user.schema';
 import { UsersController } from './users.controller';
 import { UsersService } from './users.service';
 
diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts
index 1585ae1a31d515e9a0cecfd0f65578566e0694b2..9c8c2c31b19ad0fec488cc11fd3ec1e53976d93a 100644
--- a/src/users/users.controller.ts
+++ b/src/users/users.controller.ts
@@ -1,11 +1,11 @@
 import { Body, Controller, Get, Param, Post, Query, Request, UseGuards } from '@nestjs/common';
 import { ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger';
 import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
-import { PasswordChangeDto } from './change-password.dto';
-import { EmailChangeDto } from './change-email.dto';
-import { CreateUserDto } from './create-user.dto';
-import { PasswordResetApplyDto } from './reset-password-apply.dto';
-import { PasswordResetDto } from './reset-password.dto';
+import { PasswordChangeDto } from './dto/change-password.dto';
+import { EmailChangeDto } from './dto/change-email.dto';
+import { CreateUserDto } from './dto/create-user.dto';
+import { PasswordResetApplyDto } from './dto/reset-password-apply.dto';
+import { PasswordResetDto } from './dto/reset-password.dto';
 import { UsersService } from './users.service';
 
 @Controller('users')
@@ -26,9 +26,9 @@ export class UsersController {
   public async create(@Body() createUserDto: CreateUserDto) {
     // remove structureId for creation and add structure after
     let structureId = null;
-    if (createUserDto.structuresLink.length > 0) {
-      structureId = createUserDto.structuresLink[0];
-      delete createUserDto.structuresLink;
+    if (createUserDto.pendingStructuresLink.length > 0) {
+      structureId = createUserDto.pendingStructuresLink[0];
+      delete createUserDto.pendingStructuresLink;
     }
     const user = await this.usersService.create(createUserDto);
     if (structureId) {
diff --git a/src/users/users.module.ts b/src/users/users.module.ts
index 69d7ee133b34253305a5d91968d8fe2da518deeb..ae73bfe01263691656b98892941287ea85642e23 100644
--- a/src/users/users.module.ts
+++ b/src/users/users.module.ts
@@ -2,7 +2,7 @@ import { Module } from '@nestjs/common';
 import { MongooseModule } from '@nestjs/mongoose';
 import { UsersService } from './users.service';
 import { UsersController } from './users.controller';
-import { User, UserSchema } from './user.schema';
+import { User, UserSchema } from './schemas/user.schema';
 import { MailerModule } from '../mailer/mailer.module';
 
 @Module({
diff --git a/src/users/users.service.spec.ts b/src/users/users.service.spec.ts
index e797c49a4dd38cb22d2d2b9f8ecbfe623ce3cd1b..e24a4807c60a4d93623c6d6b03220032e34905b1 100644
--- a/src/users/users.service.spec.ts
+++ b/src/users/users.service.spec.ts
@@ -1,12 +1,12 @@
 import { Test, TestingModule } from '@nestjs/testing';
 import { MailerModule } from '../mailer/mailer.module';
-import { User } from './user.schema';
+import { User } from './schemas/user.schema';
 import { UsersService } from './users.service';
 import { getModelToken } from '@nestjs/mongoose';
-import { CreateUserDto } from './create-user.dto';
+import { CreateUserDto } from './dto/create-user.dto';
 import { HttpException, HttpStatus } from '@nestjs/common';
 import { LoginDto } from '../auth/login-dto';
-import { EmailChangeDto } from './change-email.dto';
+import { EmailChangeDto } from './dto/change-email.dto';
 
 describe('UsersService', () => {
   let service: UsersService;
diff --git a/src/users/users.service.ts b/src/users/users.service.ts
index a14e86643cf2ec3d71fecdbec71d35ebf690c9b7..606f097d649200f722e7b3cd235a0770f331d7a1 100644
--- a/src/users/users.service.ts
+++ b/src/users/users.service.ts
@@ -5,15 +5,16 @@ import * as ejs from 'ejs';
 import * as crypto from 'crypto';
 import { Model } from 'mongoose';
 import { LoginDto } from '../auth/login-dto';
-import { CreateUserDto } from './create-user.dto';
-import { User } from './user.schema';
+import { CreateUserDto } from './dto/create-user.dto';
+import { User } from './schemas/user.schema';
 import { MailerService } from '../mailer/mailer.service';
-import { IUser } from './user.interface';
-import { EmailChangeDto } from './change-email.dto';
+import { IUser } from './interfaces/user.interface';
+import { EmailChangeDto } from './dto/change-email.dto';
+import { PendingStructureDto } from '../admin/dto/pending-structure.dto';
 
 @Injectable()
 export class UsersService {
-  constructor(@InjectModel(User.name) private userModel: Model<IUser>, private mailerService: MailerService) {}
+  constructor(@InjectModel(User.name) private userModel: Model<IUser>, private readonly mailerService: MailerService) {}
 
   /**
    * Create a user account
@@ -36,6 +37,7 @@ export class UsersService {
     // Send verification email
     createUser = await this.verifyUserMail(createUser);
     createUser.save();
+    this.sendAdminStructureValidationMail();
     return await this.findOne(createUserDto.email);
   }
 
@@ -124,6 +126,42 @@ export class UsersService {
     return user;
   }
 
+  /**
+   * Send to all admins validation email for structures
+   * a new account.
+   * @param user User
+   */
+  private async sendAdminStructureValidationMail(): Promise<any> {
+    const config = this.mailerService.config;
+    const ejsPath = this.mailerService.getTemplateLocation(config.templates.adminStructureClaim.ejs);
+    const jsonConfig = this.mailerService.loadJsonConfig(config.templates.adminStructureClaim.json);
+
+    const html = await ejs.renderFile(ejsPath, {
+      config,
+    });
+    const admins = await this.getAdmins();
+    admins.forEach((admin) => {
+      this.mailerService.send(admin.email, jsonConfig.subject, html);
+    });
+  }
+
+  /**
+   * Send approval email for user
+   * a new account.
+   * @param user User
+   */
+  private async sendStructureClaimApproval(userEmail: string, status: boolean): Promise<any> {
+    const config = this.mailerService.config;
+    const ejsPath = this.mailerService.getTemplateLocation(config.templates.structureClaimValidation.ejs);
+    const jsonConfig = this.mailerService.loadJsonConfig(config.templates.structureClaimValidation.json);
+
+    const html = await ejs.renderFile(ejsPath, {
+      config,
+      status: status ? 'accepté' : 'refusée',
+    });
+    this.mailerService.send(userEmail, jsonConfig.subject, html);
+  }
+
   /**
    * Check that the given token is associated to userId. If it's true, validate user account.
    * @param userId string
@@ -241,13 +279,74 @@ export class UsersService {
     throw new HttpException('Invalid token', HttpStatus.UNAUTHORIZED);
   }
 
-  public async updateStructureLinked(userEmail: string, idStructure: number): Promise<any> {
+  public async getAdmins(): Promise<User[]> {
+    return this.userModel.find({ role: 1 }).exec();
+  }
+
+  public async isStructureClaimed(structureId: string): Promise<User> {
+    return this.userModel
+      .findOne({ $or: [{ pendingStructuresLink: parseInt(structureId) }, { structuresLink: parseInt(structureId) }] })
+      .exec();
+  }
+
+  public async updateStructureLinked(userEmail: string, idStructure: number): Promise<number[]> {
     const user = await this.findOne(userEmail, true);
     if (user) {
-      user.structuresLink.push(idStructure);
+      user.pendingStructuresLink.push(idStructure);
       user.save();
-      return user.structuresLink;
+      this.sendAdminStructureValidationMail();
+      return user.pendingStructuresLink;
     }
     throw new HttpException('Invalid user', HttpStatus.NOT_FOUND);
   }
+
+  /**
+   * Return all pending attachments of all profiles
+   */
+  public async getPendingStructures(): Promise<PendingStructureDto[]> {
+    const users = await this.userModel.find();
+    const structuresPending = [];
+
+    // For each user, if they have structures in pending, push them in tab and return this tab.
+    users.forEach((user) => {
+      if (user.pendingStructuresLink.length) {
+        user.pendingStructuresLink.forEach((structureId) => {
+          structuresPending.push({ userEmail: user.email, structureId: structureId });
+        });
+      }
+    });
+    return structuresPending;
+  }
+
+  /**
+   * Validate or refuse a pending structure given a email and structure id
+   */
+  public async validatePendingStructure(
+    userEmail: string,
+    structureId: number,
+    validate: boolean
+  ): Promise<PendingStructureDto[]> {
+    const users = await this.findOne(userEmail);
+    let status = false;
+    if (!users) {
+      throw new HttpException('User not found', HttpStatus.NOT_FOUND);
+    }
+    if (users.pendingStructuresLink.includes(structureId)) {
+      users.pendingStructuresLink = users.pendingStructuresLink.filter((item) => item !== structureId);
+      // If it's a validation case, push structureId into validated user structures
+      if (validate) {
+        users.structuresLink.push(structureId);
+        // Send validation email
+        status = true;
+      }
+      this.sendStructureClaimApproval(userEmail, status);
+      await users.save();
+      return this.getPendingStructures();
+    } else {
+      throw new HttpException(
+        'Cannot validate strucutre. It might have been already validate, or the structure does`nt belong to the user',
+        HttpStatus.NOT_FOUND
+      );
+    }
+  }
 }