I'm keeping track of people registering for my site by using tables in a SQL database. I have a 'users' table in which there is a column, 'id'. I'm keeping track of people with this.
It seems that if I want to assign someone's id to a variable I have to do this inside flask:
user_id = session["user_id"]
Even though I don't have any variables called 'user_id' in my table. But, it is working. So, is 'user_id' some pre-made keyword that somehow knows the id of the user?
How does it know the right id? Is it looking inside my database to find the correct id for that user?
I tried using session["user_id"] and it actually gave the right number. But, I don't know how it works because I'm keeping track of peoples' ids manually.
Related
I've created an API using Flask-RESTFUL package for Python 3.7.
I'd like to know what the proper approach would be for returning data to a user based on which columns he should have access to.
For example, if I have an "orders" table with (order_id, order_date, price, ebay_name, revenue), but want User A and User B to have access to different data. Let's say that on route /get_data, I return all fields, but User A should have access to all data, while User B only can see the revenue field.
My current approach:
While building the JWT token when a user logins in and authenticates, would it be acceptable to store the column names of the "orders" table in the actual token? Then, when the user goes to the /get_data route, I would basically check the column names stored in the JWT and build the MySQL query with the column names found in the token (select all_columns_in_jwt from orders). I worry that exposing the table columns in the JWT token is not the best approach.
Another idea would be to check within a user permissions table each time the /get_data route is hit.
Does anyone have a suggestion for implementing this in a more efficient way?
I would do it using user permissions but you could also create separate procedures for either each individual user or groups of users based on their roles/permissions which create/replace specific views of the tables allowing the user to see only what you want them to see. For example, upon any changes to the table (or alternatively, upon login for a user/member of a user group) you could run the procedure to generate (or replace if it already exists) a view on the table for either each user or each user group which you want to restrict access to, and then your API would select data from the view rather than directly from the table
With user permissions (this is very similar to how I implement it in my own apps) you could create a permissions table and then a table of the permissions which users possess. Then, on using an API, you could query the user's permissions and using a map which you store somewhere in your code base you could look up the columns based on a combination of the relevant user permission and the relevant table and use the resulting column set as what you select in your query
I'm writing a simple flask-restful API and I need to insert some resource into database. I want to have hash id visible in the URL like this /api/resource/hSkR3V9aS rather than just simple auto-increment id /api/resource/34
My first thought was to use Hashids and just generate the hash_id from auto-increment id and store both values in the database, but the problem is that I would have to first INSERT new row of data, GET the id and then UPDATE the hash_id field.
Second attempt was to generate hash_id (e.g. sha1) not from id but some other field that I'm passing to databse and use it as a primary key (get rid of auto-inc id), but I fear that searching and comparing string each time rather than int will be much, much slower.
What is the best way to achive desired hash_id based URL along with acceptable speed of database SELECT queries?
I think this is the most related stack question, but it doesn't answer my question.
Major technology details: Python 3.6, flask_mysqldb library, MySQL database
Please let me know if I ommited some information and I will provide it.
I think I found a decent solution myself in this answer
Use cursor.lastrowid to get the last row ID inserted on the cursor
object, or connection.insert_id() to get the ID from the last insert
on that connection.
It's per-connection based so there is no fear that I'll have 2 rows with the same ID.
I'll now use previously mentioned by myself Hashids and return hashed value to client. Hashids can be also decoded and I'll do it each time I get a request from url with this hash id included.
Also I found out that MongoDB database generates this kind of hashed id by itself, maybe this is a solution for someone else with similar problem.
I have the following entities, each of which is a table in my database:
User
Application
Role
I have another table called "user_app_role" which looks like this:
table user_app_role(
user_id int not null ,
application_id int not null,
role_id int not null,
primary key(user_id, application_id, role_id)
)
where user_id, application_id, and role_id are all foreign keys on the user, application, and role tables.
An entry in that table indicates that the user has a particular role within a particular application, so a row might return 1, 1, 1 indicating that user 1 has role 1 within application 1. similarly, 1, 2, 1 would mean that user 1 also has role 2 within application 1.
I have sqlalchemy mappings defined for User, Application, and Role. What I would like is for the User object to somehow have a list of Application objects and for each Application object, that object would contain a list of Role objects.
From reading the documentation for sqlalchemy, it appears this type of relationship is impossible to map and I have found only a few other questions on stackoverflow where this has been asked, none of which have an answer. This seems like a relatively normal 3NF database relationship (I have 4 of them in my whole data model), is it possible to somehow set this up in sqlalchemy? I could do this whole thing in pure SQL in about 10 minutes but I don't want to throw away all the other useful feature of SqlAlchemy but if I can't make this somehow work, then my application will not be able to ship.
Also, PLEASE DO NOT suggest that just I alter my data model or denormalize the database or otherwise mess with that in any way. Answers of that nature will not help me. I'm happy to change my object model or add additional objects if I need to somehow magically map this one table to 2 objects or something weird like that but I am not able to change the data model.
Ok as far as I can determine, creating an actual mapping for this scenario is impossible in SqlAlchemy so here is my workaround:
class UserAppRole(Base):
__tablename__ = 'userapprole'
user_id = Column(stuff, ForeignKey(users.id))
role_id = Column(otherstuff, ForeignKey(roles.id))
app_id = Column(morestuff, ForeignKey(apps.id))
I've decided that in my application's domain, a User has roles with applications, so the relationship for this new object is going to be on the User:
class User(Base):
__tablename__ = 'users'
approles = relationship(UserAppRole, backref=backref('app_user_role', uselist=True))
# other columns, relationships, etc.
This works well, because when I load a user I want to know what applications they have access to in any way and I want to know what roles they have for those applications. In my domain, a Role is a thing and an Application is also a thing, and there are relatively few of those things and they tend not to change (although that isn't a requirement for this solution). What's important is that I can load Application and Role objects by their ID, which conveniently enough I now have in my approles list in my User object.
To bind this all together, the last thing I do is use a repository to handle persistence for my User objects. When I load a User, SqlAlchemy will populate the approles list with ID's. I can then manually load the applications and roles and build a dictionary for applications with a list of roles. Now when I add a role for a user to an application, I need to pass in the Application object (which knows what roles are valid) and a Role object (which may or may not be valid for that application). Both of those will have ID's, so it's pretty trivial for me to update the dictionary and/or approles list to contain what I want. In the unlikely event that I attempt to write to the DB with a role id or app id that doesn't exist, then the constraints in my database will reject the insert/update and I'll get an exception.
It's not my ideal solution, but it works quite well for the two situations that I'm encountering this. If anyone has a better solution though, please post it. I feel like composite adjacency lists ought to be useful for this scenario but the current SqlAlchemy documentation seems to indicate that these have to be for self-referencing tables and I haven't found a way to make this work for this particular scenario.
I have created 31 objects in my database. Now, for some reason, if I create a new object through the Django admin page, the new object will have an id of 33. Now, suppose I change I change its id and then delete it. If I try to create a new object, it's id will be 34. So, the id is always shifted by 2. I'm very new to databases and Django, is there any reason for behaving like this? Thanks
Note: I didn't upload any code, because I don't think that's the problem...
By default, the id is an integer that is always incremented at the creation of an object. It is also incremented such that ids of deleted objects are never used again.
The incrementation is handled by the database itself, not Django. For example, with PostgreSQL, the corresponding database field corresponding the "id" has the "PRIMARY KEY" constraint. It basically means that the field should be not null, and with no duplicates. Moreover the field will be associated with a sequence, that stores the id to use for the next row creation. To change this number, run this in the database shell:
ALTER SEQUENCE yourobjectstable_id_seq RESTART WITH 1234;
However, as emphasized in the comments to your question, this is something you should not do: it is better to keep the "uniqueness" feature of the primary key, even for deleted objects, since other tables may use the id to refer to a row in your main table.
I have little to no experience with databases and i'm wondering how i would go about storing certain parts of an object.
Let's say I have an object like the following and steps can be an arbitrary length. How would I store these steps or list of steps into an sql database?
class Error:
name = "" #name of error
steps = [] #steps to take to attempt to solve error
For your example you would create a table called Errors with metadata about the error such as an error_ID as the primary key, a name, date created, etc... then you'd create another table called Steps with it's own id, lets say Step_ID and any fields related to the step. The important part is you'd create a field on the Steps table that relates back to the Error that the steps are for we'll call that field again error_ID, then you'd make that field a foreign key so the database enforces that constraint.
If you want to store your Python objects in a database (or any other language objects in a database) the place to start is a good ORM (Object-Relational Mapper). For example Django has a built-in ORM. This link has a comparison of some Python Object-Relational mappers.