parent
a5d5a5b5d8
commit
2efd2af702
@ -1,7 +0,0 @@ |
|||||||
# Speech authentication with Whispeak |
|
||||||
|
|
||||||
Instructions: |
|
||||||
1. Install plugin in Chamilo. |
|
||||||
2. Set the plugin configuration with the token and API url. And enable the plugin. |
|
||||||
3. Set the `login_bottom` region to the plugin. |
|
||||||
4. Add `$_configuration['whispeak_auth_enabled'] = true;` to `configuration.php` file. |
|
||||||
@ -1,293 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
use Chamilo\CoreBundle\Entity\ExtraField; |
|
||||||
use Chamilo\CoreBundle\Entity\ExtraFieldValues; |
|
||||||
use Chamilo\UserBundle\Entity\User; |
|
||||||
|
|
||||||
/** |
|
||||||
* Class WhispeakAuthPlugin. |
|
||||||
*/ |
|
||||||
class WhispeakAuthPlugin extends Plugin |
|
||||||
{ |
|
||||||
const SETTING_ENABLE = 'enable'; |
|
||||||
const SETTING_API_URL = 'api_url'; |
|
||||||
const SETTING_TOKEN = 'token'; |
|
||||||
const SETTING_INSTRUCTION = 'instruction'; |
|
||||||
|
|
||||||
const EXTRAFIELD_AUTH_UID = 'whispeak_auth_uid'; |
|
||||||
|
|
||||||
/** |
|
||||||
* StudentFollowUpPlugin constructor. |
|
||||||
*/ |
|
||||||
protected function __construct() |
|
||||||
{ |
|
||||||
parent::__construct( |
|
||||||
'0.1', |
|
||||||
'Angel Fernando Quiroz', |
|
||||||
[ |
|
||||||
self::SETTING_ENABLE => 'boolean', |
|
||||||
self::SETTING_API_URL => 'text', |
|
||||||
self::SETTING_TOKEN => 'text', |
|
||||||
self::SETTING_INSTRUCTION => 'html', |
|
||||||
] |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @return WhispeakAuthPlugin |
|
||||||
*/ |
|
||||||
public static function create() |
|
||||||
{ |
|
||||||
static $result = null; |
|
||||||
|
|
||||||
return $result ? $result : $result = new self(); |
|
||||||
} |
|
||||||
|
|
||||||
public function install() |
|
||||||
{ |
|
||||||
UserManager::create_extra_field( |
|
||||||
self::EXTRAFIELD_AUTH_UID, |
|
||||||
\ExtraField::FIELD_TYPE_TEXT, |
|
||||||
$this->get_lang('Whispeak uid'), |
|
||||||
'' |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
public function uninstall() |
|
||||||
{ |
|
||||||
$extraField = self::getAuthUidExtraField(); |
|
||||||
|
|
||||||
if (empty($extraField)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
$em = Database::getManager(); |
|
||||||
|
|
||||||
$em->createQuery('DELETE FROM ChamiloCoreBundle:ExtraFieldValues efv WHERE efv.field = :field') |
|
||||||
->execute(['field' => $extraField]); |
|
||||||
|
|
||||||
$em->remove($extraField); |
|
||||||
$em->flush(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @return ExtraField |
|
||||||
*/ |
|
||||||
public static function getAuthUidExtraField() |
|
||||||
{ |
|
||||||
$em = Database::getManager(); |
|
||||||
$efRepo = $em->getRepository('ChamiloCoreBundle:ExtraField'); |
|
||||||
|
|
||||||
/** @var ExtraField $extraField */ |
|
||||||
$extraField = $efRepo->findOneBy( |
|
||||||
[ |
|
||||||
'variable' => self::EXTRAFIELD_AUTH_UID, |
|
||||||
'extraFieldType' => ExtraField::USER_FIELD_TYPE, |
|
||||||
] |
|
||||||
); |
|
||||||
|
|
||||||
return $extraField; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param int $userId |
|
||||||
* |
|
||||||
* @return ExtraFieldValues |
|
||||||
*/ |
|
||||||
public static function getAuthUidValue($userId) |
|
||||||
{ |
|
||||||
$extraField = self::getAuthUidExtraField(); |
|
||||||
$em = Database::getManager(); |
|
||||||
$efvRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldValues'); |
|
||||||
|
|
||||||
/** @var ExtraFieldValues $value */ |
|
||||||
$value = $efvRepo->findOneBy(['field' => $extraField, 'itemId' => $userId]); |
|
||||||
|
|
||||||
return $value; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param int $userId |
|
||||||
* |
|
||||||
* @return bool |
|
||||||
*/ |
|
||||||
public static function checkUserIsEnrolled($userId) |
|
||||||
{ |
|
||||||
$value = self::getAuthUidValue($userId); |
|
||||||
|
|
||||||
if (empty($value)) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return !empty($value->getValue()); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @return string |
|
||||||
*/ |
|
||||||
public static function getEnrollmentUrl() |
|
||||||
{ |
|
||||||
return api_get_path(WEB_PLUGIN_PATH).'whispeakauth/enrollment.php'; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param User $user |
|
||||||
* @param string $filePath |
|
||||||
* |
|
||||||
* @return array |
|
||||||
*/ |
|
||||||
public function requestEnrollment(User $user, $filePath) |
|
||||||
{ |
|
||||||
$metadata = [ |
|
||||||
'motherTongue' => $user->getLanguage(), |
|
||||||
'spokenTongue' => $user->getLanguage(), |
|
||||||
'audioType' => 'pcm', |
|
||||||
]; |
|
||||||
|
|
||||||
return $this->sendRequest( |
|
||||||
'enrollment', |
|
||||||
$metadata, |
|
||||||
$user, |
|
||||||
$filePath |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param User $user |
|
||||||
* @param string $uid |
|
||||||
* |
|
||||||
* @throws \Doctrine\ORM\OptimisticLockException |
|
||||||
*/ |
|
||||||
public function saveEnrollment(User $user, $uid) |
|
||||||
{ |
|
||||||
$em = Database::getManager(); |
|
||||||
$value = self::getAuthUidValue($user->getId()); |
|
||||||
|
|
||||||
if (empty($value)) { |
|
||||||
$ef = self::getAuthUidExtraField(); |
|
||||||
$now = new DateTime('now', new DateTimeZone('UTC')); |
|
||||||
|
|
||||||
$value = new ExtraFieldValues(); |
|
||||||
$value |
|
||||||
->setField($ef) |
|
||||||
->setItemId($user->getId()) |
|
||||||
->setUpdatedAt($now); |
|
||||||
} |
|
||||||
|
|
||||||
$value->setValue($uid); |
|
||||||
|
|
||||||
$em->persist($value); |
|
||||||
$em->flush(); |
|
||||||
} |
|
||||||
|
|
||||||
public function requestAuthentify(User $user, $filePath) |
|
||||||
{ |
|
||||||
$value = self::getAuthUidValue($user->getId()); |
|
||||||
|
|
||||||
if (empty($value)) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
$metadata = [ |
|
||||||
'uid' => $value->getValue(), |
|
||||||
'audioType' => 'pcm', |
|
||||||
]; |
|
||||||
|
|
||||||
return $this->sendRequest( |
|
||||||
'authentify', |
|
||||||
$metadata, |
|
||||||
$user, |
|
||||||
$filePath |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @return string |
|
||||||
*/ |
|
||||||
public function getAuthentifySampleText() |
|
||||||
{ |
|
||||||
$phrases = []; |
|
||||||
|
|
||||||
for ($i = 1; $i <= 6; $i++) { |
|
||||||
$phrases[] = $this->get_lang("AuthentifySampleText$i"); |
|
||||||
} |
|
||||||
|
|
||||||
$rand = array_rand($phrases, 1); |
|
||||||
|
|
||||||
return $phrases[$rand]; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @return bool |
|
||||||
*/ |
|
||||||
public function toolIsEnabled() |
|
||||||
{ |
|
||||||
return 'true' === $this->get(self::SETTING_ENABLE); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Access not allowed when tool is not enabled. |
|
||||||
* |
|
||||||
* @param bool $printHeaders Optional. Print headers. |
|
||||||
*/ |
|
||||||
public function protectTool($printHeaders = true) |
|
||||||
{ |
|
||||||
if ($this->toolIsEnabled()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
api_not_allowed($printHeaders); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @return string |
|
||||||
*/ |
|
||||||
private function getApiUrl() |
|
||||||
{ |
|
||||||
$url = $this->get(self::SETTING_API_URL); |
|
||||||
|
|
||||||
return trim($url, " \t\n\r \v/"); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param string $endPoint |
|
||||||
* @param array $metadata |
|
||||||
* @param User $user |
|
||||||
* @param string $filePath |
|
||||||
* |
|
||||||
* @return array |
|
||||||
*/ |
|
||||||
private function sendRequest($endPoint, array $metadata, User $user, $filePath) |
|
||||||
{ |
|
||||||
$moderator = $user->getCreatorId() ?: $user->getId(); |
|
||||||
$apiUrl = $this->getApiUrl()."/$endPoint"; |
|
||||||
$headers = [ |
|
||||||
//"Content-Type: application/x-www-form-urlencoded", |
|
||||||
"Authorization: Bearer ".$this->get(self::SETTING_TOKEN), |
|
||||||
]; |
|
||||||
$post = [ |
|
||||||
'metadata' => json_encode($metadata), |
|
||||||
'moderator' => "moderator_$moderator", |
|
||||||
'client' => base64_encode($user->getUserId()), |
|
||||||
'voice' => new CURLFile($filePath), |
|
||||||
]; |
|
||||||
|
|
||||||
$ch = curl_init(); |
|
||||||
curl_setopt($ch, CURLOPT_URL, $apiUrl); |
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); |
|
||||||
curl_setopt($ch, CURLOPT_POST, true); |
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post); |
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
|
||||||
$result = curl_exec($ch); |
|
||||||
curl_close($ch); |
|
||||||
|
|
||||||
$result = json_decode($result, true); |
|
||||||
|
|
||||||
if (!empty($result['error'])) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
return json_decode($result, true); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,136 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
use Chamilo\UserBundle\Entity\User; |
|
||||||
use FFMpeg\FFMpeg; |
|
||||||
use FFMpeg\Format\Audio\Wav; |
|
||||||
|
|
||||||
$cidReset = true; |
|
||||||
|
|
||||||
require_once __DIR__.'/../../../main/inc/global.inc.php'; |
|
||||||
|
|
||||||
$action = isset($_POST['action']) ? $_POST['action'] : 'enrollment'; |
|
||||||
$isEnrollment = 'enrollment' === $action; |
|
||||||
$isAuthentify = 'authentify' === $action; |
|
||||||
|
|
||||||
$isAllowed = true; |
|
||||||
|
|
||||||
if ($isEnrollment) { |
|
||||||
api_block_anonymous_users(false); |
|
||||||
|
|
||||||
$isAllowed = !empty($_FILES['audio']); |
|
||||||
} elseif ($isAuthentify) { |
|
||||||
$isAllowed = !empty($_POST['username']) && !empty($_FILES['audio']); |
|
||||||
} |
|
||||||
|
|
||||||
if (!$isAllowed) { |
|
||||||
echo Display::return_message(get_lang('NotAllowed'), 'error'); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
|
|
||||||
$plugin = WhispeakAuthPlugin::create(); |
|
||||||
|
|
||||||
$plugin->protectTool(false); |
|
||||||
|
|
||||||
if ($isAuthentify) { |
|
||||||
$em = Database::getManager(); |
|
||||||
/** @var User|null $user */ |
|
||||||
$user = $em->getRepository('ChamiloUserBundle:User')->findOneBy(['username' => $_POST['username']]); |
|
||||||
} else { |
|
||||||
/** @var User $user */ |
|
||||||
$user = api_get_user_entity(api_get_user_id()); |
|
||||||
} |
|
||||||
|
|
||||||
if (empty($user)) { |
|
||||||
echo Display::return_message(get_lang('NoUser'), 'error'); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
|
|
||||||
$path = api_upload_file('whispeakauth', $_FILES['audio'], $user->getId()); |
|
||||||
|
|
||||||
if (false === $path) { |
|
||||||
echo Display::return_message(get_lang('UploadError'), 'error'); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
|
|
||||||
$newFullPath = $originFullPath = api_get_path(SYS_UPLOAD_PATH).'whispeakauth'.$path['path_to_save']; |
|
||||||
$fileType = mime_content_type($originFullPath); |
|
||||||
|
|
||||||
if ('wav' !== substr($fileType, -3)) { |
|
||||||
$directory = dirname($originFullPath); |
|
||||||
$newFullPath = $directory.'/audio.wav'; |
|
||||||
|
|
||||||
try { |
|
||||||
$ffmpeg = FFMpeg::create(); |
|
||||||
|
|
||||||
$audio = $ffmpeg->open($originFullPath); |
|
||||||
$audio->save(new Wav(), $newFullPath); |
|
||||||
} catch (Exception $exception) { |
|
||||||
echo Display::return_message($exception->getMessage(), 'error'); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ($isEnrollment) { |
|
||||||
$result = $plugin->requestEnrollment($user, $newFullPath); |
|
||||||
|
|
||||||
if (empty($result)) { |
|
||||||
echo Display::return_message($plugin->get_lang('EnrollmentFailed')); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
|
|
||||||
$reliability = (int) $result['reliability']; |
|
||||||
|
|
||||||
if ($reliability <= 0) { |
|
||||||
echo Display::return_message($plugin->get_lang('EnrollmentSignature0'), 'error'); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
|
|
||||||
$plugin->saveEnrollment($user, $result['uid']); |
|
||||||
|
|
||||||
$message = '<strong>'.$plugin->get_lang('EnrollmentSuccess').'</strong>'; |
|
||||||
$message .= PHP_EOL; |
|
||||||
$message .= $plugin->get_lang("EnrollmentSignature$reliability"); |
|
||||||
|
|
||||||
echo Display::return_message($message, 'success', false); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
|
|
||||||
if ($isAuthentify) { |
|
||||||
$result = $plugin->requestAuthentify($user, $newFullPath); |
|
||||||
|
|
||||||
if (empty($result)) { |
|
||||||
echo Display::return_message($plugin->get_lang('AuthentifyFailed'), 'error'); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
|
|
||||||
$success = (bool) $result['audio'][0]['result']; |
|
||||||
|
|
||||||
if (!$success) { |
|
||||||
echo Display::return_message($plugin->get_lang('TryAgain'), 'warning'); |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
|
|
||||||
$loggedUser = [ |
|
||||||
'user_id' => $user->getId(), |
|
||||||
'status' => $user->getStatus(), |
|
||||||
'uidReset' => true, |
|
||||||
]; |
|
||||||
|
|
||||||
ChamiloSession::write('_user', $loggedUser); |
|
||||||
Login::init_user($user->getId(), true); |
|
||||||
|
|
||||||
echo Display::return_message($plugin->get_lang('AuthentifySuccess'), 'success'); |
|
||||||
echo '<script>window.location.href = "'.api_get_path(WEB_PATH).'";</script>'; |
|
||||||
|
|
||||||
exit; |
|
||||||
} |
|
||||||
@ -1,139 +0,0 @@ |
|||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
window.RecordAudio = (function () { |
|
||||||
function useRecordRTC(rtcInfo) { |
|
||||||
$(rtcInfo.blockId).show(); |
|
||||||
|
|
||||||
var mediaConstraints = {audio: true}, |
|
||||||
localStream = null, |
|
||||||
recordRTC = null, |
|
||||||
btnStart = $(rtcInfo.btnStartId), |
|
||||||
btnStop = $(rtcInfo.btnStopId), |
|
||||||
btnSave = $(rtcInfo.btnSaveId), |
|
||||||
tagAudio = $(rtcInfo.plyrPreviewId); |
|
||||||
|
|
||||||
function saveAudio() { |
|
||||||
var recordedBlob = recordRTC.getBlob(); |
|
||||||
|
|
||||||
if (!recordedBlob) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
var btnSaveText = btnSave.html(); |
|
||||||
var fileExtension = recordedBlob.type.split('/')[1]; |
|
||||||
|
|
||||||
var formData = new FormData(); |
|
||||||
formData.append('audio', recordedBlob, 'audio.' + fileExtension); |
|
||||||
|
|
||||||
for (var prop in rtcInfo.data) { |
|
||||||
if (!rtcInfo.data.hasOwnProperty(prop)) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
formData.append(prop, rtcInfo.data[prop]); |
|
||||||
} |
|
||||||
|
|
||||||
$.ajax({ |
|
||||||
url: _p.web_plugin + 'whispeakauth/ajax/record_audio.php', |
|
||||||
data: formData, |
|
||||||
processData: false, |
|
||||||
contentType: false, |
|
||||||
type: 'POST', |
|
||||||
beforeSend: function () { |
|
||||||
btnStart.prop('disabled', true); |
|
||||||
btnStop.prop('disabled', true); |
|
||||||
btnSave.prop('disabled', true).text(btnSave.data('loadingtext')); |
|
||||||
} |
|
||||||
}).done(function (response) { |
|
||||||
$('#messages-deck').append(response); |
|
||||||
}).always(function () { |
|
||||||
btnSave.prop('disabled', true).html(btnSaveText).parent().addClass('hidden'); |
|
||||||
btnStop.prop('disabled', true).parent().addClass('hidden'); |
|
||||||
btnStart.prop('disabled', false).parent().removeClass('hidden'); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
btnStart.on('click', function () { |
|
||||||
tagAudio.prop('src', ''); |
|
||||||
|
|
||||||
function successCallback(stream) { |
|
||||||
localStream = stream; |
|
||||||
|
|
||||||
recordRTC = RecordRTC(stream, { |
|
||||||
recorderType: StereoAudioRecorder, |
|
||||||
numberOfAudioChannels: 1, |
|
||||||
type: 'audio' |
|
||||||
}); |
|
||||||
recordRTC.startRecording(); |
|
||||||
|
|
||||||
btnSave.prop('disabled', true).parent().addClass('hidden'); |
|
||||||
btnStop.prop('disabled', false).parent().removeClass('hidden'); |
|
||||||
btnStart.prop('disabled', true).parent().addClass('hidden'); |
|
||||||
tagAudio.removeClass('show').parents('#audio-wrapper').addClass('hidden'); |
|
||||||
} |
|
||||||
|
|
||||||
function errorCallback(error) { |
|
||||||
alert(error.message); |
|
||||||
} |
|
||||||
|
|
||||||
if (navigator.mediaDevices.getUserMedia) { |
|
||||||
navigator.mediaDevices.getUserMedia(mediaConstraints) |
|
||||||
.then(successCallback) |
|
||||||
.catch(errorCallback); |
|
||||||
|
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia; |
|
||||||
|
|
||||||
if (navigator.getUserMedia) { |
|
||||||
navigator.getUserMedia(mediaConstraints, successCallback, errorCallback); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
btnStop.on('click', function () { |
|
||||||
if (!recordRTC) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
recordRTC.stopRecording(function (audioURL) { |
|
||||||
btnStart.prop('disabled', false).parent().removeClass('hidden'); |
|
||||||
btnStop.prop('disabled', true).parent().addClass('hidden'); |
|
||||||
btnSave.prop('disabled', false).parent().removeClass('hidden'); |
|
||||||
|
|
||||||
tagAudio |
|
||||||
.prop('src', audioURL) |
|
||||||
.parents('#audio-wrapper') |
|
||||||
.removeClass('hidden') |
|
||||||
.addClass('show'); |
|
||||||
|
|
||||||
localStream.getTracks()[0].stop(); |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
btnSave.on('click', function () { |
|
||||||
if (!recordRTC) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
saveAudio(); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
return { |
|
||||||
init: function (rtcInfo) { |
|
||||||
$(rtcInfo.blockId).hide(); |
|
||||||
|
|
||||||
var userMediaEnabled = (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) || |
|
||||||
!!navigator.webkitGetUserMedia || |
|
||||||
!!navigator.mozGetUserMedia || |
|
||||||
!!navigator.getUserMedia; |
|
||||||
|
|
||||||
if (!userMediaEnabled) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
useRecordRTC(rtcInfo); |
|
||||||
} |
|
||||||
} |
|
||||||
})(); |
|
||||||
@ -1,26 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
$cidReset = true; |
|
||||||
|
|
||||||
require_once __DIR__.'/../../main/inc/global.inc.php'; |
|
||||||
|
|
||||||
$plugin = WhispeakAuthPlugin::create(); |
|
||||||
|
|
||||||
$plugin->protectTool(); |
|
||||||
|
|
||||||
$form = new FormValidator('enter_username', 'post', '#'); |
|
||||||
$form->addText('username', get_lang('Username')); |
|
||||||
|
|
||||||
$htmlHeadXtra[] = api_get_js('rtc/RecordRTC.js'); |
|
||||||
$htmlHeadXtra[] = api_get_js_simple(api_get_path(WEB_PLUGIN_PATH).'whispeakauth/assets/js/RecordAudio.js'); |
|
||||||
|
|
||||||
$template = new Template(); |
|
||||||
$template->assign('form', $form->returnForm()); |
|
||||||
$template->assign('sample_text', $plugin->getAuthentifySampleText()); |
|
||||||
|
|
||||||
$content = $template->fetch('whispeakauth/view/authentify_recorder.html.twig'); |
|
||||||
|
|
||||||
$template->assign('header', $plugin->get_title()); |
|
||||||
$template->assign('content', $content); |
|
||||||
$template->display_one_col_template(); |
|
||||||
@ -1,28 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
$cidReset = true; |
|
||||||
|
|
||||||
require_once __DIR__.'/../../main/inc/global.inc.php'; |
|
||||||
|
|
||||||
api_block_anonymous_users(true); |
|
||||||
|
|
||||||
$userId = api_get_user_id(); |
|
||||||
$plugin = WhispeakAuthPlugin::create(); |
|
||||||
|
|
||||||
$plugin->protectTool(); |
|
||||||
|
|
||||||
$sampleText = $plugin->get_lang('EnrollmentSampleText'); |
|
||||||
|
|
||||||
$htmlHeadXtra[] = api_get_js('rtc/RecordRTC.js'); |
|
||||||
$htmlHeadXtra[] = api_get_js_simple(api_get_path(WEB_PLUGIN_PATH).'whispeakauth/assets/js/RecordAudio.js'); |
|
||||||
|
|
||||||
$template = new Template(); |
|
||||||
$template->assign('is_authenticated', WhispeakAuthPlugin::checkUserIsEnrolled($userId)); |
|
||||||
$template->assign('sample_text', $sampleText); |
|
||||||
|
|
||||||
$content = $template->fetch('whispeakauth/view/record_audio.html.twig'); |
|
||||||
|
|
||||||
$template->assign('header', $plugin->get_title()); |
|
||||||
$template->assign('content', $content); |
|
||||||
$template->display_one_col_template(); |
|
||||||
@ -1,14 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
$plugin = WhispeakAuthPlugin::create(); |
|
||||||
|
|
||||||
if ($plugin->toolIsEnabled()) { |
|
||||||
echo Display::toolbarButton( |
|
||||||
$plugin->get_lang('SpeechAuthentication'), |
|
||||||
api_get_path(WEB_PLUGIN_PATH).'whispeakauth/authentify.php', |
|
||||||
'sign-in', |
|
||||||
'info', |
|
||||||
['class' => 'btn-block'] |
|
||||||
); |
|
||||||
} |
|
||||||
@ -1,4 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
WhispeakAuthPlugin::create()->install(); |
|
||||||
@ -1,33 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
$strings['plugin_title'] = 'Speech authentication with Whispeak'; |
|
||||||
$strings['plugin_comment'] = 'Allow speech authentication in Chamilo.'; |
|
||||||
|
|
||||||
$strings['enable'] = 'Enable'; |
|
||||||
$strings['api_url'] = 'API URL'; |
|
||||||
$strings['api_url_help'] = 'http://api.whispeak.io:8080/v1/'; |
|
||||||
$strings['token'] = 'API key'; |
|
||||||
$strings['instruction'] = '<p>Add <code>$_configuration[\'whispeak_auth_enabled\'] = true;</code>'. |
|
||||||
'in the <code>configuration.php</code> file</p>'; |
|
||||||
|
|
||||||
$strings['EnrollmentSampleText'] = 'The famous Mona Lisa painting was painted by Leonardo Da Vinci.'; |
|
||||||
$strings['AuthentifySampleText1'] = 'Dropping Like Flies.'; |
|
||||||
$strings['AuthentifySampleText2'] = 'Keep Your Eyes Peeled.'; |
|
||||||
$strings['AuthentifySampleText3'] = 'The fox screams at midnight.'; |
|
||||||
$strings['AuthentifySampleText4'] = 'Go Out On a Limb.'; |
|
||||||
$strings['AuthentifySampleText5'] = 'Under the Water.'; |
|
||||||
$strings['AuthentifySampleText6'] = 'Barking Up The Wrong Tree.'; |
|
||||||
|
|
||||||
$strings['RepeatThisPhrase'] = 'Repeat this phrase three times after allowing audio recording:'; |
|
||||||
$strings['EnrollmentSignature0'] = 'Unsustainable signature requires a new enrollment.'; |
|
||||||
$strings['EnrollmentSignature1'] = 'Passable signature, advice to make a new enrollment.'; |
|
||||||
$strings['EnrollmentSignature2'] = 'Correct signature.'; |
|
||||||
$strings['EnrollmentSignature3'] = 'Good signature.'; |
|
||||||
$strings['SpeechAuthAlreadyEnrolled'] = 'Speech authentication already enrolled previously.'; |
|
||||||
$strings['SpeechAuthentication'] = 'Speech authentication'; |
|
||||||
$strings['EnrollmentFailed'] = 'Enrollment failed.'; |
|
||||||
$strings['EnrollmentSuccess'] = 'Enrollment success.'; |
|
||||||
$strings['AuthentifyFailed'] = 'Login failed.'; |
|
||||||
$strings['AuthentifySuccess'] = 'Authentication success!'; |
|
||||||
$strings['TryAgain'] = 'Try again'; |
|
||||||
@ -1,18 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
$strings['plugin_title'] = 'Authentification vocale avec Whispeak'; |
|
||||||
|
|
||||||
$strings['EnrollmentSampleText'] = 'Le fameux chef-d\'oeuvre Mona Lisa a été peint par Léonardo da Vinci.'; |
|
||||||
|
|
||||||
$strings['RepeatThisPhrase'] = 'Autorisez l\'enregistrement audio puis répétez cette phrase trois fois:'; |
|
||||||
$strings['EnrollmentSignature0'] = 'Signature non viable, nécessite un nouvel enrôlement'; |
|
||||||
$strings['EnrollmentSignature1'] = 'Signature passable, conseil de faire un nouvel enrôlement.'; |
|
||||||
$strings['EnrollmentSignature2'] = 'Signature correcte.'; |
|
||||||
$strings['EnrollmentSignature3'] = 'Signature bonne.'; |
|
||||||
$strings['SpeechAuthentication'] = 'Authentification de voix'; |
|
||||||
$strings['EnrollmentFailed'] = 'Échec à l\'inscription.'; |
|
||||||
$strings['EnrollmentSuccess'] = 'Inscription réussie.'; |
|
||||||
$strings['AuthentifyFailed'] = 'Échec de l\'authentification.'; |
|
||||||
$strings['AuthentifySuccess'] = 'Authentification réussie!'; |
|
||||||
$strings['TryAgain'] = 'Essayez encore'; |
|
||||||
@ -1,33 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
$strings['plugin_title'] = 'Authenticación de voz con Whispeak'; |
|
||||||
$strings['plugin_comment'] = 'Permitir autenticación de voz en Chamilo.'; |
|
||||||
|
|
||||||
$strings['enable'] = 'Habilitar'; |
|
||||||
$strings['api_url'] = 'URL del API'; |
|
||||||
$strings['api_url_help'] = 'http://api.whispeak.io:8080/v1/'; |
|
||||||
$strings['token'] = 'Llave del API'; |
|
||||||
$strings['instruction'] = '<p>Agrega <code>$_configuration[\'whispeak_auth_enabled\'] = true;</code>'. |
|
||||||
'al archivo <code>configuration.php</code></p>'; |
|
||||||
|
|
||||||
$strings['EnrollmentSampleText'] = 'El famoso cuadro de Mona Lisa fue pintado por Leonardo Da Vinci.'; |
|
||||||
$strings['AuthentifySampleText1'] = 'Cayendo como moscas.'; |
|
||||||
$strings['AuthentifySampleText2'] = 'Mantén tus ojos abiertos.'; |
|
||||||
$strings['AuthentifySampleText3'] = 'El zorro grita a medianoche.'; |
|
||||||
$strings['AuthentifySampleText4'] = 'Ir por las ramas.'; |
|
||||||
$strings['AuthentifySampleText5'] = 'Debajo del agua.'; |
|
||||||
$strings['AuthentifySampleText6'] = 'Ladrando al árbol equivocado.'; |
|
||||||
|
|
||||||
$strings['RepeatThisPhrase'] = 'Repita esta frase tres veces después de permitir la grabación de audio:'; |
|
||||||
$strings['EnrollmentSignature0'] = 'Firma insostenible, requiere una nueva inscripción.'; |
|
||||||
$strings['EnrollmentSignature1'] = 'Firma aceptable, pero se aconseja hacer una nueva inscripción.'; |
|
||||||
$strings['EnrollmentSignature2'] = 'Firma correcta.'; |
|
||||||
$strings['EnrollmentSignature3'] = 'Buena firma.'; |
|
||||||
$strings['SpeechAuthAlreadyEnrolled'] = 'Autenticación de voz registrada anteriormente.'; |
|
||||||
$strings['SpeechAuthentication'] = 'Atenticación con voz'; |
|
||||||
$strings['EnrollmentFailed'] = 'Inscripción fallida.'; |
|
||||||
$strings['EnrollmentSuccess'] = 'Inscripción correcta.'; |
|
||||||
$strings['AuthentifyFailed'] = 'Inicio de sesión fallido.'; |
|
||||||
$strings['AuthentifySuccess'] = '¡Autenticación correcta!'; |
|
||||||
$strings['TryAgain'] = 'Intente de nuevo.'; |
|
||||||
@ -1,4 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
$plugin_info = WhispeakAuthPlugin::create()->get_info(); |
|
||||||
@ -1,4 +0,0 @@ |
|||||||
<?php |
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
WhispeakAuthPlugin::create()->uninstall(); |
|
||||||
@ -1,38 +0,0 @@ |
|||||||
{% extends 'whispeakauth/view/record_audio.html.twig' %} |
|
||||||
|
|
||||||
{% block intro %} |
|
||||||
<form class="form-horizontal" action="#" method="post"> |
|
||||||
<div class="form-group "> |
|
||||||
<label for="enter_username_username" class="col-sm-4 control-label"> |
|
||||||
{{ 'Username'|get_lang }} |
|
||||||
</label> |
|
||||||
<div class="col-sm-8"> |
|
||||||
<input class="form-control" name="username" type="text" id="username"> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</form> |
|
||||||
|
|
||||||
<hr> |
|
||||||
|
|
||||||
{{ parent() }} |
|
||||||
{% endblock %} |
|
||||||
|
|
||||||
{% block config_data %} |
|
||||||
$('#username').on('change', function () { |
|
||||||
$('#record-audio-recordrtc, #btn-start-record, #btn-stop-record, #btn-save-record').off('click', ''); |
|
||||||
|
|
||||||
RecordAudio.init( |
|
||||||
{ |
|
||||||
blockId: '#record-audio-recordrtc', |
|
||||||
btnStartId: '#btn-start-record', |
|
||||||
btnStopId: '#btn-stop-record', |
|
||||||
btnSaveId: '#btn-save-record', |
|
||||||
plyrPreviewId: '#record-preview', |
|
||||||
data: { |
|
||||||
action: 'authentify', |
|
||||||
username: $('#username').val() |
|
||||||
} |
|
||||||
} |
|
||||||
); |
|
||||||
}); |
|
||||||
{% endblock %} |
|
||||||
@ -1,67 +0,0 @@ |
|||||||
<div id="record-audio-recordrtc" class="row"> |
|
||||||
<div class="col-sm-6"> |
|
||||||
{% block intro %} |
|
||||||
<p class="text-center">{{ 'RepeatThisPhrase'|get_plugin_lang('WhispeakAuthPlugin') }}</p> |
|
||||||
<div class="well well-sm"> |
|
||||||
<div class="row"> |
|
||||||
<div class="col-sm-3 text-center"> |
|
||||||
<span class="fa fa-microphone fa-5x fa-fw" aria-hidden="true"></span> |
|
||||||
<span class="sr-only">{{ 'RecordAudio'|get_lang }}</span> |
|
||||||
</div> |
|
||||||
<div class="col-sm-9 text-center"> |
|
||||||
<p class="lead">{{ sample_text }}</p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
{% endblock %} |
|
||||||
|
|
||||||
<ul class="list-inline text-center"> |
|
||||||
<li> |
|
||||||
<button class="btn btn-primary" type="button" id="btn-start-record"> |
|
||||||
<span class="fa fa-circle fa-fw" aria-hidden="true"></span> {{ 'StartRecordingAudio'|get_lang }} |
|
||||||
</button> |
|
||||||
</li> |
|
||||||
<li class="hidden"> |
|
||||||
<button class="btn btn-danger" type="button" id="btn-stop-record" disabled> |
|
||||||
<span class="fa fa-square fa-fw" aria-hidden="true"></span> {{ 'StopRecordingAudio'|get_lang }} |
|
||||||
</button> |
|
||||||
</li> |
|
||||||
<li class="hidden"> |
|
||||||
<button class="btn btn-success" type="button" id="btn-save-record" |
|
||||||
data-loadingtext="{{ 'Uploading'|get_lang }}" disabled> |
|
||||||
<span class="fa fa-send fa-fw" aria-hidden="true"></span> {{ 'SaveRecordedAudio'|get_lang }} |
|
||||||
</button> |
|
||||||
</li> |
|
||||||
</ul> |
|
||||||
<p class="hidden" id="audio-wrapper"> |
|
||||||
<audio class="center-block" controls id="record-preview"></audio> |
|
||||||
</p> |
|
||||||
</div> |
|
||||||
<div class="col-sm-5 col-sm-offset-1" id="messages-deck"> |
|
||||||
{% if is_authenticated %} |
|
||||||
<div class="alert alert-info"> |
|
||||||
<span class="fa fa-info-circle" aria-hidden="true"></span> |
|
||||||
<strong>{{ 'SpeechAuthAlreadyEnrolled'|get_plugin_lang('WhispeakAuthPlugin') }}</strong> |
|
||||||
</div> |
|
||||||
{% endif %} |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$(document).on('ready', function () { |
|
||||||
{% block config_data %} |
|
||||||
RecordAudio.init( |
|
||||||
{ |
|
||||||
blockId: '#record-audio-recordrtc', |
|
||||||
btnStartId: '#btn-start-record', |
|
||||||
btnStopId: '#btn-stop-record', |
|
||||||
btnSaveId: '#btn-save-record', |
|
||||||
plyrPreviewId: '#record-preview', |
|
||||||
data: { |
|
||||||
action: 'enrollment' |
|
||||||
} |
|
||||||
} |
|
||||||
); |
|
||||||
{% endblock %} |
|
||||||
}); |
|
||||||
</script> |
|
||||||
Loading…
Reference in new issue