Merge branch '1.1' of https://github.com/merdiano/birzha into 1.1
This commit is contained in:
commit
cf1e57fa1c
|
|
@ -30,7 +30,8 @@
|
|||
"october/system": "1.1.*",
|
||||
"october/backend": "1.1.*",
|
||||
"october/cms": "1.1.*",
|
||||
"laravel/framework": "~6.0"
|
||||
"laravel/framework": "~6.0",
|
||||
"franzose/laravel-smpp": "^1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.4|^9.3.3",
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ return [
|
|||
'providers' => array_merge(include(base_path('modules/system/providers.php')), [
|
||||
|
||||
// 'Illuminate\Html\HtmlServiceProvider', // Example
|
||||
|
||||
'LaravelSmpp\LaravelSmppServiceProvider',
|
||||
'System\ServiceProvider',
|
||||
]),
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default SMPP settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| 1. "sender" is the SMS message sender, either phone number or something like ABCDEF.
|
||||
| 2. "source_ton" is the sender's type of number
|
||||
| 3. "source_npi" is the sender's numbering plan identification
|
||||
| 4. "destination_ton" is the receiver's type of number
|
||||
| 5. "destination_npi" is the receiver's numbering plan identification
|
||||
|
|
||||
| Usually SMPP providers provide these settings to their clients.
|
||||
| Please refer to official SMPP protocol specification v3.4 to learn more about TON and NPI settings.
|
||||
|
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
'sender' => env('SMPP_SENDER','0773'),
|
||||
'source_ton' => env('SMPP_SOURCE_TON',SMPP::TON_ALPHANUMERIC),
|
||||
'source_npi' => env('SMPP_SOURCE_NPI',SMPP::NPI_UNKNOWN),
|
||||
'destination_ton' => env('SMPP_DESTINATION_TON',SMPP::TON_NATIONAL),
|
||||
'destination_npi' => env('SMPP_DESTINATION_NPI',SMPP::NPI_NATIONAL)
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom SMPP provider settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Most of the time, settings shown under the "example" key are be provided by your SMPP provider.
|
||||
| So if you don't have any of these settings, please contact your SMPP provider.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('SMPP_DEFAULT_PROVIDER','example'),
|
||||
|
||||
'providers' => [
|
||||
'example' => [
|
||||
'host' => '217.174.228.218',
|
||||
'port' => 5019,
|
||||
'timeout' => 10000,
|
||||
'login' => 'birja',
|
||||
'password' => 'Birj@1'
|
||||
]
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SMPP transport settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| For all SMPP errors listed in "transport.catchables", exceptions
|
||||
| thrown by SMPP will be suppressed and just logged.
|
||||
|
|
||||
*/
|
||||
|
||||
'transport' => [
|
||||
'catchables' => [
|
||||
SMPP::ESME_RBINDFAIL,
|
||||
SMPP::ESME_RINVCMDID,
|
||||
SMPP::ESME_RINVPARLEN
|
||||
],
|
||||
'force_ipv4' => true,
|
||||
'debug' => true
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SMPP client settings
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'client' => [
|
||||
'system_type' => 'default',
|
||||
'null_terminate_octetstrings' => false,
|
||||
'debug' => true
|
||||
]
|
||||
];
|
||||
|
|
@ -195,6 +195,7 @@ return [
|
|||
'name' => 'Name',
|
||||
'surname' => 'Surname',
|
||||
'mobile' => 'Phone number',
|
||||
'username' => 'Phone number',
|
||||
],
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ return [
|
|||
'name' => 'Имя',
|
||||
'surname' => 'Фаимилия',
|
||||
'mobile' => 'Номер телефона',
|
||||
'username' => 'Номер телефона',
|
||||
],
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ return [
|
|||
'name' => 'At',
|
||||
'surname' => 'Familiýa',
|
||||
'mobile' => 'Telefon belgiňiz',
|
||||
'username' => 'Telefon belgi',
|
||||
],
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
|
||||
|
||||
use Cms\Classes\Controller;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use AhmadFatoni\ApiGenerator\Helpers\Helpers;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use TPS\Birzha\Models\Contactmessage;
|
||||
use TPS\Birzha\Models\Settings;
|
||||
|
||||
class ContactFormApiController extends Controller
|
||||
{
|
||||
protected $helpers;
|
||||
|
||||
public function __construct(Helpers $helpers)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->helpers = $helpers;
|
||||
}
|
||||
|
||||
public function sendContactForm(Request $request) {
|
||||
$rules = [
|
||||
'name' => 'required|max:100',
|
||||
'surname' => 'required|max:100',
|
||||
'mobile' => 'required|min:6',
|
||||
'email' => 'required|email|max:100',
|
||||
'content' => 'required'
|
||||
];
|
||||
|
||||
$data = $request->all();
|
||||
|
||||
$validator = Validator::make($data, $rules);
|
||||
if($validator->fails()) {
|
||||
return $this->helpers->apiArrayResponseBuilder(400, 'fail', $validator->errors() );
|
||||
}
|
||||
|
||||
$contactMessage = new Contactmessage();
|
||||
$contactMessage->fill($data);
|
||||
$contactMessage->save();
|
||||
|
||||
$vars = [
|
||||
'firstname' => $data['name'],
|
||||
'lastname' => $data['surname'],
|
||||
'mobile' => $data['mobile'],
|
||||
'email' => $data['email'],
|
||||
'content' => $data['content']
|
||||
];
|
||||
|
||||
$admin_email = Settings::getValue('admin_email');
|
||||
|
||||
if($admin_email) {
|
||||
\Mail::send('tps.birzha::mail.message', $vars, function($message) {
|
||||
$message->to(Settings::getValue('admin_email'), 'Birzha Admin');
|
||||
$message->subject('Контактная форма');
|
||||
});
|
||||
}
|
||||
|
||||
return response()->json('Contact message sent', 201);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace AhmadFatoni\ApiGenerator\Controllers\API;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class EmailVerificationController extends KabinetAPIController
|
||||
{
|
||||
public function sendEmailVerificationLink()
|
||||
{
|
||||
if(!$this->user->email_verified) {
|
||||
$code = sha1(time());
|
||||
$vars = [
|
||||
'verification_link' => url('verify-email', ['code' => $code])
|
||||
];
|
||||
|
||||
try {
|
||||
\Mail::send('rainlab.user::mail.email_verification', $vars, function($message) {
|
||||
$message->to($this->user->email, 'Birzha User');
|
||||
$message->subject('Подтверждение Email');
|
||||
});
|
||||
} catch(Throwable $th) {
|
||||
\Log::info($th);
|
||||
|
||||
return response()->json('Cannot verify. Invalid email address.', 400);
|
||||
}
|
||||
|
||||
$this->user->email_activation_code = $code;
|
||||
$this->user->save();
|
||||
|
||||
return response()->json('Verification link has been sent. Log in to tmex.gov.tm before checking your email.', 201);
|
||||
|
||||
} else {
|
||||
return response()->json('You have already verified your email address.', 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?php namespace AhmadFatoni\ApiGenerator\Controllers\API;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use TPS\Birzha\Models\Settings;
|
||||
|
||||
class ExchangeRequestsController extends KabinetAPIController
|
||||
{
|
||||
protected $helpers;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function withdrawFromBalance(Request $request) {
|
||||
|
||||
$exRequest = $this->user->exchangerequests()->create([
|
||||
'content' => 'Exchange creating a request',
|
||||
'payed_for_request' => $request->get('fee'),
|
||||
'status' => 'failed', // before transaction is saved
|
||||
'currency' => $request->get('currency'),
|
||||
'total_price' => $request->get('total_price'),
|
||||
'converted_to_tmt' => $request->get('fee')
|
||||
]);
|
||||
|
||||
if(!is_null($exRequest->transaction)) {
|
||||
$exRequest->update(['status' => 'success']);
|
||||
}
|
||||
|
||||
$vars = array_merge($request->all(), [
|
||||
'phone' => $this->user->username,
|
||||
'status' => $exRequest->status,
|
||||
'withdraw_from_balance' => $exRequest->transaction->amount
|
||||
]);
|
||||
|
||||
$admin_email = Settings::getValue('admin_email');
|
||||
|
||||
if($admin_email) {
|
||||
\Mail::send('tps.birzha::mail.requests', $vars, function($message) use ($admin_email){
|
||||
$message->to($admin_email, 'Birzha Admin');
|
||||
$message->subject('Биржа - Запрос пользователя (раздел Импортные цены)');
|
||||
});
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 201,
|
||||
'response' => $exRequest,
|
||||
'message' => 'Successfully created response'
|
||||
], 201);
|
||||
}
|
||||
}
|
||||
|
|
@ -272,7 +272,10 @@ class MessagesapiController extends Controller
|
|||
// return response()->json(['chatrooms' => $seller->chatrooms]);
|
||||
// return response()->json(['users' => $seller->chatrooms->users]);
|
||||
// return response()->json(['chatroomNeeded' => $chatroomNeeded]);
|
||||
return $this->helpers->apiArrayResponseBuilder(200, 'success', ['messages' => $this->getMessagesFromChatroom($chatroomNeeded, $currentUser)]);
|
||||
return $this->helpers->apiArrayResponseBuilder(200, 'success', [
|
||||
'chatroom_id' => $chatroomNeeded->id,
|
||||
'messages' => $this->getMessagesFromChatroom($chatroomNeeded, $currentUser)
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,15 @@ use Illuminate\Support\Facades\Validator;
|
|||
|
||||
class NotificationsApiController extends Controller
|
||||
{
|
||||
public function index(Request $request) {
|
||||
public function __construct()
|
||||
{
|
||||
if (!$user = \JWTAuth::parseToken()->authenticate()) {
|
||||
return response()->json('Unauthorized', 401);
|
||||
}
|
||||
}
|
||||
|
||||
public function index(Request $request) {
|
||||
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'records_per_page' => 'numeric',
|
||||
|
|
@ -39,10 +44,6 @@ class NotificationsApiController extends Controller
|
|||
*/
|
||||
public function markAsRead($id)
|
||||
{
|
||||
if (!$user = \JWTAuth::parseToken()->authenticate()) {
|
||||
return response()->json('Unauthorized', 401);
|
||||
}
|
||||
|
||||
$notification = $user->notifications()
|
||||
->applyUnread()
|
||||
->find($id);
|
||||
|
|
@ -65,4 +66,4 @@ class NotificationsApiController extends Controller
|
|||
],
|
||||
], 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace AhmadFatoni\ApiGenerator\Controllers\API;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use LaravelSmpp\SmppServiceInterface;
|
||||
use TPS\Birzha\Classes\SMPP as SMPPV2;
|
||||
use TPS\Birzha\Classes\SMS;
|
||||
|
||||
class SmsController extends KabinetAPIController
|
||||
{
|
||||
public function index(SmppServiceInterface $smpp) {
|
||||
// $smpp->sendOne(99363432211, 'Hi, this SMS was send via SMPP protocol');
|
||||
$tx=new SMPPV2('217.174.228.218', 5019); // make sure the port is integer
|
||||
// $tx->debug=true;
|
||||
$tx->bindTransmitter("birja","Birj@1");
|
||||
// dump('bind transmitter');
|
||||
$result = $tx->sendSMS("0773",'99363432211','message');
|
||||
// dump('send sms attempt');
|
||||
// echo $tx->getStatusMessage($result);
|
||||
$tx->close();
|
||||
unset($tx);
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
public function sendSmsCode()
|
||||
{
|
||||
if($this->user->dial_code != '+993') {
|
||||
return response()->json([
|
||||
'dial_code' => $this->user->dial_code,
|
||||
'message' => 'This user is not a resident of Turkmenistan.'
|
||||
], 400);
|
||||
}
|
||||
|
||||
if($this->user->phone_verified && $this->user->dial_code == '+993') {
|
||||
return response()->json('User phone already verified', 200);
|
||||
}
|
||||
|
||||
$code = random_int(1000, 9999);
|
||||
|
||||
$result = SMS::send(str_replace(array('+', ' ', '(' , ')', '-'), '', $this->user->username), $code);
|
||||
// $result = 0;
|
||||
|
||||
switch ($result) {
|
||||
case 0:
|
||||
$this->user->phone_activation_code = $code;
|
||||
$this->user->save();
|
||||
return response()->json([
|
||||
'result' => $result,
|
||||
'message' => 'Message has been succesfully sent'
|
||||
], 201);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
return response()->json([
|
||||
'result' => $result,
|
||||
'message' => 'Error'
|
||||
], 500);
|
||||
break;
|
||||
|
||||
default:
|
||||
return response()->json([
|
||||
'result' => $result,
|
||||
'message' => 'Error'
|
||||
], 500);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function checkSmsCode(Request $request)
|
||||
{
|
||||
if($this->user->dial_code != '+993') {
|
||||
return response()->json([
|
||||
'dial_code' => $this->user->dial_code,
|
||||
'message' => 'This user is not a resident of Turkmenistan.'
|
||||
], 400);
|
||||
}
|
||||
|
||||
if($this->user->phone_verified && $this->user->dial_code == '+993') {
|
||||
return response()->json('User phone already verified', 200);
|
||||
}
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'sms_code' => 'required|digits:4',
|
||||
]);
|
||||
if($validator->fails()) {
|
||||
return response()->json($validator->errors(), 400);
|
||||
}
|
||||
|
||||
if($this->user->phone_activation_code == $request->get('sms_code')) {
|
||||
$this->user->phone_verified = true;
|
||||
$this->user->phone_activation_code = null;
|
||||
$this->user->save();
|
||||
return response()->json('User phone has been succesfully verified', 201);
|
||||
} else {
|
||||
return response()->json('Wrong sms code', 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ Route::group(['prefix' =>'api/v1','namespace' =>'AhmadFatoni\ApiGenerator\Contro
|
|||
|
||||
Route::get('products', ['as' => 'products.index', 'uses' => 'ProductsApiController@index']);
|
||||
Route::get('products/{id}', ['as' => 'products.show', 'uses' => 'ProductsApiController@show']);
|
||||
Route::get('test',['as' => 'test', 'uses' => 'SmsController@index']);
|
||||
|
||||
// Route::get('products/{id}/delete', ['as' => 'products.delete', 'uses' => 'ProductsApiController@destroy']);
|
||||
|
||||
|
|
@ -21,6 +22,8 @@ Route::group(['prefix' =>'api/v1','namespace' =>'AhmadFatoni\ApiGenerator\Contro
|
|||
Route::resource('terms', 'TermsapiController', ['except' => ['destroy', 'create', 'edit']]);
|
||||
// Route::get('terms/{id}/delete', ['as' => 'terms.delete', 'uses' => 'TermsapiController@destroy']);
|
||||
|
||||
Route::post('send-contact-form', 'ContactFormApiController@sendContactForm');
|
||||
|
||||
Route::middleware(['\Tymon\JWTAuth\Middleware\GetUserFromToken'])->group(function () {
|
||||
|
||||
Route::post('products', 'ProductsApiController@store');
|
||||
|
|
@ -55,6 +58,13 @@ Route::group(['prefix' =>'api/v1','namespace' =>'AhmadFatoni\ApiGenerator\Contro
|
|||
Route::get('transactions', 'TransactionsApiController@index');
|
||||
Route::get('my-balance', 'TransactionsApiController@myBalance');
|
||||
|
||||
Route::post('withdraw-from-balance', 'ExchangeRequestsController@withdrawFromBalance');
|
||||
|
||||
Route::post('send-sms-code', 'SmsController@sendSmsCode');
|
||||
Route::post('check-sms-code', 'SmsController@checkSmsCode');
|
||||
|
||||
Route::post('send-email-verification-link', 'EmailVerificationController@sendEmailVerificationLink');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ Route::group(['prefix' =>'api/v1','namespace' =>'AhmadFatoni\ApiGenerator\Contro
|
|||
Route::resource('terms', 'TermsapiController', ['except' => ['destroy', 'create', 'edit']]);
|
||||
// Route::get('terms/{id}/delete', ['as' => 'terms.delete', 'uses' => 'TermsapiController@destroy']);
|
||||
|
||||
|
||||
Route::post('send-contact-form', 'ContactFormApiController@sendContactForm');
|
||||
|
||||
Route::middleware(['\Tymon\JWTAuth\Middleware\GetUserFromToken'])->group(function () {
|
||||
Route::post('products', 'ProductsApiController@store');
|
||||
|
|
@ -56,6 +56,13 @@ Route::group(['prefix' =>'api/v1','namespace' =>'AhmadFatoni\ApiGenerator\Contro
|
|||
Route::get('transactions', 'TransactionsApiController@index');
|
||||
Route::get('my-balance', 'TransactionsApiController@myBalance');
|
||||
|
||||
Route::post('withdraw-from-balance', 'ExchangeRequestsController@withdrawFromBalance');
|
||||
|
||||
Route::post('send-sms-code', 'SmsController@sendSmsCode');
|
||||
Route::post('check-sms-code', 'SmsController@checkSmsCode');
|
||||
|
||||
Route::post('send-email-verification-link', 'EmailVerificationController@sendEmailVerificationLink');
|
||||
|
||||
});
|
||||
});
|
||||
{{route}}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
/vendor/
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# How to contribute
|
||||
|
||||
Contributions to this project are highly welcome.
|
||||
|
||||
1. Submit your pull requests to the `develop` branch
|
||||
1. Adhere to the [PSR-2 coding](http://www.php-fig.org/psr/psr-2/) standard
|
||||
1. If you are not sure if your ideas are fit for this project, create an issue and ask
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016 OFFLINE GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php namespace OFFLINE\CORS;
|
||||
|
||||
use OFFLINE\CORS\Classes\HandleCors;
|
||||
use OFFLINE\CORS\Classes\HandlePreflight;
|
||||
use OFFLINE\CORS\Classes\ServiceProvider;
|
||||
use OFFLINE\CORS\Models\Settings;
|
||||
use System\Classes\PluginBase;
|
||||
|
||||
class Plugin extends PluginBase
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
\App::register(ServiceProvider::class);
|
||||
|
||||
$this->app['Illuminate\Contracts\Http\Kernel']
|
||||
->prependMiddleware(HandleCors::class);
|
||||
|
||||
if (request()->isMethod('OPTIONS')) {
|
||||
$this->app['Illuminate\Contracts\Http\Kernel']
|
||||
->prependMiddleware(HandlePreflight::class);
|
||||
}
|
||||
}
|
||||
|
||||
public function registerPermissions()
|
||||
{
|
||||
return [
|
||||
'offline.cors.manage' => [
|
||||
'label' => 'Can manage cors settings',
|
||||
'tab' => 'CORS',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function registerSettings()
|
||||
{
|
||||
return [
|
||||
'cors' => [
|
||||
'label' => 'CORS-Settings',
|
||||
'description' => 'Manage CORS headers',
|
||||
'category' => 'system::lang.system.categories.cms',
|
||||
'icon' => 'icon-code',
|
||||
'class' => Settings::class,
|
||||
'order' => 500,
|
||||
'keywords' => 'cors',
|
||||
'permissions' => ['offline.cors.manage'],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# CORS plugin for October CMS
|
||||
|
||||
This plugin is based on [https://github.com/barryvdh/laravel-cors](https://github.com/barryvdh/laravel-cors/blob/master/config/cors.php).
|
||||
|
||||
All configuration for the plugin can be done via the backend settings.
|
||||
|
||||
The following cors headers are supported:
|
||||
|
||||
* Access-Control-Allow-Origin
|
||||
* Access-Control-Allow-Headers
|
||||
* Access-Control-Allow-Methods
|
||||
* Access-Control-Allow-Credentials
|
||||
* Access-Control-Expose-Headers
|
||||
* Access-Control-Max-Age
|
||||
|
||||
Currently these headers are sent for every request. There is no per-route configuration possible at this time.
|
||||
|
||||
## Setup
|
||||
|
||||
After installing the plugin visit the CORS settings page in your October CMS backend settings.
|
||||
|
||||
You can add `*` as an entry to `Allowed origins`, `Allowed headers` and `Allowed methods` to allow any kind of CORS request from everywhere.
|
||||
|
||||
It is advised to be more explicit about these settings. You can add values for each header via the repeater fields.
|
||||
|
||||
> It is important to set these intial settings once for the plugin to work as excpected!
|
||||
|
||||
### Filesystem configuration
|
||||
|
||||
As an alternative to the backend settings you can create a `config/config.php` file in the plugins root directory to configure it.
|
||||
|
||||
The filesystem configuration will overwrite any defined backend setting.
|
||||
|
||||
```php
|
||||
<?php
|
||||
// plugins/offline/cors/config/config.php
|
||||
return [
|
||||
'supportsCredentials' => true,
|
||||
'maxAge' => 3600,
|
||||
'allowedOrigins' => ['*'],
|
||||
'allowedHeaders' => ['*'],
|
||||
'allowedMethods' => ['GET', 'POST'],
|
||||
'exposedHeaders' => [''],
|
||||
];
|
||||
```
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace OFFLINE\CORS\Classes;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Based on asm89/stack-cors
|
||||
*/
|
||||
class Cors implements HttpKernelInterface
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
|
||||
*/
|
||||
private $app;
|
||||
|
||||
/**
|
||||
* @var CorsService
|
||||
*/
|
||||
private $cors;
|
||||
|
||||
private $defaultOptions = [
|
||||
'allowedHeaders' => [],
|
||||
'allowedMethods' => [],
|
||||
'allowedOrigins' => [],
|
||||
'exposedHeaders' => false,
|
||||
'maxAge' => false,
|
||||
'supportsCredentials' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Cors constructor.
|
||||
*
|
||||
* @param HttpKernelInterface $app
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $app, array $options = [])
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->cors = new CorsService(array_merge($this->defaultOptions, $options));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param int $type
|
||||
* @param bool $catch
|
||||
*
|
||||
* @return bool|Response
|
||||
*/
|
||||
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
|
||||
{
|
||||
if ( ! $this->cors->isCorsRequest($request)) {
|
||||
return $this->app->handle($request, $type, $catch);
|
||||
}
|
||||
|
||||
if ($this->cors->isPreflightRequest($request)) {
|
||||
return $this->cors->handlePreflightRequest($request);
|
||||
}
|
||||
|
||||
if ( ! $this->cors->isActualRequestAllowed($request)) {
|
||||
return new Response('Not allowed.', 403);
|
||||
}
|
||||
|
||||
$response = $this->app->handle($request, $type, $catch);
|
||||
|
||||
return $this->cors->addActualRequestHeaders($response, $request);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,199 @@
|
|||
<?php
|
||||
|
||||
namespace OFFLINE\CORS\Classes;
|
||||
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Based on asm89/stack-cors
|
||||
*/
|
||||
class CorsService
|
||||
{
|
||||
private $options;
|
||||
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->options = $this->normalizeOptions($options);
|
||||
}
|
||||
|
||||
private function normalizeOptions(array $options = [])
|
||||
{
|
||||
$options += [
|
||||
'supportsCredentials' => false,
|
||||
'maxAge' => 0,
|
||||
];
|
||||
|
||||
// Make sure these values are arrays, if not specified in the backend settings.
|
||||
$arrayKeys = [
|
||||
'allowedOrigins',
|
||||
'allowedHeaders',
|
||||
'exposedHeaders',
|
||||
'allowedMethods',
|
||||
];
|
||||
|
||||
foreach ($arrayKeys as $key) {
|
||||
if (!$options[$key]) {
|
||||
$options[$key] = [];
|
||||
}
|
||||
}
|
||||
|
||||
// normalize array('*') to true
|
||||
if (in_array('*', $options['allowedOrigins'])) {
|
||||
$options['allowedOrigins'] = true;
|
||||
}
|
||||
if (in_array('*', $options['allowedHeaders'])) {
|
||||
$options['allowedHeaders'] = true;
|
||||
} else {
|
||||
$options['allowedHeaders'] = array_map('strtolower', $options['allowedHeaders']);
|
||||
}
|
||||
|
||||
if (in_array('*', $options['allowedMethods'])) {
|
||||
$options['allowedMethods'] = true;
|
||||
} else {
|
||||
$options['allowedMethods'] = array_map('strtoupper', $options['allowedMethods']);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function isActualRequestAllowed(Request $request)
|
||||
{
|
||||
return $this->checkOrigin($request);
|
||||
}
|
||||
|
||||
public function isCorsRequest(Request $request)
|
||||
{
|
||||
return $request->headers->has('Origin') && $request->headers->get('Origin') !== $request->getSchemeAndHttpHost();
|
||||
}
|
||||
|
||||
public function isPreflightRequest(Request $request)
|
||||
{
|
||||
return $this->isCorsRequest($request)
|
||||
&& $request->getMethod() === 'OPTIONS'
|
||||
&& $request->headers->has('Access-Control-Request-Method');
|
||||
}
|
||||
|
||||
public function addActualRequestHeaders(Response $response, Request $request)
|
||||
{
|
||||
if ( ! $this->checkOrigin($request)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response->headers->set('Access-Control-Allow-Origin', $request->headers->get('Origin'));
|
||||
|
||||
if ( ! $response->headers->has('Vary')) {
|
||||
$response->headers->set('Vary', 'Origin');
|
||||
} else {
|
||||
$response->headers->set('Vary', $response->headers->get('Vary') . ', Origin');
|
||||
}
|
||||
|
||||
if ($this->options['supportsCredentials']) {
|
||||
$response->headers->set('Access-Control-Allow-Credentials', 'true');
|
||||
}
|
||||
|
||||
if ($this->options['exposedHeaders']) {
|
||||
$response->headers->set('Access-Control-Expose-Headers', implode(', ', $this->options['exposedHeaders']));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function handlePreflightRequest(Request $request)
|
||||
{
|
||||
if (true !== $check = $this->checkPreflightRequestConditions($request)) {
|
||||
return $check;
|
||||
}
|
||||
|
||||
return $this->buildPreflightCheckResponse($request);
|
||||
}
|
||||
|
||||
private function buildPreflightCheckResponse(Request $request)
|
||||
{
|
||||
$response = new Response();
|
||||
|
||||
if ($this->options['supportsCredentials']) {
|
||||
$response->headers->set('Access-Control-Allow-Credentials', 'true');
|
||||
}
|
||||
|
||||
$response->headers->set('Access-Control-Allow-Origin', $request->headers->get('Origin'));
|
||||
|
||||
if ($this->options['maxAge']) {
|
||||
$response->headers->set('Access-Control-Max-Age', $this->options['maxAge']);
|
||||
}
|
||||
|
||||
$allowMethods = $this->options['allowedMethods'] === true
|
||||
? strtoupper($request->headers->get('Access-Control-Request-Method'))
|
||||
: implode(', ', $this->options['allowedMethods']);
|
||||
$response->headers->set('Access-Control-Allow-Methods', $allowMethods);
|
||||
|
||||
$allowHeaders = $this->options['allowedHeaders'] === true
|
||||
? strtoupper($request->headers->get('Access-Control-Request-Headers'))
|
||||
: implode(', ', $this->options['allowedHeaders']);
|
||||
$response->headers->set('Access-Control-Allow-Headers', $allowHeaders);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function checkPreflightRequestConditions(Request $request)
|
||||
{
|
||||
if ( ! $this->checkOrigin($request)) {
|
||||
return $this->createBadRequestResponse(403, 'Origin not allowed');
|
||||
}
|
||||
|
||||
if ( ! $this->checkMethod($request)) {
|
||||
return $this->createBadRequestResponse(405, 'Method not allowed');
|
||||
}
|
||||
|
||||
$requestHeaders = [];
|
||||
// if allowedHeaders has been set to true ('*' allow all flag) just skip this check
|
||||
if ($this->options['allowedHeaders'] !== true && $request->headers->has('Access-Control-Request-Headers')) {
|
||||
$headers = strtolower($request->headers->get('Access-Control-Request-Headers'));
|
||||
$requestHeaders = explode(',', $headers);
|
||||
|
||||
foreach ($requestHeaders as $header) {
|
||||
if ( ! in_array(trim($header), $this->options['allowedHeaders'])) {
|
||||
return $this->createBadRequestResponse(403, 'Header not allowed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function createBadRequestResponse($code, $reason = '')
|
||||
{
|
||||
return new Response($reason, $code);
|
||||
}
|
||||
|
||||
private function checkOrigin(Request $request)
|
||||
{
|
||||
if ($this->options['allowedOrigins'] === true) {
|
||||
// allow all '*' flag
|
||||
return true;
|
||||
}
|
||||
$origin = $request->headers->get('Origin');
|
||||
|
||||
foreach ($this->options['allowedOrigins'] as $allowedOrigin) {
|
||||
if (OriginMatcher::matches($allowedOrigin, $origin)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function checkMethod(Request $request)
|
||||
{
|
||||
if ($this->options['allowedMethods'] === true) {
|
||||
// allow all '*' flag
|
||||
return true;
|
||||
}
|
||||
|
||||
$requestMethod = strtoupper($request->headers->get('Access-Control-Request-Method'));
|
||||
|
||||
return in_array($requestMethod, $this->options['allowedMethods']);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace OFFLINE\CORS\Classes;
|
||||
|
||||
use Closure;
|
||||
|
||||
class HandleCors
|
||||
{
|
||||
/**
|
||||
* The CORS service
|
||||
*
|
||||
* @var CorsService
|
||||
*/
|
||||
protected $cors;
|
||||
|
||||
/**
|
||||
* @param CorsService $cors
|
||||
*/
|
||||
public function __construct(CorsService $cors)
|
||||
{
|
||||
$this->cors = $cors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request. Based on Asm89\Stack\Cors by asm89
|
||||
* @see https://github.com/asm89/stack-cors/blob/master/src/Asm89/Stack/Cors.php
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if ( ! $this->cors->isCorsRequest($request)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
if ( ! $this->cors->isActualRequestAllowed($request)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
/** @var \Illuminate\Http\Response $response */
|
||||
$response = $next($request);
|
||||
|
||||
return $this->cors->addActualRequestHeaders($response, $request);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace OFFLINE\CORS\Classes;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Http\Kernel;
|
||||
use Illuminate\Routing\Router;
|
||||
|
||||
class HandlePreflight
|
||||
{
|
||||
/**
|
||||
* @param CorsService $cors
|
||||
*/
|
||||
public function __construct(CorsService $cors, Router $router, Kernel $kernel)
|
||||
{
|
||||
$this->cors = $cors;
|
||||
$this->router = $router;
|
||||
$this->kernel = $kernel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming OPTIONS request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$response = $next($request);
|
||||
if ($this->cors->isPreflightRequest($request) && $this->hasMatchingCorsRoute($request)) {
|
||||
$preflight = $this->cors->handlePreflightRequest($request);
|
||||
$response->headers->add($preflight->headers->all());
|
||||
}
|
||||
$response->setStatusCode(204);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the current OPTIONS request matches a CORS-enabled route
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function hasMatchingCorsRoute($request)
|
||||
{
|
||||
// Check if CORS is added in a global middleware
|
||||
if ($this->kernel->hasMiddleware(HandleCors::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if CORS is added as a route middleware
|
||||
$request = clone $request;
|
||||
$request->setMethod($request->header('Access-Control-Request-Method'));
|
||||
|
||||
try {
|
||||
$route = $this->router->getRoutes()->match($request);
|
||||
// change of method name in laravel 5.3
|
||||
if (method_exists($this->router, 'gatherRouteMiddleware')) {
|
||||
$middleware = $this->router->gatherRouteMiddleware($route);
|
||||
} else {
|
||||
$middleware = $this->router->gatherRouteMiddlewares($route);
|
||||
}
|
||||
|
||||
return in_array(HandleCors::class, $middleware);
|
||||
} catch (\Exception $e) {
|
||||
app('log')->error($e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
namespace OFFLINE\CORS\Classes;
|
||||
|
||||
class OriginMatcher
|
||||
{
|
||||
|
||||
public static function matches($pattern, $origin)
|
||||
{
|
||||
if ($pattern === $origin) {
|
||||
return true;
|
||||
}
|
||||
$scheme = parse_url($origin, PHP_URL_SCHEME);
|
||||
$host = parse_url($origin, PHP_URL_HOST);
|
||||
$port = parse_url($origin, PHP_URL_PORT);
|
||||
|
||||
$schemePattern = static::parseOriginPattern($pattern, PHP_URL_SCHEME);
|
||||
$hostPattern = static::parseOriginPattern($pattern, PHP_URL_HOST);
|
||||
$portPattern = static::parseOriginPattern($pattern, PHP_URL_PORT);
|
||||
|
||||
$schemeMatches = static::schemeMatches($schemePattern, $scheme);
|
||||
$hostMatches = static::hostMatches($hostPattern, $host);
|
||||
$portMatches = static::portMatches($portPattern, $port);
|
||||
|
||||
return $schemeMatches && $hostMatches && $portMatches;
|
||||
}
|
||||
|
||||
public static function schemeMatches($pattern, $scheme)
|
||||
{
|
||||
return is_null($pattern) || $pattern === $scheme;
|
||||
}
|
||||
|
||||
public static function hostMatches($pattern, $host)
|
||||
{
|
||||
$patternComponents = array_reverse(explode('.', $pattern));
|
||||
$hostComponents = array_reverse(explode('.', $host));
|
||||
foreach ($patternComponents as $index => $patternComponent) {
|
||||
if ($patternComponent === '*') {
|
||||
return true;
|
||||
}
|
||||
if ( ! isset($hostComponents[$index])) {
|
||||
return false;
|
||||
}
|
||||
if ($hostComponents[$index] !== $patternComponent) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return count($patternComponents) === count($hostComponents);
|
||||
}
|
||||
|
||||
public static function portMatches($pattern, $port)
|
||||
{
|
||||
if ($pattern === "*") {
|
||||
return true;
|
||||
}
|
||||
if ((string)$pattern === "") {
|
||||
return (string)$port === "";
|
||||
}
|
||||
if (preg_match('/\A\d+\z/', $pattern)) {
|
||||
return (string)$pattern === (string)$port;
|
||||
}
|
||||
if (preg_match('/\A(?P<from>\d+)-(?P<to>\d+)\z/', $pattern, $captured)) {
|
||||
return $captured['from'] <= $port && $port <= $captured['to'];
|
||||
}
|
||||
throw new \InvalidArgumentException("Invalid port pattern: ${pattern}");
|
||||
}
|
||||
|
||||
public static function parseOriginPattern($originPattern, $component = -1)
|
||||
{
|
||||
$matched = preg_match(
|
||||
'!\A
|
||||
(?: (?P<scheme> ([a-z][a-z0-9+\-.]*) ):// )?
|
||||
(?P<host> (?:\*|[\w-]+)(?:\.[\w-]+)* )
|
||||
(?: :(?P<port> (?: \*|\d+(?:-\d+)? ) ) )?
|
||||
\z!x',
|
||||
$originPattern,
|
||||
$captured
|
||||
);
|
||||
if ( ! $matched) {
|
||||
throw new \InvalidArgumentException("Invalid origin pattern ${originPattern}");
|
||||
}
|
||||
$components = [
|
||||
'scheme' => $captured['scheme'] ?: null,
|
||||
'host' => $captured['host'],
|
||||
'port' => array_key_exists('port', $captured) ? $captured['port'] : null,
|
||||
];
|
||||
switch ($component) {
|
||||
case -1:
|
||||
return $components;
|
||||
case PHP_URL_SCHEME:
|
||||
return $components['scheme'];
|
||||
case PHP_URL_HOST:
|
||||
return $components['host'];
|
||||
case PHP_URL_PORT:
|
||||
return $components['port'];
|
||||
}
|
||||
throw new \InvalidArgumentException("Invalid component: ${component}");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace OFFLINE\CORS\Classes;
|
||||
|
||||
use October\Rain\Support\ServiceProvider as BaseServiceProvider;
|
||||
use OFFLINE\CORS\Models\Settings;
|
||||
|
||||
class ServiceProvider extends BaseServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton(CorsService::class, function ($app) {
|
||||
return new CorsService($this->getSettings());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default Settings
|
||||
*/
|
||||
protected function getSettings()
|
||||
{
|
||||
$supportsCredentials = (bool)$this->getConfigValue('supportsCredentials', false);
|
||||
$maxAge = (int)$this->getConfigValue('maxAge', 0);
|
||||
$allowedOrigins = $this->getConfigValue('allowedOrigins', []);
|
||||
$allowedHeaders = $this->getConfigValue('allowedHeaders', []);
|
||||
$allowedMethods = $this->getConfigValue('allowedMethods', []);
|
||||
$exposedHeaders = $this->getConfigValue('exposedHeaders', []);
|
||||
|
||||
return compact(
|
||||
'supportsCredentials',
|
||||
'allowedOrigins',
|
||||
'allowedHeaders',
|
||||
'allowedMethods',
|
||||
'exposedHeaders',
|
||||
'maxAge'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an effective config value.
|
||||
*
|
||||
* If a filesystem config is available it takes precedence
|
||||
* over the backend settings values.
|
||||
*
|
||||
* @param $key
|
||||
* @param null $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getConfigValue($key, $default = null)
|
||||
{
|
||||
return $this->filesystemConfig($key) ?: $this->getValues(Settings::get($key, $default));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filesystem config value if available.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function filesystemConfig($key)
|
||||
{
|
||||
return config('offline.cors::' . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the repeater field values.
|
||||
*
|
||||
* @param mixed $values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getValues($values)
|
||||
{
|
||||
return \is_array($values) ? collect($values)->pluck('value')->toArray() : $values;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "offline/oc-cors-plugin",
|
||||
"description": "Setup and manage Cross-Origin Resource Sharing headers in October CMS",
|
||||
"type": "october-plugin",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Tobias Kündig",
|
||||
"email": "tobias@offline.swiss"
|
||||
}
|
||||
],
|
||||
"require": {}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php return [
|
||||
'plugin' => [
|
||||
'name' => 'CORS',
|
||||
'description' => 'Verwalte Cross-Origin Resource Sharing Header in October CMS',
|
||||
],
|
||||
];
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php return [
|
||||
'plugin' => [
|
||||
'name' => 'CORS',
|
||||
'description' => 'Setup and manage Cross-Origin Resource Sharing headers',
|
||||
],
|
||||
];
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace OFFLINE\CORS\Models;
|
||||
|
||||
use Model;
|
||||
|
||||
class Settings extends Model
|
||||
{
|
||||
public $implement = ['System.Behaviors.SettingsModel'];
|
||||
public $settingsCode = 'offline_cors_settings';
|
||||
public $settingsFields = 'fields.yaml';
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
fields:
|
||||
supportsCredentials:
|
||||
label: Supports credentials
|
||||
type: switch
|
||||
comment: 'Set Access-Control-Allow-Credentials header to true'
|
||||
default: false
|
||||
span: left
|
||||
maxAge:
|
||||
label: Max age
|
||||
type: number
|
||||
comment: 'Set Access-Control-Max-Age to this value'
|
||||
default: 0
|
||||
span: right
|
||||
tabs:
|
||||
fields:
|
||||
allowedOrigins:
|
||||
label: Allowed origins
|
||||
tab: Allowed origins
|
||||
type: repeater
|
||||
span: left
|
||||
form:
|
||||
fields:
|
||||
value:
|
||||
type: text
|
||||
label: Origin
|
||||
allowedHeaders:
|
||||
label: Allowed headers
|
||||
tab: Allowed headers
|
||||
type: repeater
|
||||
span: left
|
||||
form:
|
||||
fields:
|
||||
value:
|
||||
type: text
|
||||
label: Header
|
||||
allowedMethods:
|
||||
label: Allowed methods
|
||||
tab: Allowed methods
|
||||
type: repeater
|
||||
span: left
|
||||
form:
|
||||
fields:
|
||||
value:
|
||||
type: text
|
||||
label: Method
|
||||
exposedHeaders:
|
||||
label: Exposed headers
|
||||
tab: Exposed headers
|
||||
type: repeater
|
||||
span: left
|
||||
form:
|
||||
fields:
|
||||
value:
|
||||
type: text
|
||||
label: Header
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
plugin:
|
||||
name: 'offline.cors::lang.plugin.name'
|
||||
description: 'offline.cors::lang.plugin.description'
|
||||
author: 'OFFLINE GmbH'
|
||||
icon: oc-icon-code
|
||||
homepage: ''
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
1.0.1:
|
||||
- Initial release.
|
||||
1.0.2:
|
||||
- Fixed backend settings label (thanks to LukeTowers)
|
||||
1.0.3:
|
||||
- Added support for filesystem configuration file / Added plugin to Packagist (https://packagist.org/packages/offline/oc-cors-plugin)
|
||||
1.0.4:
|
||||
- Fixed minor bug when running the plugin without custom settings
|
||||
1.0.5:
|
||||
- "Return proper 204 response code for preflight requests (thanks to @adrian-marinescu-ch on GitHub)"
|
||||
1.0.6:
|
||||
- "Dummy release to sync with Packagist version"
|
||||
1.0.7:
|
||||
- "Optimized compatibility with October v2"
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<?php namespace RainLab\Notify\NotifyRules;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Mail;
|
||||
use Lang;
|
||||
use Config;
|
||||
|
|
@ -48,6 +49,7 @@ class SendMailTemplateAction extends ActionBase
|
|||
throw new ApplicationException('Missing valid recipient or mail template');
|
||||
}
|
||||
|
||||
Log::info($template);
|
||||
Mail::sendTo($recipient, $template, $params, function($message) use ($replyTo) {
|
||||
if ($replyTo) {
|
||||
$message->replyTo($replyTo);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ use Cms\Classes\ComponentBase;
|
|||
use RainLab\User\Models\User as UserModel;
|
||||
use RainLab\User\Models\Settings as UserSettings;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
use TPS\Birzha\Classes\SMS;
|
||||
|
||||
/**
|
||||
* Account component
|
||||
|
|
@ -109,9 +111,9 @@ class Account extends ComponentBase
|
|||
/*
|
||||
* Activation code supplied
|
||||
*/
|
||||
if ($code = $this->activationCode()) {
|
||||
$this->onActivate($code);
|
||||
}
|
||||
// if ($code = $this->activationCode()) {
|
||||
// $this->onActivate($code);
|
||||
// }
|
||||
|
||||
$this->prepareVars();
|
||||
}
|
||||
|
|
@ -228,7 +230,7 @@ class Account extends ComponentBase
|
|||
* Authenticate user
|
||||
*/
|
||||
$credentials = [
|
||||
'login' => array_get($data, 'login'),
|
||||
'login' => array_get($data, 'dial_code') . array_get($data, 'login'),
|
||||
'password' => array_get($data, 'password')
|
||||
];
|
||||
|
||||
|
|
@ -303,7 +305,15 @@ class Account extends ComponentBase
|
|||
$data['password_confirmation'] = post('password');
|
||||
}
|
||||
|
||||
$rules = (new UserModel)->rules;
|
||||
$rules = array_merge((new UserModel)->rules, [
|
||||
'username' => [
|
||||
'required',
|
||||
'unique' => function($attribute, $value, $fail) use($data) {
|
||||
$u = UserModel::find($data['dial_code'] . $value);
|
||||
if(!is_null($u)) $fail();
|
||||
}
|
||||
],
|
||||
]);
|
||||
|
||||
if ($this->loginAttribute() !== UserSettings::LOGIN_USERNAME) {
|
||||
unset($rules['username']);
|
||||
|
|
@ -337,7 +347,9 @@ class Account extends ComponentBase
|
|||
$automaticActivation = UserSettings::get('activate_mode') == UserSettings::ACTIVATE_AUTO;
|
||||
$userActivation = UserSettings::get('activate_mode') == UserSettings::ACTIVATE_USER;
|
||||
$adminActivation = UserSettings::get('activate_mode') == UserSettings::ACTIVATE_ADMIN;
|
||||
$user = Auth::register($data, $automaticActivation);
|
||||
$user = Auth::register(array_merge($data, [
|
||||
'username' => $data['dial_code'] . $data['username']
|
||||
]), $automaticActivation);
|
||||
|
||||
Event::fire('rainlab.user.register', [$user, $data]);
|
||||
|
||||
|
|
@ -345,9 +357,10 @@ class Account extends ComponentBase
|
|||
* Activation is by the user, send the email
|
||||
*/
|
||||
if ($userActivation) {
|
||||
$this->sendActivationEmail($user);
|
||||
|
||||
Flash::success(Lang::get(/*An activation email has been sent to your email address.*/'rainlab.user::lang.account.activation_email_sent'));
|
||||
// $this->sendActivationEmail($user);
|
||||
//
|
||||
// Flash::success(Lang::get(/*An activation email has been sent to your email address.*/'rainlab.user::lang.account.activation_email_sent'));
|
||||
//todo open activation view
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -380,6 +393,101 @@ class Account extends ComponentBase
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send sms with 6 digits code to user
|
||||
*/
|
||||
public function onSendSmsCode()
|
||||
{
|
||||
try {
|
||||
if($this->user()->dial_code == '+993' && !$this->user()->phone_verified) {
|
||||
$code = random_int(1000, 9999);
|
||||
|
||||
$result = SMS::send(str_replace(array('+', ' ', '(' , ')', '-'), '', $this->user()->username), $code);
|
||||
// $result = 0;
|
||||
|
||||
switch ($result) {
|
||||
case 0:
|
||||
$this->user()->phone_activation_code = $code;
|
||||
$this->user()->save();
|
||||
break;
|
||||
case 1:
|
||||
return \Redirect::to('/error');
|
||||
break;
|
||||
|
||||
default:
|
||||
return \Redirect::to('/error');
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(Throwable $th) {
|
||||
\Log::info($th);
|
||||
return \Redirect::to('/error');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check SMS code sent by user
|
||||
*/
|
||||
public function onCheckSmsCode()
|
||||
{
|
||||
$data = post();
|
||||
|
||||
$validator = \Validator::make($data, [
|
||||
'sms_code' => 'required|digits:4',
|
||||
]);
|
||||
if($validator->fails()) {
|
||||
throw new ValidationException($validator);
|
||||
}
|
||||
|
||||
if($this->user()->phone_activation_code == $data['sms_code']) {
|
||||
$this->user()->phone_verified = true;
|
||||
$this->user()->phone_activation_code = null;
|
||||
$this->user()->save();
|
||||
|
||||
Flash::success('Your phone number has been succesfully verified');
|
||||
|
||||
return \Redirect::to('profile');
|
||||
} else {
|
||||
Flash::error('Invalid sms code');
|
||||
|
||||
return \Redirect::to('profile');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email with the verification link to the user
|
||||
*/
|
||||
public function onSendEmailVerificationLink()
|
||||
{
|
||||
if(!$this->user()->email_verified) {
|
||||
$code = sha1(time());
|
||||
$vars = [
|
||||
'verification_link' => $this->controller->pageUrl('kabinet/verify_email.htm', ['code' => $code])
|
||||
];
|
||||
|
||||
try {
|
||||
\Mail::send('tps.birzha::mail.' . app()->getLocale() . '.email_verify', $vars, function($message) {
|
||||
$message->to($this->user()->email, 'Birzha User');
|
||||
$message->subject('Подтверждение Email');
|
||||
});
|
||||
} catch(Throwable $th) {
|
||||
\Log::info($th);
|
||||
|
||||
Flash::error('tps.birzha::mail.' . app()->getLocale() . '.email_verify');
|
||||
|
||||
return \Redirect::to('profile');
|
||||
}
|
||||
|
||||
$this->user()->email_activation_code = $code;
|
||||
$this->user()->save();
|
||||
|
||||
Flash::success('Please check your email');
|
||||
|
||||
return \Redirect::to('profile');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the user
|
||||
* @param string $code Activation code
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class User extends UserBase
|
|||
'username' => 'required|unique:users',
|
||||
'password' => 'required:create|between:8,255|confirmed',
|
||||
'password_confirmation' => 'required_with:password|between:8,255',
|
||||
'dial_code' => 'required', // +993, +375...
|
||||
];
|
||||
|
||||
public $messages = [
|
||||
|
|
@ -55,7 +56,7 @@ class User extends UserBase
|
|||
public $hasMany = [
|
||||
'products' => ['TPS\Birzha\Models\Product', 'key' => 'vendor_id'],
|
||||
'transactions' => ['TPS\Birzha\Models\Transaction'],
|
||||
|
||||
'exchangerequests' => ['TPS\Birzha\Models\Exchangerequest'],
|
||||
|
||||
];
|
||||
|
||||
|
|
@ -71,7 +72,8 @@ class User extends UserBase
|
|||
'password',
|
||||
'password_confirmation',
|
||||
'created_ip_address',
|
||||
'last_ip_address'
|
||||
'last_ip_address',
|
||||
'dial_code'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -174,6 +176,16 @@ class User extends UserBase
|
|||
public function getUserBalanceAttribute(){
|
||||
return $this->getBalance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutators
|
||||
*/
|
||||
// public function setUsernameAttribute($value)
|
||||
// {
|
||||
// dd($this->attributes);
|
||||
// return $this->attributes['username'] = $this->attributes['dial_code'] . $value;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Gets a code for when the user is persisted to a cookie or session which identifies the user.
|
||||
* @return string
|
||||
|
|
@ -546,4 +558,17 @@ class User extends UserBase
|
|||
{
|
||||
$this->password = $this->password_confirmation = Str::random(static::getMinPasswordLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an activation code for the given user.
|
||||
* @return string
|
||||
*/
|
||||
public function getActivationCode()
|
||||
{
|
||||
$this->activation_code = $activationCode = random_int(1000, 9999);;
|
||||
|
||||
$this->forceSave();
|
||||
|
||||
return $activationCode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,4 +15,14 @@ class UserRegisteredEvent extends UserEventBase
|
|||
'group' => 'user'
|
||||
];
|
||||
}
|
||||
public static function makeParamsFromEvent(array $args, $eventName = null)
|
||||
{
|
||||
$user = array_get($args, 0);
|
||||
|
||||
$params = $user->getNotificationVars();
|
||||
$params['activation_code'] = $user->getActivationCode();
|
||||
$params['user'] = $user;
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,3 +15,6 @@ attributes:
|
|||
|
||||
email:
|
||||
label: Email address
|
||||
|
||||
phone_verified:
|
||||
label: Phone verified
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
layout = "birzha_email"
|
||||
==
|
||||
|
||||
<h1>Confirm your account</h1>
|
||||
|
||||
<a href="{{verification_link}}">Click here</a> <span>to verify your email</span>
|
||||
|
|
@ -6,6 +6,7 @@ use RainLab\Notify\NotifyRules\SaveDatabaseAction;
|
|||
use System\Classes\PluginBase;
|
||||
use TPS\Birzha\Actions\MailToAdminsAction;
|
||||
use TPS\Birzha\Actions\SendSMSAction;
|
||||
use TPS\Birzha\Actions\VerifyAction;
|
||||
use TPS\Birzha\Models\Category;
|
||||
use TPS\Birzha\Models\Message;
|
||||
use TPS\Birzha\Models\Product;
|
||||
|
|
@ -213,7 +214,34 @@ class Plugin extends PluginBase
|
|||
// ]);
|
||||
// });
|
||||
}
|
||||
public function registerMailLayouts()
|
||||
{
|
||||
return [
|
||||
'birzha_default' => 'tps.birzha::mail.layout-default',
|
||||
'birzha_system' => 'tps.birzha::mail.layout-system',
|
||||
];
|
||||
}
|
||||
|
||||
public function registerMailTemplates()
|
||||
{
|
||||
return [
|
||||
'tps.birzha::mail.ru.activate',
|
||||
'tps.birzha::mail.en.activate',
|
||||
'tps.birzha::mail.tm.activate',
|
||||
'tps.birzha::mail.message',
|
||||
'tps.birzha::mail.request',
|
||||
|
||||
// email verification
|
||||
'tps.birzha::mail.ru.email_verify',
|
||||
'tps.birzha::mail.en.email_verify',
|
||||
'tps.birzha::mail.tm.email_verify',
|
||||
|
||||
// product reviewed
|
||||
// 'tps.birzha::mail.ru.product_reviewed',
|
||||
// 'tps.birzha::mail.en.product_reviewed',
|
||||
// 'tps.birzha::mail.tm.product_reviewed',
|
||||
];
|
||||
}
|
||||
|
||||
public function registerNotificationRules()
|
||||
{
|
||||
|
|
@ -228,8 +256,10 @@ class Plugin extends PluginBase
|
|||
'actions' => [
|
||||
SendSMSAction::class,
|
||||
MailToAdminsAction::class,
|
||||
VerifyAction::class
|
||||
],
|
||||
'conditions' => [
|
||||
\RainLab\User\NotifyRules\UserAttributeCondition::class
|
||||
],
|
||||
'groups' => [
|
||||
'payment' => [
|
||||
|
|
@ -285,6 +315,7 @@ class Plugin extends PluginBase
|
|||
'TPS\Birzha\Components\MyOffers' => 'myOffers',
|
||||
'TPS\Birzha\Components\Balance' => 'balance',
|
||||
'TPS\Birzha\Components\ContactForm' => 'contactForm',
|
||||
'TPS\Birzha\Components\EmailVerify' => 'emailverify',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,19 @@
|
|||
|
||||
namespace TPS\Birzha\Actions;
|
||||
|
||||
use Backend\Models\UserGroup as AdminGroupModel;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use RainLab\Notify\Classes\ActionBase;
|
||||
use TPS\Birzha\Classes\SMS;
|
||||
|
||||
class SendSMSAction extends ActionBase
|
||||
{
|
||||
public $recipientModes = [
|
||||
'user' => 'User phone number (if applicable)',
|
||||
// 'admin' => 'Back-end administrators phones',
|
||||
'custom' => 'Specific phone number',
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns information about this event, including name and description.
|
||||
*/
|
||||
|
|
@ -17,17 +26,48 @@ class SendSMSAction extends ActionBase
|
|||
'icon' => 'icon-envelope'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines validation rules for the custom fields.
|
||||
* @return array
|
||||
*/
|
||||
public function defineValidationRules()
|
||||
{
|
||||
return [
|
||||
'send_to_mode' => 'required',
|
||||
'send_to_custom' => 'required_if:send_to_mode,custom',
|
||||
// 'send_to_admin' => 'required_if:send_to_mode,admin',
|
||||
'message' => 'required|string|max:160'
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Field configuration for the action.
|
||||
*/
|
||||
// public function defineFormFields()
|
||||
public function defineFormFields()
|
||||
{
|
||||
return 'fields.yaml';
|
||||
}
|
||||
|
||||
public function getSendToModeOptions()
|
||||
{
|
||||
$modes = $this->recipientModes;
|
||||
|
||||
return $modes;
|
||||
}
|
||||
|
||||
// public function getSendToAdminOptions()
|
||||
// {
|
||||
// return 'fields.yaml';
|
||||
// $options = ['' => '- All administrators -'];
|
||||
//
|
||||
// $groups = AdminGroupModel::lists('name', 'id');
|
||||
//
|
||||
// return $options + $groups;
|
||||
// }
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
// if ($this->isAdminMode()) {
|
||||
// return 'Send sms to administrators';
|
||||
// }
|
||||
return 'Send sms to customers';
|
||||
}
|
||||
|
||||
|
|
@ -44,5 +84,21 @@ class SendSMSAction extends ActionBase
|
|||
public function triggerAction($params)
|
||||
{
|
||||
|
||||
if($this->host->send_to_mode == 'user' && $params['user']){
|
||||
if(!$params['user']['phone_verified'])
|
||||
return;
|
||||
$to = $params['user']['username'];
|
||||
|
||||
}else{
|
||||
$to = $this->host->send_to_custom;
|
||||
}
|
||||
|
||||
SMS::send($to,$this->host->message);
|
||||
|
||||
// Log::info(json_encode($params));
|
||||
}
|
||||
// protected function isAdminMode()
|
||||
// {
|
||||
// return $this->host->send_to_mode == 'admin';
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
namespace TPS\Birzha\Actions;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Mail;
|
||||
use October\Rain\Exception\ApplicationException;
|
||||
use RainLab\Notify\Classes\ActionBase;
|
||||
use System\Models\MailTemplate;
|
||||
use TPS\Birzha\Classes\SMS;
|
||||
|
||||
class VerifyAction extends ActionBase
|
||||
{
|
||||
public $recipientModes = [
|
||||
'email' => 'Send verification email',
|
||||
'sms' => 'Send verification sms',
|
||||
'email&sms' => 'Send verification email and sms',
|
||||
'email_sms' => 'Send verification sms to local numbers (+993), emails to foreign numbers',
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns information about this event, including name and description.
|
||||
*/
|
||||
public function actionDetails()
|
||||
{
|
||||
return [
|
||||
'name' => 'Verify user',
|
||||
'description' => 'Verify user email/phone',
|
||||
'icon' => 'icon-envelope'
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Defines validation rules for the custom fields.
|
||||
* @return array
|
||||
*/
|
||||
public function defineValidationRules()
|
||||
{
|
||||
return [
|
||||
'send_to_mode' => 'required',
|
||||
'mail_template' => 'required_unless:send_to_mode,sms',
|
||||
];
|
||||
}
|
||||
public function getMailTemplateOptions()
|
||||
{
|
||||
$codes = array_keys(MailTemplate::listAllTemplates());
|
||||
$result = array_combine($codes, $codes);
|
||||
return $result;
|
||||
}
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Send vefification code tu user';
|
||||
}
|
||||
|
||||
public function getActionIcon()
|
||||
{
|
||||
return 'icon-envelope-square';
|
||||
}
|
||||
|
||||
public function triggerAction($params)
|
||||
{
|
||||
// Log::info(json_encode($params));
|
||||
$code = $params['activation_code'];
|
||||
$phone = $params['username'];
|
||||
$dial_code = $params['user']['dial_code'];
|
||||
|
||||
switch ($this->host->send_to_mode) {
|
||||
case 'sms':
|
||||
$this->sendSMS($phone,$code);
|
||||
break;
|
||||
case 'email':
|
||||
$this->sendEmail($params['email'],$code);
|
||||
break;
|
||||
case 'email&sms':
|
||||
$this->sendSMS($phone,$code);
|
||||
$this->sendEmail($params['email'],$code);
|
||||
break;
|
||||
case 'email_sms':
|
||||
$dial_code === '+993' ? $this->sendSMS($phone,$code) : $this->sendEmail($params['email'],$code);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function sendMail($email,$code){
|
||||
$template = $this->host->mail_template;
|
||||
if (!$email || !$template) {
|
||||
throw new ApplicationException('Missing valid recipient or mail template');
|
||||
}
|
||||
|
||||
Mail::sendTo($email, 'tps.birzha::mail.activate', ['code'=>$code], function($message){
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private function sendSMS($phone,$code){
|
||||
$message = "tmex.gov.tm%20verification%20code:%20{$code}";
|
||||
SMS::send($phone,$message);
|
||||
}
|
||||
|
||||
public function getSendToModeOptions()
|
||||
{
|
||||
$modes = $this->recipientModes;
|
||||
|
||||
return $modes;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
# ===================================
|
||||
|
||||
fields:
|
||||
mail_template:
|
||||
label: Mail template
|
||||
type: dropdown
|
||||
placeholder: Select template
|
||||
# mail_template:
|
||||
# label: Mail template
|
||||
# type: dropdown
|
||||
# placeholder: Select template
|
||||
|
||||
send_to_mode:
|
||||
label: Send to
|
||||
|
|
@ -19,24 +19,16 @@ fields:
|
|||
action: show
|
||||
field: send_to_mode
|
||||
condition: value[custom]
|
||||
#
|
||||
# send_to_admin:
|
||||
# label: Send to admin group
|
||||
# span: right
|
||||
# type: dropdown
|
||||
# trigger:
|
||||
# action: show
|
||||
# field: send_to_mode
|
||||
# condition: value[admin]
|
||||
|
||||
send_to_admin:
|
||||
label: Send to admin group
|
||||
span: right
|
||||
type: dropdown
|
||||
trigger:
|
||||
action: show
|
||||
field: send_to_mode
|
||||
condition: value[admin]
|
||||
|
||||
reply_to_mode:
|
||||
label: Reply-to address
|
||||
type: radio
|
||||
span: left
|
||||
|
||||
reply_to_custom:
|
||||
message:
|
||||
cssClass: radio-align
|
||||
trigger:
|
||||
action: show
|
||||
field: reply_to_mode
|
||||
condition: value[custom]
|
||||
label: Message
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
fields:
|
||||
send_to_mode:
|
||||
label: Send to
|
||||
type: radio
|
||||
span: left
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ namespace TPS\Birzha\Classes;
|
|||
*/
|
||||
|
||||
/**
|
||||
*This class is also a merge from smpp lib of onlinecity
|
||||
*This class is also a merge from smpp lib of onlinecity
|
||||
* @see https://github.com/onlinecity/php-smpp
|
||||
*/
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ class SMPP{
|
|||
const OUTBIND = 0x0000000B;
|
||||
const ENQUIRE_LINK = 0x00000015;
|
||||
const ENQUIRE_LINK_RESP = 0x80000015;
|
||||
|
||||
|
||||
// Command status - SMPP v3.4 - 5.1.3 page 112-114
|
||||
const ESME_ROK = 0x00000000; // No Error
|
||||
const ESME_RINVMSGLEN = 0x00000001; // Message Length is invalid
|
||||
|
|
@ -123,7 +123,7 @@ class SMPP{
|
|||
var $sms_replace_if_present_flag=0;
|
||||
var $sms_data_coding=0;
|
||||
var $sms_sm_default_msg_id=0;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the smpp class
|
||||
* @param $host - SMSC host name or host IP
|
||||
|
|
@ -156,9 +156,9 @@ class SMPP{
|
|||
$hours = (int)($duration/60/60);
|
||||
$minutes = (int)($duration/60)-$hours*60;
|
||||
$seconds = (int)$duration-$hours*60*60-$minutes*60;
|
||||
|
||||
|
||||
if($this->debug){
|
||||
echo 'Seconds from last enquire link = ' . $seconds . PHP_EOL;
|
||||
echo "<br>" . 'Seconds from last enquire link = ' . $seconds . PHP_EOL;
|
||||
}
|
||||
|
||||
if ($seconds >= $this->enquirelink_timeout){
|
||||
|
|
@ -176,11 +176,11 @@ class SMPP{
|
|||
|
||||
if($this->state!="open")return false;
|
||||
if($this->debug){
|
||||
echo "Binding receiver...\n\n";
|
||||
echo "<br>" . "Binding receiver...\n\n";
|
||||
}
|
||||
$status=$this->_bind($login, $pass, SMPP::BIND_RECEIVER);
|
||||
if($this->debug){
|
||||
echo "Binding status : $status\n\n";
|
||||
echo "<br>" . "Binding status : $status\n\n";
|
||||
}
|
||||
if($status===0)$this->state="bind_rx";
|
||||
return ($status===0);
|
||||
|
|
@ -196,11 +196,11 @@ class SMPP{
|
|||
|
||||
if($this->state!="open")return false;
|
||||
if($this->debug){
|
||||
echo "Binding transmitter...\n\n";
|
||||
echo "<br>" . "Binding transmitter...\n\n";
|
||||
}
|
||||
$status=$this->_bind($login, $pass, SMPP::BIND_TRANSMITTER);
|
||||
if($this->debug){
|
||||
echo "Binding status : $status\n\n";
|
||||
echo "<br>" . "Binding status : $status\n\n";
|
||||
}
|
||||
if($status===0)$this->state="bind_tx";
|
||||
|
||||
|
|
@ -213,11 +213,11 @@ class SMPP{
|
|||
function close(){
|
||||
if($this->state=="closed")return;
|
||||
if($this->debug){
|
||||
echo "Unbinding...\n\n";
|
||||
echo "<br>" . "Unbinding...\n\n";
|
||||
}
|
||||
$status=$this->sendCommand(SMPP::UNBIND,"");
|
||||
if($this->debug){
|
||||
echo "Unbind status : $status\n\n";
|
||||
echo "<br>" . "Unbind status : $status\n\n";
|
||||
}
|
||||
fclose($this->socket);
|
||||
$this->state="closed";
|
||||
|
|
@ -225,7 +225,7 @@ class SMPP{
|
|||
|
||||
/**
|
||||
* Read one SMS from SMSC. Can be executed only after bindReceiver() call.
|
||||
* Receiver not send enquirelink
|
||||
* Receiver not send enquirelink
|
||||
* This method bloks. Method returns on socket timeout or enquire_link signal from SMSC.
|
||||
* @return sms associative array or false when reading failed or no more sms.
|
||||
*/
|
||||
|
|
@ -246,7 +246,7 @@ class SMPP{
|
|||
//read pdu
|
||||
do{
|
||||
if($this->debug){
|
||||
echo "read sms...\n\n";
|
||||
echo "<br>" . "read sms...\n\n";
|
||||
}
|
||||
$pdu=$this->readPDU();
|
||||
//check for enquire link command
|
||||
|
|
@ -270,16 +270,16 @@ class SMPP{
|
|||
function sendSMS($from, $to, $message){
|
||||
if (strlen($from)>20 || strlen($to)>20 || strlen($message)>160)return false;
|
||||
if($this->state!="bind_tx")return false;
|
||||
|
||||
|
||||
//TON
|
||||
$this->sms_source_addr_ton = $this->setTon($from);
|
||||
$this->sms_dest_addr_ton = $this->setTon($to);
|
||||
$this->sms_source_addr_ton = 2;//$this->setTon($from);
|
||||
$this->sms_dest_addr_ton = 2;$this->setTon($to);
|
||||
|
||||
//NPI
|
||||
$this->sms_source_addr_npi = $this->setNPI($from);
|
||||
$this->sms_dest_addr_npi = $this->setNPI($to);
|
||||
|
||||
$pdu = pack('a1cca'.(strlen($from)+1).'cca'.(strlen($to)+1).'ccca1a1ccccca'.(strlen($message)+1),
|
||||
$pdu = pack('a1cca'.(strlen($from)+1).'cca'.(strlen($to)+1).'ccca1a1ccccca'.(strlen($message)),
|
||||
$this->sms_service_type,
|
||||
$this->sms_source_addr_ton,
|
||||
$this->sms_source_addr_npi,
|
||||
|
|
@ -310,7 +310,7 @@ class SMPP{
|
|||
function getStatusMessage($statuscode)
|
||||
{
|
||||
if (is_bool($statuscode)) return 'Connection Error';
|
||||
|
||||
|
||||
switch ($statuscode) {
|
||||
case SMPP::ESME_ROK: return 'OK';
|
||||
case SMPP::ESME_RINVMSGLEN: return 'Message Length is invalid';
|
||||
|
|
@ -391,7 +391,7 @@ class SMPP{
|
|||
//If empty and length is > 8 then TON is International (1)
|
||||
if(empty($address) || strlen($address) > $NationalNumberLenght) return 1; //International
|
||||
}
|
||||
|
||||
|
||||
//If address is alphanumeric then TON is Alphanumeric (5)
|
||||
if (!ctype_digit($address)) return 5; //Alphanumeric
|
||||
|
||||
|
|
@ -422,7 +422,7 @@ public function enquireLink()
|
|||
if ($response == 0) {
|
||||
$this->lastenquire = microtime(true);
|
||||
if ($this->debug){
|
||||
echo "ENQUIRE!!" . PHP_EOL;
|
||||
echo "<br>" . "ENQUIRE!!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
|
|
@ -480,9 +480,9 @@ public function enquireLink()
|
|||
'short_message'=>$this->getString($ar,255)
|
||||
);
|
||||
if($this->debug){
|
||||
echo "Delivered sms:\n";
|
||||
echo "<br>" . "Delivered sms:\n";
|
||||
print_r($sms);
|
||||
echo "\n";
|
||||
echo "<br>" . "\n";
|
||||
}
|
||||
//send response of recieving sms
|
||||
$this->sendPDU(SMPP::DELIVER_SM_RESP, "\0", $pdu['sn']);
|
||||
|
|
@ -513,21 +513,21 @@ public function enquireLink()
|
|||
$length=strlen($pdu) + 16;
|
||||
$header=pack("NNNN", $length, $command_id, 0, $seq_number);
|
||||
if($this->debug){
|
||||
echo "Send PDU : $length bytes\n";
|
||||
echo "<br>" . "Send PDU : $length bytes\n";
|
||||
$this->printHex($header.$pdu);
|
||||
echo "command_id : ".$command_id."\n";
|
||||
echo "sequence number : $seq_number\n\n";
|
||||
echo "<br>" . "command_id : ".$command_id."\n";
|
||||
echo "<br>" . "sequence number : $seq_number\n\n";
|
||||
}
|
||||
|
||||
$writed = @fwrite($this->socket, $header.$pdu, $length);
|
||||
|
||||
//Close conection if not bind
|
||||
if ($writed == FALSE) {
|
||||
if ($this->debug) echo "Lost connection to SMSC" . PHP_EOL;
|
||||
if ($this->debug) echo "<br>" . "Lost connection to SMSC" . PHP_EOL;
|
||||
exit();
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -584,12 +584,12 @@ public function enquireLink()
|
|||
$body="";
|
||||
}
|
||||
if($this->debug){
|
||||
echo "Read PDU : $length bytes\n";
|
||||
echo "<br>" . "Read PDU : $length bytes\n";
|
||||
$this->printHex($tmp.$tmp2.$body);
|
||||
echo "body len : " . strlen($body) . "\n";
|
||||
echo "Command id : $command_id\n";
|
||||
echo "Command status : $command_status\n";
|
||||
echo "sequence number : $sequence_number\n\n";
|
||||
echo "<br>" . "body len : " . strlen($body) . "\n";
|
||||
echo "<br>" . "Command id : $command_id\n";
|
||||
echo "<br>" . "Command status : $command_status\n";
|
||||
echo "<br>" . "sequence number : $sequence_number\n\n";
|
||||
}
|
||||
$pdu=array(
|
||||
'id'=>$command_id,
|
||||
|
|
@ -631,4 +631,4 @@ public function enquireLink()
|
|||
}
|
||||
print "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace TPS\Birzha\Classes;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use October\Rain\Support\Facades\Http;
|
||||
use TPS\Birzha\Classes\SMPP;
|
||||
|
||||
class SMS
|
||||
{
|
||||
public static function send($to, $content){
|
||||
|
||||
try {
|
||||
$tx = new SMPP(env('SMPP_IP','217.174.228.218'), env('SMPP_PORT',5019)); // make sure the port is integer
|
||||
|
||||
$tx->bindTransmitter(env('SMPP_USER',"birja"),env('SMPP_PASS',"Birj@1"));
|
||||
|
||||
$result = $tx->sendSMS(env('SMPP_SENDER',"0773"),$to,$content);
|
||||
|
||||
$tx->close();
|
||||
unset($tx);
|
||||
return $result;
|
||||
}
|
||||
catch (\Throwable $th){
|
||||
Log::info($th);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use Cms\Classes\ComponentBase;
|
||||
use TPS\Birzha\Models\Contactmessage;
|
||||
use TPS\Birzha\Models\Settings;
|
||||
|
||||
class ContactForm extends ComponentBase
|
||||
{
|
||||
|
|
@ -40,13 +41,17 @@ class ContactForm extends ComponentBase
|
|||
'lastname' => \Input::get('surname'),
|
||||
'mobile' => \Input::get('mobile'),
|
||||
'email' => \Input::get('email'),
|
||||
'content' => \Input::get('message')
|
||||
'content' => \Input::get('content')
|
||||
];
|
||||
|
||||
\Mail::send('tps.birzha::mail.message', $vars, function($message) {
|
||||
$message->to(env('TPS_EMAIL_GETTER'), 'Birzha Admin');
|
||||
$message->subject('Birzha web site contact form');
|
||||
});
|
||||
$admin_email = Settings::getValue('admin_email');
|
||||
|
||||
if($admin_email) {
|
||||
\Mail::send('tps.birzha::mail.message', $vars, function($message) use($admin_email){
|
||||
$message->to($admin_email, 'Birzha Admin');
|
||||
$message->subject('Контактная форма');
|
||||
});
|
||||
}
|
||||
|
||||
return [
|
||||
'#form-steps' => $this->renderPartial('@message_sent')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<?php namespace Tps\Birzha\Components;
|
||||
|
||||
use Cms\Classes\ComponentBase;
|
||||
|
||||
class EmailVerify extends ComponentBase
|
||||
{
|
||||
public function componentDetails() {
|
||||
return [
|
||||
'name' => 'Email Verification',
|
||||
'description' => 'Email Verification'
|
||||
];
|
||||
}
|
||||
|
||||
public function defineProperties()
|
||||
{
|
||||
return [
|
||||
'code' => [
|
||||
'title' => 'Verificaiton code',
|
||||
'description' => 'Verificaiton code',
|
||||
'default' => '{{ :code }}',
|
||||
'type' => 'string',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function onRun() {
|
||||
$user = \Auth::user();
|
||||
|
||||
if(!$user->email_verified) {
|
||||
if($user->email_activation_code == $this->property('code')) {
|
||||
$user->email_verified = true;
|
||||
$user->email_activation_code = null;
|
||||
$user->save();
|
||||
|
||||
$this->page['message'] = 'Your email address has been succesfully verified';
|
||||
|
||||
} else {
|
||||
|
||||
$this->page['message'] = 'Invalid verification link';
|
||||
}
|
||||
} else {
|
||||
|
||||
$this->page['message'] = 'You have already verified your email address';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<section class="thanks">
|
||||
<div class="auto_container">
|
||||
<div class="thanks_wrap">
|
||||
|
||||
<div class="thanks_text">
|
||||
{{message}}
|
||||
</div>
|
||||
|
||||
<div class="link">
|
||||
<a href="{{'index'|page}}" class="home_link">
|
||||
<span>OK</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php namespace TPS\Birzha\Controllers;
|
||||
|
||||
use Backend\Classes\Controller;
|
||||
use BackendMenu;
|
||||
|
||||
class Exchangerequests extends Controller
|
||||
{
|
||||
public $implement = [ 'Backend\Behaviors\ListController' ];
|
||||
|
||||
public $listConfig = 'config_list.yaml';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
BackendMenu::setContext('TPS.Birzha', 'birzha-menu', 'exchange-requests');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<div data-control="toolbar">
|
||||
<button
|
||||
class="btn btn-default oc-icon-trash-o"
|
||||
disabled="disabled"
|
||||
onclick="$(this).data('request-data', {
|
||||
checked: $('.control-list').listWidget('getChecked')
|
||||
})"
|
||||
data-request="onDelete"
|
||||
data-request-confirm="<?= e(trans('backend::lang.list.delete_selected_confirm')) ?>"
|
||||
data-trigger-action="enable"
|
||||
data-trigger=".control-list input[type=checkbox]"
|
||||
data-trigger-condition="checked"
|
||||
data-request-success="$(this).prop('disabled', true)"
|
||||
data-stripe-load-indicator>
|
||||
<?= e(trans('backend::lang.list.delete_selected')) ?>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
list: $/tps/birzha/models/exchangerequest/columns.yaml
|
||||
modelClass: TPS\Birzha\Models\Exchangerequest
|
||||
title: Exchangerequests
|
||||
noRecordsMessage: 'backend::lang.list.no_records'
|
||||
showSetup: true
|
||||
showCheckboxes: true
|
||||
recordsPerPage: 20
|
||||
toolbar:
|
||||
buttons: list_toolbar
|
||||
search:
|
||||
prompt: 'backend::lang.list.search_prompt'
|
||||
|
|
@ -0,0 +1 @@
|
|||
<?= $this->listRender() ?>
|
||||
|
|
@ -6,17 +6,22 @@ scopes:
|
|||
status:
|
||||
label: Status
|
||||
type: group
|
||||
conditions: status in (:filtered)
|
||||
options:
|
||||
new: new
|
||||
payed: payed
|
||||
approved: approved
|
||||
declined: declined
|
||||
failed: failed
|
||||
payment_type:
|
||||
label: 'Payment type'
|
||||
type: group
|
||||
conditions: payment_type in (:filtered)
|
||||
options:
|
||||
bank: Bank
|
||||
online: Online
|
||||
gift: Gift
|
||||
user:
|
||||
label: Seller
|
||||
modelClass: RainLab\User\Models\User
|
||||
nameFrom: name
|
||||
nameFrom: email
|
||||
conditions: user_id in (:filtered)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<div data-control="toolbar">
|
||||
<a href="<?= Backend::url('tps/birzha/sliders/create') ?>" class="btn btn-primary oc-icon-plus"><?= e(trans('backend::lang.form.create')) ?></a>
|
||||
<a href="<?= Backend::url('tps/birzha/sliders/reorder') ?>" class="btn btn-default oc-icon-list"><?= e(trans('backend::lang.reorder.default_title')) ?></a>
|
||||
<!-- <a href="<?= Backend::url('tps/birzha/sliders/reorder') ?>" class="btn btn-default oc-icon-list"><?= e(trans('backend::lang.reorder.default_title')) ?></a> -->
|
||||
<button
|
||||
class="btn btn-default oc-icon-trash-o"
|
||||
disabled="disabled"
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ scopes:
|
|||
user:
|
||||
label: Seller
|
||||
modelClass: RainLab\User\Models\User
|
||||
nameFrom: name
|
||||
nameFrom: email
|
||||
conditions: user_id in (:filtered)
|
||||
|
|
|
|||
|
|
@ -21,23 +21,23 @@ class MessageReceivedEvent extends \RainLab\Notify\Classes\EventBase
|
|||
/**
|
||||
* Defines the usable parameters provided by this class.
|
||||
*/
|
||||
public function defineParams()
|
||||
{
|
||||
return [
|
||||
'name' => [
|
||||
'title' => 'Name',
|
||||
'label' => 'Name of the user',
|
||||
],
|
||||
// ...
|
||||
];
|
||||
}
|
||||
// public function defineParams()
|
||||
// {
|
||||
// return [
|
||||
// 'name' => [
|
||||
// 'title' => 'Name',
|
||||
// 'label' => 'Name of the user',
|
||||
// ],
|
||||
// // ...
|
||||
// ];
|
||||
// }
|
||||
|
||||
public static function makeParamsFromEvent(array $args, $eventName = null)
|
||||
{
|
||||
|
||||
return [
|
||||
'user' => array_get($args, 0),
|
||||
'message' => array_get($args, 1)
|
||||
'message' => array_get($args, 1),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ class PaymentReviewedEvent extends EventBase
|
|||
{
|
||||
return [
|
||||
'payment' => array_get($args, 0),
|
||||
'user' => array_get($args, 1)
|
||||
'user' => array_get($args, 1),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
<?php namespace TPS\Birzha\Models;
|
||||
|
||||
use Model;
|
||||
use RainLab\User\Models\User;
|
||||
|
||||
/**
|
||||
* Model
|
||||
*/
|
||||
class Exchangerequest extends Model
|
||||
{
|
||||
use \October\Rain\Database\Traits\Validation;
|
||||
|
||||
use \October\Rain\Database\Traits\SoftDelete;
|
||||
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
|
||||
/**
|
||||
* @var string The database table used by the model.
|
||||
*/
|
||||
public $table = 'tps_birzha_exchange_requests';
|
||||
|
||||
public $fillable = ['payed_for_request', 'content', 'status', 'currency', 'total_price', 'converted_to_tmt'];
|
||||
|
||||
/**
|
||||
* @var array Validation rules
|
||||
*/
|
||||
public $rules = [
|
||||
];
|
||||
|
||||
/**
|
||||
* Relations
|
||||
*/
|
||||
public $belongsTo = [
|
||||
'user' => User::class,
|
||||
];
|
||||
|
||||
public $morphOne = [
|
||||
'transaction' => [Transaction::class, 'name' => 'transactable']
|
||||
];
|
||||
|
||||
private function createTransaction(){
|
||||
$transaction = new Transaction([
|
||||
'user_id' => $this->user_id,
|
||||
'amount' => 0 - $this->payed_for_request,
|
||||
'description' => "Kotirowkalar (import bahalar) #{$this->id} ucin arzaň tutumy."
|
||||
]);
|
||||
$this->transaction()->save($transaction);
|
||||
}
|
||||
|
||||
public function afterCreate()
|
||||
{
|
||||
parent::afterCreate();
|
||||
|
||||
$this->createTransaction();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<?php namespace TPS\Birzha\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Model;
|
||||
use October\Rain\Support\Facades\Event;
|
||||
|
||||
|
|
@ -58,6 +59,7 @@ class Payment extends Model
|
|||
public function afterUpdate()
|
||||
{
|
||||
if($this->status == 'approved' && $this->payment_type == 'bank' ){
|
||||
// Log::info($this);
|
||||
Event::fire('tps.payment.reviewed',[$this,$this->user]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
columns:
|
||||
id:
|
||||
label: ID
|
||||
type: number
|
||||
sortable: true
|
||||
payed_for_request:
|
||||
label: Fee
|
||||
type: number
|
||||
sortable: true
|
||||
user_id:
|
||||
label: User
|
||||
type: text
|
||||
relation: user
|
||||
valueFrom: email
|
||||
content:
|
||||
label: Content
|
||||
type: text
|
||||
invisible: true
|
||||
created_at:
|
||||
label: 'Created At'
|
||||
type: datetime
|
||||
status:
|
||||
label: Status
|
||||
type: text
|
||||
sortable: true
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
fields:
|
||||
content:
|
||||
label: Content
|
||||
span: auto
|
||||
type: text
|
||||
description:
|
||||
label: Description
|
||||
size: ''
|
||||
span: auto
|
||||
type: textarea
|
||||
payed_for_request:
|
||||
label: Fee
|
||||
span: auto
|
||||
type: number
|
||||
user_id:
|
||||
label: User
|
||||
nameFrom: email
|
||||
descriptionFrom: description
|
||||
span: auto
|
||||
type: relation
|
||||
created_at:
|
||||
label: 'Created at'
|
||||
mode: datetime
|
||||
span: auto
|
||||
type: datepicker
|
||||
status:
|
||||
label: Status
|
||||
options:
|
||||
success: success
|
||||
failed: failed
|
||||
span: auto
|
||||
type: balloon-selector
|
||||
|
|
@ -10,6 +10,7 @@ columns:
|
|||
label: User
|
||||
type: user
|
||||
relation: user
|
||||
sortable: false
|
||||
valueFrom: email
|
||||
amount:
|
||||
label: Amount
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ columns:
|
|||
label: User
|
||||
type: vendor
|
||||
relation: vendor
|
||||
sortable: false
|
||||
valueFrom: email
|
||||
status:
|
||||
label: Status
|
||||
|
|
|
|||
|
|
@ -89,4 +89,7 @@ tabs:
|
|||
tab: Bank Info
|
||||
label: Bank address
|
||||
span: left
|
||||
admin_email:
|
||||
tab: General
|
||||
label: Admin Email
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ navigation:
|
|||
icon: icon-usd
|
||||
permissions:
|
||||
- payment
|
||||
exchange-requests:
|
||||
label: 'Exchange Req.'
|
||||
url: tps/birzha/exchangerequests
|
||||
icon: icon-sitemap
|
||||
frontend:
|
||||
label: Frontend
|
||||
url: tps/birzha/sliders
|
||||
|
|
|
|||
|
|
@ -15,15 +15,3 @@ Route::namespace('TPS\Birzha\Controllers')->group(function () {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
// Route::get('bank_result/{payment_id}', ['as'=>'paymentReturn','uses'=>'...@checkPayment'] );
|
||||
Route::get('tm/check-sms', function() {
|
||||
|
||||
$tx=new SMPP('217.174.228.218', 5019); // make sure the port is integer
|
||||
$tx->debug=false;
|
||||
$tx->bindTransmitter("birja","Birj@1");
|
||||
$result = $tx->sendSMS("0773","99365611968","Hello world");
|
||||
echo $tx->getStatusMessage($result);
|
||||
$tx->close();
|
||||
unset($tx);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?php namespace TPS\Birzha\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class BuilderTableCreateTpsBirzhaExchangeRequests extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::create('tps_birzha_exchange_requests', function($table)
|
||||
{
|
||||
$table->engine = 'InnoDB';
|
||||
$table->increments('id');
|
||||
$table->decimal('payed_for_request', 10, 2);
|
||||
$table->integer('vendor_id');
|
||||
$table->timestamp('created_at')->nullable();
|
||||
$table->timestamp('updated_at')->nullable();
|
||||
$table->timestamp('deleted_at')->nullable();
|
||||
$table->string('content')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('tps_birzha_exchange_requests');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php namespace TPS\Birzha\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class BuilderTableUpdateTpsBirzhaExchangeRequests extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('tps_birzha_exchange_requests', function($table)
|
||||
{
|
||||
$table->renameColumn('vendor_id', 'user_id');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('tps_birzha_exchange_requests', function($table)
|
||||
{
|
||||
$table->renameColumn('user_id', 'vendor_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php namespace TPS\Birzha\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class BuilderTableUpdateTpsBirzhaExchangeRequests2 extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('tps_birzha_exchange_requests', function($table)
|
||||
{
|
||||
$table->string('status')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('tps_birzha_exchange_requests', function($table)
|
||||
{
|
||||
$table->dropColumn('status');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php namespace TPS\Birzha\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class BuilderTableUpdateTpsBirzhaExchangeRequests3 extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('tps_birzha_exchange_requests', function($table)
|
||||
{
|
||||
$table->string('currency');
|
||||
$table->decimal('total_price', 10, 2);
|
||||
$table->decimal('converted_to_tmt', 10, 2);
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('tps_birzha_exchange_requests', function($table)
|
||||
{
|
||||
$table->dropColumn('currency');
|
||||
$table->dropColumn('total_price');
|
||||
$table->dropColumn('converted_to_tmt');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php namespace TPS\Birzha\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class BuilderTableUpdateUsers extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->boolean('verified')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->dropColumn('verified');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php namespace TPS\Birzha\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class BuilderTableUpdateUsers extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->renameColumn('verified', 'phone_verified');
|
||||
$table->boolean('email_verified')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->renameColumn('phone_verified', 'verified');
|
||||
$table->dropColumn('email_verified');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php namespace TPS\Birzha\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class BuilderTableUpdateUsers extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->string('email_activation_code', 191)->nullable();
|
||||
$table->string('phone_activation_code', 191)->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->dropColumn('email_activation_code');
|
||||
$table->dropColumn('phone_activation_code');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php namespace TPS\Birzha\Updates;
|
||||
|
||||
use Schema;
|
||||
use October\Rain\Database\Updates\Migration;
|
||||
|
||||
class BuilderTableUpdateUsers extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->string('dial_code');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->dropColumn('dial_code');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -20,9 +20,6 @@
|
|||
1.0.8:
|
||||
- 'Updated table tps_birzha_product'
|
||||
- builder_table_update_tps_birzha_product.php
|
||||
#1.0.9:
|
||||
# - 'Created table tps_birzha_messages'
|
||||
# - builder_table_create_tps_birzha_messages.php
|
||||
1.0.11:
|
||||
- 'Created table tps_birzha_terms'
|
||||
- builder_table_create_tps_birzha_terms.php
|
||||
|
|
@ -251,3 +248,27 @@
|
|||
1.0.87:
|
||||
- 'Updated table tps_birzha_contactform_messages'
|
||||
- builder_table_update_tps_birzha_contactform_messages_2.php
|
||||
1.0.88:
|
||||
- 'Created table tps_birzha_exchange_requests'
|
||||
- builder_table_create_tps_birzha_exchange_requests.php
|
||||
1.0.89:
|
||||
- 'Updated table tps_birzha_exchange_requests'
|
||||
- builder_table_update_tps_birzha_exchange_requests.php
|
||||
1.0.90:
|
||||
- 'Updated table tps_birzha_exchange_requests'
|
||||
- builder_table_update_tps_birzha_exchange_requests_2.php
|
||||
1.0.91:
|
||||
- 'Updated table tps_birzha_exchange_requests'
|
||||
- builder_table_update_tps_birzha_exchange_requests_3.php
|
||||
1.0.94:
|
||||
- 'Updated table users'
|
||||
- builder_table_update_users_table_18_01_2022_14_26.php
|
||||
1.0.95:
|
||||
- 'Updated table users'
|
||||
- builder_table_update_users_table_02_02_2022_16_55.php
|
||||
1.0.96:
|
||||
- 'Updated table users'
|
||||
- builder_table_update_users_table_03_02_2022_17_12.php
|
||||
1.0.97:
|
||||
- 'Updated table users'
|
||||
- builder_table_update_users_table_04_02_2022_15_20.php
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
subject = "Confirm your account"
|
||||
description = "Activate a new user"
|
||||
==
|
||||
Hello {{ user.name }}
|
||||
|
||||
We need to verify that this is your email address.
|
||||
|
||||
Please enter this code: {{ message.text }}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
subject = "Confirm your account"
|
||||
description = "Activate a new user"
|
||||
==
|
||||
Hello {{ name }}
|
||||
|
||||
We need to verify that this is your email address.
|
||||
|
||||
Please enter this code: {{ code }}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
layout="birzha_system"
|
||||
==
|
||||
|
||||
<p>
|
||||
Hello. You successfully registered on the website of the State Stock
|
||||
Exchange of Turkmenistan. In order to verify your email address and completely activate
|
||||
your account, go through <a href="{{ verification_link }}">the link.</a>
|
||||
</p>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
name = "Default layout birzha"
|
||||
==
|
||||
{{ content|raw }}
|
||||
==
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: aqua;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>header - default layout - birzha</header>
|
||||
<main>{{ content|raw }}</main>
|
||||
<footer>footer - default layout - birzha</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
name = "Sys layout birzha"
|
||||
==
|
||||
{{ content|raw }}
|
||||
==
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: coral;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>header - system layout - birzha</header>
|
||||
<main>{{ content|raw }}</main>
|
||||
<footer>footer - system layout - birzha</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -3,4 +3,4 @@
|
|||
<p><b>Тел.: </b>{{mobile}}</p>
|
||||
<p><b>Email: </b>{{email}}</p>
|
||||
<p><b>Текст сообщения:</b></p>
|
||||
<p>{{content}} fgftgrtgt</p>
|
||||
<p>{{content}} </p>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<p><b>ФИО: </b>{{ first_name }} {{ last_name }}</p>
|
||||
<p><b>Тел.: </b>{{ phone }}</p>
|
||||
<p><b>Email: </b>{{ email }}</p>
|
||||
<p><b>Тип организации: </b>{{ org_type }}</p>
|
||||
<p><b>Статус: </b>{{ status }}</p>
|
||||
<p><b>Снято за отправку запроса: </b>{{ withdraw_from_balance }} TMT</p>
|
||||
<table class="requests-table">
|
||||
<thead>
|
||||
<th>Наименование</th>
|
||||
<th>Страна</th>
|
||||
<th>Единица</th>
|
||||
<th>Валюта</th>
|
||||
<th>Цена</th>
|
||||
</thead>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>{{ item.title }}</td>
|
||||
<td>{{ item.country }}</td>
|
||||
<td>{{ item.unit }}</td>
|
||||
<td>{{ item.currency }}</td>
|
||||
<td>{{ item.price }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
subject = "Confirm your account"
|
||||
description = "Activate a new user"
|
||||
==
|
||||
Hello {{ name }}
|
||||
|
||||
We need to verify that this is your email address.
|
||||
|
||||
Please enter this code: {{ code }}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
layout="birzha_default"
|
||||
==
|
||||
|
||||
<p>
|
||||
Здравствуйте. Вы успешно зарегистрировались на сайте Государственной
|
||||
товарно-сырьевой биржи Туркменистана. Чтобы подтвердить адрес электронной почты
|
||||
и полностью активировать учетную запись, перейдите по <a href="{{ verification_link }}">ссылке.</a>
|
||||
</p>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
subject = "Confirm your account"
|
||||
description = "Activate a new user"
|
||||
==
|
||||
Hello {{ name }}
|
||||
|
||||
We need to verify that this is your email address.
|
||||
|
||||
Please enter this code: {{ code }}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
layout="birzha_default"
|
||||
==
|
||||
|
||||
<p>
|
||||
Salam. Siz Türkmenistanyň Döwlet
|
||||
haryt-çig mal biržasynyň web-sahypasynda üstünlikli hasaba alyndyňyz.
|
||||
Email salgyňyzy tassyklamak üçin, <a href="{{ verification_link }}">şu düwmäni basyň.</a>
|
||||
</p>
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
use RainLab\User\Models\User as UserModel;
|
||||
use RainLab\User\Models\Settings as UserSettings;
|
||||
use Vdomah\JWTAuth\Models\Settings;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
Route::group(['prefix' => 'api'], function() {
|
||||
|
||||
|
|
@ -13,10 +14,11 @@ Route::group(['prefix' => 'api'], function() {
|
|||
$login_fields = Settings::get('login_fields', ['email', 'password']);
|
||||
|
||||
$credentials = Input::only($login_fields);
|
||||
$username = $credentials['username'];
|
||||
|
||||
try {
|
||||
// verify the credentials and create a token for the user
|
||||
if (! $token = JWTAuth::attempt($credentials)) {
|
||||
if (! $token = JWTAuth::attempt(array_merge($credentials, ['username' => $credentials['dial_code'] . $username]))) {
|
||||
return response()->json(['error' => [
|
||||
'ru' => trans('validation.no_user', [], 'ru'),
|
||||
'en' => trans('validation.no_user', [], 'en'),
|
||||
|
|
@ -45,6 +47,7 @@ Route::group(['prefix' => 'api'], function() {
|
|||
'username' => $userModel->username,
|
||||
'email' => $userModel->email,
|
||||
'is_activated' => $userModel->is_activated,
|
||||
'user_balance' => $userModel->user_balance
|
||||
];
|
||||
}
|
||||
// if no errors are encountered we can return a JWT
|
||||
|
|
@ -55,7 +58,14 @@ Route::group(['prefix' => 'api'], function() {
|
|||
if (Settings::get('is_refresh_disabled'))
|
||||
App::abort(404, 'Page not found');
|
||||
|
||||
$token = Request::get('token');
|
||||
$validation = \Validator::make($request->all(), [
|
||||
'token' => 'required'
|
||||
]);
|
||||
if ($validation->fails()) {
|
||||
return response()->json(['error' => $validation->errors()], 400);
|
||||
}
|
||||
|
||||
$token = $request->get('token');
|
||||
|
||||
try {
|
||||
// attempt to refresh the JWT
|
||||
|
|
@ -96,6 +106,17 @@ Route::group(['prefix' => 'api'], function() {
|
|||
$login_fields = Settings::get('signup_fields', ['email', 'password', 'password_confirmation']);
|
||||
$credentials = Input::only($login_fields);
|
||||
|
||||
$rules = [
|
||||
'email' => 'required|between:6,191|email',
|
||||
'username' => 'required|digits_between:8,20|numeric',
|
||||
'dial_code' => 'required',
|
||||
];
|
||||
|
||||
$validation = \Validator::make($credentials, $rules,(new UserModel)->messages);
|
||||
if ($validation->fails()) {
|
||||
return Response::json(['error' => $validation->errors()], 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* activation is set to be automatic
|
||||
*/
|
||||
|
|
@ -107,7 +128,9 @@ Route::group(['prefix' => 'api'], function() {
|
|||
if (!array_key_exists('password_confirmation', $credentials) && array_key_exists('password', $credentials)) {
|
||||
$credentials['password_confirmation'] = $credentials['password'];
|
||||
}
|
||||
$userModel = Auth::register($credentials, $automaticActivation);
|
||||
$userModel = Auth::register(array_merge($credentials,[
|
||||
'username' => $credentials['dial_code'] . $credentials['username']
|
||||
]), $automaticActivation);
|
||||
|
||||
if ($userModel->methodExists('getAuthApiSignupAttributes')) {
|
||||
$user = $userModel->getAuthApiSignupAttributes();
|
||||
|
|
@ -117,6 +140,7 @@ Route::group(['prefix' => 'api'], function() {
|
|||
'name' => $userModel->name,
|
||||
'surname' => $userModel->surname,
|
||||
'username' => $userModel->username,
|
||||
'dial_code' => $userModel->dial_code,
|
||||
'email' => $userModel->email,
|
||||
'is_activated' => $userModel->is_activated,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
<?php return array (
|
||||
'franzose/laravel-smpp' =>
|
||||
array (
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'LaravelSmpp\\LaravelSmppServiceProvider',
|
||||
),
|
||||
),
|
||||
'laravel/tinker' =>
|
||||
array (
|
||||
'providers' =>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
24 => 'October\\Rain\\Argon\\ArgonServiceProvider',
|
||||
25 => 'October\\Rain\\Redis\\RedisServiceProvider',
|
||||
26 => 'October\\Rain\\Validation\\ValidationServiceProvider',
|
||||
27 => 'System\\ServiceProvider',
|
||||
27 => 'LaravelSmpp\\LaravelSmppServiceProvider',
|
||||
28 => 'System\\ServiceProvider',
|
||||
),
|
||||
'eager' =>
|
||||
array (
|
||||
|
|
@ -43,7 +44,8 @@
|
|||
8 => 'October\\Rain\\Filesystem\\FilesystemServiceProvider',
|
||||
9 => 'October\\Rain\\Html\\UrlServiceProvider',
|
||||
10 => 'October\\Rain\\Argon\\ArgonServiceProvider',
|
||||
11 => 'System\\ServiceProvider',
|
||||
11 => 'LaravelSmpp\\LaravelSmppServiceProvider',
|
||||
12 => 'System\\ServiceProvider',
|
||||
),
|
||||
'deferred' =>
|
||||
array (
|
||||
|
|
|
|||
|
|
@ -4,4 +4,21 @@ url = "/2"
|
|||
layout = "static"
|
||||
is_hidden = 0
|
||||
navigation_hidden = 0
|
||||
==
|
||||
==
|
||||
<p>Web sahypasynda akkaunty hasaba almak Öz hasabyňyzyň bolmagy, haryt satmak üçin (satyjylar üçin) mahabat ibermäge ýa-da belliklerden we araçy tutumlardan (alyjylar üçin) geçip, satyjylardan özbaşdak satyn almaga mümkinçilik berer. Söwda gatnaşyklaryna gatnaşyjylar aragatnaşyk gurup we ähli zerur soraglary derrew aýdyňlaşdyryp bilerler.</p>
|
||||
|
||||
<p><strong>Nädip hasaba alynmaly:</strong></p>
|
||||
|
||||
<p>1. Kompýuteriňiziň brauzerinde Türkmenistanyň Döwlet haryt-çig mal biržasynyň web sahypasyny açyň (https://tmex.gov.tm/) we sahypanyň ýokarky sag böleginde “Hasaba alyş” elementini saýlaň ýa-da göni baglanyşygyň üsti bilen hasaba alyşa geçiň. Hasaba alyş amalyny geçmezden ozal sahypanyň ýokarky sag böleginde zerur interfeýs dilini saýlaň.</p>
|
||||
|
||||
<p>2. Ondan soňra zerur meýdanlary dolduryň: e-poçta salgysyny (e-mail), el telefonyňyzyň belgisini we özboluşly paroly giriziň. “Hasaby almagy dowam etdirmek” basyň.</p>
|
||||
|
||||
<p>3. Indiki tapgyrda görkezilen telefon belgisine işjeňleşdirme tassyklaýyş kody bolan SMS habary iberilmelidir. Ony sahypada girizmeli we “Dowam et” düwmesine basmaly. Eger-de SMS habary gelmedik ýagdaýynda, “Kod ibermek” düwmesini ulanyň.</p>
|
||||
|
||||
<p>4. Açylan sahypada zerur meýdanlary (Ady we familiýasy), islegiňize görä galanlaryny dolduryp maglumaty giriziň. Soňra “Saklamak” düwmesine basyň.</p>
|
||||
|
||||
<p>Paroly üýtgetmek isleseňiz, şu ýerde edip bilersiňiz: paroly düzüň we täzeden gaýtalaň. Hasap üçin parol girizilende giriş setiriniň gapdalyndaky görkezijä üns beriň, onuň güýç derejesini görkeziň.</p>
|
||||
|
||||
<p>5. Şeýlelikde web sahypadaky profiliňiz hasaba almak we işjeňleşdirmek üstünlikli tamamlandy we Siz hasap açmagyň üstünlikli tamamlanandygyny barada habary görmeli.</p>
|
||||
|
||||
<p>6. Web saýtda doly hukukly işe başlamak üçin hasabyňyzy doldurmak galýar. Muny iki ýol bilen edip bolýar. Hasabyňyzy nädip maliýeleşdirmelidigini okaň.</p>
|
||||
|
|
@ -62,6 +62,20 @@ function onStart(){
|
|||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% flash success %}
|
||||
<p data-control="flash-message" data-interval="5" class="success">
|
||||
{{ message }}
|
||||
</p>
|
||||
{% endflash %}
|
||||
|
||||
{% flash error %}
|
||||
<p data-control="flash-message" data-interval="5" class="error">
|
||||
{{ message }}
|
||||
</p>
|
||||
{% endflash %}
|
||||
|
||||
|
||||
{% partial 'header' %}
|
||||
{% page %}
|
||||
{% partial 'footer' %}
|
||||
|
|
@ -69,6 +83,32 @@ function onStart(){
|
|||
|
||||
{% framework extras %}
|
||||
{% scripts %}
|
||||
|
||||
<!-- Try to find a hash when parsing a url -->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
switch (location.hash.substr(1)) {
|
||||
case 'register':
|
||||
$('.register').addClass('active');
|
||||
$('#btn-2').addClass('active');
|
||||
$('body').addClass('active');
|
||||
$('.register_content').addClass('active');
|
||||
break;
|
||||
|
||||
case 'login':
|
||||
$('.register').addClass('active');
|
||||
$('#btn-1').addClass('active');
|
||||
$('body').addClass('active');
|
||||
$('.register_content_2').addClass('active');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<!-- End hash script -->
|
||||
|
||||
<script src="{{'assets/js/main.js'|theme}}"></script>
|
||||
<script>
|
||||
$('.iti__country').click(function (e) {
|
||||
|
|
@ -87,6 +127,8 @@ function onStart(){
|
|||
let code = $(this).find('.iti__dial-code').text()
|
||||
$('.phone_box-code').html(code)
|
||||
|
||||
$('input[name="dial_code"]').val(code)
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -21,9 +21,13 @@ items:
|
|||
isExternal: '0'
|
||||
-
|
||||
title: Sorag-jogap
|
||||
nesting: null
|
||||
type: cms-page
|
||||
url: null
|
||||
code: ''
|
||||
reference: terms
|
||||
cmsPage: null
|
||||
replace: null
|
||||
viewBag:
|
||||
locale:
|
||||
en:
|
||||
|
|
@ -55,4 +59,20 @@ items:
|
|||
isHidden: '0'
|
||||
cssClass: ''
|
||||
isExternal: '0'
|
||||
-
|
||||
title: Kotirowkalar
|
||||
type: url
|
||||
url: /app
|
||||
code: ''
|
||||
viewBag:
|
||||
locale:
|
||||
en:
|
||||
title: Quotations
|
||||
url: /app
|
||||
ru:
|
||||
title: Котировки
|
||||
url: /app
|
||||
isHidden: '0'
|
||||
cssClass: ''
|
||||
isExternal: '0'
|
||||
name: main-top
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ localeTitle[ru] = "Профиль"
|
|||
|
||||
[session]
|
||||
security = "user"
|
||||
redirect = "index"
|
||||
==
|
||||
<!-- Add post ============================================================= -->
|
||||
<section class="post">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
title = "Verify Email"
|
||||
url = "/verify-email/:code"
|
||||
layout = "default"
|
||||
is_hidden = 0
|
||||
|
||||
[session]
|
||||
security = "user"
|
||||
redirect = "index"
|
||||
|
||||
[emailverify]
|
||||
code = "{{ :code }}"
|
||||
==
|
||||
{% component 'session' %}
|
||||
|
||||
{% component 'emailverify' %}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
title = "Gizlinlik syýasaty"
|
||||
url = "/gizlinlik-syyasaty"
|
||||
layout = "default"
|
||||
is_hidden = 0
|
||||
|
||||
[viewBag]
|
||||
localeTitle[en] = "Privacy policy"
|
||||
localeTitle[ru] = "Политика конфиденциальности"
|
||||
localeUrl[en] = "/privacy-policy"
|
||||
localeUrl[ru] = "/politika-konfidencialnosti"
|
||||
==
|
||||
|
||||
<section class="thanks">
|
||||
<div class="auto_container">
|
||||
<div class="thanks_wrap">
|
||||
|
||||
<h3 class="thanks_text">
|
||||
{{this.page.title}}
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
<!-- This messages are shawn when a user attempts tp verify the phone number. -->
|
||||
|
||||
<!-- Flash messages end. -->
|
||||
|
||||
{{ form_ajax('onUpdate',{class:'post_form','data-request-validate':''}) }}
|
||||
|
||||
<div class="post_input">
|
||||
|
|
@ -16,6 +20,21 @@
|
|||
<label for="phone_num">{{'auth.phone'|_}}</label>
|
||||
<input type="text" id="phone_num" name="username" value="{{user.username}}">
|
||||
<div data-validate-for="username"></div>
|
||||
|
||||
<!-- Phone verification -->
|
||||
{% if user.dial_code == '+993' and not user.phone_verified %}
|
||||
<a href="#" onclick="$('.sms-code').addClass('active'); $(this).request('onSendSmsCode', {
|
||||
error: function(e) {
|
||||
console.error(e);
|
||||
$('.sms-code').removeClass(active);
|
||||
}
|
||||
}); return false;"
|
||||
>
|
||||
|
||||
Verify phone
|
||||
</a>
|
||||
{% endif %}
|
||||
<!-- End Phone verification -->
|
||||
</div>
|
||||
|
||||
|
||||
|
|
@ -23,6 +42,19 @@
|
|||
<label for="blue_mail">{{'auth.email'|_}}</label>
|
||||
<input type="email" id="blue_mail" name="email" value="{{user.email}}">
|
||||
<div data-validate-for="email"></div>
|
||||
|
||||
<!-- Email verification -->
|
||||
{% if not user.email_verified %}
|
||||
<a href="#" onclick="$(this).request('onSendEmailVerificationLink', {
|
||||
error: function(e) {
|
||||
console.error(e);
|
||||
}
|
||||
}); return false;"
|
||||
>
|
||||
Verify email
|
||||
</a>
|
||||
{% endif %}
|
||||
<!-- End Email verification -->
|
||||
</div>
|
||||
|
||||
<div class="post_input">
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
<div>
|
||||
<span class="error_span t-c" data-validate-for="no_user" style="color: red;"></span>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="dial_code" value="+993">
|
||||
|
||||
<div class="register_input pl-100">
|
||||
<div class="phone_box ">
|
||||
<div class="phone_box-flag iti__flag iti__tm">
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
<input type="email" name="email" placeholder="{{'auth.email'|_}}">
|
||||
<div data-validate-for="email"></div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="dial_code" value="+993">
|
||||
|
||||
<div class="register_input pl-100">
|
||||
<div class="phone_box">
|
||||
<div class="phone_box-flag iti__flag iti__tm">
|
||||
|
|
|
|||
|
|
@ -68,6 +68,76 @@ code = "main-top"
|
|||
</section>
|
||||
<!-- Header Top end ========================================================= -->
|
||||
|
||||
{% if not account.user %}
|
||||
<!-- Password ==================================================== -->
|
||||
<section class="password">
|
||||
<div class="auto_container">
|
||||
<div class="pass_wrap">
|
||||
<div class="pass_mail">
|
||||
<div class="pass_title">
|
||||
Забыли пароль
|
||||
</div>
|
||||
<form action="#" class="password_form">
|
||||
<div class="pass_input">
|
||||
<input type="text" placeholder="Ваш электронный адрес">
|
||||
</div>
|
||||
<button type="submit" class="pass_btn">
|
||||
Отправить
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="pass_change">
|
||||
<div class="pass_title">
|
||||
Забыли пароль
|
||||
</div>
|
||||
<form action="#" class="password_form">
|
||||
<div class="pass_input">
|
||||
<input type="text" placeholder="Введите новый пароль">
|
||||
</div>
|
||||
<div class="pass_input">
|
||||
<input type="text" placeholder="Введите еще раз новый пароль">
|
||||
</div>
|
||||
<button type="submit" class="pass_btn">
|
||||
Отправить
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Password end ==================================================== -->
|
||||
|
||||
{% else %}
|
||||
|
||||
{% if user.dial_code == '+993' and not user.phone_verified %}
|
||||
|
||||
<!-- Sms code input ==================================================== -->
|
||||
<section class="password sms-code">
|
||||
<div class="auto_container">
|
||||
<div class="pass_wrap">
|
||||
<div class="pass_mail">
|
||||
<div class="pass_title">
|
||||
Enter 4 digits SMS code
|
||||
</div>
|
||||
<form action="#" data-request="onCheckSmsCode" data-request-validate data-request-flash class="password_form">
|
||||
<div class="pass_input">
|
||||
<input type="text" name="sms_code" placeholder="SMS code" required>
|
||||
<span data-validate-for="sms_code" style="color: red;"></span>
|
||||
</div>
|
||||
<button type="submit" class="pass_btn" data-attach-loading>
|
||||
Send
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Sms code input end ==================================================== -->
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
<!--Header ============================================================= -->
|
||||
<header class="header" id="header">
|
||||
<div class="auto_container">
|
||||
|
|
@ -135,6 +205,8 @@ code = "main-top"
|
|||
</div>
|
||||
<div class="profile_drop">
|
||||
|
||||
|
||||
|
||||
<a href="{{'kabinet/profile'|page}}" class="profile_item">
|
||||
<div class="profile_icon">
|
||||
<img src="{{'assets/images/svg/user-plus.svg'|theme}}" alt="">
|
||||
|
|
|
|||
Loading…
Reference in New Issue