when i print the id before returning, the code print the right value ( same with id in mongo ).
but the client received a deferent id.
my query code :
def resolve_account(root, info, **kwargs):
email = kwargs.get('email', None)
password = kwargs.get('password', None)
accounts = AccountModel.objects(email=email, password=password)
if accounts.first() is None:
return ResponseMessageField(is_success=False, message="Not found")
print(accounts[0].id)
return AccountResults(accounts=[AccountField(id=account.id,
name=account.name)
for account in accounts])
console printed : `5e5f28a41e92b7cdb5cf30ea'
but my client received :
{
"data": {
"accountLogin": {
"accounts": [
{
"name": "test1",
"id": "QWNjb3VudEZpZWxkOjVlNWYyOGE0MWU5MmI3Y2RiNWNmMzBlYQ=="
}
]
}
}
}
python 3.6.9
mongoengine 0.1.9
graphene 2.1.8
graphene_mongo 0.1.1
flask 1.1.1
This is acutally an adavantage of graphene-django, if you're using auto-increment ID's.
Anyway it encodes them using base64 encoding, to get the real value, you can do
this in vanilla JS:
>> atob('QWNjb3VudEZpZWxkOjVlNWYyOGE0MWU5MmI3Y2RiNWNmMzBlYQ==')
>> "AccountField:5e5f28a41e92b7cdb5cf30ea"
So if you want to mutate something, and you have the ID, which is not bas64 encoded, what you'll have to do is:
>> btoa("AccountField:5e5f28a41e92b7cdb5cf30ea")
>> "QWNjb3VudEZpZWxkOjVlNWYyOGE0MWU5MmI3Y2RiNWNmMzBlYQ=="
In python, graphene provides an import, to_global_id and from_global_id to convert to and fro b/w base64 encoded values and the real IDs.
Related
I have attached the code. I want chat_id to be accessed from the text file located at my local machine.
#constants.py
chatid_list = []
file1 = open(r'D:\\folder1\\chatids.txt', "r")
for chat_id in file1:
chatid_list.append(chat_id)
#main.py
def start(update, context):
chat_id = update.message.chat_id
first_name =update.message.chat.first_name
last_name = update.message.chat.last_name
username = update.message.chat.username
if chat_id in cp.chatid_list:
print("chat_id : {} and firstname : {} lastname : {} username {}". format(chat_id, first_name, last_name , username))
context.bot.send_message(chat_id, 'Hi ' + first_name + ' Whats up?')
update.message.reply_text( text=main_menu_message(),reply_markup=main_menu_keyboard())
else:
print("WARNING: Unauthorized access denied for {}.".format(chat_id))
update.message.reply_text('User disallowed.')
My guess would be that the elements of chatid_list are strings because you read them from a text file, but chat_id is an integer. So you'd either have to convert chat_id to a string or the elements of chatid_list to integers.
As a cleaner alternative, you could consider using environment variables (e.g. with dotenv) to add configuration elements like the chat IDs (as strings, as noted by #CallMeStag).
That would remove the necessity of having to format and read a file for that purpose. In this case, you can have a .env file in the same directory with:
#.env file
# allowed ids - users allowed to use bot
ALLOWED_IDS = 12345678, 24567896
I'm assuming you're using python 3 and can use f-strings.
So, you can throw your constants.py away and your main.py would look like below:
#main.py file
import os
from dotenv import load_dotenv
load_dotenv()
def start(update, context):
chat_id = update.message.chat_id
first_name = update.message.chat.first_name
last_name = update.message.chat.last_name
username = update.message.chat.username
if chat_id in os.getenv('ALLOWED_IDS'):
print(f'chat_id : {chat_id } and firstname : {first_name } lastname : {last_name } username {username }')
context.bot.send_message(chat_id, f'Hi {first_name}, Whats up?')
update.message.reply_text(text=main_menu_message(),reply_markup=main_menu_keyboard())
else:
print(f'WARNING: Unauthorized access denied for {chat_id}.')
update.message.reply_text('User disallowed.')
Finally, in case you want multiple functions to be "protected", you can use a wrapper as shown here.
Edit: added alternative local file types after OP's comment.
You could also store your allowed users in a JSON (ids.json):
{
"allowed_users": [
{
"name": "john wick",
"id": 1234567
},
{
"name": "rick wick",
"id": 2345738
}
]
}
And then read the allowed IDs as follows:
import json
with open(r'./ids.json', 'r') as in_file:
allowed_users = json.load(in_file)['allowed_users']
allowed_ids = [user['id'] for user in allowed_users]
OR, you could simply drop all the IDs into a text file (ids.txt), with one ID per line:
1234567
2345738
And then read them as follows:
allowed_ids = []
with open(r'./ids.txt', 'r') as in_file:
for row in in_file:
allowed_ids.append(int(row.strip()))
Finally, replace os.getenv('ALLOWED_IDS') from the above code snippet with allowed_ids.
I have a problem with my AWS python code.
I am trying to send a post request to my code on AWS but I have key problems
My code on AWS
import json
import random
def lambda_handler(event, context):
name = surname = birthDate = favoriteFilm = password = ""
indexList = keysArray = []
setParams(event, name, surname, birthDate, favoriteFilm)
fillArray(keysArray, name, surname, birthDate, favoriteFilm)
arrayLength = len(keysArray)
while len(password)<6:
index = getRandomRangeIndex(arrayLength)
if index in indexList:
continue
password = password + keysArray[index]
indexList.append(index)
return {
'statusCode': 200,
'body': json.dumps(password)
}
def setParams(event, name, surname, birthDate, favoriteFilm):
name = event['first_name']
surname = event['last_name']
birthDate = event['d_o_b']
favoriteFilm = event['favorite_film']
def fillArray(keysArray, name, surname, birthDate, favoriteFilm):
for names in name.split():
keysArray.append(names)
keysArray.append(surname)
for dates in birthDate.split('-'):
keysArray.append(dates)
for films in favoriteFilm.split():
keysArray.append(films)
def getRandomRangeIndex(arrayLength):
return random.randint(0, arrayLength-1)
My Postman request header
{
"first_name": "John",
"last_name": "Smith",
"d_o_b": "1985-12-04",
"favorite_film": "Back to the Future"
}
My problem log
[ERROR] KeyError: 'first_name'
Traceback (most recent call last):
File "/var/task/password.py", line 7, in lambda_handler
setParams(event, name, surname, birthDate, favoriteFilm)
File "/var/task/password.py", line 24, in setParams
name = event['first_name']
I am not able to find any solution. How can I fix this problem? Thank you.
When you submit your json though api gateway, the event object that your function receives is different than what you submit. The format is shown in aws docs.
In your case the event will be something like this:
{
"resource": "/test",
"path": "/test",
"httpMethod": "POST",
#
# a banch of data removed for length
#
"body": "{\n \"first_name\": \"John\",\n \"last_name\": \"Smith\",\n \"d_o_b\": \"1985-12-04\",\n \"favorite_film\": \"Back to the Future\"\n}",
"isBase64Encoded": false
}
Thus, to get your actual data and you have to parse body you can use python's ast. You body is not json string, thus need to use ast:
import json
import random
import ast
def lambda_handler(event, context):
# overwrite event to keep using event in later parts of your code
event = ast.literal_eval(event['body'])
#....
I have a json file with values - {"testID":"smoke_01","testID":"smoke_02","testID":"smoke_04"}.
I read the values for testID and saved to array. Now I was trying to make it as a simple string like -
testcase = smoke_01,smoke_02,smoke_02. My code is below :
def props = readJSON file: 'input.json'
def list = []
props.each { key, value ->
list.push("$value")
}
echo "$list"
def asString = list.join(", ")
def testcase = asString.join(", ")
But when i print testcase - its printing as [smoke_01, smoke_02, smoke_04] . Please help me to understand where I am wrong.
Assuming you really have this invalid strange JSON (keys must be unique in an Object in basically every language you parse to, but yours are not), and that readJSON actually parses your custom JSON into something you can iterate over as if it were a Map... then, this should do what you want:
def props = readJSON file: 'input.json'
def testCase = props.values().join(', ')
println testCase
Assuming you use proper JSON
By proper JSON I mean something that does not break JSON semantics, hence can be parsed by any JSON parser, not your custom one.
You JSON file should look more like this:
{ "tests": [
{ "testID": "smoke_01" },
{ "testID": "smoke_02" },
{ "testID": "smoke_03" }
] }
In which case you would parse it with:
def json = new JsonSlurper().parse(new File('input.json'))
def testCase = json.tests.collect { it.testID }.join(', ')
println testCase
There are other ways to represent this in JSON, but you should study how JSON works and what suits you best depending on how it is going to be used.
Here's the JSON spec which is simple enough you can learn it in 20 minutes:
https://www.json.org/json-en.html
I'm trying to remove key pair values if they are not provided in my payload from SQLAlchemy query.
payload1 = {
"username": "James",
"ssn": "102-00-1911",
"state": "New York"
}
payload2 = {
"username": "James"
}
def search_database(body):
"""
Searches Database for user
"""
query = db_session.query(DatabaseModel).filter_by(
username=body['username'],
ssn=body.get('ssn', None), # kwarg should be omitted if it's not in body
state=body.get('state', None), # kwarg should be omitted if it's not in body
).all()
return query
search_database(payload1) # should not omit anything
search_database(payload2) # Should omit `ssn` and `state` from query
Currently I'm unable to find a way to dynamically remove a key pair from my query. I tried passing None as an alternative to the value if a key is missing but that did not work.
If the payload is missing ssn or state I would like to omit it from the query
I realized you can pass a dictionary in filter_by. I was able to filter using a Dict comprehension on the body before passing it to the query.
def search_database(body):
"""
Searches Database for user
"""
permitted = [
"username",
"ssn",
"state"
]
filtered = {key: body[key] for key in permitted if key in body}
query = db_session.query(DatabaseModel).filter_by(**filtered).all()
return query
In using lambda, the docs say you must send a base64 encoded JSON object for the ClientContext. It also says Client Context must be a 'str' not bytes.
http://boto3.readthedocs.io/en/latest/reference/services/lambda.html#Lambda.Client.invoke
Since python3's base64 library now encodes using bytes, not string - this appears to have stumped me.
import boto3
import base64
CLIENT = boto3.client('lambda')
client_context = b'{ "client_name": "Andy"}'
encoded_context = base64.b64encode(client_context)
CLIENT.invoke(
FunctionName='testFunction',
InvocationType='RequestResponse',
LogType='Tail',
ClientContext=encoded_context
)
The error I get is:
Invalid type for parameter ClientContext, value: b'eyAiY2xpZW50X25hbWUiOiJGUkVFSFVCIiB9', type: <class 'bytes'>, valid types: <class 'str'>
or when I set str(encoded_context):
botocore.errorfactory.InvalidRequestContentException: An error occurred (InvalidRequestContentException) when calling the Invoke operation: Client context must be a valid Base64-encoded JSON object.
Thanks in advance.
The code below is an example for passing Client Context via boto3.
import boto3
import base64
import json
client = boto3.client("lambda")
def lambda_context(custom=None,
env=None,
client=None):
client_context = dict(
custom=custom,
env=env,
client=client)
json_context = json.dumps(client_context).encode('utf-8')
return base64.b64encode(json_context).decode('utf-8')
context = {
"custom": {"foo": "bar"},
"env": {"test": "test"},
"client": {}
}
client.invoke(FunctionName="<YOUR_LAMBDA_FUNCTIONS>",
ClientContext=lambda_context(**context),
Payload=YOUR_PAYLOAD)
Note that env and custom in the Client Context dict object could be anything. For client, only the following keys can be accepted:
app_version_name
app_title
app_version_code
app_package_name
installation_id
Btw, if your lambda function is implemented in Python. The Client Context object may be referred as context.client_context. env(context.cilent_context.env) and custom(context.client_context.custom) are two dict objects. If any of env, custom, or client is not passed from boto3's invoke method, the corresponding one in the context.client_context would be a None.
From Lambda.invoke() doesn't send client context · Issue #1388 · aws/aws-sdk-js:
var ctx = {
custom: { foo: 'bar' },
client: { snap: ['crackle', 'pop']},
env: { fizz: 'buzz' },
};
la.invoke({
FunctionName: 'contextPrinter',
ClientContext: AWS.util.base64.encode(JSON.stringify(ctx)),
InvocationType: 'RequestResponse',
Payload: JSON.stringify({ baz: 'quux' })
}, function (err, data) { return console.log(err, data); });
While this is JavaScript rather than Python, it should give a general idea of how to encode context.