I have Wordpress 5.8.3 (from package center) installed om my synology nas. Also installed "Application passwords" plugin to create passwords.
I created this simple python script:
import requests
import base64
wordpress_user = "blabla"
wordpress_password = "6xxx xxx xxxx xxxt xxx xxxx"
wordpress_credentials = wordpress_user + ":" + wordpress_password
wordpress_token = base64.b64encode(wordpress_credentials.encode())
wordpress_header = {'Authorization': 'Basic ' + wordpress_token.decode('utf-8')}
def read_wordpress_posts():
api_url = 'http://192.xxx.x.x/wordpress/wp-json/wp/v2/posts'
response = requests.get(api_url)
response_json = response.json()
print(response_json)
def create_wordpress_post():
api_url = 'http://192.xxx.x.x/wordpress/wp-json/wp/v2/posts'
data = {
'title' : 'Example wordpress post',
'status': 'publish',
'slug' : 'example-post',
'content': 'This is the content of the post'
}
response = requests.post(api_url,headers=wordpress_header, json=data)
print(response)
#read_wordpress_posts()
create_wordpress_post()
The read works but the create gives an 401 error
My nas uses an http connection
What could be the problem here?
AM building a USSD application, in Django with this API https://documenter.getpostman.com/view/7705958/UyrEhaLQ#intro. I get the responses from the API and initialize the data to be processed. But I don't get the menu (MSG) to display on the user phone successfully. The error I get is invalid(empty) response. This is the response to the user’s request. The content provider should provide a response to the request in the same format.
USERID = This is the ID provided by NALO to the client
MSISDN = The mobile number of the user
MSG =This is a mandatory parameter that holds the message to be displayed on the user’s phone
MSGTYPE = This indicates whether the session should continue or be terminated (True/false)
#csrf_exempt
def ussd(request):
if request.method == 'GET':
html = "<html><body>Nothing here baby!</body></html>"
return HttpResponse(html)
elif request.method == 'POST':
url = "https://99c9-102-176-94-213.ngrok.io/ussd"
response_data = json.loads(request.body)
code_id = response_data["USERID"]
serviceCode = response_data["MSISDN"]
type = response_data["MSGTYPE"]
session_id = response_data["SESSIONID"]
text = response_data["USERDATA"]
msg = ""
if text == "":
msg = "Welcome To TEST Dev"
elif text == "1":
msg = "This is Test Two"
payload ={
"USERID": code_id,
"MSISDN": serviceCode,
"MSGTYPE": type,
"USERDATA": text,
"SESSIONID": session_id,
"MSG": msg,
}
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=json.dumps(payload))
return HttpResponse(response, status=200)
Package versioning
Flask 1.0.2
Flask-HTTPAuth 3.2.4
Flask-RESTful 0.3.8
itsdangerous 0.24
I'm working on a API project where a POST request to a Todo resource requires an user to have a token. Upon trying to test for this scenario, I'm getting the following assertion error: AssertionError: 401 != 201. Both BasicHTTPAuth and TokenHTTPAutth from flask-HTTPAuth are handling Authorization credentials.
Based on a User having a token to access this resource, I'm not clear on why I'm getting an Unauthorized error.
tests.py
class TestAuthenicatedUserPostTodo(ApiTestCase):
'''Verify that an API user successfully adds a Todo'''
def setUp(self):
super().setUp()
previous_todo_count = Todo.select().count()
user = User.get(User.id == 1)
token_serializer = Serializer(SECRET_KEY)
self.token = token_serializer.dumps({'id': user.id})
def test_todo_collection_post_todo_success(self):
with app.test_client() as client:
http_response = client.post(
"/api/v1/todos/",
headers={
'Authorization': f"Bearer {self.token}"
},
content_type="application/json",
data={
"name": "Must do a todo",
"user": 1
}
)
current_todo_count = Todo.select().count()
self.assertEqual(http_response.status_code, 201)
self.assertGreater(current_todo_count, previous_todo_count)
auth.py
basic_auth = HTTPBasicAuth()
token_auth = HTTPTokenAuth(scheme="Bearer")
auth = MultiAuth(token_auth, basic_auth)
#basic_auth.verify_password
def verify_password(username, password):
try:
api_user = User.get(User.username == username)
except User.DoesNotExist:
return False
user_verified = api_user.check_password(password)
if user_verified:
g.user = api_user
return True
return False
#token_auth.verify_token
def verify_token(token):
timed_serializer = Serializer(SECRET_KEY)
try:
user = timed_serializer.loads(token)
api_user = User.get_by_id(user['id'])
except (SignatureExpired, BadSignature) as e:
abort(400, description=str(e))
return True
todo.py
#auth.error_handler
def errorhandler():
return jsonify(unauthorized="Cannot add Todo. Login required."), 401
class TodoCollection(Resource):
#auth.login_required
def post(self):
import pdb; pdb.set_trace()
args = self.request_parser.parse_args()
if not args['name']:
return make_response(
{'invalid_request': "Invalid todo provided"}, 400
)
new_todo = Todo.create(**args)
return (
marshal(set_todo_creator(new_todo), todo_fields, 'new_todo'),
201, {'Location': f'{new_todo.location}'}
)
I am trying to upload a pdf generated in Python as an attachment to a salesforce object using the simple_salesforce Python package. I have tried several different ways to accomplish this, but have had no luck so far. Here is the code
import base64
import json
from simple_salesforce import Salesforce
instance = ''
sessionId = sf.session_id
def pdf_encode(pdf_filename):
body = open(pdf_filename, 'rb') #open binary file in read mode
body = body.read()
body = base64.encodebytes(body)
body = pdf_encode('PDF_Report.pdf')
response = requests.post('https://%s.salesforce.com/services/data/v29.0/sobjects/Attachment/' % instance,
headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer %s' % sessionId },
data = json.dumps({
'ParentId': parent_id,
'Name': 'test.txt',
'body': body
})
)
I get this error.
TypeError: Object of type bytes is not JSON serializable
I have also tried to use
body = base64.encodebytes(body).decode('ascii')
in my code, but I can't get that to work either. I get the error
UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)
Any suggestions on how to upload a PDF in Python 3 into Salesforce as an attachment using simple_salesforce?
I was working on this and found a few resources to upload files. I created one for myself using that.
Below is the code that you can use for Python and have the file uploaded on Salesforce.
import requests
import base64
import json
params = {
"grant_type": "password",
"client_id": "Your_Client_Id",
"client_secret": "Your_Client_Secret",
"username": "YOUR_EMAIL#procureanalytics.com.pcsandbox", # The email you use to login
"password": "YOUR_PASSWORD+YOUR_SECURITY_TOKEN" # Concat your password and your security token
}
r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)
# if you connect to a Sandbox, use test.salesforce.com instead
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
print("Access Token:", access_token)
print("Instance URL", instance_url)
#######################################################################################
# Helper function
#######################################################################################
def sf_api_call(action, parameters = {}, method = 'get', data = {}):
"""
Helper function to make calls to Salesforce REST API.
Parameters: action (the URL), URL params, method (get, post or patch), data for POST/PATCH.
"""
headers = {
'Content-type': 'application/json',
'Accept-Encoding': 'gzip',
'Authorization': 'Bearer %s' % access_token
}
if method == 'get':
r = requests.request(method, instance_url+action, headers=headers, params=parameters, timeout=30)
elif method in ['post', 'patch']:
r = requests.request(method, instance_url+action, headers=headers, json=data, params=parameters, timeout=10)
else:
# other methods not implemented in this example
raise ValueError('Method should be get or post or patch.')
print('Debug: API %s call: %s' % (method, r.url) )
if r.status_code < 300:
if method=='patch':
return None
else:
return r.json()
else:
raise Exception('API error when calling %s : %s' % (r.url, r.content))
# Test connection
print(json.dumps(sf_api_call('/services/data/v40.0/query/', {
'q': 'SELECT Account.Name, Name, CloseDate from Opportunity where IsClosed = False order by CloseDate ASC LIMIT 1'
}), indent=2))
#######################################################################################
# File Upload from directory
#######################################################################################
# 1) Create a ContentVersion
path = "Folder_name\Sample_pdf.pdf"
with open(path, "rb") as f:
encoded_string = base64.b64encode(f.read()).decode("utf-8")
ContentVersion = sf_api_call('/services/data/v40.0/sobjects/ContentVersion', method="post", data={
'Title': 'Sample_pdf file',
'PathOnClient': path,
'VersionData': encoded_string,
})
ContentVersion_id = ContentVersion.get('id')
# 2) Get the ContentDocument id
ContentVersion = sf_api_call('/services/data/v40.0/sobjects/ContentVersion/%s' % ContentVersion_id)
ContentDocument_id = ContentVersion.get('ContentDocumentId')
# 3) Create a ContentDocumentLink
Id = "Abcd123" # This Id can be anything: Account_Id or Lead_Id or Opportunity_Id
ContentDocumentLink = sf_api_call('/services/data/v40.0/sobjects/ContentDocumentLink', method = 'post', data={
'ContentDocumentId': ContentDocument_id,
'LinkedEntityId': Id,
'ShareType': 'V'
})
How to use
Step 1:
Key in your email address and password here. Please note that the password here is a string of 'your password' and your 'security token'.
# Import libraries
import requests
import base64
import json
params = {
"grant_type": "password",
"client_id": "Your_Client_Id",
"client_secret": "Your_Client_Secret",
"username": "YOUR_EMAIL#procureanalytics.com.pcsandbox", # The email you use to login
"password": "YOUR_PASSWORD+YOUR_SECURITY_TOKEN" # Concat your password and your security token
}
r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)
# if you connect to a Sandbox, use test.salesforce.com instead
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
print("Access Token:", access_token)
print("Instance URL", instance_url)
You can get your security token on Salesforce through Account >> Settings >> Reset My Security Token.
You will receive an email from salesforce with your security token.
Step 2:
Choose appropriate link for request.post
For Sandbox environment:
r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)
For Production enviroment:
r = requests.post("https://login.salesforce.com/services/oauth2/token", params=params)
After your initial connection is ready, the output on the second cell should look something like this:
Access Token: !2864b793dbce2ad32c1ba7d71009ec84.b793dbce2ad32c1ba7d71009ec84
Instance URL https://your_company_name--pcsandbox.my.salesforce.com
Step 3:
Under the 'File upload from a directory' cell (Cell #5), specify your file path.
In my case, this is
# 1) Create a ContentVersion
path = "Folder_name\Sample_pdf.pdf"
with open(path, "rb") as f:
encoded_string = base64.b64encode(f.read()).decode("utf-8")
Step 4:
Under the same cell, mention the Id in which you would like to upload your file.
The sample code below is uploading a file on Accounts object for an account with Id: Abcd123
# 3) Create a ContentDocumentLink
Id = "Abcd123" # This Id can be anything: Account_Id or Lead_Id or Opportunity_Id
ContentDocumentLink = sf_api_call('/services/data/v40.0/sobjects/ContentDocumentLink', method = 'post', data={
'ContentDocumentId': ContentDocument_id,
'LinkedEntityId': Id,
'ShareType': 'V'
})
I am using token based authentication to restrict the access to user for my site, I am getting following error
{"_status": "ERR", "_error": {"message": "Please provide proper credentials", "code": 401}}weber#weber-desktop:/var/www/lunar-cloud-web-ui/kukunako$
my sample code shown below.
class TokenAuth(TokenAuth):
def check_auth(self, token, allowed_roles, resource, method):
accounts = app.data.driver.db['people']
return accounts.find_one({'token': token})
app = Eve(__name__,static_url_path='/static', auth = TokenAuth)
app.debug = True,
app.config.update(
DEBUG=True,
#EMAIL SETTINGS
MAIL_SERVER='smtp.gmail.com',
MAIL_PORT=465,
MAIL_USE_SSL=True,
MAIL_USERNAME = '<username>',
MAIL_PASSWORD = '<password>'
)
mail=Mail(app)
socketio = SocketIO(app)
def create_token(user):
payload = {
'sub': str(user['_id']),
'iat': datetime.now(),
'exp': datetime.now() + timedelta(days=14)
}
token = jwt.encode(payload, TOKEN_SECRET)
return token.decode('unicode_escape')
def login_required(f):
#wraps(f)
def decorated_function(*args, **kwargs):
if not request.headers.get('Authorization'):
response = jsonify(error='Missing authorization header')
response.status_code = 401
return response
payload = parse_token(request)
if datetime.fromtimestamp(payload['exp']) < datetime.now():
response = jsonify(error='Token has expired')
response.status_code = 401
return response
g.user_id = payload['sub']
return f(*args, **kwargs)
return decorated_function
#app.route('/auth/login', methods=['POST'])
def login():
accounts = app.data.driver.db['people']
user = accounts.find_one({'email': request.json['email']})
if not user:
response = jsonify(error='Your email does not exist')
response.status_code = 401
return response
if not user['email_confirmed'] == True:
response = jsonify(error='Email is not confirmed')
response.status_code = 401
return response
if not user or not check_password_hash(user['password']['password'], request.json['password']):
response = jsonify(error='Wrong Email or Password')
response.status_code = 401
return response
token = create_token(user)
return jsonify(token=token)
my all code is show in following for settings file and server code file
settings file
server code file
How are you testing it?
I can think of two possible problems.
JWT token needs to be base64 encoded
You may have forgotten : at the end
e.g. If your token is as follows (Taken from jwt.io site)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
You need to do the following:
$ echo 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ:' | base64
ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnpkV0lpT2lJeE1qTTBOVFkzT0Rrd0lpd2libUZ0WlNJNklrcHZhRzRnUkc5bElpd2lZV1J0YVc0aU9uUnlkV1Y5LlRKVkE5NU9yTTdFMmNCYWIzMFJNSHJIRGNFZnhqb1laZ2VGT05GaDdIZ1E6Cg==
Now use this as follows (with curl)
curl -H "Authorization Basic ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnpkV0lpT2lJeE1qTTBOVFkzT0Rrd0lpd2libUZ0WlNJNklrcHZhRzRnUkc5bElpd2lZV1J0YVc0aU9uUnlkV1Y5LlRKVkE5NU9yTTdFMmNCYWIzMFJNSHJIRGNFZnhqb1laZ2VGT05GaDdIZ1E6Cg==" http://127.0.0.1:5000/my_secure_endpoint