Simple question, I have an application and dependant on whether you are in the administration system or on the public website I want to show different results.
Example: in the database for a news story in the administration I may set the column value 'showonsite' to false. So I would like this to show in the administration panel only and not on the live site.
My question is, because I require the same information just with the only one column change, live site to only show true values and administration to show both. What is the most effective way of achieving this without copy paste of code?
Thanks
Please see the second query.
I may be missing something. For non-adminstrative users, could you simply not SELECT news stories with the showonsite column set to false?
For example:
SELECT
*
FROM
dbo.NewsStory
WHERE
showOnSite = 1
Edit:
Oh! I see. You're talking about copying and pasting the query. It's late. >.<
If you have a stored procedure, you can pass a value to indicate whether the given user is an administrator:
SELECT
*
FROM
dbo.NewsStory
WHERE
showOnSite = 1
OR #isAdmin = 1
Depends on where you write your code - if you use stored procedures, then just a parameter like #liveonly should be sufficient. Sameway if you use an inline sql query directly in a C# method, then a parameter live_only should be good enough, to determine whether the extra where condition will be added or not.
For eg. in the SP
SELECT *
FROM news
WHERE ((#live_only=true AND showonsite=true) or (#live_only=false))
This way it can be called with #live_only = false for admin panel, but with value true for the actual site.
No, I wouldn't use a view for that, an I wouldn't copy any code. It sounds like this is just a conditional filter on your queries.
You don't make it clear how you are doing the data-access, but this might mean aasdij an extra line of TSQL, adding adding a so parameter, adding an extra LINQ .Where clause, etc
Related
I am allowing users to generate expressions against predefined columns on the table. A user can create columns, tables, and can define constraints such as unique and not null columns. I also want to allow them to generate "Calculated columns". I am aware that PostgreSQL does not allow calculated columns so to get around that I'll use expressions like this:
SELECT CarPrice, TaxRate, CarPrice + (CarPrice * TaxRate) AS FullPrice FROM CarMSRP
The user can enter something like this
{{CarPrice}} + ({{CarPrice}} * {{TaxRate}})
Then it gets translated to
CarPrice + (CarPrice * TaxRate)
Not sure if this is vulnerable to sql injection. If so, how would I make this secure?
Why don't you utilize STORED PROCEDURES to conduct this?
This way, you can, for instance, define variables to receive what user wrote and check if there are some BLACKLISTED words (like DELETE, TRUNCATE, ALL, *, and so forth).
I don't know PostgreSQL, but if it's not possible there, you can also check those problematic commands BEFORE translate them to call your SELECT statement.
If I understand you correctly, you just take user input as desribed above and substitute in select column list. If so, that is sure not safe, because something like:
"* from SomeSystemTable--({{CarPrice}} + ({{CarPrice}} * {{TaxRate}})"
Will allow user to select anything from any other tables he has permissions for. You can try to build expression tree to avoid that: parse user input into some structure describing variables and arithmetic operations between them (like parsing arithmetic expressions). Otherwise you can remove all {{}} from your string (ensure that any {{}} corresponds to a column in a table) and check if only "+-*()" and whitespace characters left.
Note that from user experience viewpoint you will need to parse expression anyway, to warn user about errors without actually running the query.
I am converting a VB6 app to C# with an SQL Server back end. The app includes a very general query editor that allows the user to write any select query and return the results visually in a grid control. Some of the tables have several hundred columns (poor design, I know but I have no control over this). A typical use case for an admin user would be to
select * from A_Table_With_Many_Columns
However, while they want to be able to view all the data, they are particularly interested in 2 columns and they want these to be displayed as the first 2 columns in the grid (instead of 67th and 99th for example) so instead they execute the following statement:
select First_Interesting_Field, Second_Interesting_Field, *
from A_Table_With_Many_Columns
Then they will go and modify the data in the grid. However, when saving this data, it results in a concurrency violation (DBConcurrencyException). This worked fine with the connected RecordSets of VB6 but not so well in C#. I have tried a myriad of solutions to no avail.
Does anyone know how to handle this exception in a generic way? (Remember, the user can type ANY select statement or join etc. into the query editor)
Does anyone know how I might manipulate the columns returned such that I delete the 2 columns that appear further on in the list? (My difficulty here is that if the column name in the database is EMail so I do select Email, * from Blah the 2 pertinent columns returned are EMail and ADO.NET or C# aliases the second EMail column from the * portion of the query as EMail1 so I am not able to detect the second column as a duplicate and remove it)
Does anyone have an alternate solution I have not thought of?
Thank you very much
Actually, you could rename all variables to something like email_userdefined by doing something like this:
SELECT First_Interesting_Field as First_Interesting_Field_userdefined, Second_Interesting_Field as Second_Interesting_Field_userdefined, *
from A_Table_With_Many_Columns
Replace user_defined with whatever you want, like order number or anything else user acceptable
I am developing a project which access a database in sql server 2012 through C# and performs CRUD modifications on it. Here is the main form:
both listboxes on the right are used to deal with informations contained in an intermediate tables (many-to-many relationship). Here is how they work: Basically, you choose types and abilities from the comboboxes, then click on 'add' and they are added in the respective listboxes. To delete items in the listboxes, you just need to select one item and then click 'delete'.
Here's another print to clear any doubts:
On the first print I've provided here, you will see a 'Bulbasaur' data. The PokémonID = 1 is represented by the 'Bulbasaur'; TypeID = 1 and 12 are 'Grass' and 'Poison', respectively; and AbilityID = 1 is 'Overgrow'.
I was trying to create an update function (update_click) using sql queries (SqlCommand, SqlDataReader and so on...), but without deleting the whole associations of a pokémon and its types (and abilities) and then re-adding them, based on the new modifications on the listboxes. I want to avoid it in order to save some memory in cases that some pokémon may hold thousands of types and abilities...
Is it possible? If necessary, I can send you my C# project for more details.
I would suggest a combination of:
1) Use table-valued parameters to send all the data (in its present state in your listboxes) to your T-SQL query or stored procedure at once
2) Consider using the EXCEPT and/or INTERSECT operators (as well as any necessary LEFT or RIGHT JOIN) to compare the contents of your table-valued parameter (essentially a table itself) with the data currently in the underlying tables
3) UPDATE/DELETE/INSERT accordingly
Essentially it sounds like what you are saying you'd like to do is to only "send the changes" to the database:
add any abilities that were not there before;
remove any abilities that were in the database but have been removed
If that's the case then what you need to be able to do is simple set operations:
Set Union
Set Intersect
Set Difference
while you can perform these operations using simple arrays or lists, it is much more efficient to use an actual set implementation such as a generic HashSet<>. With a correct implementation using sets or hash tables you ca achieve linear-time performance.
I hope this helps point you in the right direction..
Right now, I have a simple web application that displays the entries of a database. One of the fields that is visible in the database is a bool?, which is true, false, or neither. Everything in the database originally should have the bool? set to neither.
Here's what I want to get working: when a user edits an entry in the table by selecting either true or false for the bool? field, I want to be able to run some C# code (that I have already written) and have that entry deleted from the database. This means that the next time that the database is loaded, once again all the entries will have neither true nor false selected in the bool? field.
Does someone know how I can do this simply? (I know very little about querying databases or creating web apps in general.)
My problem was less about how to delete the items and more about how to pick out from the database those chosen to be deleted.
I found that this does the trick:
var toBeRemoved = from m in db.Issues
where m.Remove.HasValue && m.Remove
select m;
I believe when you say "true, false, or neither", the neither means null in the database, so, without seeing your code, I believe you could change the SELECT that retrieves the rows for the view to display, to have a WHERE *field* IS NULL in it. If this doesn't help, please post us some control, view, and model code.
string sqlQuery = "unknown";
I need to write a function which receives a sql query as parameter e.g. sqlQuery. I would like to execute it only if it is select statement and return data. In other case, if parameter sqlQuery contains delete, update or truncate, the function should return null.
I wonder if there is way to achieve this without parsing contents of parameter sqlQuery.
I would like to do this using c sharp for oracle queries.
Any tips. Thanks.
Update:
This should work for all kinds of users with all privileges.
Run the query in the context of a user who only has select privileges. Any other type of query will error out.
SET TRANSACTION READ ONLY, then execute the string. If it attempts to modify data, it will generate an ORA-01456 error. You can trap this and return whatever you want.
If you really have to work with a constructed string that will operate on the database, you should use the DBMS_ASSERT database package to make sure you have a pure query that's not subject to SQL injection. There's a nice paper on the Oracle site about that here.
The basics are:
only give the minimum privileges necessary, for example only giving the user "select" as described in an earlier reply. And then only on the minimum necessary set of tables. Views are really helpful here in limiting access.
Use bind variables where that's possible.
If you can't use bind variables then check the purity of your statement using DBMS_ASSERT
You can probably search the string for keywords like "update", "delete", "truncate" and all the other ways you can do ddl or dml on the table, but it is very error-prone. You have to eliminate strings in the query which might have these keywords and there are a lot of keywords that you have to take into account.
If your requirement is to return null, Why not give just the select privilege on the necessary objects and return null if you encounter the Insufficient Privileges error?
http://download.oracle.com/docs/cd/E11882_01/server.112/e17069/strms_trapply.htm#STRMS1065
I would not allow the client to specify a SQL select string. Too many possible attack vectors.
Have you considered using Linq? The caller could pass a Func<T, bool> that could be passed to a Where clause. Since Linq will generate the select statement for you, there's no possibility of a non-select statement occuring.
Bear in mind a SELECT column FROM table FOR UPDATE will still take an exclusive lock on every row on that table. And it only needs SELECT privileges (none of INSERT, UPDATE or DELETE are required).
You can use ADO.NET SqlCommand http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.aspx. It has methods ExecuteReader for a select type query and ExecuteNonQuery for other sql expression, you jest set the CommandText string attribute. If I'm right it throws exception if the query is not a select in ExecuteReader but you must check it.
string sqlQuery = "("+evil_sql+")";
Only a subquery can start with a parentheses. This will stop DML, DDL, and the FOR UPDATE issue that Gary mentioned. You still have to execute everything, just catch all the errors. I've done this on a public-facing website without any issues.
Even if your user is not directly granted anything you'll need to check for unnecessary PUBLIC grants. And of course keep your system patched. There have been exploits in functions that can be called in a SELECT.