Skip to content

Instantly share code, notes, and snippets.

@Anubarak
Created March 5, 2019 08:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Anubarak/990691e0d55e03ae24c774e1de494673 to your computer and use it in GitHub Desktop.
Save Anubarak/990691e0d55e03ae24c774e1de494673 to your computer and use it in GitHub Desktop.
import axios from 'axios';
// my vuex store
import store from './../store';
axios.defaults.withCredentials = true;
const apiVersion = 'v1';
const apiClient = axios.create({
baseURL: 'https://XYZ/api/' + apiVersion + '/',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'CRAFT_CSRF_TOKEN': '',
'X-Requested-With': 'XMLHttpRequest'
}
});
apiClient.interceptors.request.use(
config => {
if (store !== undefined) {
// inject the csrf token into the headers
config.headers.CRAFT_CSRF_TOKEN = store.getters['user/getCsrfTokenValue'];
}
return config;
},
error => Promise.reject(error)
);
// Add a response interceptor
apiClient.interceptors.response.use(
response => {
return response;
},
error => {
// Response is my service to handle all Ajax Requests
// in case of global errors to display generic error messages
// that can't be handled via `response.data.error` property
Response.handleAjaxError(error);
//store.dispatch('response/showError');
return Promise.reject(error);
}
);
export default apiClient;
//
// ...
//
// usage example
import apiClient from "./index";
export default {
saveUser(data){
return apiClient.post('user', data);
},
fetchUsers(){
return apiClient.get('user');
},
fetchUser(id){
return apiClient.get('user/' + id);
},
logout(){
return apiClient.get('user/logout');
},
login(data){
return promise = apiClient.post('user/login', data);
},
getIdentity(){
return apiClient.get('/user/get-identity');
},
checkRemainingSessionTime(extend = false){
let url = '/user/get-remaining-session-time';
if(extend === false){
url += '?dontExtendSession=1'
}
return apiClient.get(url);
}
}
<?php
/**
* Module for Craft CMS 3.x
* The base Web Controller to handle Axios Requests
*
* Created with PhpStorm.
*
* @link https://github.com/Anubarak/
* @email anubarak1993@gmail.com
* @copyright Copyright (c) 2019 Robin Schambach
*/
namespace modules\api\base\base;
use Craft;
use craft\web\Controller;
class WebController extends Controller
{
/**
* @var array List of allowed verbs for this Controller
*/
public $verbs = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];
/**
* actions
*
* @return array
*
* @author Robin Schambach
* @since 05.03.2019
*/
public function actions(): array
{
$actions = parent::actions();
$actions['options'] = [
'class' => OptionsAction::class // the action to handle `OPTIONS` Requests in order to return the correct headers
];
return $actions;
}
/**
* behaviors
*
* @return array
*
* @author Robin Schambach
* @since 04.03.2019
*/
public function behaviors(): array
{
$behaviors = parent::behaviors();
// add a CORS Behavior to send and accept the correct headers
$tokenName = Craft::$app->getConfig()->getGeneral()->csrfTokenName;
$behaviors[] = [
'class' => \modules\api\base\filters\Cors::class,
'cors' => [
// restrict access to domains:
'Allow' => $this->verbs,
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Methods' => $this->verbs,
'Access-Control-Allow-Headers' => [
$tokenName, //'CRAFT_CSRF_TOKEN',
'X-CSRF-Token, Origin',
'X-Requested-With',
'Content-Type',
'Accept'
],
'Access-Control-Request-Headers' => [
$tokenName, //'CRAFT_CSRF_TOKEN'
'X-CSRF-Token, Origin',
'X-Requested-With',
'Content-Type',
'Accept'
],
// input your correct allowed URLs here
'Access-Control-Allow-Origin' => ['http://localhost:8080', 'http://localhost:8082'],
'Origin' => ['http://localhost:8080', 'http://localhost:8082'],
'Access-Control-Max-Age' => 3600
],
];
return $behaviors;
}
}
<?php
// ...
Event::on(
UrlManager::class,
UrlManager::EVENT_REGISTER_SITE_URL_RULES,
function(RegisterUrlRulesEvent $event) {
// Add a Web Controller
// handle POST and GET request with the corresponding action
$event->rules[] = [
'class' => \yii\web\UrlRule::class,
'pattern' => 'api/v1/translations/<action>',
'verb' => ['GET', 'POST'],
'route' => 'v1/translations/<action>',
'defaults' => [
'action' => 'index'
]
];
// handle OPTIONS requests always with the `OPTIONS` action
$event->rules[] = [
'class' => \yii\web\UrlRule::class,
'pattern' => 'api/v1/translations/<action>',
'verb' => ['OPTIONS'],
'route' => 'v1/translations/options',
'defaults' => [
'action' => 'options'
]
];
// How to register Rest Controller Rules
$event->rules[] = [
'class' => \yii\rest\UrlRule::class,
'prefix' => 'api',
'controller' => ['v1/user'],
'pluralize' => false,
'extraPatterns' => [
'OPTIONS login' => 'options',
'OPTIONS test' => 'options',
'OPTIONS logout' => 'options',
'OPTIONS get-identity' => 'options',
'OPTIONS get-remaining-session-time' => 'options',
'POST login' => 'login',
'GET get-remaining-session-time' => 'get-remaining-session-time',
'GET get-identity' => 'get-identity',
'GET logout' => 'logout',
'GET login' => 'login',
]
];
<?php
/**
* Module for Craft CMS 3.x
*
* Created with PhpStorm.
*
* @link https://github.com/Anubarak/
* @email anubarak1993@gmail.com
* @copyright Copyright (c) 2019 Robin Schambach
*/
namespace modules\api\base\base;
use Craft;
use yii\base\Action;
class WebOptions extends Action
{
/**
* @var array the HTTP verbs that are supported by the collection URL
*/
public $collectionOptions = ['GET', 'POST', 'HEAD', 'OPTIONS'];
/**
* @var array the HTTP verbs that are supported by the resource URL
*/
public $resourceOptions = ['GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];
/**
* Responds to the OPTIONS request.
* @param string $id
*/
public function run($id = null)
{
if (Craft::$app->getRequest()->getMethod() !== 'OPTIONS') {
Craft::$app->getResponse()->setStatusCode(405);
}
$options = $id === null ? $this->collectionOptions : $this->resourceOptions;
$headers = Craft::$app->getResponse()->getHeaders();
$headers->set('Allow', implode(', ', $options));
$headers->set('Access-Control-Allow-Methods', implode(', ', $options));
$headers->set('Access-Control-Allow-Headers', 'X-CSRF-Token, Origin, X-Requested-With, Content-Type, Accept');
$headers->set('Access-Control-Allow-Origin', '*');
}
}
<?php
/**
* Module for Craft CMS 3.x
*
* Created with PhpStorm.
*
* @link https://github.com/Anubarak/
* @email anubarak1993@gmail.com
* @copyright Copyright (c) 2019 Robin Schambach
*/
namespace modules\api\v1\controllers;
use Craft;
use craft\db\Query;
use modules\api\base\base\WebController;
/**
* Class TranslationsController
* @package modules\api\v1\controllers
* @since 05.03.2019
*/
class TranslationsController extends WebController
{
/**
* There won't be a user yet... ¯\_(ツ)_/¯
*
* @var bool $allowAnonymous
*/
public $allowAnonymous = true;
/**
* Set it to false since this is one of the first requests
*
* @var bool $enableCsrfValidation
*/
public $enableCsrfValidation = false;
/**
* actionIndex default action to return all the
* required translations for the App
*
* @return \yii\web\Response
*
* @author Robin Schambach
* @since 04.03.2019
*/
public function actionIndex(): \yii\web\Response
{
$query = (new Query())
->from(['source' => '{{%source_message}}'])
->where(['source.category' => 'desk']);
$query->select(
[
'source.id',
'source.category',
'source.comment',
'source.message',
'source.dateCreated',
'source.dateUpdated',
'message.fuzzy',
'message.translation',
'message.language'
]
);
$query->leftJoin('{{%message}} message', '[[message.id]] = [[source.id]] AND message.language = :lang');
$query->addParams(['lang' => Craft::$app->language]);
$translations = $query->all();
return $this->asJson(
[
'success' => true,
'translations' => $translations
]
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment