On my website I use cron job on cpanel.
I have this code below in the construct area of controller but it stops the cpanel cron job from working.
if (!$this->input->is_cli_request()) {
show_error('Direct access is not allowed');
}
Question Do I need the code above. if I use my cpanel cron job? I just want to make it more secure.
<?php
class Cron extends CI_Controller {
public function __construct() {
parent::__construct();
if (!$this->input->is_cli_request()) {
show_error('Direct access is not allowed');
}
$this->load->library('email');
$this->load->model('members_model');
}
public function message()
{
$admin_email = $this->config->item('email_host');
$admin_email_pass = $this->config->item('email_password');
$companyname = 'Riwaka';
$config = array(
'protocol' => 'smtp',
'smtp_host' => 'ssl://mail.yourdomain.co.nz',
'smtp_port' => 465,
'smtp_user' => $admin_email,
'smtp_pass' => $admin_email_pass,
'mailtype' => 'html',
'charset' => 'iso-8859-1'
);
$this->email->initialize($config);
$members = $this->members_model->get_approved_members_for_cron_job();
if ($members) {
foreach ($members as $member) {
if ($member['approved'] == '1' && $member['approved_email_sent'] == '0')
{
$this->email->set_newline("\r\n");
$this->email->clear();
$this->email->from($admin_email, 'Admin');
$this->email->to($member['email']);
$this->email->subject($companyname .' Account Approved');
$this->email->message('test');
$update = array(
'approved_email_sent' => '1',
);
$this->members_model->update_approve_email_send($member['email'], $update);
$this->email->send();
}
}
}
}
}
To prevent direct access from a webpage:
you need to add this line
/* deny direct call from web browser */
if (isset($_SERVER['REMOTE_ADDR'])) die('Permission denied.');
with CI 3.0 you can
Make your cron-jobs inaccessible from being loaded in the URL by
checking the return value of is_cli().
is_cli() returns TRUE if the application is run through the command line and FALSE if not.
as by my comment, the cpanel cron job pattern is:
/usr/bin/php /var/www/website/public_html/cli.php controller method
,
see docs here
related post
Solved now. CodeIgniter Cron Job through Cpanel
It seem to be a issue from path I had used. On cpanel before I had
php --silent http://mysubdomain.mydomain.co.nz/cron/message
That was not working proper if I wanted to use this code to prevent access
if (!$this->input->is_cli_request()) {
show_error('Direct access is not allowed');
}
So now I changed to
php-cli /home/myusername/public_html/mysubdomain/index.php Cron message
All works fine now
Related
So I was building chat functionality in laravel for a website using Pusher , everything was working fine till yesterday. But when I run the chat module again, I found out that trigger() method is giving error (Internal server error).
`
use App\Http\Controllers\Controller;
use App\Model\Chatting;
use App\Model\Seller;
use App\Model\Shop;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Events\Message;
use Pusher\Pusher;
class ChattingController extends Controller
{
public function seller_message_store(Request $request)
{
//return 'hello';
if ($request->message == '') {
Toastr::warning('Type Something!');
return response()->json('type something!');
} else {
$shop_id = Shop::where('seller_id', auth('seller')->id())->first()->id;
$message = $request->message;
$time = now();
DB::table('chattings')->insert([
'user_id' => $request->user_id, //user_id == seller_id
'seller_id' => auth('seller')->id(),
'shop_id' => $shop_id,
'message' => $request->message,
'sent_by_seller' => 1,
'seen_by_seller' => 0,
'created_at' => now(),
]);
//return auth('seller')->user()->seller_plan_id;
if(auth('seller')->user()->seller_plan_id>2){
// pusher
$options = array(
'cluster' => 'ap2',
'useTLS' => false
);
$pusher = new Pusher('app auth key','app secret','app_id',$options);
//return $request->user_id;
$data = ['from' => auth('seller')->id(), 'to' => $request->user_id,'message'=>$request->message]; // sending from and to user id when pressed enter
$pusher->trigger('channel-name', 'event', $data);//here is the issue
}
return response()->json(['message' => $message, 'time' => $time]);
}
}
}
`
If I comment out the trigger line, it gives no error.
It was working completely fine till yesterday.
The version 5.0 of pusher is broken and has given me errors in the past.
What you could do is, change
"pusher/pusher-php-server": "5.0"
to
"pusher/pusher-php-server": "^5.0"
And then run the command composer update
Background
I have developed a React app that uses Laravel as an API. I have added logins via Passport and have been using the Personal Access Client approach quite successfully. I can add new users and tokens, I can revoke tokens, I can reset passwords... All API calls (except login and register) are guarded by the API middleware and it works. If I remove the Bearer ${token} from the header on any of these calls it returns 401 unauthenticated due to the ->middleware('auth:api') wrapper.
The Problem
Everything works completely as expected... until I move everything to my Raspberry Pi server. As soon as I moved everything, the problem began. I can login and I can register, but as soon as I use the new bearer token (that I received from my login or register call(s)) on any of the endpoint calls that follow in my flow, it fails with 401 unauthenticated, immediately. I ran the php artisan passport:client --personal command and successfully entered the id and secret into my .env file as usual. I installed all the composer and vendor packages. I installed all passport package(s) and CLI commands.
It only fails on calls that use the auth middleware.
I have done some digging and it seems the only change I can find (significantly) is that the Pi runs a 32 bit PHP where my localhost runs a 64 bit PHP. Other than that its the same code, DB, versions of Laravel and PHP, everything.
I have tried using the command php artisan passport:client --personal --name="app-name" --redirect_uri="http://192.168.1.1/" which puts a record in the "oauth_clients" table but shows the redirect as http://localhost/. I then try to use SQL to change the value of the column named "redirect" to http://localhost/, manually... but again the change does nothing. Calls still return 401 unauthenticated.
The only other things I can find that might be an issue are:
The fact that all tokens in the database table "oauth_access_tokens", under the column called "redirect", are created with the redirect_uri of http://localhost. No matter what I do it's always localhost and not my servers domain or IP address (which is concerning). Manually changing SQL as I said does nothing but I know Laravel uses a few "read-only" columns for auth so I wonder if this is one of them... perhaps personal access tokens only work on localhost?
My email_verified_at column in my "users" table (generated by passport commands) is null because I was not able to setup the "forgot my password" flow of Passport on localhost since emails won't send out on localhost.
What I have setup is this:
public function boot()
{
$this->registerPolicies();
Passport::pruneRevokedTokens();
Passport::tokensExpireIn(Carbon::now()->addDays(1));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(14));
Passport::personalAccessTokensExpireIn(Carbon::now()->addDays(1));
}
AuthServiceProvider Class
public function register(Request $request) {
$validatedData = $request->validate([
'image_url' => 'required',
'last_name' => 'required|max:55',
'image_url' => 'required|max:250',
'first_name' => 'required|max:55',
'password' => 'required|confirmed',
'email' => 'email|required|unique:users',
]);
$validatedData['password'] = bcrypt($request->password);
if ($request->hasFile('image_url')) {
$imageFile = $request->file('image_url');
$imageExtension = $imageFile->extension();
if (strtolower($imageExtension) === 'png' || strtolower($imageExtension) === 'jpg') {
$validatedData['image_url'] = Storage::url( $request->file('image_url')->store('user_pics', 'public') );
}
$user = User::create($validatedData);
date_default_timezone_set('UTC');
$date = new \DateTime( date('Y-m-d H:i:s') );
$user->email_verified_at = $date->format('c');
$accessToken = $user->createToken('authToken-'.$user->id, ['*'])->accessToken;
return response([ 'user' => $user, 'access_token' => $accessToken ]);
} else {
abort(404, 'Cannot register user without a user image!');
}
}
public function login(Request $request) {
$loginData = $request->validate([
'email' => 'email|required',
'password' => 'required'
]);
if (!auth()->attempt($loginData)) {
return response()->json(['statusText' => 'Unauthorized'], 401);
}
$user = auth()->user();
$accessToken = auth()->user()->createToken('authToken-'.$user->id, ['*'])->accessToken;
return response([ 'user' => $user, 'access_token' => $accessToken ]);
}
public function logout(Request $request) {
if (auth()->guard('api')->check()) {
auth()->guard('api')->user()->OauthAcessToken()->delete();
return response()->json([ 'msg' => 'Successfully logged out!' ]);
} else {
return abort(404, 'Must be logged in to log a user out');
}
}
public function refreshToken(Request $request) {
if (auth()->guard('api')->check()) {
$user = auth()->user();
$accessToken = auth()->user()->createToken('authToken-'.$user->id, ['*'])->accessToken;
return response([ 'user' => $user, 'access_token' => $accessToken ]);
} else {
return abort(404, 'Must be logged in to refresh a token!');
}
}
AuthController Class
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users'
],
],
config/Auth.php
APP_NAME=MyName
APP_ENV=dev
APP_DEBUG=true
APP_URL=http://192.168.1.1
PASSPORT_PERSONAL_ACCESS_CLIENT_ID="1"
PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET="[SOME LONG HASH]"
.env File
Finally solved it!!
Turns out it was Apache on the Raspberry Pi server blocking the Authorization header. This finally unblocked me and solved my issues.
For anyone else coming from a Google search, you can go into your /etc/apache2/apache2.conf file and at the very bottom, paste:
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
I am using a Raspberry Pi 4 with 32 bit PHP and Apache2.
Also, I didn't mention in my post that I have been using the following for my apache server root htaccess:
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
.htaccess file, server root
I am working on a Register and Login application with CodeIgniter 3 and Twitter Bootstrap.
When a user registers, an email should be send to the address he/she provided, with an account confirmation link. The problem is that the confirmation email does not send.
In the Usermodel I have:
public function activationEmail($first_name='', $last_name='', $email='', $verification_key='')
{
$this->load->library('email');
$config = Array(
'protocol' => 'smtp',
'smtp_host' => 'smtp.code-love.tk',
'smtp_port' => 465,
'smtp_user' => 'razvan#code-love.tk',
'smtp_pass' => '******',
'smtp_crypto' => 'ssl',
'mailtype' => 'html',
'charset' => 'iso-8859-1'
);
$messg = 'Wellcome, '. $first_name . ' ' . $last_name . '! Click the <strong>confirmation link</strong> to confirm your account.';
$this->email->initialize($config);
$this->email->set_newline('\r\n');
$this->email->from('mail.code-love.tk','Razvan Zamfir');
$this->email->to($email);
$this->email->subject('Account activation');
$this->email->message($messg);
if (!$this->email->send()) {
show_error($this->email->print_debugger());
}
else {
echo 'Your e-mail has been sent!';
}
}
In my Signup controller I have this code:
public function signup() {
$this->form_validation->set_rules('first_name', 'First name', 'required');
$this->form_validation->set_rules('last_name', 'Last name', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|trim|valid_email');
$this->form_validation->set_rules('password', 'Password', 'required|min_length[6]');
$this->form_validation->set_rules('cpassword', 'Confirm password', 'required|matches[password]');
$this->form_validation->set_error_delimiters('<p class="error">', '</p>');
if ($this->form_validation->run()) {
$first_name = $this->input->post('first_name');
$last_name = $this->input->post('last_name');
$email = $this->input->post('email');
$password = $this->input->post('password');
$verification_key = md5($email);
$date_created = date('Y-m-d H:i:s');
$date_updated = date('Y-m-d H:i:s');
$active = 0;
// Load user model
$this->load->model('Usermodel');
// If email does not already exist in the database
// signup new user
if (!$this->Usermodel->email_exists($email)) {
if ($this->Usermodel->user_register($first_name, $last_name, $email, $password, $verification_key, $date_created, $date_updated, $active) && $this->Usermodel->activationEmail($first_name, $last_name, $email, $verification_key)) {
$this->session->set_flashdata("signup_success", "Your account has just bean created. You must confirm it before you can sign in. We have send you a confirmation email at $email for this purpose.");
} else {
// unless sigup does not fail for whatever reason
$this->session->set_flashdata("signup_failure", "We ware unable to create your account.");
}
redirect('signup');
} else {
// If email is already in the database
// urge user to sign in (redirect to signup page too)
$this->session->set_flashdata("email_exists", "The email address $email already exists in the database. Please signin.");
redirect('signin');
}
} else {
$this->load->view('signup');
}
}
The sign up does happen, with the error below, and the verification email is not send. I am not doing this from a local XAMPP/WAMP/MAMP server, but from a "live" one, you can signup yourself.
Severity: Warning
Message: fsockopen(): php_network_getaddresses: getaddrinfo failed: Name or service not known
Filename: libraries/Email.php
Line Number: 1950
Backtrace:
File: /home/roxoqdat/code-love.tk/ciauth/application/models/Usermodel.php
Line: 52
Function: send
File: /home/roxoqdat/code-love.tk/ciauth/application/controllers/Signup.php
Line: 42
Function: activationEmail
File: /home/roxoqdat/code-love.tk/ciauth/index.php
Line: 292
Function: require_once
What am I doing wrong?
Check if you have the required SMTP service.
Try with google SMTP service.
$config = Array(
'protocol' => 'smtp',
'smtp_host' => 'ssl://smtp.googlemail.com',
'smtp_port' => 465,
'smtp_user' => 'xxx',
'smtp_pass' => 'xxx',
'mailtype' => 'html',
'charset' => 'iso-8859-1'
);
$this->load->library('email', $config);
$this->email->set_newline("\r\n");
$this->email->from('mygmail#gmail.com', 'myname');
$this->email->to('target#gmail.com');
$this->email->subject('Email Test');
$this->email->message('Testing the email class.');
$result = $this->email->send();
Next try with:
$config = array('mailtype' => 'html');
Remove the rest from $config = array.
First of all, after setting flashdata, I don't see you redirecting the user to where they can see it...
Also, send the mail first, then you set flash data as An Activation Link Has Been Sent To Your Email, Please Check Your Email To Activate Your Account!
So,
User Registers,
An email is sent to them only if it doesn't exist already,
Set flashdata for any errors that may arise... Eg:
Assign a variable to the email sending function:
$send_email = $this->activationEmail('params');
In your activationEmail function, make sure there is a simple control structure like this:
$success=$this->email->send();
if($success){ return true; } else{ return false; }
Now in your controller, compare to see if mail is actually sent:
if($send_email == true){ $this->session->flashdata('success','Your success message');
// use the redirect() helper function to the function that loads your view
} else { //set failed flashdata and redirect to where you want it seen like above}
You then will know where the problem is.
Let the program flow in your mind first, then implement it. Try that first and get back to me right after.
Hope it somehow helps
Debug whether your parameters are passing or not (specially last_name). Try to write the model method like this to avoid showing errors
public function activationEmail($first_name='', $last_name='', $email='', $verification_key='')
Try adding header to your email (You are setting mailtype twice, might be an issue).
$this->email->set_header('MIME-Version', '1.0; charset=utf-8');
$this->email->set_header('Content-type', 'text/html');
A client requires that all GET/POST requests are logged and stored for 90 days for their applicaiton. I have written a HOOK which seems to record some of the GETS / POSTS but there is less data than I would expect. For example, when submitting form data, the entries don't seem to be put in the log. Has anyone written something similar which works?
Here is my version thus far:
class Logging {
function __construct() {
$this->CI =& get_instance();
}
function index() {
$this->CI->load->model('Logging_m');
$this->CI->load->model('Portal_m');
//get POST and GET values for LOGGING
$post = trim(print_r($this->CI->input->post(), TRUE));
$get = trim(print_r($this->CI->input->get(), TRUE));
$this->CI->Logging_m->logPageView(array(
'portal_id' => $this->CI->Portal_m->getPortalId(),
'user_id' => (!$this->CI->User_m->getUserId() ? NULL : $this->CI->User_m->getUserId()),
'domain' => $_SERVER["SERVER_NAME"],
'page' => $_SERVER["REQUEST_URI"],
'post' => $post,
'get' => $get,
'ip' => $this->CI->input->ip_address(),
'datetime' => date('Y-m-d H:i:s')
));
}
}
This data is stored in a model called 'Logging_m' which looks like this:
<?php
class Logging_m extends CI_Model {
function __construct() {
parent::__construct();
}
function logPageView($data) {
$this->db->insert('port_logging', $data);
}
}
/* End of file logging_m.php */
/* Location: ./application/models/logging_m.php */
As mentionned by Patrick Savalle you should use hooks. Use the post_controller_constructor hook so you can use all other CI stuff.
1) In ./application/config/config.php set $config['enable_hooks'] = TRUE
2) In ./application/config/hooks.php add the following hook
$hook['post_controller_constructor'] = array(
'class' => 'Http_request_logger',
'function' => 'log_all',
'filename' => 'http_request_logger.php',
'filepath' => 'hooks',
'params' => array()
);
3) Create the file ./application/hooks/http_request_logger.php and add the following code as example.
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Http_request_logger {
public function log_all() {
$CI = & get_instance();
log_message('info', 'GET --> ' . var_export($CI->input->get(null), true));
log_message('info', 'POST --> ' . var_export($CI->input->post(null), true));
log_message('info', '$_SERVER -->' . var_export($_SERVER, true));
}
}
I've tested it and it works for me (make sure you have logging activated in your config file).
Sept 2 update:
This has become a very difficult puzzle to solve. Setting up a basic auth, which is all that I want, should involve very few steps. I have done many tests, adding and removing code, reviewing the cake manual, reading tutorials and going step by step through the cakePHP 1.3 application development cookbook by Mariano Iglesias - good book. http://goo.gl/93BGw
But the problem I'm still facing is that the app controller is the only place the 'allowed' actions work. In individual controllers the parent:beforeFilter doesn't get recognized and I'm redirected back to the users login page.
Any help with this is really appreciated. What I'm wondering is how I might debug this type of problem. Are there any other configuration settings I should look at, like 'prefix routing'?
=======================
Sept 1 update:
After a lot of testing what appears to be the issue is that the 'before:filter' in individual controllers isn't being recognized. Example in the post controller:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow = array('edit');
}
Has anyone had this happen before? I've referred to the cakePHP manual as well as many online articles and tutorials and it doesn't make any sense to me. I've even tried to build a simple application with just the users and post controller and still, the before:filter settings in each controller aren't being recognized.
=======================
Original question.
I am using the Cakephp auth component to manage an admin section. This is using version 1.3.11
The problem I'm having is that even with allowed actions in each controller, I'm being redirected to the user login page.
Here is what's in the app controller:
class AppController extends Controller {
var $components = array(
'Auth' => array(
'authorize' => 'controller'
),
'Session',
'RequestHandler'
);
public function isAuthorized() {
return true;
}
function beforeFilter(){
$this->Auth->authorize = 'controller';
$this->Auth->fields = array('username' => 'username', 'password' => 'password');
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->authError = 'Please login to view that page ';
$this->Auth->loginError =' The user name or password you entered did not work, please try again ' ;
$this->Auth->allow('display');
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'logout');
$this->Auth->loginRedirect = array('controller' => 'pages', 'action' => 'display', 'home');
}
This is what's in the users controller:
class UsersController extends AppController {
var $name = 'Users';
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow = array('add');
}
This is what's in the posts controller:
class PostsController extends AppController {
var $name = 'Posts';
var $components = array('Session','RequestHandler', 'Email');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow = array('edit');
}
What I do find is that after I've logged in I'm able to access the home page, as expected. Then when I go to the logout the session isn't entirely destroyed so I can go back to the 'admin' section.
I did try using $this-session('destroy'); in the logout action, but when I did the allowed actions didn't work again.
Does this make sense? Shouldn't allowed actions be independent of a current session?
Thanks, Paul
Make sure you are not using requestAction in any of your elements or views, make sure that the actions called by requestAction are allowed too.... this should fix it.
For the one when you logout and I can still access admin section: the logout() should have $this->redirect($this->Auth->logout()); It should clear the Auth session data.
Here's what I suggest for the beforeFilter() in appcontroller:
function beforeFilter(){
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'dashboard');
}
and for the pages controller: $this->Auth->allow('display', 'view');