I recently started developing a Desktop python application and I would like to know how more expert people would handle this issue.
I used to develop (about 5-10 years ago) web applications in the past using PHP + MySQL and there, since the code/program is located on the server where the user doesn't have access (except the web page), I could simply store the user/group permissions in the database in a table say users, users_groups, users_permissions, and so on. I would then check at every page load if the user had the right to access that page / update that record in the database.
With a desktop application where the user has access to the executable (which can relatively easy be decompiled to source code, being written in Python) the approach will likely be quite different.
Since MySQL has forked into MariaDB and is not so actively developed anymore, PostgreSQL looked promising to start. I thought about creating different users on PostgreSQL level and letting PostgreSQL handle the permissions (instad of my application handling them directly).
However, this only allows tuning of the permissions down to the table level. A user will be allowed to create/delete/update records in a table, however no further control is available. AFAIK you cannot tell "let this user only update his own records" or "this user can only delete the records from this group", or "users from group X can only update their own records while users from group Y can update everybody's records".
My understanding as how to handle this kind of issue would be to put some kind of middleware application between the user and the database, located on the server, such as:
Desktop application <-----> Server-side application permissions handler <-----> Database
Where server-side permission handler could be as simple as adding a "WHERE user=..." to each query as well as much more advanced stuff (first check user permissions stored in the database, based on that decide if letting user execute the query or reject it). I think this is a common problem for all desktop applications and would therefore expect that such a server-side application already exist. Am I missing something obvious or maybe PostgreSQL allows for more detailed fine-tuning?
Thank you for all your help ;)
Your intuition is right. It is never a good idea having a client access directly a database. Take a look a Django https://www.djangoproject.com and https://www.django-rest-framework.org
This would be the the basis for your server side. You would handle here business logic, authentication, authorization. The client should basically present the data within the UI and delegate all the decision making to the server.
Here you can find a step by step tutorial about how to implement a REST api with user authentication in Django. https://wsvincent.com/django-rest-framework-authentication-tutorial/
Related
I'm currently working on a project to make data entry easier for myself,
I have sql tables set up in an azure database, and i can write python code that adds data to them easily enough,
but what i want to do next is to have a webapp that users can login to, to do their data entry,
so when you login, your user and password will be checked against a sql table,
and then if correct you will move onto a data entry page where it will show you the fields you need to enter and then once submitted, these will be added to the sql table,
so far, i have tried coming up with the python code and the html for the site, and getting them to work together using Flask but i am not sure if this is the best way to do it and my main concern is i dont know how to host this code anywhere other than on my local device,
Thanks for your time! this problem is really bugging me as i'm confident i can alter and add to sql tables however i need to, i'm just trying to figure out the best way to make this a usable app for other people,
Yes Flask is a good solution for what you're going to do. Even if there are many other possibilities.
Once your app is ready. You can make it available for others from your computer.
Or you can host it on a server.
In really short you have to :
get a Serveur
get a domain name
install a database
upload your project (with the new database configuration)
Run the project
Here are some links, where you can read more on it
https://www.freecodecamp.org/news/how-to-build-a-web-application-using-flask-and-deploy-it-to-the-cloud-3551c985e492/
https://www.linode.com/docs/development/python/flask-and-gunicorn-on-ubuntu/
I'm tasked with creating a web app (I think?) for my job that will tracker something in our system. It'll be an internal tool that staff uses to keep track of the status of one of the things we do. It should look like trello, with cards that drag from step to step. That frontend exists, but my job is to make the system update when the cards are dragged. This requires using an API in Python and isn't that complicated to grab from/update. I have no idea how to put all of this together. My job is almost completely nontechnical and there's no one internally who knows what I'm doing except for me. I'm in so over my head here and have no idea where to begin. Is this something I should deploy on Elastic Beanstalk? EC2? How do I tie this together and put it somewhere?
Are you trying to pull in live data from Trello or from your companies own internal project management tool?
An EC2 might be useful, but honestly, it may be completely unnecessary if your company has its own servers. An EC2 is basically just a collection of rental computers to help with scaling. I have never used beanstalk so my input would be useless there.
From what I can assume from the question, you could have a python script running to pull from the API and make the changes without an EC2.
First thing you should do is gather as much information about what the end product should look like. From your question, I have the feeling that you have only a vague idea of what the stakeholders want. Don't be afraid to ask more clarification about an unclear task. It's better to spend 30 minutes discussing and taking note than to show the end-product after a month and realizing that's not what your boss/team wanted.
Question I would Ask
Who is going to be using this app? (technical or non-technical person)
For what purpose is this being developed?
Does it need to be on the web or can it be used locally?
How many users need to have access to this application?
Are we handling sensitive information with this application?
Will this need to be augmented with other functionality at some point?
This is just a sample of what I would ask, during the conversation with the stakeholder a lot more will pop up for sure.
What I think you have to do
You need to make a monitoring system for the tasks that need to be done by your development team (like a Kanban)
What I think you already have
A frontend with the card that are draggable to each bin. I also assume that you can create a new card and delete one in the frontend. The frontend is most likely written in React, Angular or Vue.js. You might also have no frontend framework (a mix of jQuery and vanilla js), but usually frontend developper end up picking a framework of sort to help the development.
A backend API in Python (in Flask or with Django-rest-framework most likely) that is communicating with a SQL database like postgresql or a Document database like MongoDB.
I'm making a lot of assumption here, but your aim should be to understand the technology you will be working with in order to check which hosting would work best. For instance, if the database that is setup is a MySQL database you might have some trouble with some hosting provider.
What I think you are missing
Currently the frontend and the backend don't communicate to each other. When you drag a card it won't persist if you refresh the page. Also, all of this is sitting in your computer and cannot be used by any one from your staff. You need to first connect the frontend with the backend so that the application has persistance. Then you need to deploy this application somewhere so that it is reachable by your staff.
What I would do is first work locally to make sure that the layer of persistance is working. This imply having the API server, the frontend server and the database server running simultaneously on your computer to develop. You should then fetch data from the API to know which cards are there in the database and then create them visually in your frontend at the right spot.
When you drop a card to a new spot after having dragging it should trigger a POST request to your API server in order to update the status of this particular card (look at the documentation of your API to check what you need to send).
The server should be sending back an updated version of the cards status if the POST request was sucessful, so your application should then just redraw the card at the right spot (it won't make a difference for you since they are already at the right spot and your frontend framework will most likely won't act on this change since the state hasn't changed). That's all I would do for that part.
I would then move to the deployment phase to make sure that whatever you did locally can still work online. I would use Heroku to start instead of jumping directly to AWS. Heroku is a service built on top of AWS which manage a lot of the complexity of AWS for you. This is great for prototyping and it means that when your stuff is ready you can migrate to AWS easily and be confident that a setup exist to make your app work. You might also be tied up to your company servers, which is another thing I would ask to the stakeholder (i.e. where can I put this application and where I can't put it).
The flow for a frontend + api + database application on Heroku is usually as follow. You create a github repo for your frontend (make it private) and you create an app on Heroku that will watch this repository for changes. It will re-deploy the application for you when it sees a change at a specific subdomain of Heroku hosting. You will need to configure some procfiles that will tell Heroku what to do with a given application type. This is where you need to double check what frontend you are using since that might change the procfiles used. It's most likely a node.js based frontend (React, Angular or Vue) so head over here for the documentation of how to put that online.
You will need to make a repo for the backend also that is separate from the frontend, these two entities are distinct and they only communicate through HTTP request (frontend->backend) and JSON (backend->frontend). You will need to follow the same idea as with the frontend to deploy, head over here.
Once you have these two online, you need to create a database on Heroku. This is done by adding a datastore to your api, head over here. There are some framework specific configuration you need to do to make the API talk to an online database, but then you will need to find that configuration on the framework documentation. The database could also be already up and living on your server, if this is the case you just need to configure your online backend to talk to that particular database at a particular address.
Once all of the above is done, re-test your application to check if you get the same behavior as before. This is a usable MVP, however there are no layer of security. Anyone with the right URL could just fetch your frontend and start messing around with your data.
There is more engineering that need to be done to make this a viable end product. This leads us to my final remark: why you are not using a product like Trello, Jira, or even Github Project? If it is to save some money on not paying for a subscription I think you should factor in the cost of development, security and maintenance of this application.
Hope it helps!
One simple option is Heroku for deploy your API and your frontend application.
I've got a question concerning Python and MySQL. I come from a PHP background and I am wondering how the workflow will be in Python. I can't find any good answers on that on the web and hope anybody can help me understanding this thing. So let me quickly explain what i'm stucked with:
In PHP i did a lot of little things in combination with MySQL, meaning loading data from a database and writing to it. As long as the server on which the php files were stored was correctly set up, it was save to do that. The connection to the database including the username, servername, password and database name was saved in the php file. As php files get stored on the server and the source code won't get shown to the user itself, the user couldn't see the authentication data to connect to the database.
Now, I am wondering how that whole concept can be transfered to Python in a secure way so that the user can't see the authentication data in the source text.
I plan to program a Python program in which the user has to authenticate. Let's assume I created a MySQL database on a webserver and in the Python program the user can login. As soon the user clicks on the login-button a connection to the web-database is done. That would mean that in my source code i need to write down the neccessary data like username, password, db-name and server name for that specific database. Here is my Question: That would mean that everybody could see that authentication data which would be very unsecure, wouldn't it? Even if the user has just a .pyc file he could then recompile it and see the standard .py file in which he could see all that very sensitive data.
So I was wondering how to securely hide that authentication data from the user who will later use my Python program.
As a pythoneer who long time ago was working in php, I think I know what you are after.
First of all, the HTML code will not contain any database credentials unless you put them into the HTML view. An easy way of structuring what goes into the HTML views is to use a framework like Django. It handles the MVC of web applications and does connections to databases.
If you want your database credentials to be very safe, you can have your web application ask for them at startup, thus never having them written down in a file. Keep them secure using keypass or similar password storage systems.
This way they are also not checked in to any version control system, where the most common place for database password leakage occurs.
If you are a newbie to webapp programming in python, I would suggest to follow a Django tutorial it should help you get on the track.
I have a Python client program (which will be available to a limited number of users) that fetches data from a remote MySQL-DB using the pymysql-Module.
The problem is that the login data for the DB is visible for everyone who takes a look at the code, so everyone could manipulate or delete data in the DB. Even if I would store the login data in an encrypted file, some still could edit the code and insert their own MySql queries (and again manipulate or delete data).
So how can I access the DB from my program and still SELECT, DELETE or UPDATE data in it, but make sure that no one can execute his own (evil) SQL Code (except the ones that are triggered by using the GUI)?
You can prevent injections just by parameterising arguments, for example:
"SELECT * FROM Users WHERE name=\"".name."\";"
Will read
SELECT * FROM Users WHERE name="AlecTeal";
But an be "injected" with:
name="\" or UserType=\"Admin"
Then it will read
SELECT * FROM Users WHERE name="" or UserType="Admin";
That's bad, you can prevent that with stuff like:
SELECT * FROM Users WHERE name=?
and binding your variables, then the SQL server doesn't actually parse any data from the user, it sees the ? and just reads from the parameters.
You cannot hide the SQL statements yourself
You can obscure them sure, but they'll be in your .pyo or .py code somewhere!
You have two options:
MySQL supports users - and this is what users are for and assume "Only fairly trustworthy people will get my program" so you can have a user like Debbie_From_Accounts" who can select from theUserstable, and update/delete/insert/select fromFinancial` Tables say.
OR!
You can use some sort of API on the server and have like a set of PHP scripts that do the DB work and you just http get the pages.
This happens to be one of the reasons desktop client-server architecture gave way to web architecture. Once a desktop user has access to a dbms, they don't have to use just the SQL in your application. They can do whatever their privileges allow.
In those bad old days, client-server apps only could change rows in the DBMS via stored procedures. They didn't have direct privileges to INSERT, UPDATE, or DELETE rows. The users of those apps had accounts that were GRANTed a limited set of privileges; they could SELECT rows and run procedures, and that was it. They certainly did not have any create / drop / table privilege.
(This is why a typical DBMS has such granular privilege control.)
You should restrict the privileges of the account or accounts employed by the users of your desktop app. (The same is, of course, true for web app access accounts.) Ideally, each user should have her own account. It should only grant access to the particular database your application needs.
Then, if you don't trust your users to avoid trashing your data, you can write, and test, and deploy, stored procedures to do every insert, update, or delete needed by your app.
This is a notoriously slow and bureaucratic way to get IT done; you may want to make good backups and trust your users, or switch to a web app.
If you do trust them tolerably well, then restrict them to the particular database employed by your app.
Can you advice me with some articles/applications that allows you create SaaS(Software as a Service) application with Python and Django.
For the moment the general topics I do not understand are:
Do you have one working application for all clients or one app per client
How do you manage database access, permissions or different DB for each client
Are there any tools that allows you to convert one app to SaaS
one project, this will make maintenance easier. I handle host resolution with middleware in django-ikari.
you don't. see #1
I use the following :
django-ikari : anchored (sub)domains
django-guardian : per object permissions
django-tastypie : easy RESTful api
django-userprofiles : better than django-registration
django-billing : plan based subscription controls
django-pricing : plan based subscription definition
While not necessary, the following will help in the long run:
django-hunger : private beta signups
django-waffle : feature flip
django-classy-tags : nice, easy and neat templatetag creation
django-merchant : abstracted payment gateway framework
django-mockups : fast testing with models
django-merlin : better multi-step forms (wizards)
Finally, nice to have
django-activity-stream
A very basic, elementary example of how you would go about it.
Suppose you have a simple app designed to solve a particular business case. For example, you created an app to handle room reservations at your office.
To "convert" this app into a service you have to configure it such that most of the user-specific parts of the application are parametric (they can be "templatized" - for lack of better word).
This is how the front end would be converted. You might create variables to hold the logo, headline, teaser, color scheme for the app; allowing each user to customize their instance.
So far, your app is able to customize itself on the front end. It is still using the same database that was designed in phase one.
Now comes the matter of showing only those fields that are relevant to a particular user. This would be parameterizing the database. So you might add a column that identifies each row as belonging to a particular user; then create views or stored procedures that filter records based on the logged in user.
Now the application is able to be "rented" out; since you are able to customize the instance based on the user.
It then just gets bigger from here - depending on the scale, type and intended customization of your application. You might decide that your application performs better when each user has their own dedicated database instead of the stored procedure + view combo.
You may decide that for some user types (or "packages"), you need a dedicated instance of your application running. So for "premium" or "ultra" users you want to have their own dedicated system running.
If your application requires lots of storage - you might decide to charge separately for storage.
The bottom line is it has nothing to do with the language used. Its more an architecture and design problem.
Software as a Service is just a marketing word, it's technically no different from a server that is accessible over the internet. So question 3 makes no sense. That leaves us with question 1 and 2:
What do you mean with 'app' in this context? Your web application (built with Python and Django) can have multiple Django apps (components that make up the web application) but I think that's not what you mean. You can build your website in Python/Django and have various customization options depending on which user (client) is logged in. For example, a premium client can have several advanced options enabled but it's still part of the same codebase. It's just that some options (buttons/controls, etc) are not shown for certain clients
Django has plenty of tools for user management, permissions and groups. You can give each user (each client) different permissions and these permissions determine what they can do. Database access should be managed by your web application. For example, the code determines what information needs to be displayed on the webpage (depending on which client is logged in) and that code retrieves the information from the database. Depending on the scale that you're aiming for, you can also specify which database should be used to retrieve the information from.
I have a blog post describing my proposal of how to go about making a multi tenant SAAS web application using Django. Multi-tenancy here means that when user registers, they have their sub-domain. To recap:
All tenants share one database, but each has their own schemas. Imagine you have website abc.com and someone registered a xyz tenant so that they access their page through xyz.abc.com, then for a tenant xyz you have a separate schema containing all the tables thus encapsulating data related only to xyz tenant. There are other ways, like having one database and one schema for all, or having even separate databases. But schemas approach is the best trade-off. The django-tenants library's documentation contains more detailed info if you are interested
Use django-tenants library to abstract away work with tenants. When someone accesses xyz.abc.com, you need to know that xyz is the tenant and that you should use xyz schema. django-tenants library does this for you so on each request you can obtain the tenant object by simply doing current_tenant = request.tenant
You need to differentiate between shared tables and tenant-specific tables. For example, having table with list of orders is tenant-specific. Every tenant might have their own database containing all their orders. This table should be inside xyz schema. At the same time, you will have some core Django tables, like user. The data can be shared, for example, to disallow two users registering with the same email.
You need to configure your DNS to catch a wildcard expression *.abc.com, for which you can add an A record inside your CPanel with *.abc.com linking to the IP of your server