I am looking for solution to show the url with username. I am using Joomla 3.3.0 stable version.
Ex. site_url/userp-username
I tried to solve this using .htaccess with following rules that I have used for my core PHP websites.
RewriteRule ^userp-([a-zA-Z0-9-_]+)/?$ site_url/index.php?option ... er_name=$1 [R=301,L]
When I hit the url for example http://sitename.com/userp-vishal07 it execute the code that I want to call for this url and it shows the results correctly. But url does not remain as it is and turn into http://vicciivital.com/index.php/en/component/users/profile?layout=view_profile&user_name=vishal07
I am not able to understand how the Joomla redirect works. Please correct me if I am doing any mistakes here.
For reasons I have never understood the com_users router does not route any profiles except the users own profile.
/**
* Method to get a route configuration for the profile view.
*
* #return mixed Integer menu id on success, null on failure.
* #since 1.6
*/
public static function getProfileRoute()
{
// Get the items.
$items = self::getItems();
$itemid = null;
// Search for a suitable menu id.
//Menu link can only go to users own profile.
foreach ($items as $item)
{
if (isset($item->query['view']) && $item->query['view'] === 'profile')
{
$itemid = $item->id;
break;
}
}
return $itemid;
}
What you would need to do is extend this method to handle everyone's profiles. Just make sure to deal with the situation that there is a content item or tag with the same alias as the alias for the user.
In general the easiest workaround is to use com_contact as a profile instead. Turning on the contact creator plugin will create contacts for your new users automatically and contact can display anything from a profile plugin. Also it can display articles by the user and then you can also add plugins for other things if you want. To me it always works a lot better then messing with the com_users profile.
Related
Route::get('/atomic/{id}',[ApiController::class,'index'])->defaults('task', 'atomic');
why use defaults here and what is a task & atomic, and Api controller does not have an index function. Please explain this route properly.
I am new to laravel I tried to google for a solution but no result
defaults method helps to pass extra params to controller without passing as route params
As a backend engineer you’ll often be asked to produce URL patterns
that just don’t work with the rest of the site without breaking your
current routing structure. Often you’ll create what’s known as a slug
for your content, a simple hyphen separated string which is unique in
the system. A typical slug would be just generated from the title like
“My Simple Article” becomes as a slug my-simple-article. This way
there’s a unique string in the system for each post.
If you’ve already been implementing routes like this in your system
you’ll likely have urls that look like /post/{slug} but you know now
that’s not going to be good enough. Your company’s marketing team or
SEO wizards want it to be /{slug} and that’s pretty tricky. You can’t
create the pattern /{post-slug} because it’s going to confuse the
system. What is you have an About Us page or a Contact Us page which
equally important urls like /about-us and /contact-us respectively.
The problem here being that the routing system might pick up the
/about-us link and believe it’s meant to be a slug for a Post model.
At this point Laravel will simply not find the model and throw a HTTP
404 error instead. Not good.
This is where the ‘defaults’ method on routes comes into use to save
the day.
if I consider your example then
Route::get('/atomic/{id}',[ApiController::class,'index'])->defaults('task', 'atomic');
while hitting URL http://127.0.0.1:8002/atomic/1 then in the controller,you will get both params $id and $task
public function index($id,$task){
dump($task);
dump($id);
}
the output of the above will be atomic and 1
defaults() method nothing but key-value pair params
/**
* Set a default value for the route.
*
* #param string $key
* #param mixed $value
* #return $this
*/
public function defaults($key, $value)
{
$this->defaults[$key] = $value;
return $this;
}
suppose if you want to pass multiple array params then use setDefaults method like below
Route::get('/atomic/{id}',[ApiController::class,'index'])->setDefaults([
'tasks'=> 'atomics',
'postTitle'=>'post title goes here'
]);
then in controller
public function index($id,$tasks,$postTitle){
dump($tasks);
dump($postTitle);
dump($id);
}
now if you hit URL http://127.0.0.1:8002/atomic/1 then it will print
atomics
post title goes here
1
Ref : The Power of Laravel’s Route ‘defaults’ for making root level SEO pages
Within EasyAdmin for Symfony you can use the AdminUrlGenerator for easily generating URLs to for example EasyAdmin CRUD Controllers.
Documentation here: https://symfony.com/doc/current/EasyAdminBundle/crud.html#generating-admin-urls
In my case i want to generate an URL to CRUD controller which is also linked within the Dashboard. If i create a link to a CRUD controller, the link works, but the corresponding MenuItem is not highlighted.
I found out, that EasyAdmin highlights the MenuItem with an URL parameter calling menuIndex. I can unset the menuIndex during Link Generation, but then no menuItem is highlightd in the menu.
I havn't found any information on how to get the correct menuIndex for a generated CRUD URL.
So how can i generate Admin URLs with correct menuIndex?
I want to give one possible answer. But to be honest, i don't really like my solution. Maybe someone has a better solution.
So, i am iterating over the configured menuItems within the DashboardController and trying to determine the menuIndex for a given Entity.
The code lookes like this:
private function getIndexLinkForCrudController(string $controller): string
{
return $this->adminUrlGenerator
->unsetAll()
->setController($controller)
->setAction(Action::INDEX)
->set('menuIndex', $this->determineMenuIndexForEntity($controller::getEntityFqcn()))
->generateUrl();
}
private function determineMenuIndexForEntity(string $entity): ?int
{
$menuItems = $this->configureMenuItems();
foreach ($menuItems as $id => $menuItem) {
/* #var MenuItemInterface $menuItem */
$routeParameter = $menuItem->getAsDto()->getRouteParameters();
if (
is_array($routeParameter) &&
array_key_exists(EA::ENTITY_FQCN, $routeParameter) &&
$routeParameter[EA::ENTITY_FQCN] == $entity
) {
return $id;
}
}
return null;
}
This code works for me. But this code only works within the DashboardController. If i want to create Admin URLs within a CRUD controller i need to move the menu config to a static method and accessing it there.
Also i am not fetching the error case when i cannot determine the menuIndex and returning null. For my case it's fine.
Maybe this is helpfull for someone.
If somebody has better solution, i would be happy to here about it.
I need to show my registration page in another language, keeping this separate from his natural behaviour.
In particular this page must be showed in English on the page of the site it owns to, but i need to show it in Italian on another site into an iframe.
Now, common sense tells me i need a page
www.example.com/user
and a
www.example.com/it/user
and i tried to achieve this by "admin/config/regional/language/configure" and the option "Determine the language from the URL (Path prefix or domain)." and all works fine, but, for some reason, as i activate this option, ALL my site pages get a "/en/" in their url, breaking a lot of things into the site (that is extremely complex).
There's a way to achieve this behaviour for the registration page only? (be able to call a page www.example.com/it/user to show registration in italian and having www.example.com/user and all other pages in the site work without any changes?)
My solution would be a small custom module.
Pros:
Easy to tweak and install
Lightweight, code based so you can just check it into VCS and deploy
Can be extended for other language sets
Cons:
Not scaleable.
Requires a dev if you want to change the text
.info file:
name = User Registration Languages
description = Alter the user registration form to present alternative translations
core = 7.x
.module file
<?php
/**
* implements hook_form_FORM_ID_alter()
* https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_form_FORM_ID_alter/7
*
* #param $form
* #param $state
*/
function userreglang_form_user_register_form_alter(&$form, &$state) {
// the arg() function returns a path component (zero based index)
// https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/arg/7
// in this case we're looking for:
// user/register/{language_arg} e.g user/register/it
$lang = arg(2);
// uncomment the following if you want take a look at the form array prior to modification
// be sure to temporarily give the anonymous user role the ability to "Access developer information"
/*if(module_exists('devel')) {
dpm($form);
} // */
if($lang && $map = _userreglang_languages($lang)) {
$form['account']['name']['#title'] = $map['name'];
$form['account']['name']['#description'] = $map['name_desc'];
$form['account']['mail']['#title'] = $map['mail'];
$form['account']['mail']['#description'] = $map['mail_desc'];
$form['actions']['submit']['#value'] = $map['button'];
}
// uncomment the following if you want take a look at the form array after modification
/*if(module_exists('devel')) {
dpm($form);
} // */
}
/**
* helper function for different language maps you might have for the user registration form
*
* #param $lang
* #return array|null
*/
function _userreglang_languages($lang) {
$map = [
'it' => [
'name' => 'Your name, yo!',
'name_desc' => 'Input your username fool!',
'mail' => 'Email, you gots it?',
'mail_desc' => 'Seriously do you not know what email is?',
'button' => 'Click it baby!',
]
];
if(isset($map[$lang])) {
return $map[$lang];
}
else {
return null;
}
}
On drupal.stackoverflow i got a simpler answer. Here it is:
Navigate to /admin/config/regional/language within your site, and verify these things (and correct where appropriate):
Use "English" as your default language
use the "Edit" link for "English" on that page, which will bring you to "/admin/config/regional/language/edit/en". On that page, make sure the value for "Path prefix language code" is "blank".
https://drupal.stackexchange.com/questions/163754/how-to-show-registration-page-in-another-language-in-drupal-7-maintaining-its-n
UPDATE:
#Elin:
Thanks for the link! And sorry for the awful formating of my comments, I just don't make line-breaks working.
But what I try is not really to change a user. I just wanted to create it.
However, I changed my plans of what my plugin should do. Perhaps you have an idea how to make my plan working:
I explored the following:
If I have an user with username 1 with password 1 in Joomla DB and the same user with another password (this is important because otherwise the user would directly authenticate against Joomla DB) in my external DB, a login in frontend with the password from the external DB works without any problems.
A login to backend works ONLY with the password (and so with) the user in Joomlas DB, even if all details are the same (even the groups).
How can I log the user who was authenticated against my external DB into backend?!
One more time many thanks in advance!
_____ End of update ____
I have a (hopefully) little problem that drives me crazy:
I juste wrote a plugin for Joomla 3.1. This plugin allows an authentication against an external webserver script (with onUserAuthenticate()). Works properly.
Than I thought it was better to make backend access possible. So I wrote a second plugin to make that possible.
This plugin searches the authorized user in Joomlas DB and adds him if not found to #__users and #__user_usergroup_map. To here it works properly as well.
Now my question:
Frontend login works, backend doesn't (only a blank white page is displayed).
Do I have to insert the user in any other tables as well? Or is anything missing? Did I forget something?!
My code for the login plugin:
<?php
/**
* #package Joomla.Plugin
* #subpackage Authentication.External
*
* #copyright Copyright (C) 2014 Stefan Herzog. All rights reserved.
* #license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* External Authentication Plugin
*
* #package Joomla.Plugin
* #subpackage Authentication.external
* #since 3.1
*/
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );
class PlgUserExternal extends JPlugin
{
/**
* Load the language file on instantiation. Note this is only available in Joomla 3.1 and higher.
* If you want to support 3.0 series you must override the constructor
*
* #var boolean
* #since 3.1
*/
protected $autoloadLanguage = true;
/**
* This method should handle any authentication and report back to the subject
*
* #param array $credentials Array holding the user credentials
* #param array $options Array of extra options
* #param object &$response Authentication response object
* #param object $response Authentication response object
* #param array $result Authenticataion response array
* #return boolean
*
* #since 1.5
*/
public function onUserLogin($user, $options = array())
{
// Set default values
$allow_backend_access = FALSE;
if(isset($user['admin']) AND $user['admin'] === 1)
{
$allow_backend_access = TRUE; // works! This parameter is delievered with $response from onUserAuthentication()
}
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
// Select all records from the user profile table where key begins with "custom.".
// Order it by the ordering field.
$query->select($db->quoteName(array('id')));
$query->from($db->quoteName('#__users'));
$query->where($db->quoteName('username') . ' = '. $db->quote($user['username']));
// Reset the query using our newly populated query object.
$db->setQuery($query);
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$results = $db->loadAssoc();
if(count($results) == 0)
{
$checkUser = 0;
}
elseif(count($results) >= 1)
{
$checkUser = 1;
$user_id = $results['id'];
}
if($checkUser === 0)
{
// Create a new query object.
$query = $db->getQuery(true);
// Insert columns.
$columns = array('name', 'username','email','password');
// Insert values.
$values = array($db->quote($user['fullname']), $db->quote($user['username']), $db->quote($user['email']), $db->quote($user['password']));
// Prepare the insert query.
$query
->insert($db->quoteName('#__users'))
->columns($db->quoteName($columns))
->values(implode(',', $values));
// Set the query using our newly populated query object and execute it.
$db->setQuery($query);
$db->query();
$user_id = $db->insertid();
if($user_id >> 0)
{
/************* Insert user into user_usergroup_map table *************/
foreach($user['groups'] AS $group_id)
{
$columns = NULL;
$values = NULL;
$query = $db->getQuery(true);
// Insert columns.
$columns = array('user_id', 'group_id');
// Insert values.
$values = array($db->quote($user_id), $db->quote($group_id));
// Prepare the insert query.
$query
->insert($db->quoteName('#__user_usergroup_map'))
->columns($db->quoteName($columns))
->values(implode(',', $values));
// Set the query using our newly populated query object and execute it.
$db->setQuery($query);
$db->query();
}
//$instance = $this->_getUser($user, $options);
}
}
// $instance = JFactory::getUser($user_id); // works
}
}?>
Thank you for every help!
Best regards
Stefan
This ones is pretty involved, lol. A couple of thoughts to provide some direction.
Firstly, you should only need one authentication plugin to handle both front and back end authentication. Within the authentication plugin you can identify whether the request is from the front or back-end login form by using:
JFactory::getApplication()->isSite();
and
JFactory::getApplication()->isAdmin();
Secondly, and I'm not sure if you are doing this from the you post, but you should always create a Joomla user in the DB when a new site visitor authenticates against your external DB, regardless if they authenticate in the front or back-end.
Thirdly, when creating users I would recommend letting Joomla core do all the work by creating the new user using the JUser object. For instance, you could create and save a user doing so:
$user = new JUser();
$user->set('name', $columns['name']);
$user->set('username', $columns['username']);
$user->set('email', $columns['email']);
$user->set('password', $columns['password']);
$user->save();
Now this of course is very simplified and without any data validation or scrubbing, so you must be diligent to perform these checks within your code.
EDIT 1
As op pointed out, I failed to provide any feedback regarding the groups. If you know the group id you can add it using the users helper class. You should have the new user id in the JUser object after you execute the save:
JUserHelper::addUserToGroup($user->id, $group_id);
Good luck!
The Joomla backend has certain built in security features that make it basically much more difficult to log into the back end. For example if you have ever tried to make a REST request against the backend you will hit the white screen. If you look at com_login in the backend you will see it is really different than the login view of com_users. You need to basically force the process of use creation (possibily invisibly to the user) to go through the front end. To allow admin access what you want to do is make a default user group that has the login.admin permission. You can override that configuration setting in your plugin.
As mentioned above, you should only ever use the Joomla API to create users as it is complex, involving a number of tables plus you need to handle the encryption properly. You might need a user plugin as well as an authentication plugin. You may want to look at how cookie authentication works in Joomla, although it is specifically blocked from the backend.
Update
I didn't understand that you were trying to change an existing user. If you look at the JUser code you will see that changing a user requires a session with a user that has permissions to change users . The session you have is a session of a user who (because her groups are not changed yet) definitely does not have user edit permissions. Further to add a super admin that session needs to belong to a super admin. The problem is that you don't have a session. There is a way to fake this that I used here. Since you actually know the id of the admin user you can hard code that even.
Update 2
Because of what I mentioned (same issue as for REST) you are going to have to have challenges. Basically the authorization and authentication flow is different in the two applications. In the backend you must go through the login, so your plugin really needs to simulate the login process. Notice how it is hard coded there in JApplicationAdmin. There are some plugins out there that implement basic auth for the admin and that is another possibility but only if you are using ssl in my opinion unless you are behind a fire wall 100%. Com_config does a shared session thing which could possibly be helpful.
How to disable front-end login component in Joomla 3?
I have managed to disable front-end user registration by disallowing registration as below.
But still the login form is accessible via below url
index.php?option=com_users&view=login
How can I disable front-end login component without editing the core files?
Given that I have gone through below. I don't want to use a RewriteRule to get it done. I want to show a msg to user that it's disabled.
joomla 3 - how to disable front end login component?
Try this,
Joomla default login module is protected. So you can't edit/disable it from admin side.
Just check extensions-> extension manager -> Search for login
Then that module will display. but you can't make it disable.
So the solution for override this feature without touching core files is template override.
You can simply override this view index.php?option=com_users&view=login in your template.
Editing Protected extension via DB tables
The extensions can not be edited, but you can manage it by turning it
ON, or OFF. Protected, mean that this extension can not be managed,
otherwise it will broke structure of your site. However, if you wish
to bring extension to unlocked status, you can access your DB (in my
case MySQL edited by phpMyAdmin), find reliable table of structure,
find desired string, and change "Status" from "1" to "0". Usually your
host providing you with some DB administering tools.
Hope it helps..
I wrote a plugin for that. It completely disables 'Users' at the front-end.
You could also disable a specific view only for these:
index.php?option=com_users&view=login
index.php?option=com_users&view=registration
index.php?option=com_users&view=profile&layout=edit
This is the code for completely disable users at the front-end
<?php defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Router\Route;
class PlgSystemCobizDisableLogin extends CMSPlugin
{
public function onAfterInitialise()
{
$this->disableLogin();
}
protected function disableLogin()
{
$app = Factory::getApplication();
if ($app->isClient('site') === false) return;
$disable_users = $this->params->get('disable_users', 1);
if (!$disable_users) return;
$option = $app->input->getCmd('option');
if ($option == 'com_users') {
$this->redirect();
}
}
protected function redirect()
{
$Itemid = $this->getHomePageItemid();
$app = Factory::getApplication();
$link = Route::_('index.php?Itemid=' . $Itemid);
Factory::getApplication()->enqueueMessage('Toegang gewijgerd', 'error');
$app->redirect($link);
}
protected function getHomePageItemid()
{
$tableName = '#__menu';
$db = Factory::getDbo();
$query = $db->getQuery(true);
$query->select('id');
$query->from($db->quoteName($tableName));
$query->where($db->quoteName('published') . ' = ' . $db->quote(1));
$query->where($db->quoteName('home') . ' = ' . $db->quote(1));
$db->setQuery($query);
$data = $db->loadResult();
return $data;
}
}
Or am I overlooking something here? I acknowledge this disables also registration for users on the front-end. But in most cases that's what I want as well! :-)
in joomla 3.x a
simple way i have found is to edit /components/com-users/controller.php
and mark view string login like that. i got 404 server response but thats what i wanted.
since this is not a url but a component view it is abit hard to redirect.
// Set the default view name and format from the Request.
// $vName = $this->input->getCmd('view', 'login');
$vFormat = $document->getType();
If you want to avoid the 404 server response, after editing /components/com-users/controller.php as indicated in the previous comment, you can create a redirection to send from the frontend login page to wherever you want, say the homepage. It does work.