Merge branch 'email_confirmation' into 'develop'

Email confirmation(Parent profile form)

See merge request !41
parents a5e2f4fb c3ad3f8a
......@@ -34,3 +34,17 @@ function epal_theme() {
],
];
}
function epal_mail($key, &$message, $params) {
$options = array(
'langcode' => $message['langcode'],
);
switch ($key) {
case 'send_verification_code':
$message['from'] = \Drupal::config('system.site')->get('mail');
$message['subject'] = t('Email Confirmation Needed', $options);
$message['body'][] = $params['message'];
break;
}
}
user_data:
epal.user.send_verification_code:
path: '/epal/user/sendvercode'
options:
_auth: [ 'basic_auth' ]
defaults:
_controller: '\Drupal\epal\Controller\CurrentUser::sendVerificationCode'
requirements:
_user_is_logged_in: 'TRUE'
epal.user.verify_verification_code:
path: '/epal/user/verifyvercode'
options:
_auth: [ 'basic_auth' ]
defaults:
_controller: '\Drupal\epal\Controller\CurrentUser::verifyVerificationCode'
requirements:
_user_is_logged_in: 'TRUE'
epal.user.save_profile:
path: '/epal/user/save'
options:
_auth: [ 'basic_auth' ]
defaults:
_controller: '\Drupal\epal\Controller\CurrentUser::saveUserProfile'
requirements:
_user_is_logged_in: 'TRUE'
epal.user.get_data:
path: '/epal/userdata'
options:
_auth: [ 'basic_auth' ]
......@@ -6,7 +30,7 @@ user_data:
_controller: '\Drupal\epal\Controller\CurrentUser::getEpalUserData'
requirements:
_user_is_logged_in: 'TRUE'
current_user:
epal.current_user:
path: '/epal/curuser'
options:
_auth: [ 'basic_auth' ]
......
......@@ -8,20 +8,32 @@ use Symfony\Component\HttpFoundation\JsonResponse;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Database\Connection;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
class CurrentUser extends ControllerBase
{
protected $entityTypeManager;
protected $logger;
protected $connection;
public function __construct(EntityTypeManagerInterface $entityTypeManager)
public function __construct(
EntityTypeManagerInterface $entityTypeManager,
Connection $connection,
LoggerChannelFactoryInterface $loggerChannel
)
{
$this->entityTypeManager = $entityTypeManager;
$this->connection = $connection;
$this->logger = $loggerChannel->get('epal');
}
public static function create(ContainerInterface $container)
{
return new static(
$container->get('entity_type.manager')
$container->get('entity_type.manager'),
$container->get('database'),
$container->get('logger.factory')
);
}
......@@ -62,6 +74,7 @@ class CurrentUser extends ControllerBase
'userFathername' => mb_substr($epalUser->fathername->value,0,4,'UTF-8') !== "####" ? $epalUser->fathername->value : '',
'userMothername' => mb_substr($epalUser->mothername->value,0,4,'UTF-8') !== "####" ? $epalUser->mothername->value : '',
'userEmail' => mb_substr($user->mail->value,0,4,'UTF-8') !== "####" ? $user->mail->value : '',
'verificationCodeVerified' => $epalUser->verificationcodeverified->value,
], Response::HTTP_OK);
} else {
return $this->respondWithStatus([
......@@ -76,6 +89,167 @@ class CurrentUser extends ControllerBase
}
}
public function sendVerificationCode(Request $request)
{
if (!$request->isMethod('POST')) {
return $this->respondWithStatus([
"message" => t("Method Not Allowed")
], Response::HTTP_METHOD_NOT_ALLOWED);
}
$authToken = $request->headers->get('PHP_AUTH_USER');
$trx = $this->connection->startTransaction();
try {
$epalUsers = $this->entityTypeManager->getStorage('epal_users')->loadByProperties(array('authtoken' => $authToken));
$epalUser = reset($epalUsers);
if ($epalUser) {
$user = $this->entityTypeManager->getStorage('user')->load($epalUser->user_id->target_id);
if ($user) {
$postData = null;
if ($content = $request->getContent()) {
$postData = json_decode($content);
$verificationCode = uniqid();
$epalUser->set('verificationcode', $verificationCode);
$epalUser->set('verificationcodeverified', FALSE);
$epalUser->save();
$user->set('mail', $postData->userEmail);
$user->save();
$this->sendEmailWithVerificationCode($postData->userEmail, $verificationCode, $user);
return $this->respondWithStatus([
'userEmail' => $postData->userEmail,
'verCode' => $verificationCode,
], Response::HTTP_OK);
}
else {
return $this->respondWithStatus([
'message' => t("post with no data"),
], Response::HTTP_BAD_REQUEST);
}
} else {
return $this->respondWithStatus([
'message' => t("user not found"),
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
} else {
return $this->respondWithStatus([
'message' => t("EPAL user not found"),
], Response::HTTP_FORBIDDEN);
}
} catch (\Exception $ee) {
$this->logger->warning($ee->getMessage());
$trx->rollback();
return false;
}
}
private function sendEmailWithVerificationCode($email, $vc, $user) {
$mailManager = \Drupal::service('plugin.manager.mail');
$module = 'epal';
$key = 'send_verification_code';
$to = $email;
$params['message'] = 'verification code=' . $vc;
$langcode = $user->getPreferredLangcode();
$send = true;
$mail_sent = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);
if ($mail_sent) {
$this->logger->info("Mail Sent successfully.");
}
else {
$this->logger->info("There is error in sending mail.");
}
return;
}
public function verifyVerificationCode(Request $request)
{
if (!$request->isMethod('POST')) {
return $this->respondWithStatus([
"message" => t("Method Not Allowed")
], Response::HTTP_METHOD_NOT_ALLOWED);
}
$authToken = $request->headers->get('PHP_AUTH_USER');
$epalUsers = $this->entityTypeManager->getStorage('epal_users')->loadByProperties(array('authtoken' => $authToken));
$epalUser = reset($epalUsers);
if ($epalUser) {
$user = $this->entityTypeManager->getStorage('user')->load($epalUser->user_id->target_id);
if ($user) {
$postData = null;
if ($content = $request->getContent()) {
$postData = json_decode($content);
if ($epalUser->verificationcode->value !== $postData->verificationCode) {
return $this->respondWithStatus([
'userEmail' => $user->mail->value,
'verificationCodeVerified' => false
], Response::HTTP_OK);
} else {
$epalUser->set('verificationcodeverified', true);
$epalUser->save();
return $this->respondWithStatus([
'userEmail' => $user->mail->value,
'verificationCodeVerified' => true
], Response::HTTP_OK);
}
}
} else {
return $this->respondWithStatus([
'message' => t("user not found"),
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
} else {
return $this->respondWithStatus([
'message' => t("EPAL user not found"),
], Response::HTTP_FORBIDDEN);
}
}
public function saveUserProfile(Request $request)
{
if (!$request->isMethod('POST')) {
return $this->respondWithStatus([
"message" => t("Method Not Allowed")
], Response::HTTP_METHOD_NOT_ALLOWED);
}
$authToken = $request->headers->get('PHP_AUTH_USER');
$epalUsers = $this->entityTypeManager->getStorage('epal_users')->loadByProperties(array('authtoken' => $authToken));
$epalUser = reset($epalUsers);
if ($epalUser) {
$postData = null;
if ($content = $request->getContent()) {
$postData = json_decode($content);
$epalUser->set('name', $postData->userProfile->userName);
$epalUser->set('surname', $postData->userProfile->userSurname);
$epalUser->set('mothername', $postData->userProfile->userMothername);
$epalUser->set('fathername', $postData->userProfile->userFathername);
$epalUser->save();
return $this->respondWithStatus([
'message' => t("profile saved"),
], Response::HTTP_OK);
} else {
return $this->respondWithStatus([
'message' => t("post with no data"),
], Response::HTTP_BAD_REQUEST);
}
} else {
return $this->respondWithStatus([
'message' => t("EPAL user not found"),
], Response::HTTP_FORBIDDEN);
}
}
private function respondWithStatus($arr, $s) {
$res = new JsonResponse($arr);
......
......@@ -473,6 +473,31 @@ class EpalUsers extends ContentEntityBase implements EpalUsersInterface {
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['verificationcode'] = BaseFieldDefinition::create('string')
->setLabel(t('Email Verification Code'))
->setDescription(t('Generated email verification code'))
->setSettings(array(
'max_length' => 20,
'text_processing' => 0,
))
->setDefaultValue('')
->setDisplayOptions('view', array(
'label' => 'above',
'type' => 'string',
'weight' => -4,
))
->setDisplayOptions('form', array(
'type' => 'string_textfield',
'weight' => -4,
))
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
$fields['verificationcodeverified'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Email Verification Code Verified'))
->setDescription(t('A boolean indicating whether the email verification code was verified.'))
->setDefaultValue(FALSE);
$fields['accesstoken'] = BaseFieldDefinition::create('string')
->setLabel(t('Access-Token από taxis'))
->setDescription(t('Access-Token από taxis.'))
......
langcode: el
status: true
dependencies: { }
id: applicant
label: applicant
weight: 3
is_admin: null
permissions:
- 'add epal student class entities'
- 'add epal student entities'
- 'add epal student course field entities'
- 'add epal student epal chosen entities'
- 'add epal student sector field entities'
- 'add epal users entities'
- 'delete epal student class entities'
- 'delete epal student entities'
- 'delete epal student course field entities'
- 'delete epal student epal chosen entities'
- 'delete epal student sector field entities'
- 'delete epal users entities'
- 'edit epal student class entities'
- 'edit epal student entities'
- 'edit epal student course field entities'
- 'edit epal student epal chosen entities'
- 'edit epal student sector field entities'
- 'edit epal users entities'
- 'view published epal student class entities'
- 'view published epal student entities'
- 'view published epal student course field entities'
- 'view published epal student epal chosen entities'
- 'view published epal student sector field entities'
- 'view published epal users entities'
- 'view unpublished epal student class entities'
- 'view unpublished epal student entities'
- 'view unpublished epal student course field entities'
- 'view unpublished epal student epal chosen entities'
- 'view unpublished epal student sector field entities'
- 'view unpublished epal users entities'
- 'view published eepal admin area entities'
- 'view published eepal prefecture entities'
- 'view published eepal region entities'
- 'view published eepal school entities'
- 'view published eepal sectors entities'
- 'view published eepal sectors in epal entities'
- 'view published eepal specialties in epal entities'
- 'view published eepal specialty entities'
- 'view unpublished eepal admin area entities'
- 'view unpublished eepal prefecture entities'
- 'view unpublished eepal region entities'
- 'view unpublished eepal school entities'
- 'view unpublished eepal sectors entities'
- 'view unpublished eepal sectors in epal entities'
- 'view unpublished eepal specialties in epal entities'
- 'view unpublished eepal specialty entities'
......@@ -216,7 +216,7 @@ class CBController extends ControllerBase
$this->logger->warning($e->getMessage());
$trx->rollback();
return false;
} catch (Exception $ee) {
} catch (\Exception $ee) {
$this->logger->warning($ee->getMessage());
$trx->rollback();
return false;
......
<div class = "loading" *ngIf="(epalUserData$ | async) === {}"></div>
<form [formGroup]="formGroup">
<div class="form-group">
<label for="userEmail">Email Επικοινωνίας</label><input #userEmail class="form-control" type="text" formControlName="userEmail">
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userEmail').hasError('required')">
Το πεδίο δεν μπορεί να αφεθεί κενό!
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userEmail').hasError('pattern')">
Πληκτρολογήστε ένα σωστό συντακτικά email!
</div>
<div class="row" *ngIf="(userEmailEnabled | async) && formGroup.get('userEmail').valid" style="margin-top: 20px; margin-bottom: 20px;">
<div class="col-md-12">
<button type="button" class="btn-primary btn-sm pull-right" (click)="sendVerificationCode()">
Λήψη Κωδικού Επαλήθευσης
</button>
</div>
</div>
<div class="row" style="margin-bottom: 20px;">
<div class="col-md-12">
<div *ngIf="(userEmailEnabled | async) && (epalUserData$ | async).userEmail !== ''">
<button type="button" class="btn-primary btn-sm pull-right" (click)="resetUserEmail();">
Ακύρωση Αλλαγής Email
</button>
</div>
<div *ngIf="!(userEmailEnabled | async)" style="margin-left: 10px;" >
<button type="button" class="btn-primary btn-sm pull-right" (click)="enableUserEmail();">
Αλλαγή Email
</button>
</div>
</div>
</div>
<div class="form-group" *ngIf="(verificationCodeSent | async) && !(verificationCodeVerified | async)">
<label for="verificationCode">Κωδικός επαλήθευσης</label><input class="form-control" type="text" formControlName="verificationCode">
</div>
<div class="row" *ngIf="(verificationCodeSent | async) && !(verificationCodeVerified | async)">
<div class="col-md-12">
<button type="button" class="btn-primary btn-sm pull-right" (click)="verifyVerificationCode()">
Αποστολή Κωδικού Επαλήθευσης
</button>
</div>
</div>
<div class="form-group" *ngIf="!(userEmailEnabled | async) && (verificationCodeVerified | async)">
<label for="userName">Όνομα</label><input class="form-control" type="text" formControlName="userName">
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userName').touched && formGroup.get('userName').hasError('required') ">
Το πεδίο δεν μπορεί να αφεθεί κενό!
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userName').hasError('pattern')">
Πληκτρολογήστε το όνομά σας!
</div>
<div class="form-group" *ngIf="!(userEmailEnabled | async) && (verificationCodeVerified | async)">
<label for="userSurname">Επώνυμο</label><input class="form-control" type="text" formControlName="userSurname">
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userSurname').touched && formGroup.get('userSurname').hasError('required') ">
Το πεδίο δεν μπορεί να αφεθεί κενό!
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userSurname').hasError('pattern')">
Πληκτρολογήστε το επώνυμό σας!
</div>
<div class="form-group" *ngIf="!(userEmailEnabled | async) && (verificationCodeVerified | async)">
<label for="userFathername">Πατρώνυμο</label><input class="form-control" type="text" formControlName="userFathername">
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userFathername').touched && formGroup.get('userFathername').hasError('required') ">
Το πεδίο δεν μπορεί να αφεθεί κενό!
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userFathername').hasError('pattern')">
Πληκτρολογήστε το όνομα του πατέρα σας!
</div>
<div class="form-group" *ngIf="!(userEmailEnabled | async) && (verificationCodeVerified | async)">
<label for="userMothername">Μητρώνυμο</label><input class="form-control" type="text" formControlName="userMothername">
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userMothername').touched && formGroup.get('userMothername').hasError('required') ">
Το πεδίο δεν μπορεί να αφεθεί κενό!
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('userMothername').hasError('pattern')">
Πληκτρολογήστε το όνομα της μητέρας σας!
</div>
<div class="row" *ngIf="!(userEmailEnabled | async) && (verificationCodeVerified | async)">
<div class="col-md-12">
<button type="button" class="btn-primary btn-sm pull-right" (click)="saveProfileAndContinue()" [disabled]="((userEmailEnabled | async) && !(verificationCodeVerified | async))">
Αποθήκευση - Συνέχεια
<i class="fa fa-forward"></i> </button>
</div>
</div>
</form>
import { Component, OnInit, OnDestroy, Injectable } from '@angular/core';
import { Component, OnInit, OnDestroy, Injectable, ViewChild, ElementRef, Renderer } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject, Subscription } from 'rxjs/Rx';
import { VALID_EMAIL_PATTERN } from '../../constants';
import { VALID_EMAIL_PATTERN, VALID_NAMES_PATTERN } from '../../constants';
import { HelperDataService } from '../../services/helper-data-service';
import {
......@@ -15,60 +15,117 @@ import {AppSettings} from '../../app.settings';
@Component({
selector: 'parent-form',
template: `
<div class = "loading" *ngIf="(epalUserData$ | async) === {}"></div>
<form [formGroup]="formGroup">
<div class="form-group">
<label for="email">Email Επικοινωνίας</label><input class="form-control" type="text" formControlName="email">
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('email').touched && formGroup.get('email').hasError('required') ">
Το πεδίο δεν μπορεί να αφεθεί κενό!
</div>
<div class="alert alert-danger" *ngIf="formGroup.get('email').dirty && formGroup.get('email').hasError('pattern')">
Πληκτρολογήστε ένα σωστό συντακτικά email!
</div>
<div class="row">
<div class="col-md-12">
<button type="button" class="btn-primary btn-lg pull-right" (click)="sendVerificationCode()">
Αποστολή Κωδικού Επαλήθευσης </button>
</div>
</div>
<div class="form-group">
<label for="verification_code">Κωδικός επαλήθευσης</label><input class="form-control" type="text" formControlName="verification_code">
</div>
<div class="row">
<div class="col-md-12">
<button type="button" class="btn-primary btn-lg pull-right" (click)="verifyCodeAndContinue()">
<i class="fa fa-forward"></i> </button>
</div>
</div>
</form>
`
templateUrl: 'parent.form.html'
})
@Injectable() export default class ParentForm implements OnInit {
@Injectable() export default class ParentForm implements OnInit, OnDestroy {
public formGroup: FormGroup;
private respond: any;
private epalUserData$: BehaviorSubject<any>;
private epalUserDataSub: Subscription;
private userEmailSub: Subscription;
private verificationCodeSent: BehaviorSubject<boolean>;
private verificationCodeVerified: BehaviorSubject<boolean>;
private userEmailEnabled: BehaviorSubject<boolean>;
@ViewChild('userEmail') userEmail: ElementRef;
constructor(private fb: FormBuilder,
private router: Router,
private hds: HelperDataService) {
this.epalUserData$ = new BehaviorSubject({});
this.formGroup = this.fb.group({
name: ['', [Validators.pattern(VALID_EMAIL_PATTERN),Validators.required]],
});
};
private hds: HelperDataService,
private rd: Renderer) {
this.verificationCodeSent = new BehaviorSubject(false);
this.verificationCodeVerified = new BehaviorSubject(false);
this.userEmailEnabled = new BehaviorSubject(false);
this.formGroup = this.fb.group({
userName: ['', [Validators.pattern(VALID_NAMES_PATTERN),Validators.required]],
userSurname: ['', [Validators.pattern(VALID_NAMES_PATTERN),Validators.required]],
userFathername: ['', [Validators.pattern(VALID_NAMES_PATTERN),Validators.required]],
userMothername: ['', [Validators.pattern(VALID_NAMES_PATTERN),Validators.required]],
userEmail: [{value: '', disabled: true}, [Validators.pattern(VALID_EMAIL_PATTERN),Validators.required]],
verificationCode: ['', []]
});
this.epalUserData$ = new BehaviorSubject({});
}
ngOnInit() {
this.epalUserDataSub = this.hds.getEpalUserData().subscribe(this.epalUserData$);
this.epalUserDataSub = this.hds.getEpalUserData().subscribe(
x => {
this.epalUserData$.next(x);
this.formGroup.get('userEmail').setValue(x.userEmail);
this.formGroup.get('userName').setValue(x.userName);
this.formGroup.get('userSurname').setValue(x.userSurname);
this.formGroup.get('userFathername').setValue(x.userFathername);
this.formGroup.get('userMothername').setValue(x.userMothername);
if (typeof(x.verificationCodeVerified) !== 'undefined' && x.verificationCodeVerified === "1") {
this.verificationCodeVerified.next(true);
} else {
this.verificationCodeVerified.next(false);
}
if (typeof(x.userEmail) !== 'undefined' && x.userEmail.length > 0)
this.userEmailEnabled.next(false);
else {
this.enableUserEmail();
this.userEmailEnabled.next(true);
}
}
);
this.userEmailSub = this.formGroup.get('userEmail').valueChanges.subscribe(
x => {
if (this.formGroup.get('userEmail').value === '') {
this.enableUserEmail();
}
}