Change 'edit account' URL in Drupal - drupal

When going to edit account or edit profile in Drupal 7, the URL looks something like http://localhost/user/123/edit where 123 is the user id. Because of this, anyone can see how many users the site has, which I don't want. Is there a way that I can change it to something like http://localhost/user/edit or something without an ID?
I've tried setting up a menu entry in my module, that acts as the edit account/profile page, but had no success.
Also, I don't want to install a new module for this, I'd rather just write my code.

In theory, you could combine the Pathauto module (the widely-used module, used on over 250,000 D6 and D7 sites, which provides URL aliases for normal node and user paths, etc) with the Sub-pathauto module (a new D7 module, currently used on only a few hundred sites). The Sub-pathauto module is the only Drupal 7 module I'm aware of which will allow you to alias the user/uid part of a user/uid/edit -type path.
On the other hand, if your goal is simply to create the illusion that you might have more than a handful of users, when launching a new Drupal site, you could simply increment the UID index by adding (then deleting) a bunch of auto-generated users (with Devel generate), or since this is an auto-increment index, you could likely manually create a user entry in the database with an index of 1507 or something, and then any entry created by Drupal after that would start at 1508, even after you've removed the dummy entry from the table. (Caveat: I've never done this, but in theory it should work.)
Hope that helps. :-)

There is already a module that allows to do what you are trying to do, but as you want to avoid installing a module, you can create a module that contains the following code:
function mymodule_url_outbound_alter(&$path, &$options, $original_path) {
if (preg_match('|^user/([0-9]+)(/.*)?|', $path, $matches)) {
if ($user = user_load($matches[1])) {
$path = 'user/' . $user->name . $matches[2];
}
}
}
function mymodule_url_inbound_alter(&$path, $original_path, $path_language) {
if (preg_match('|^user/([^/]+)(/.*)?|', $path, $matches)) {
$uid = db_query("SELECT uid FROM {users} WHERE name = :name", array(':name' => $matches[1]))->fetchField();
if ($uid) {
$path = "user/$uid" . $matches[2];
}
}
}
This code works if usernames are unique, on your site. This is what normally happens on Drupal sites, where the username is forced to be unique; if a user tried to create an account using a username that already exist, he will get an error message.
The first hook rewrite paths such as "user/100" in "user/username," and the other hook make the inverse operation. This is necessary because Drupal expects user paths in the format "user/userid" and it would not be able to handle a user path containing the username (except when you are using a path alias).
As you are said you don't like that people can know how many users your site has, there is an easier way to avoid that. The fact people know that 123 is a valid user ID, though, doesn't mean they know how many users are registered in your site: You could have 1,000 users, 140,000 users. They just know that you could have 123 users, but if you have blocked users in your site, then some of the user IDs are not usable.
Create a user account that will never be used to log in, and create content on your site.
Editing the "users" database table increase the user ID of the account you created. Supposing that its user ID is 146, increase that number of 100.
Now, the next user that will register on your site will have a user ID equal to 247.
Increase the user ID of the dummy account you created incrementing the higher user ID.
In this way, if somebody notice that there is a user account with ID equal to 247, he will wrongly suppose you have 247 users.

What I did after all, was to create a hook_user_insert and to add 2 URL aliases in the urlalias table:
user/$user->uid/edit -> user/$user->name/edit
and
user/$user->uid/edit/profile -> user/$user->name/edit/profile
Hope this helps somebody.

Related

How to remove user id on url drupal 9

http://localhost/drupal-9.3.3/user/372#myaccount
How to remove user id on URL . Please suggest how to change these type security isssue.
If you want to change the url structure to remove ids, use pathauto https://www.drupal.org/project/pathauto
You can choose to have an url structure for user profiles that can be generated from any user field.
Someone told me that everything you write on the front end or in your main folder is always just basically a suggestion a.k.a. not secure.
Good ways to secure site:
Authenticate users using backend like firebase read/write permissions
Use randomized urls / keys (which firebase also does)
Also catch exceptions and deal with them, perferably at the the place where that function is created, not when it is executed:
Example
yes:
function() => {
// do something
//catch error
}
function(); // call function;
No:
function().then(error => { //do something})

Two wordpress database with same users

I want to have the same WordPress users in two different databases
For example, if a user registers on SiteA, then he can login to SiteB. And reverse.
Also i want create same cookie for both after login.
mywebsite.com/ (SiteA_DB)
mywebsite.com/blog/ (SiteB_DB)
I've never done this before and maybe Wordpress has hooks to archive this, but I prefer using mysql for such a trick.
You could try ..
.. using 'federated storage' ( https://stackoverflow.com/a/24532395/10362812 )This is my favorite, because you don't even have to share a database or even the mysql serverThe downside is, that it doesn't work with db cache and uses an additional connection.
.. creating a 'view' ( https://stackoverflow.com/a/1890165/10362812 )This should be possible when using the database-name in the query itself and it would be the simplest solution if it works. Downside: The 2 tables have to share the same mysql-server and have to be assigned to the same user as far as I know.
-- **Backup your database before trying!** --
DROP TABLE `second_database`.`wp_users`;
DROP TABLE `second_database`.`wp_usermeta`;
CREATE VIEW `second_database`.`wp_users` AS SELECT * FROM `first_database`.`wp_users`;
CREATE VIEW `second_database`.`wp_usermeta` AS SELECT * FROM `first_database`.`wp_usermeta`;
This should work, according to: Creating view across different databases
.. creating a 'shadow copy' ( https://stackoverflow.com/a/1890166/10362812 )Works with caching and is a standalone tableDownsides as 2. solution + a bit of setup and I think it might be the worst option in performance
This were answers to this question: How do I create a table alias in MySQL
I merged them together for you and made them fit your use-case.
Please also notice, that solution 1 and 2 will replace your current user-tables auf "second_database" because you write directly into "first_database" when querying the fed. storage or the view. This can lead to problems with user-role plugins. You should take care of syncing the plugin-options too, if you should use one of them and in case it uses different tables or 'wp_options' values.
Let me know if this works, I have to do a similar task next week. While researching I found the linked answers.
EDIT: I was missing the point of "cookie-sharing" in my answer. Your example shows a blog on the same domain - you should be able to change the way wordpress sets its cookies to be domain-wide. What I did once for 2 different domains was, that I hooked into the backend (is_admin) and added a javascript which did a post-request to siteB, receiving a token which is stored but marked as 'invalid' on siteB. This token then was passed back to my plugin on siteA which checked if the user is logged_in and (in my case) have adminrights (current_user_can()) and if so, it was sending this token back to sideB which was marking this token as valid to login. (Make sure only sideA can tell sideB to make this token valid!) Once a user is seen with this token in a cookie on siteB, the user is logged-in automatically in the background. Also I made this bidirectional. I am sorry, that I can't share the code for you. I don't have access to it anymore.
Greetings, Eric!

How do you have managed a status of contents in Symfony2

How do you have created a status of blog, micropost and etc?
I simply have created a status which each application entity has a status code of boolean.
False is private, true is public.
It is a multi-user environment in fosuserbundle.
It was created without any problems until now.
However, I wanted to be able to set user, group, and other status set in a multi-user environment.
(like a linux permissions, 744, etc...)
So, I think that it might create a bundle that manages the status.
The comment bundle that I have created is relation each application bundle by the ID of the string.
{{ render(controller('MyCommentBundle:Default:embed', {
'id' : 'for_example_micropost_' ~ micropost.id, // => relation id
'name' : micropost.owner.username,
'request': app.request
})) }}
However, it can not use when viewing list of application contents.
(Because the query occurs in one by one)
For example, either simply relationship by creating a column for each application.
Status Entity
blog_id
micropost_id
picture_id
etc...
But I think it inconvenient.
It require care of additional column when generated for each new application.
And I feel it is not a smart also.
For example, do so in the list part. Conditions of the string if possible in DQL.
public function find_all($owner, $limit, $offset)
{
$q = $this->getEntityManager()->createQuery('
SELECT p FROM MyMicropostBundle:Post p
LEFT JOIN MyStatusBundle s
With s.relation_id = :prefix + p.id
WHERE s.code > 744
')
->setParameter("prefix", 'for_example_micropost_')
->setParameter("owner", $owner)
->setMaxResults($limit)
->setFirstResult($offset);
return $q->getResult();
}
Etc., various I think, but I do not know the best way.
How do you have created a status?
Do you know status bundle already?
Or do you know bundle may be relevant to me.
If there is an optimal way and ideas, please tell me.
StatusBundle process:
It check a access user first.
It check a status code and groups and owner associated with the contents.
It compare a status code, groups and owner of the content to a access user.
I think it is possible to create (relation) bundle within a single page in my skills.
However, problem is how to relations at such a list display page that query to get the contents of the large number.
For example, I get the data of the last 10 blog posts.
I get the last 10 of public status posts if a access user is not the owner.
It is easy if Post entity has a status.
However, I think how to check a status, groups and owner if a status of a post has been registered in the status entity of other bundle.
I think that how to handle the status bundle while I get the data of the contents of the large number.

Avoid "user cross access" in Symfony

I am currently working on a project based on Symfony 1.4. I am using the sfDoctrineGuardPlugin to authenticate my two kinds of users : users and admins. For each module and each action in a module, I am using credentials to prevent unauthorized actions execution.
But I am facing a problem : if an user wants to edit a project, for example, the URL will look like frontend.php/project/edit/id/1. Here, we suppose that the project #1 belongs to him. Now, let's suppose that project #2 does not belong to him. If he types the URL frontend.php/project/edit/id/2, he will have access to the edit form, and will be able to edit a project that does not belong to him.
How can I prevent that behaviour ?
I would like to avoid verifying the ownership of each editable model before displaying the edit form... But can I do differently ?
Do you have any good practice or advices to prevent this behaviour ?
Thanks a lot !
Since you will have to check in the projet to know if the current user is allowed to edit the project, I don't think you will have other way than verifying before the edit, in the action part. Why don't you want to do it this way?
This check can be done inside the preExcute function:
public function preExecute()
{
$request = $this->getRequest()
if ($request->hasParameter('id'))
{
$project = Doctrine_Core::getTable('Project')->find($request->getParameter('id'));
$user_id = $this->getUser()->getGuardUser()->getId();
$this->forward404If(
$project->getUserId() !== $user_id,
'User #'.$user_id.' is not allowed to edit project #'.$project->getId()
);
}
}

Drupal module to control user post frequency?

We've been having a new type of spam-bot this week at PortableApps.com which posts at a rate of about 10 comments a minute and doesn't seem to stop - at least the first hour or so (we've always stopped it within that time so far). We've had them about a dozen times in the last week - sometimes stopping it at 50 or 60, sometimes up to 250 or 300. We're working to stop it and other spam bots as much as possible, but at the moment it's still a real pest.
I was wondering whether in the mean time whether there's any sort of module to control the frequency a user can post at to e.g. 50 an hour or something like 10 in an hour for new users. That at least would mean that instead of having to clear up 300 comments 50 at a time in admin/content/comment we'd have a smaller number to clear. (A module to add a page to delete all content by a user and block them would also be helpful!)
I believe that there's a plugin to do this available for WordPress, but can't find any such thing for Drupal.
For your second question, i would have a look at the code of the User Delete module (click).
The module also disables the user account and unpublished all nodes/comments from a certain user. By extending the code, you could easily create another possibility to unpublish + delete all nodes/comments from a certain user and blocking the account.
After the unpublish code in the module, you should just put delete code (in sql if the module is selecting by a sql-query or by using the drupal delete functions).
Another option would be so make a view (using the view module) only to be viewed by administrators, where you choose a certain user using the filters and then lists his/her posts. Then in the node-contenttype.tpl.php you place a button that calls a function which deletes all nodes/comments and the user.
First problem (post frequency)
I've been thinking about the comment post limit. If I remember correctly Drupal stores comments in a seperate table and has comment specific functions.
I'd create a new module and using the comment_nodeapi function i would check in the operation 'insert' how much comments the current user has already made within a certain timeframe.
To check this I would write a custom sql query on the database which takes the count of alle comments made by uid where the post_date is larger then NOW-1hour. If that count is larger then 10 or 15 or whatever post frequency you want then you give a message back to the user. You can retrieve the user id and name by using the global $user variable.
(example: print $user->name;)
You have to check on your own for the sql query but here's some code when you have the amount:
<?php
function comment_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'insert':
//PLACE HERE THE SQL TO GET THE COUNT
if($count > 15){
$repeat = FALSE;
$type = 'status'
drupal_set_message("You have reached the comment limit for this time.", $type, $repeat);
break;
}else{
db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->changed, $node->uid);
break;
}
}
}
?>
(this code has not been tested so no guarantees, but this should put you on the right track)
I would suggest something like Mollom (from the creator of Drupal). It scans the message for known spam pattern/keywords/... and if this scan fails, it displays a CAPTCHA to the user to make sure that it's a real human that wants to enter content that has the same properties like spam.
They offer a free service and some paid solutions. We are using it for some customers and it's worth the money. It also integrates very well in Drupal.
Comment Limit is probably what you need.
http://drupal.org/project/spam
http://drupal.org/project/antispam - with akismet support

Resources