Elegant Web Permission Schemes - permissions

I'm currently writing a web application that have about 6-12 pages. On each one of these pages, I want the user to be able to do some (or all) of the following actions: View, Add, Update, and Delete.
The current permission scheme I thought of is having an integer in a database. This integer will correspond to a binary number (e.g.: 26 -> 11010). The resulting binary number acts as a "toggle" and determines what permissions the user has. The definition of what bit represents what permission is stored in another table.
My problem is, if each page has 4 options (view, Add, Edit, Delete), then this way of determining permissions can get out of hand.
Does anyone have any other ideas for a permission scheme that would be as flexible (with respect to configurability) as this, but not as overwhelming (with respect to integer limits)?

Perhaps a better answer, if you really need to go this route, is to have a per-page/per-user row in your database, with a set of permissions, so your table looks like so:
page user create read update delete
===== ===== ====== ==== ====== ======
test.html joe y y y n
test2.html joe n y y n
Alternately, as is usually the case, you're better off having roles, like author, editor, reviewer, admin, and giving your roles the fined-grained permissions, and putting the users into roles.

I would suggest you do not resort to bits. Use separate columns in the DB for each category of permissions and use integers 1 and 0 to indicate whether that permission is granted or not. This would save you from bit manipulations and would be fast as well. The only downside will be a larger number of columns which, by your description, does not seem much of an issue.

Related

SQL Server: Avoid simultaneous updates increasing a column value over its target

I have a SQL Server table called AD where ad's to be viewed are stored as
create table Sponsors.AD
(
ADID varchar(40) primary key,
SponsorID varchar(30),
PurchasedViews int , --How many views the ad must reach before it is disabled
CurrentViewCount int, --Keeps track of how many views the ad has gotten
{...}
Active bit -- for easier checking of whether the AD still has clicks to give
)
This feeds into a webpage where, to access a feature, users first need to view an ad. Users can pick one ad from a menu that displays three options [they pick one, the ad's media is displayed and the feature is unlocked at the conclusion].
After they view the ad, its CurrentViewCount should be updated (increased by 1).
This is handled by a stored procedure that includes an update call for the table - separate from the stored procedure that fetches 3 ads at random for the option menu - but I'm looking for suggestions on how to solve the problem of synchronizing all concurrent AD views - as it could happen that
two or more users have the same ad in their 3-choice-menu
two or more users view the same ad at the same time
1 and 2 are not a problem on their own but they could be if the ad is one click away from it's set maximum.
One way I've thought to solve this is to set the active flag as false if the ad is one click away from it's target when it is displayed in the 3-option menu, and if the user does not click it, the flag will be reset to true -- but then I'd need to handle cases where the user exits the option dialogue or disconnects, times out, etc. I feel like there must be a better way.
Another suggestion I've heard is to automatically increase the counter when the ads are summoned to the 3-option menu but that's even more overhead than the other and suffers the same issues.
Locking the table is absolutely infeasible unless we wanted to only serve one ad view at a time - so I'm not even considering it.
I'm sure something like this has been discussed before but don't know what keywords/etc to search to find more on this.
I would not count the clicks within the same table... Could avoid your locking issues...
But, to get to your question: maybe you could handle this "fuzzy". Not the thight active=yes/no but rather something like an InactivityLevel together with a timeout.
As long as your flag would be true, everything is fine. If the counter exceeds, you switch to "No new visitors" and set a timestamp, so your add won't display in a new context. You set this to "inactive" after a given timeout.

Filtering user access based on tabled responses

I am building a "Survey" type application. The user answers a set of questions with pre-vetted answers.
Question: Where do you live?
Answers: England, Finland, Spain, France, Monrovia
The answers in this case would be in a DropDownList.
Once the user has completed the basic responses (location, age, sex etc) I would like to be able to prevent them accessing the rest of the survey based on their answers.
So for example, if they live anywhere but England I want to direct them to a page which says "Thanks, but Monrovian's can't complete this survey". I need my filtering to be user configurable (Table based) and I need to be able to have ANDs and ORs.
So one filter being the user MUST earn 100k+ a year.
Another being they must either live in Spain, or be female AND like model trains - "100k+ && (Spain || (Female && Trains))"
I would usually use Enums and bitmasking for this, but as my country list is 200+ items long, I can't think of a sensible way to store the filtering.
Hopefully I have made some sense and someone has a decent solution :)
I don't know if I can answer your question completely, but I'll try...
So, we have a bunch of Views that are only visible to the user if she previously chose some answers, like, she will see view#3 if she is older that 30, and view#4 if she is younger than 30 AND from China, and view#5 if she is older than 40 AND from Spain OR Italy, and so on...I want also to introduce the notion of **step**, and for each step we could have 1, 2, or more corresponding views. Each view should have a set of rules (like the ones above) that define if it is displayed or not.
How to create these rules? These rules could be simple instances of a Filter class/interface that, when asked, should return true/false. Like this:
interface Filter {
boolean apply();
}
Then you can create Filters like 'older than 30', 'from Spain', whatever. Remember that each view is configured with a set of rules (Filters) so it can answer yes/no if asked if it can display itself.
Next, how to apply these filters?
We could have a controller object that only knows about **steps** (each step can have one or more corresponding views, as I said), and, after the user pressed **next** at the current step, it should collect the answers and apply them against the rules attached to each view. Like, take the answers from step one, and apply them to all views from step two, and see which one matches (returns true). For example, at step two, you can have two separate views, one for young people, other for old people, and you apply the rules from each view to decide if you show the old or young view.
I could give you one code example, and you could also do research on your own, since I know nothing about your technical environment. I have used Google Guava's predicates on a similar problem and here it is: suppose we are dealing with Witch objects, and each of them has name(string), age(int) and spells(collection) attributes. If I have a list of witches and I need to sort them based on specific criteria, I can do:
// first I want to sort witches by age(natural ordering) then by spells,
// and then by name lexicographically
Ordering.natural()
.compound(new BySpellsWitchOrdering())
.compound(new ByNameWitchOrdering())
.sortedCopy(witchList);
The above line of code is going to take the witch list and return a list of sorted witches according to the criteria. Your situation is pretty similar.
Next, how to create the answers? For each view(page), you have possible answers, like, for view#1, you can have : age, sex, race, country. You can construct some answers, in the form of strings, ints, enums, and pass them to the controller, which in turn is going to apply them to each view corresponding to the next step.
As for how to store the rules in the database, as an example, you could have a column defining rule name (like, OLDER THAN) and one column for value, say, 30. Again, I do not know that much about your environment, and it is a really general issue, so I will stop here...

Invalid Login attempts in Perl

I am working on Login Form in perl. I wish to limit 3 times for invalid login attempts for 30 min. In which way shall I use. Give me some idea where to store the invalid login attempts.
You have a few different options:
Cookies - least secure, as different browsers, clearing cookies, etc. can all impact this. Not recommend but listed for completeness.
Database - if you are using a database then you can create a table that records every failed login attempt. Within this table login_attempts you record the following values: date, username. Then during any attempted login you (pseudo SQL) SELECT COUNT(*) FROM login_attempts WHERE username = '$the_user_name' AND date BETWEEN '$now' AND '$now-30m'. If the returned value is >= 3, deny the login. Make sure you create a clustered index on username and date descending. If you are concerned about space then you can have a job that runs nightly and removes any records with dates older than, say, 8 hours. (Though left in tact this serves as an audit log.)
File system - this option is so Byzantine I'm not going to go in-depth describing it, assuming you have some sort of database backing store already in place. If you have to go this route, then it looks like the database solution, above, without the SELECT statement and likely involves user names as directories with a file containing each login attempt and where the (mtime + 30m < now) will have to be true to permit a successful login. You'd need to make sure you have mtime enabled for the disk of course, or record the time within the file.

MySQL joins for friend feed

I'm currently logging all actions of users and want to display their actions for the people following them to see - kind of like Facebook does it for friends.
I'm logging all these actions in a table with the following structure:
id - PK
userid - id of the user whose action gets logged
actiondate - when the action happened
actiontypeid - id of the type of action (actiontypes stored in a different table - i.e. following other users, writing on people's profiles, creating new content, commenting on existing content, etc.)
objectid - id of the object they just created (i.e. comment id)
onobjectid - id of the object they did the action to (i.e. id of the content that they commented on)
Now the problem is there are several types of actions that get logged (actiontypeid).
What would be the best way of retrieving the data to display to the user?
The easiest way out would be gabbing the people the user follows dataset and then just go from there and grab all other info from the other tables (i.e. the names of the users the people you're following just started following, names of the user profiles they wrote on, etc.). This however would create a a huge amount of small queries and trips to the database in a while loop. Not a good idea.
I could use joins to retrieve everything in one massive data set, but how would I know where to grab the data from in just one query? - there's different types of actions that require me to look into several different tables to retrieve data, based on the actiontypeid...
i.e. To get User X is now following User Y I'd have to get my data (User Y's username) from the followers table, whereas User X commented on content Y would need me to look in the content table to get the content's title and URL.
Any tips are welcome, thanks!
Consider creating several views for different actiontypeids. Union them to have one full history.

Need Help Writing SQL To Apply Promotions to Shopping Basket at Checkout

Don't laugh but I'm a Lotus Notes (non-relational database!) developer trying to work with SQL and, although I have the basic concepts nailed, I'm stuck on something I'd consider to be "advanced".
Imagine a user reaches an online checkout having added a set of products to their basket. I need to apply promotions to the basket.
These promotions look at the items in the basket and add "points" for any combination that matches a pre-defined "bundle". The promotions also need to be able to target users in specific countries (information gained at point of registration) and other personal details.
The promotions are entered and maintained by the site admin team and need to be as flexible as possible. So they can reward people for things like "Buy X products of type Y and get 50% extra points" or "3 or more XE-123s and get 500 points added" etc.
Right now I'm looking for general direction. How should I store the criteria that matches the items in a basket to any of the running promotions? Would one big Stored Procedure do or should the C# code that builds the basket loop through all promotions and see which fit?
Right now I don't even have a table schema. Just the knowledge of how it should work and little idea where to start.
Jake
My suggestion is to not use SQL for this sort of business logic.
The database is a good place to keep information about products like whether they are type Y or type X. This keeps the database design pretty straightforward.
What you mention about C# seems like a better direction. There is a lot of searchable information about 3-tier architecture that can help explain the benefits of this strategy well.
'As flexible as possible' is a red flag (IMHO). I'd try to nail that down to:
"Fixed-point and/or percentage (of total basket / bundle points) bonus (three columns in a helper table)
When the basket contains a combination that matches a pre-defined 'bundle', where 'bundle' is contained in a helper table, with multiply rows, with a bundleID and a row for each item in the bundle, containing at least ItemID and Quantity.
And no other kinds of reward possible. This to keep the project / requirement manageable.
Then have a SP which checks for the presence of bundles within the basket and applies relevant promotions (as stored in the first helper table).
Also make sure you know the requirement whether 1 or multiple promotions are possible.