Jose: Hi guys, and welcome back!
In this video we're going to talk about
how to store sensitive data in your code.
Or how not to store sensitive data in your code.
So, what is sensitive data?
Well, now we no longer
will connect to the data.db file.
Therefore, we need to put our ElephantSQL
username and password, really the whole thing,
including the host name and everything else,
somewhere in our code so that our code
can actually connect to it.
But, often when we're working with code,
we're sharing it with other people,
or with everyone on sites like GitHub,
so we don't want to open up our entire database
by putting our username and password in there,
because people can then go and you know,
delete tables or drop the entire thing, or you know,
find our data in there and read peoples passwords
and all that stuff.
So we need to be a bit careful with sensitive data.
What we're gonna do instead is in our programme,
we're going to write some code that expects
a connection string to be defined.
And then we're simply gonna tell other developers
that want to look at our code that,
yeah, they can look at everything,
except the connection string,
and that they need to define
their own connection string to
connect to their own database if so they want.
The way we do this is normally with environment variables.
Environment variables are context-dependent names
that have values,
and the context can be for example,
an environment variable that effects every programme
in a computer,
so every programme has access to it,
or it can be for specific programmes,
so only specific programmes have access to the variable,
or it can be programmes started by this user,
you know there's a whole bunch of different contexts,
but what we're gonna do,
is we're going to define an environment variable
that contains the connection string
and we're gonna use that from our code.
When other coders want to use our code,
they will have to define their own
environment variable in their computers
with their own connection string.
Okay, so I just got ahead of myself there,
but that essentially what they have to do,
our programme will be coded to expect the variable,
and then it's gonna read it and connect to
whatever that connection string is.
Of course we're gonna assume the connection string
is a valid connection string,
and we're not gonna be checking that ourselves.
To create environment variables,
well every operating system has a different
way of creating them manually.
In Windows, for example, you have to go into your settings
and change some things there,
in macOS you have to export a new variable and so forth,
but in coding,
we normally create a text file called .env,
and there we put our environment variables.
Then, when we run the programme,
we tell the operating system
to turn the contents of that file
into environment variables valid for this operating system.
And fortunately,
there is a library called python-dotenv
that does this for us.
So all we have to do is create the .env file,
and then run python-dotenv,
and that is going to turn the contents of the
.env file into environment variables,
and we don't have to worry about creating them ourselves,
which as I said, can be different depending on
the operating system that you're using.
So, our .env file is going to look something like this.
This is the .env file,
and the contents are "DATABASE_URL"
that's the name of our environment variable,
equal,
and then come the connection string.
So postgres:// username, password, et cetera.
We are not going to share this file with anybody,
so this file will remain private.
Even if we were putting our code up on GitHub,
we would still not share this file.
Instead what we would do
is we would create a new file called .env.example,
and that would contain "DATABASE_URL="
and then nothing.
That way we can share this file with other coders,
and they'll know that they have to create a .env file
with this value in it, and a valid database URL.
So again, we would not share our .env file,
we would share .env.example.
Similarly, if you are zipping your code up
and sending it to someone else or something like that,
make sure to not include your .env file in there,
since that would give them access to your database.
So, let's do this in our code.
We'll create the .env and .env.example files,
we will instal python-dotenv
and we'll load the environment variables
when we start the app,
and we will use the environment variable value
as our connection string.
Note that when you're installing python-dotenv,
you may also see a couple other libraries, such as .env,
and make sure to not instal those.
Instal python-dotenv.
I'll guide you through how to do that just now.
All right, so here we are in PyCharm,
and as I mentioned,
I've copied everything from our movie watch list project
in the last section over here.
Now the first thing to do is to instal python-dotenv.
So, we're gonna go over to file, settings,
or preferences on the Mac,
and find the project interpreter section,
click the plus icon,
and type python-dotenv,
make sure to not instal just .env,
and we're gonna instal this package.
This is just really a helper to load the .env file
and make it into environment variables
that our computer understand.
So now that we've got that,
we are going to go ahead and make use of it.
But first, we have to create our .env file.
So, we're gonna create a new file,
just an empty file here,
and call it .env.
Notice that PyCharm is gonna ask you,
you know, what sort of file is this?
And we can just say text, don't worry about it,
it's gonna be a very simple file.
And you may see the plugins supported,
and you can instal plugins,
and that's gonna give you a bit of syntax highlighting,
I wouldn't worry about it.
Here we're gonna put our DATABASE_URL,
and then an equals sign,
and then the value that you copy from ElephantSQL.
So I've put it in here,
then we're also gonna right click again,
create a new file and call it .env.example,
again the same thing up here,
but we can just click okay,
and then here we're gonna put DATABASE_URL=, nothing.
So these are our two files,
remember the .env file,
we're never going to share with other people.
So if you were using Git for this project,
you would now ignore the .env file
using the .gitignore config file.
But, we're not doing that at the moment,
so I won't bore you with all those details.
So, here we've got the rest of our code.
Now, we have to load the .env file
when we run this code.
So, let's go over to our database.py file,
and we need to import a couple of things,
we're gonna do import os,
we're gonna stop importing sqlite3,
and instead we're gonna import psycopg2,
and then we're gonna do from dotenv, import load_dotenv,
and then immediately after, we're going to run it.
load_dotenv can take a few arguments,
as PyCharm will kindly tell you
when you stop typing in there,
but if you leave it empty, it's going to try to load
the dotenv file in your root folder,
which is what we've got,
so we don't really have to do anything
other than call this function.
When that happens, any code after this one
will be able to use those environment variables.
Any code that runs before this runs
will not be able to use the environment variables.
So, that's why we do this at the top,
and then when we connect to our database down here,
we're going to be able to use
the environment variable to connect.
So, just to recap, python-dotenv is going to load
our dotenv file and make it available to us,
after we run load_dotenv.
Then, down here, we're going to use
the environment variable to load up the connection string,
and then give it to psycopg2 to connect.
So, how do we connect with psycopg2?
Well, we just do psycopg2.connect,
and then we pass in the connection string here.
The connection string we can access with the os library.
This is part of the standard library,
so nothing to instal there, and we can do os.environ,
for environment variable, then inside square brackets,
because this is a dictionary, we put in DATABASE_URL.
And that is gonna get the DATABASE_URL key
from the environ dictionary in the os package,
and give it to us so that we can connect to it.
All right, so I mentioned earlier on in the course,
that whenever we use psycopg2,
we need to create cursors,
and we can't do just connection.execute
as we have been doing, so we're gonna have to
change a few things in here,
but let's do that in the next video.
Thank you guys for joining me, I'll see you soon.