How to store users action (finished queries) in a table? - php

So this is my situation:
I have an admin user, that can add,delete and edit other users. I'm looking for an a solution how to record the admins action. Should i compare the table, that is affected before and after the query is done and how can i store the difference in another table?
This is the table that would be afected:
TABLE `t_user` (
`user_id` int(11) NOT NULL,
`username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`password` char(32) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`reg_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`active` tinyint(1) NOT NULL,
`current_desk_book` int(11) NOT NULL,
`last_login` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Lets say the admin tries to delete a user with id=3, the query would be
"DELETE FROM t_user WHERE user_id= 3"
These are the deleted user data:
(3, 'user3', 'fa6daddc77ac9b5ee42ffd31e7d6e014', 'user3#mail.bg', '2016-09-08 11:29:38', 1, 1, NULL)
Im looking to store "Deleted " + the deleted users data in another table.

Two ways :
Simple solution, better have a flag as "deleted" and mark it to "1" admin deletes it. This is soft delete method.
Hard Delete: Create a log table similar to base users table.
Have a trigger, when delete happens. store it into another table.
CREATE TRIGGER log_user_delete AFTER DELETE on users
FOR EACH ROW
BEGIN
INSERT INTO users_log (user_id, username, etc, deletedby_newfield, deletedtime_newfield) values (old.user_id, old.username, '1', NOW());
END

Why you want to store it in database? any specific requirement. Generally people store these kind of information in logs (file). I will suggest that along with deleted use data you should also store the query he has executed that will help you to track things in a better way.
To store the different you can try something like this - whenever he executes a command with where clause you do a select statement with that clause and store it in logs and repeat again after his command execution finishes except in delete case.

Related

How can mysql not handle two insert request called at same time?

I have created rest api in php (slim framework with mysql as database) for keeping records of multiple android app's users, So when our app is opened by user it calls register api and sends parameters to trigger insert or update operation
Here's structure for users table
CREATE TABLE IF NOT EXISTS `users` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`app_code` varchar(255) NOT NULL,
`api_key` varchar(255) NOT NULL,
`device_id` varchar(100) NOT NULL,
`device_token` varchar(255) NOT NULL,
`device_model` varchar(50) NOT NULL,
`device_name` varchar(50) NOT NULL,
`device_memory` varchar(50) NOT NULL,
`device_os` varchar(100) NOT NULL,
`last_access` int(14) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2130346 ;
before inserting record api checks if user already present in users table using two parameters app_code & device_id
If its present then just update user's last_access(and device_token if its different than previous one) fields and return flag:2(user already exist)
update query looks like this
UPDATE users SET device_token='asadiwp0qidkqwdpkpka2',last_access='1498912512' WHERE id = '2132079'
and if user is not present return flag:1(new user).
mysql insert query looks like this
"INSERT INTO users(app_code, api_key, device_id, device_token,device_model, device_name, device_memory, device_os, last_access) values('YEVZ6I', 'b005e8a2babe0163a8eb4bfb2fe87b78', '66BBEG13B5F2G3EG', 'asadiwp0qidkqwdpkpka','Moto E3', 'Motorola E3 Power', '2GB', 'M', '1498912256')"
Where mendatory parameters are "app_code, api_key, device_id, device_token".
Now problem is that currently i am getting register request two times from same device at the same time same second, So mysql insert statement is being called twice at the same time and same user record is inserted twice as a new user, it duplicates record.

Build a Matrix style Grid of User Permission Setting with PHP and MySQL

I've been tasked with adding in a link/menu dashboard for my work. It needs to have user permissions to view/not view each link record on a per user basis.
Most time this is done with user groups, I need to do it per-user for per-link.
I have started by using a middle database table to join users and links as well as hold the user permission if they are allowed to view each link. I will show the Database design below.
What I need help with is build a table/grid to mass set permissions for each user on each menu link.
I would like to do it similar to this image below...
View full size image
So I need to pull in users from the database and the links from the database as well as the permission records.
Build a grid with users in the vertical column and links in the horizontal.
The permissions setting will then fill in the grid spaces and I think it would be best to have a simple Form Selection field for a yes/no value.
Admin can change permissions for each user and submit the form which will need to then update every Permission record!
Here is what my 3 demo database tables look like...
Links table
CREATE TABLE IF NOT EXISTS `links` (
`id` int(11) NOT NULL,
`parent` int(11) NOT NULL DEFAULT '0',
`sort` int(11) NOT NULL DEFAULT '0',
`text` char(32) COLLATE utf8_bin NOT NULL,
`link` text COLLATE utf8_bin NOT NULL,
`permission` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
User table
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL DEFAULT '0',
`name` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT 'user',
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
**Permission table: user_link_permissions **
CREATE TABLE IF NOT EXISTS `user_link_permissions` (
`id` int(100) NOT NULL,
`user_id` int(30) NOT NULL,
`link_id` int(30) NOT NULL,
`permission` int(2) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=latin1;
Where I need some help...
I am not sure how to best generate the Grid of Users, Links, and Permissions.
As well as how submitting all that data could be processed in the backend to save all settings.
I will post more progress as it comes but right now I could use some direction please?
I realize i'll need to query and get all users as well as all links and then all user_link_permissions but I am at a loss as to how to create this grid and make it all correspond with the correct values, etc.
UPDATE:
I just found this link which seems to do something similar which looks like a good reference. It even saves the grid value with AJAX which should simplify things and load I believe. http://runastartup.com/how-to-update-a-mysql-field-in-a-multi-table-matrix/

Different user roles for logging in with PHP and Mysql

I have a project coming up for doing Admin functions so my question is this. I will try and be clear as possible.
I will have one SUPER-USER who updates all information for other regular-users/people(being our clients).
The clients/regular-users when they log in will only see their info and download files uploaded by SUPER-USER and not see for regular-users.
So if you are Client:#01 you will see the dashboard (welcome page) and your info. Can anyone suggest possible database designs for this.
How to use left/right sql-joins between the user and files table?
UPDATE
I have a users table as well as a company table that the user belongs to. So essentially I want something like this::
$sql = select everything in the users table where the username and pass = to the given form, then left or right join that username to the company that he belong to.
Then they will see their information. if logged in successfully. Because user #01 belongs to company #03 /#01 etc...
USER TABLE looks so
`id` int(11) NOT NULL AUTO_INCREMENT,
`fname` varchar(50) NOT NULL,
'lname` varchar(100) NOT NULL,
`username` varchar(50) ,
`password` varchar(100) ,
`company` varchar(50) // the company name that ther user belongs to
PRIMARY KEY (`id`)
COMPANY table
'id' int(11) not null auto_increment,
'user_id' int(11) //This is to tie the users to this table
'description' varchar(text),
'filename' varchar(25) not null,
'mimetype' varchar (25) not null
PRIMARY KEY ('id')
Well, it depends on how simple or complex you want to go. with something like this I usually will keep it relatively simple and have a main user database (for all users) example:
CREATE TABLE IF NOT EXISTS `user` (
`user_id` int(255) NOT NULL AUTO_INCREMENT,
`user_name` varchar(50) NOT NULL,
`user_pass` varchar(100) NOT NULL,
`user_permissions` tinyint(1) NOT NULL DEFAULT '0',
`active` tinyint(1) NOT NULL DEFAULT '1',
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MYISAM;
Then I would have possible a second table of permissions depending on how many permissions I was going to have. If all you are going to have is users and super users then you could probably just assign users a value of 0 and then super user a value of 1.
Then in your PHP script it would treat the users different based on their "user_permissions" value.
Now if you are intending to have lots of different levels of permissions then I would definitely create at least one more table to define permissions example:
CREATE TABLE IF NOT EXISTS `permission` (
`permission_id` int(255) NOT NULL AUTO_INCREMENT,
`permission_name` varchar(100) NOT NULL,
`permission_value` int(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MYISAM;
Then in the permissions table you could assign all sorts of different permissions... read, write, publish, admin, regular user, super user etc.
This is just a very simple starting point. hope that helps.

MySQL + PHP: select multiple rows on a join, then update those rows/insert new ones

I want to do the following:
Select multiple rows on an INNER JOIN between two tables.
Using the primary keys of the returned rows, either:
Update those rows, or
Insert rows into a different table with the returned primary key as a foreign key.
In PHP, echo the results of step #1 out, ideally with results of #2 included (to be consumed by a client).
I've written the join, but not much else. I tried using a user-defined variable to store the primary keys from step #1 to use in step #2, but as I understand it user-defined variables are single-valued, and my SELECT can return multiple rows. Is there a way to do this in a single MySQL transaction? If not, is there a way to do this with some modicum of efficiency?
Update: Here are the schemas of the tables I'm concerned with (names changed, 'natch):
CREATE TABLE IF NOT EXISTS `widgets` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`author` varchar(75) COLLATE utf8_unicode_ci NOT NULL,
`text` varchar(500) COLLATE utf8_unicode_ci NOT NULL,
`created` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` timestamp
NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `downloads` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`widget_id` int(11) unsigned NOT NULL,
`lat` float NOT NULL,
`lon` float NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
I'm currently doing a join to get all widgets paired with their downloads. Assuming $author and $batchSize are php vars:
SELECT w.id, w.author, w.text, w.created, d.lat, d.lon, d.date
FROM widgets AS w
INNER JOIN downloads AS d
ON w.id = d.widget_id
WHERE w.author NOT LIKE '$author'
ORDER BY w.updated ASC
LIMIT $batchSize;
Ideally my query would get a bunch of widgets, update their updated field OR insert a new download referencing that widget (I'd love to see answers for both approaches, haven't decided on one yet), and then allow the joined widgets and downloads to be echoed. Bonus points if the new inserted download or updated widgets are included in the echo.
Since you asked if you can do this in a single Mysql transaction I'll mention cursors. Cursors will allow you to do a select and loop through each row and do the insert or anything else you want all within the db. So you could create a stored procedure that does all the logic behind the scenes that you can call via php.
Based on your update I wanted to mention that you can have the stored procedure return the new recordset or an I'd, anything you want. For more info on creating stored procedures that return a recordset with php you can check out this post: http://www.joeyrivera.com/2009/using-mysql-stored-procedure-inout-and-recordset-w-php/

CakePHP: findById returning incorrect row?

PHP version: 5.2.17
CakePHP version: 1.3.11
MySQL version: 5.5.9
I'm working on a very simple internal message board website for a client. Since it's for internal use only, the client requested that rather than having usernames and passwords, there is just a password. No usernames. There is one password for the administrator and another password for everybody else.
Here is the database structure:
CREATE TABLE `messages` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`date` date DEFAULT NULL,
`time` time DEFAULT NULL,
`from` varchar(255) DEFAULT NULL,
`to` varchar(255) DEFAULT NULL,
`subject` varchar(255) DEFAULT NULL,
`regards` varchar(255) DEFAULT NULL,
`memo` text,
`deleted` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `date` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=28 ;
CREATE TABLE `passwords` (
`id` tinyint(1) unsigned NOT NULL AUTO_INCREMENT,
`password` varchar(40) NOT NULL,
`is_admin_password` char(1) DEFAULT 'N',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
This is my "User" model:
class User extends AppModel {
var $name = 'User';
var $useTable = 'passwords';
}
I'm working on the "Change Password" portion of the website now, which is only accessible to the administrator. The form has a dropdown menu where they choose which password they're changing and then they have to type in the current password, new password, and confirm the new password.
Once the administrator submits the "Change Password" form, the controller checks which password they are changing and then looks up that password in the database to verify that they typed in the correct current password. This is the code that looks up the password:
$this->User->findById($this->data['User']['id'])
For some reason, this is the SQL generated by CakePHP no matter what the $this->data['User']['id'] variable is set to (as long as it's a string):
SELECT `User`.`id`, `User`.`password`, `User`.`is_admin_password` FROM `passwords` AS `User` WHERE `User`.`id` = 1 LIMIT 1
Why is it always looking up ID 1 even when I tell it to look up ID 2? I've also tried changing the "findById" to a regular "find" and that didn't change anything. It seems to only be when I use the "id" field as the condition. Why is this happening?
Your passwords table has its id field defined as tinyint(1) i.e. it can only ever be 0 or 1. CakePHP is doing the right thing.
A bit off topic, but what would happen if one day your client asks you to have a third type of role, meaning not administrator and not what you call today 'everyone else' ? With your database structure it would be difficult to do that.
Personaly I would start with a standard users datatable (i.e. with a username), and well, ok, if you are asked to never display it, well, never display it in the view, but this would be really much more evolutive because the database would be ready for more functionnalities.
And by the way, the fact that you called the model for the 'passwords' datatable 'User' makes me think that your are not far from thinking the same ;-)
Just my two cents...

Categories