Django Stripe API Key Issues - python

I have these lines (among other things) in my Django base settings file:
import os
STRIPE_PUBLIC_KEY = os.environ.get("STRIPE_PUBLIC_KEY", "your publishable test key")
STRIPE_SECRET_KEY = os.environ.get("STRIPE_SECRET_KEY", "your secret test key")
I created those two environment variables in my virtualenv like this:
export STRIPE_SECRET_KEY="sk_test_example"
export STRIPE_PUBLIC_KEY="pk_test_example"
When I run env | grep STRIPE, I get this:
STRIPE_SECRET_KEY=sk_test_example
STRIPE_PUBLIC_KEY=pk_test_example
But for some reason, I keep getting this Stripe error: ""Invalid API Key provided: \"\u003C**** ****** **** key\u003E\". This key contains at least one space. Please delete the spaces and try again."
I tried exporting the environment variables again, once without quotation marks and once with single quotation marks, and I got the same result, so I tried printing the STRIPE_SECRET_KEY and STRIPE_PUBLIC_KEY from the settings file, and it returned the defaults, "your publishable test key" and "your secret test key". So that's why there were spaces. But why weren't the environment variables getting picked up?
So I tried getting rid of the defaults in my base settings so the variables look like this:
STRIPE_PUBLIC_KEY = os.environ.get("STRIPE_PUBLIC_KEY")
STRIPE_SECRET_KEY = os.environ.get("STRIPE_SECRET_KEY")
That threw a NoneType error. I also tried the following:
STRIPE_PUBLIC_KEY = os.environ['STRIPE_PUBLIC_KEY']
STRIPE_SECRET_KEY = os.environ['STRIPE_SECRET_KEY']
That threw "KeyError: u'STRIPE_PUBLIC_KEY'". What do I need to change? I really don't want to hard-code these API keys.

It turns out that I'd forgotten (argh) to export the environment variables in my virtualenv postactivate file and was running the server in a different window, so once I put the Stripe API keys in the postactivate file, I needed to deactivate and activate the virtualenv before running the server.

For API keys, the quotes aren't necessary
export STRIPE_SECRET_KEY=sk_test_example
export STRIPE_PUBLIC_KEY=pk_test_example
It looks like the string format constructed with bash quotes is different than what Python is accepting. I don't know what formats these are, but this would definitely make sense.
Alternatively, you might want to look into a "dotenv" implementation such as django-dotenv.
This is a much more reliable way to work with strings like this. The problem is that when you're using different string formats (UTF-8 vs UTF-16 or Unicode), you may run into the situation where some program is expecting one format but receives another. The output you included is an example of what this looks like (hence my concern here).
Hope this helps!

Related

Using error names rather than error codes in pydocstyle's ignore file

My team's repo using pydocstyle to manage doc string standardization. I've been tasked with reformatting the relevant configuration file. Currently it looks something like this:
[pydocstyle]
ignore = D100,D203,D405
match = *.py
but we want something more like:
[pydocstyle]
ignore = "error-name1", "error-name2", "error-name3"
match = *.py
so that it's more obvious to readers what rules are being ignored. However from what I can see this is not mentioned in the documentation (here).
Instead I thought I'd do something like this:
[pydocstyle]
ignore =
D100, # corresponds to "error-name1"
D203, # corresponds to "error-name2"
D405 # corresponds to "error-name3"
match = *.py
But I don't know if this is valid syntax in this file, or how to check.
So my questions are:
Is there a way to the original task I was given (ignore="error-name1" etc)?
If not, would my pseudo-solution work?
Really appreciate any help!
The pseudo-solution is fine. You can test it by just running
pydocstyle --config=name_of_config_file
in console. Note name_of_config_file must conform to one of the standards listed here.

Refer to variables dynamically

Context: I am creating a Django management command which will accept a positional argument. This argument is a location. My goal is to use the location value to refer to a corresponding variable.
I have a global variable named Boston_webhook. This is a simple string which contains a long URL which is just a MSteams webhook...
I have an additional global variable named Budapest_webhook which contains the same data type, but instead refers to a webhook related to the Budapest location.
In my script, a connector variable has to be defined in order to send the message to the correct place.
myTeamsMessage = pymsteams.connectorcard()
If someone entered python manage.py report Boston I want to insert this into the connector params, but I am unsure how to refer to variables dynamically.
Is it possible to refer to Boston_webhook when the location == 'Boston' using some sort of concatenation...?
something like myTeamsMessage = pymsteams.connectorcard(location + _webhook) would be ideal
I would like to avoid using conditionals as it is not scalable. I need to be able to add locations to the database without having to change code...
Use dictionary to map names of webhooks to webhooks itself - like this
webhooks = {
"Boston": "boston url",
"Budapest": "budapest url"
}
Now you can refer to your webhooks like this
# this will give you Boston webhook
myTeamsMessage = pymsteams.connectorcard(location + webhooks["Boston"])
This is simpliest way to do it. I think it would be better to create new class only for this and convert that class to string using a method , but this would be enough if you don't need anything more complex
I was able to determine a suitable solution;
myTeamsMessage = pymsteams.connectorcard(webhooks["{}".format(location)])
where the webhooks are stored in a dictionary keyed by location name.
i.e:
webhooks = {'Boston':'www.url.com',
'Budapest':'www.url1.com',
}
Thanks for the recommendations everyone!

Python Variable For Get Request?

I am trying to move over some API calls I had working over to python from postman, I am having some issues making a variable callable by my next get request. I've found a few things while searching but never found a 100% answer on how to call the environment variable in the get request...is it correct to use the {{TEST}} to call that var. Example below.
Test = Myaccoount
Json_Response_Test = requests.get('https://thisisjustatesttoaccessmyaccount/{{Test}}')
How can I carry over Test into the request?
Your code will almost work as you have it if you use the feature of newer version of Python called "format strings". These are denoted by a f at the beginning of the string. This works like this in such versions of Python:
Test = Myaccoount
Json_Response_Test = requests.get(f'https://thisisjustatesttoaccessmyaccount/{Test}')
as long as Myaccoount is a valid value that can be expanded by Python into the format string.
If you're using an older version of Python, you could do something like this:
Test = Myaccoount
Json_Response_Test = requests.get('https://thisisjustatesttoaccessmyaccount/{}'.format(Test))
BTW, it's not good form to use uppercase first character names for variables. The convention is to use uppercase only for class and type names, and use lowercase for variable and field names.

Changing Django's default list of Common Password

I just try to use Django. when i try to create superuser with the createsuperuser and i try to use some common password like abcd1234 (because abc or 123 isn't allowed), it cannot accept it because apparently that my password is too common, i know that the createsuperuser use somekind of password list to match mine with theirs. I want to ask that whether it is possible to change the password list.
i already tried to open manage.py to find the createsuperuser method but i didnt find it because it only contains run(sys.argv)
You should be able to.
Look for a folder which follows the path:
\Python3\Lib\site-packages\django\contrib\auth or the equivalent on your system.
In it, you should see a file named common-passwords.txt.gz.
Inside it, there will be a file called common-passwords.new.txt
You should just be able to change the passwords on the list. One password per line. Passwords should be entirely lowercase as Django automatically translates passwords to lowercase for comparison against the common password list.
Relevant documentation: https://docs.djangoproject.com/en/2.2/topics/auth/passwords/#django.contrib.auth.password_validation.CommonPasswordValidator
Welcome to Stackoverflow!
You can follow the other answer as well. But you will have to place your password file whenever you change your virtualenv. Here is the way to keep it in the project.
Place your file in project folder where manage.py exists
Open settings.py from your projects folder and add the following
FILE_NAME = "custom_common_password_list.txt"
Create a file custom_common_password.py under projects folder
# projectname/custom_common_password.py
import os
from django.contrib.auth.password_validation import CommonPasswordValidator
from django.conf import settings
class CustomCommonPasswordValidator(CommonPasswordValidator):
def __init__(self):
super().__init__(password_list_path=os.path.join(settings.BASE_DIR, settings.FILE_NAME))
We are basically calling the CommonPasswordValidator with our file path.
Modify the AUTH_PASSWORD_VALIDATORS and add the following:
AUTH_PASSWORD_VALIDATORS = [
# ...
{
'NAME': 'projectname.custom_common_password.CustomCommonPasswordValidator',
},
#...
]
We comment the existing CommonPasswordValidator and place our custom validator. Make sure to replace projectname with your project name.
I would definitely recommend using a safer password.
Why? You don't want hackers to guess your password and hijack your website. Even small websites are targets of large fishing attempts and can be used to spread malware and do bad stuff.
One method that hackers use to gain entrance to your system is by using common password lists. So make sure that you choose a password that is not in such lists.
An easy to remember password which is still safe might consist of several words. As an alternative, you could use a password manager to remember a random string of characters for you.
You can find more suggestions here on how to create safe passwords: https://www.bu.edu/tech/support/information-security/security-for-everyone/how-to-choose-a-strong-password/

grabbing HTTP GET parameter from url using Box API in python

I am dealing with the Box.com API using python and am having some trouble automating a step in the authentication process.
I am able to supply my API key and client secret key to Box. Once Box.com accepts my login credentials, they supply me with an HTTP GET parameter like
'http://www.myapp.com/finish_box?code=my_code&'
I want to be able to read and store my_code using python. Any ideas? I am new to python and dealing with APIs.
This is actually a more robust question than it seems, as it exposes some useful functions with web dev in general. You're basically asking how to separate my_code in the string 'http://www.myapp.com/finish_box?code=my_code&'.
Well let's take it in bits and pieces. First of all, you know that you only really need the stuff after the question mark, right? I mean, you don't need to know what website you got it from (though that would be good to save, let's keep that in case we need it later), you just need to know what arguments are being passed back. Let's start with String.split():
>>> return_string = 'http://www.myapp.com/finish_box?code=my_code&'
>>> step1 = return_string.split('?')
["http://www.myapp.com/finish_box","code=my_code&"]
This will return a list to step1 containing two elements, "http://www.myapp.com/finish_box" and "code=my_code&". Well hell, we're there! Let's split the second one again on the equals sign!
>>> step2 = step1[1].split("=")
["code","my_code&"]
Well lookie there, we're almost done! However, this doesn't really allow any more robust uses of it. What if instead we're given:
>>> return_string = r'http://www.myapp.com/finish_box?code=my_code&junk_data=ohyestheresverymuch&my_birthday=nottoday&stackoverflow=usefulplaceforinfo'
Suddenly our plan doesn't work. Let's instead break that second set on the & sign, since that's what's separating the key:value pairs.
step2 = step1[1].split("&")
["code=my_code",
"junk_data=ohyestheresverymuch",
"my_birthday=nottoday",
"stackoverflow=usefulplaceforinfo"]
Now we're getting somewhere. Let's save those as a dict, shall we?
>>> list_those_args = []
>>> for each_item in step2:
>>> list_those_args[each_item.split("=")[0]] = each_item.split("=")[1]
Now we've got a dictionary in list_those_args that contains key and value for every argument the GET passed back to you! Science!
So how do you access it now?
>>> list_those_args['code']
my_code
You need a webserver and a cgi-script to do this. I have setup a single python script solution to this to run this. You can see my code at:
https://github.com/jkitchin/box-course/blob/master/box_course/cgi-bin/box-course-authenticate
When you access the script, it redirects you to box for authentication. After authentication, if "code" is in the incoming request, the code is grabbed and redirected to the site where tokens are granted.
You have to setup a .htaccess file to store your secret key and id.

Categories

Resources