adonisjs lucid module not found - mysql

I used adonis make:model Thing --migration to create and migrate. Therefore i have 'Thing.js file in my models with the following code in it:
'use strict'
const Model = use('Model')
class Thing extends Model {
}
module.exports = Thing
I then replaced 'Model' with 'Lucid' since I'd like to structure a relational database. But this is the error I get on my terminal when I run server.js: "Cannot find module 'Lucid'".
and this is how it looks inside the start/app.js file:
const providers = [
'#adonisjs/framework/providers/AppProvider',
'#adonisjs/framework/providers/ViewProvider',
'#adonisjs/lucid/providers/LucidProvider',
'#adonisjs/bodyparser/providers/BodyParserProvider',
'#adonisjs/cors/providers/CorsProvider',
'#adonisjs/shield/providers/ShieldProvider',
'#adonisjs/session/providers/SessionProvider',
'#adonisjs/auth/providers/AuthProvider',
'#adonisjs/validator/providers/ValidatorProvider'
]
and at the end:
module.exports = { providers, aceProviders, aliases, commands }
What is the reason for this? How do I fix it?
ps: the project was initialized the typical way thus the folder structure is as is: adonis new myprojectsname

use('Model') will use the Model class of Lucid provider. You don't need to change it to create a relational database.

Related

Should I have a layer in between my controller and model in Node-Express app?

I have an Express application where I use Sequelize to interact with my MySQL database. The models just represent the database tables with corresponding fields, without containing any additional logic. I want my controllers to not be fat and for that I think I should have a layer in between which contains all of the logic and which uses the model to interact with the database.
Is this a good practice and if it is what should I call this layer and what exactly should it contain?
Thanks, in advance!
First of all, great question.
Second of all, this is how I would do it:
in your models, say you have a user model, users.js.
In that model for your user/db interface, after your
const User = module.exports = <sql declaration and model reference>;
you can create other module exports like this:
module.exports.getUserById = function(id, callback){
<Sequelize logic goes here>
};
And this is essentially middleware/controller for your model class for handling routines.
You might use this by importing your user model and then calling your exported module:
const User = require("../models/users")
and then when it's time to call your function:
User.getUserById(id, function(err, user) {
<some logic with regard to your user>
});
You can extend your sequelize models and instances with methods and hooks, your controllers would ideally only make a few calls to these methods.
For instance, you could add something like this to your User model:
instanceMethods: {
encryptPassword: function(plainPassword) {
if(!this.salt){
this.salt = randomString.generate(10);
}
var cipher = crypto.createCipher('aes-256-cbc', this.salt);
cipher.update(plainPassword, 'utf8', 'base64');
var encryptedPassword = cipher.final('base64')
return encryptedPassword;
},
decryptPassword: function(){
var decipher = crypto.createDecipher('aes-256-cbc', this.salt);
decipher.update(this.password, 'base64', 'utf8');
var decryptedPassword = decipher.final('utf8');
return decryptedPassword;
}
}
And maybe even add a pre-save hook to check if the user is new and then encrypt the password before saving, you could create authentication methods to call this from your model and not your controller, and so on...

Yii2 fixtures not unloading, not loading with dependencies

Unloading issue
I'm trying to create fixtures in Yii2 to be able to fill my tables with some test data. I'm not using Codeception yet. I'm following the Yii2 guide on fixtures. The first table is the User table:
namespace tests\unit\fixtures;
use yii\test\ActiveFixture;
/**
* User fixture
*/
class UserFixture extends ActiveFixture
{
public $modelClass = 'common\models\User';
}
This one works when I ssh into Vagrant and load the fixture, but the entries are still there after I do an unload. According to the terminal output the fixture was successfully unloaded. What am I missing here? Should this work out of the box or should you create your own unload function?
Edit:
What did help was adding this to the User fixture:
public function unload(){
parent::unload();
$this->resetTable();
}
I would expect this to be present in unload anyhow, but I have read the (very slow) discussion in the link posted below. I don't know if the parent::unload() line was necessary, it worked without the line, but BaseActiveFixture defines it and empties $this->data and $this->_models.
Depends issue
My second fixture depends on the User fixture:
namespace tests\unit\fixtures;
use yii\test\ActiveFixture;
/**
* User Libraries fixture
*/
class UserLibrariesFixture extends ActiveFixture
{
public $modelClass = 'common\models\UserLibraries';
// Dependencies
public $depends = [
'tests\unit\fixtures\UserFixture',
];
}
This one also loads correctly according to the terminal, but the UserLibraries table remains empty. It doesn't say it will load the dependencies, but I don't know if it should say that it will.
I've kept the data files as simple as possible and the correct data appears in the User table. I only added data for the required fields for the UserLibraries table, so I don't know if that could be an issue. Is there a log file that I can check for entries regarding the fixtures?
Edit:
The UserLibraries fixture is now able to create data in the User table (but not the UserLibraries table), so disabling the foreign key check works for fixtures with dependencies. That makes me think there is an error in my data file for the UserLibraries. To check that I need a log file.
Edit2:
Fixture loading issue solution
The fixtures would not load because of an underscore in the table names. The table names userLibraries and user_libraries will result in model, controller and view files with identical file names when created with Gii. With the camelcase name table I am able to load fixtures.
Unloading fixtures is a question "under discussion" (see here). But this is my mysql workaround for it (I also commented there) and should be added to each fixture model that has some dependant table:
<?php
namespace tests\codeception\common\fixtures;
use yii\test\ActiveFixture;
class VariationFixture extends ActiveFixture
{
public $modelClass = 'common\models\Variation';
public function beforeLoad() {
parent::beforeLoad();
$this->db->createCommand()->setSql('SET FOREIGN_KEY_CHECKS = 0')->execute();
}
public function afterLoad() {
parent::afterLoad();
$this->db->createCommand()->setSql('SET FOREIGN_KEY_CHECKS = 1')->execute();
}
}
As to the loading, using codeception you can use /tests/codeception/common/_support/FixtureHelper::fixtures() to define the fixtures you want to be loaded before each test case:
public function fixtures()
{
return [
'user' => [
'class' => UserFixture::className(),
'dataFile' => '#tests/codeception/common/fixtures/data/init_login.php',
],
'room' => [
'class' => RoomFixture::className(),
'dataFile' => '#tests/codeception/common/fixtures/company/data/room.php',
],
...
];
}

Meaning of Yii::$app->user->identity->role->role_name;

In a book called Yii2 for Beginners, which is mainly about the advanced template, I have encountered the following unexplained code, which seems relevant to RBAC:
$userHasRoleName = Yii::$app->user->identity->role->role_name;
What exactly does this mean? For example, I guess that this:
Yii::$app->user
refers to this file:
vendor\yiisoft\yii2\web\User.php
Is this correct?
In any case, what does the rest of the code refer to? Specifically:
->identity->role->role_name
In the above User.php file, I have not been able to find anything like "function identity()", so it can't be that. I have found numerous $identity variables, but I don't know which one the code might be referring to. And there is no $role variable at all.
What is this code referring to:
Yii::$app->user->identity->role->role_name;
Yii described magic methods like __get, __set and so on, to get access for inaccessible properties. Oftenly such methods begins from get or set (in Yii implementation it is). To get access to ->identity, \yii\web\User has method getIdentity. This method return identity wich you described in config with identityClass property for user component. Oftenly identityClass is a AR model which implements IdentityInterface.
'components' => [
'user' => [
'identityClass' => 'common\models\User',
]
]
To get access to ->role for example you must to create a new method
namespace common\models;
class User extends ActiveRecord implements IdentityInterface {
public function getRole(){
// if user can have only one role
return current( \Yii::$app->authManager->getRolesByUser( $this->id ) );
}
}
Btw implementation of ->role->role_name may be very different.

Upgrading Laravel 4.2 to 5.0, getting [ReflectionException] Class App\Http\Controllers\PagesController does not exist

I was updating my project from laravel 4.2 to laravel 5.0. But, after I am facing this error and have been trying to solve it for the past 4 hours.
I didn't face any error like this on the 4.2 version. I have tried composer dump-autoload with no effect.
As stated in the guide to update, I have shifted all the controllers as it is, and made the namespace property in app/Providers/RouteServiceProvider.php to null. So, I guess all my controllers are in global namespace, so don't need to add the path anywhere.
Here is my composer.json:
"autoload": {
"classmap": [
"app/console/commands",
"app/Http/Controllers",
"app/models",
"database/migrations",
"database/seeds",
"tests/TestCase.php"
],
Pages Controller :
<?php
class PagesController extends BaseController {
protected $layout = 'layouts.loggedout';
public function getIndex() {
$categories = Category::all();
$messages = Message::groupBy('receiver_id')
->select(['receiver_id', DB::raw("COUNT('receiver_id') AS total")])
->orderBy('total', 'DESC'.....
And, here is BaseController.
<?php
class BaseController extends Controller {
//Setup the layout used by the controller.
protected function setupLayout(){
if(!is_null($this->layout)) {
$this->layout = View::make($this->layout);
}
}
}
In routes.php, I am calling controller as follows :
Route::get('/', array('as' => 'pages.index', 'uses' => 'PagesController#getIndex'));
Anyone please help. I have been scratching my head over it for the past few hours.
Routes are loaded in the app/Providers/RouteServiceProvider.php file. If you look in there, you’ll see this block of code:
$router->group(['namespace' => $this->namespace], function($router)
{
require app_path('Http/routes.php');
});
This prepends a namespace to any routes, which by default is App\Http\Controllers, hence your error message.
You have two options:
Add the proper namespace to the top of your controllers.
Load routes outside of the group, so a namespace isn’t automatically prepended.
I would go with option #1, because it’s going to save you headaches in the long run.

Execute my code before any action of any controller

I would like to check if my user have filled certain fields in his profile before he can access any action of any controller.
For example
if(empty(field1) && empty(field2))
{
header("Location:/site/error")
}
In yii1 I could do it in protected\components\Controller.php in init() function
But in yii2 I'm not sure where to put my code. I cannot modify core files, but not sure what to do in backend of my advanced application to make it work.
I know I can user beforeAction() but I have too many controllers to do that and to keep track of every controller
In case you need to execute a code before every controller and action, you can do like below:
1 - Add a component into your components directory, for example(MyGlobalClass):
namespace app\components;
class MyGlobalClass extends \yii\base\Component{
public function init() {
echo "Hi";
parent::init();
}
}
2 - Add MyGlobalClass component into your components array in config file:
'components' => [
'MyGlobalClass'=>[
'class'=>'app\components\MyGlobalClass'
],
//other components
3 - Add MyGlobalClass into bootstarp array in config file:
'bootstrap' => ['log','MyGlobalClass'],
Now, you can see Hi before every action.
Please note that, if you do not need to use Events and Behaviors you can use \yii\base\Object instead of \yii\base\Component
Just add in config file into $config array:
'on beforeAction' => function ($event) {
echo "Hello";
},
Create a new controller
namespace backend\components;
class Controller extends \yii\web\Controller {
public function beforeAction($event)
{
..............
return parent::beforeAction($event);
}
}
All your controllers should now extend backend\components\Controller and not \yii\web\Controller. with this, you should modify every controller. I would go for this solution.
I believe you might also replace 1 class with another (so no change to any controller necessary), something like
\Yii::$classMap = array_merge(\Yii::$classMap,[
'\yii\web\Controller'=>'backend\components\Controller',
]);
See more details here: http://www.yiiframework.com/doc-2.0/guide-tutorial-yii-integration.html and I took the code from here: https://github.com/mithun12000/adminUI/blob/master/src/AdminUiBootstrap.php
you can put this in your index.php file. However, make sure you document this change very well as somebody that will come and try to debug your code will be totally confused by this.
Just i think this code on config file can help you:
'on beforeAction' => function ($event) {
// To log all request information
},
'components' => [
'response' => [
'on beforeSend' => function($event) {
// To log all response information
},
],
];
Or, https://github.com/yiisoft/yii2/blob/master/docs/guide/security-authorization.md use RBAC, to restrict access to controllers actions one at a time based on rules. Why would you want to restrict access to controller actions based on user fields is beyond me. You will not be able to access anything (including the login form) if you put a restriction there.