Best Practices: Creating a simple CRUD web application with users/roles - php

After searching online a good amount, I couldn't find anything that was exactly what I was looking for or that outlined how to create a web application with users. The closest thing I could find was this stackoverflow post, which outlined how to create a web application with users/roles on a SQL server.
I also found a couple alternatives from this post.
Create a simple relational database
make a 'meta-table'
I'm creating a web application on CodeIgniter that is a wine management tool, similar to CellarTracker. Each user has their own 'cellar', or collection of wines that they can perform the CRUD operations on. What would be a conventional way to make this. How should I structure the database? Are there any CI Libraries that would make User-management, roles, permissions, etc. easier?
(I have already found that TankAuth seems like its the best authentication library).
Here's how I would structure (part of) the database:
**users_table**
id
email
password
**wines_table**
id
user_id
My plan is to have each bottle of wine have a user's id associated with it. I doubt that this is the most secure or efficient way to handle a CRUD web application with many users though.
I have experience with the CRUD operations, but am not sure how I can connect them with a user-management system.

consider having a completely separate table just for wines that is not associated with users.
this table has wine parents and children. the parent contains fields for the winery, the name of the wine, location, etc. the children would be the specific years of the vintage.
so a user enters a wine name in his tracker. the system looks it up - if its not found then the user creates the record. system creates a parent record and a separate child record with the year.
if the wine is found - then the user can update the parent record, and either chose a year, or enter a new one.
system would then add a record to a separate table - users_wines - with the id of the parent (the wine) and the id of the child (the specific year)
this opens up many different possibilities including having wine lists that are shared by groups of users.
you also can easily change the relationship of the user and his wine bottle - because they are separate. the user can change status on users_wines - wine in cellar, drinking the wine, empty wine bottle - and this does not affect the record for the wine itself.
====
Edit - yeah mentioning the wine.com api would have been good info. that gets into much larger questions. suggest that you first define what your users are able to do. My first question is - what if a user does not like the name coming back from wine.com? and what if there is an actual mistake in the api? are you going to customer service a wrong wine name coming back from the api?
Or - Can a user rename a wine in their list? if they can then the data relationship with wine.com is going to be very different.
personally i would think it would be annoying to try and create a wine list, but you cant edit the names. it seems like thats removing too much control from the user.
however if this is an app for restaurants that need accountability - then having the wine name be unchangeable could be considered a feature.
so spend some time with your user roles and user stories. then let that inform the data relationships.

Related

How to properly extend a database model with PHP

I know that the title of this question is not intuitive, but let's go to the question.
I've designed a "core system" for all my backend web apps (control panels, systems to manage clientes, balances, etc). This "core" is the start point for developing new modules according to the new system specific needs, but I always keep the "core modules":
Users (to manage user roles)
User type (in distinct systems there are distinct kinds of users, so it's nice to manage them dinamicly)
Modules (to create new modules and add permissions to them)
Dashboard
My main question is for the User module. Since it has the default columns
UserId; Name; Login; e-Mail; Password; isRoot; isPowerUser; UserTypeId
I want to create new control panels and apps, but dont want to change this table to keep the "core" updatable with an easy process in the future. My ideia of design is to create table named User_Extra which will contai all the extra columns for this specific user.
Is this a good approach? I'll also will create a new class named UserExtra.class.php.
If u want to take a look at the project to get the ideia: https://bitbucket.org/alexandrekop/akop-core
Imagine looking at your database schema, and seeing a table named "user_extra" with a bunch of fields that aren't related to each other in any way and each field is related to a different module, does it feel 'right'?
My suggestion is to split the extra fields into relevant tables, possibly per module, or per logical group.
For example, if one module was related to addresses, you would have a table "user_addresses", with things only specific to the address of the user.

Many to Many Relationships in Mongo

Hey,
I've got a bit of a problem right now trying to figure out how to resolve a specific many to many model in Mongo.
I have an event scheduling system for the CRM I am building that allows events to be assigned to both users and teams. These events are particular to each lead.
So for example, I have a call at 5:00pm Thursday with Jimmy Dolittle. My sales team also has a call Thursday at 7:00am with Bob Jones.
If this were SQL, I would just create a leads table, events table, users table, and teams table. I was thinking about putting the events in the users collection and in the teams collection but then the problem arises when I have a list of leads and want to display the callback date next to each lead. Referencing like that in Mongo is going to be sloooow with a list of 500 leads.
I was also thinking about storing the events in the leads collection, but that would mean I would have to do the same sort of search for leads with events assigned to a particular user or team (there might be 500,000 leads in the database but only 500 have events for a particular user.
This kind of relationship is just going to be a problem in Mongo. In that situation, I would probably write a function for connecting those objects at the application level. Whenever a connection is made, save the relationship in both objects. Then you can search either direction with ease. You'll have redundant data and that causes a risk of getting them out of sync, but that's the price you have to pay with a non-relational structure. Your updates won't be as fast since you'll have to update two docs, but your selects should be speedy.
As Tim Suggests a good idea would be to solve this at the app level.
What i'd do here is create a new collection 'Events' then store an array of _id's of related events inside the user and team objects from here it will be super fast to do a look up. It may mean a lot more queries but queries on the _id field alone are highly optimised and not very resource intensive (unless you have millions of events per user) so if a team has the app up they can see their events and if a user has theirs up they can see their events.
Also i recommend storing back links to the user and team _id's in the event object. Yes this is redundant data but its only a reference and if managed properly at the app level should keep the schema nice and tidy.
Best of Luck.

Proper way to design an inventory system

I am a pretty good programmer but I am not great when it comes to designing system architectures. I have a pretty simple inventory system I am making however I would like to know a good way to structure it.
I have around 20 pieces of equipment that users can [View All | Update | Delete | Add] each of them. However I have different access levels for different equipment (which needs to be dynamic, change who can view or delete what).
For example, one piece of equipment would have?
addPart1.php
removePart1.php
updatePart1.php
index.php (view all parts)
addPart2.php
removePart2.php
updatePart2.php
index.php (view all parts)
For all parts? Im confused on trying to design a good, scalable and efficient structure.
An access control list (ACL) is a list of permissions attached to an object. An ACL specifies which users or system processes are granted access to objects, as well as what operations are allowed to be performed on given objects. In a typical ACL, each entry in the list specifies a subject and an operation (e.g. the entry (Alice, delete) on the ACL for file WXY gives Alice permission to access file WXY).
Source: WIKI
Please take a look at:
http://dev.juokaz.com/php/acl-made-easy-part-1 (tutorial on ACL)
http://sourceforge.net/projects/tackle/
You could categorize your products table, so each kind of equipment has its own "category" or "group". You can do that by assigning a "group_id" to each product (on a new column on your table). If you have 300 products, some of them will be on group 1, others on group 2, etc.
Then, on your users table (the one that contains usernames/password for each admin), you need to add an additional field called "group_permissions". On that field you have to store a list of "group ids" each user can view. You can store those permissions separated by comma.
$permissions = '1,2,5,9';
Each time a user access one of your PHP files, you get its permissions and do a simple check like this:
SELECT * FROM products WHERE group_id IN($permissions)
That will only return the products that user has permissions to edit or view. This will vary depending of your interface.

Flexible forms and supporting database structure

I have been tasked with creating an application that allows administrators to alter the content of the user input form (i.e. add arbitrary fields) - the contents of which get stored in a database. Think Modx/Wordpress/Expression Engine template variables.
The approach I've been looking at is implementing concrete tables where the specification is consistent (i.e. user profiles, user content etc) and some generic field data tables (i.e. text, boolean) to store non-specific values. Forms (and model fields) would be generated by first querying the tables and retrieving the relevant columns - although I've yet to think about how I would setup validation.
I've taken a look at this problem, and it seems to be indicating an EAV type approach - which, from my brief research - looks like it could be a greater burden than the blessings it's flexibility would bring.
I've read a couple of posts here, however, which suggest this is a dangerous route:
How to design a generic database whose layout may change over time?
Dynamic Database Schema
I'd appreciate some advice on this matter if anyone has some to give
regards
SWK
I created a very large EVA database years ago (PHP w/ PostgreSQL). It turned out great, but it was large project ($$$). All the forms were completely dynamic, with form/field versioning, publishing workflows, matching dynamic reporting, etc.
EVA basics are easy enough. Getting data in is not the hard part. But form versioning and reporting....you can spend years getting it right.
If I was doing it again today, I would research using one of the newer NoSQL solutions ( http://en.wikipedia.org/wiki/NoSQL#Document_store ). I'd thing about creating a DTO style class that could be passed to a form generator. "Modifying" the form, would actually be modifying the DTO. Then I would persist that DTO into a document/object database.
Also, as you are building your alpha solution, think of how to solve test cases that encompass versioning and reporting needs.
Here is an example of what I mean: A simple "Ask Question form".
Original (version 1): has First,Last,Question
Add email field(Version 2): First,Last,Email,Question
Somebody changes their mind about email: (version 3): First,Last,Question
New marketing guy comes in and changes it: (version 4): Full Name,Email,Question
Now, you need to generate a report (csv). Things get tricky. How do you do it?
We solved this problem with field level versioning with references to their previous versions. Plus the reporting system required the end user to assemble the definition of the report data sources before running. (binding report fields to data fields, etc).
However with the document DB's I'd imagine you can do it differently. I believe the new DB's like CouchDB (others??) have mechanism built in for handling these issues.
Good luck!!
When developing user profiles in my last webapp, I've chosen Key/Value table approach. Here's how my DB design looks:
Users table with fixed columns:
id
login
name
regdate
Users table linked with Profiles table (User HasMany Profile).
Profiles table with different data:
user_id
field
value
This way user can add any additional field to his profile. For example:
user_id = 1
field = 'Facebook'
value = 'http://facebook.com/...'
and
user_id = 1
field = 'Stackoverflow'
value = 'http://stackoverflow.com/user/...'
and so on..
Depending on your needs, it might not be worth even raising the form fields to the "DB fields" level. You could instead serialize these fields in (what is essentially a) dynamic blob and store it in the DB. This is NOT recommended if you have folks who need to query these dynamic fields outside of your app (i.e., the DB design is part of a larger public contract with integrated systems), but if you're just using the app to simply to persist these dynamic fields or if any aggregation/search capabilities within the fields are minor, then I would consider it (esp given CPU capabilities these days). I have used the pattern many times and I have - thus far - never had to refactor. (however, I can understand a case where you might need to).

Access control for multiple users in a web application

I'am working on a PHP + MySQL Social Networking application, now i need to setup different access control (read,create,edit,delete) for global (all items) and/or self items (item which created by themselves) for each module to group or specific user.
Does anyone has suggestions in doing this (table structures, etc)?
okay here i provide more detail, currently i have a tbl_module, tbl_user, and tbl_user_role. Each user and role can have different access to specific module.
read
update
create
delete
and devided by global access or self only (own account or records created by themselves).
and my current approach: i create another table to hold the access detail:
acl_uid
mod_id (fk module uid)
target_id (fk user uid or role uid)
acl_type (user/role to identify the target id reference)
acl_read
acl_update
acl_create
acl_delete
acl_read, acl_update, acl_create, acl_delete value ranges:
0 deny
1 allow
2 refer to lower priority check (if user has value 2 then refer to role)
3 self only
i believe that theres more efficient way to solve this, or may an improvement to my current approach.
thanks for your responses.
That's a pretty broad question, so you're likely to only get very broad answers.
Most CMS systems have a table that lists the types of content that can be produced on the system.
Another table describes how each type of content is displayed (on the front page, on individual blog pages, etc).
Another table gives each user one or more "user types" or "groups" such as admin, unregistered, moderator, etc.
A last table is an access table of sorts - it shows what each group has power to do, including the types of content it can create, edit, publish, etc.
I recommend you spend a little time studying the database schemas of other CMS software, such as Slashcode, Drupal, or one of the other millions of CMS systems.
-Adam
It is in fact a very broad question. Assuming you have a clear separation of application tiers (eg, using MVC), then this is the sort of stuff going in the business layer.
Taking your direct requirements, it could be fairly simple. In your users table, have a hasEdit, hasView, etc. For each item, attach a userid to it representing the creator. In the business layer, the rule is they have edit permission if they are the creator, or they have hasEdit = true.
Taking it up a notch, if you have different types, and the hasEdit permission is per-type, you need another entity for that.
userPermission
userPermissionId
userId (FK)
typeId (FK)
hasEdit (boolean)
hasView
etc..
To find out if they have permission to edit, you check if either they're the owner, or look up that items type and the current user in the userPermission table, and check hasEdit. You could make additional rules, like putting a global hasEdit in the user table. Or representing global hasEdit by an entry in userPermissionId with a NULL typeId.
This can get way more complex, using roles and variable numbers of permissions.. it all comes down to your requirements. You need to carefully spec out your business requirements (come up with a bunch of use cases), and then you can design from there. As is, there's really not enough information to come up with anymore than I've outlined here (and even this is probably not exactly what you need).
I like to use a kind of firewall rules approach or similarly a mysql tables rules approach: you can grant users or groups of users certain rights on certain objects or groups of objects. Make each rule be a row in your rules table. When you need to do an action like edit, you can inner join on your rules table for the current user, current user's group, the boolean edit column and the object id or object group. If you get any rows back then the permission is granted.
There are quite a few ways of designing security, and I've liked quite a few for different situations. There's UNIX-style user-group-other. I happen to like PmWiki's security model.
I developed a website which used user-role-permissions structure similar to Apache. With that website, I used a template system that used a header include file and a footer include file to wrap the page contents with the "standard stuff". A page with restricted content could set a variable to the required permission, that the header script looks for, and if set, calls an auth function that checks the user belongs to a role that permission.
The nice thing about using the user-role-permissions model is if most of your users fall into neat categories of authorization, setting the authorization for a user is a simple matter of adding the right role to that user. The permissions are linked to roles, not users directly, so you can adjust the permissions of entire classes of users easily.

Categories