Keycloak. Put RealmRepresentation using Admin API gives "no String-argument constructor/factory method to deserialize from String value" - jackson

I want to change settings in my realm using the Admin API. The following GET code works
url = keycloak_url + '/admin/realms/master'
headers=...
requests.get(url, headers=headers)
However, when I try to do a PUT, I get a 500 error.
params = dict(registrationAllowed=True, rememberMe=True)
# both below don't work
x = requests.put(url, headers=headers, json=json.dumps(params))
x = requests.put(url, headers=headers, data=params)
The error in the server logs is:
Uncaught server error: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot
construct instance of
org.keycloak.representations.idm.RealmRepresentation (although at
least one Creator exists): no String-argument constructor/factory
method to deserialize from String value ('{"registrationAllowed":
true, "rememberMe": true}') at [Source:
(io.undertow.servlet.spec.ServletInputStreamImpl); line: 1, column: 1]
at
com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at
com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
at
com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)
at
com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
at
com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
at
com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1366)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at
com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1574)
at
com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:965)
at
org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider.readFrom(ResteasyJackson2Provider.java:135)
at
org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.readFrom(AbstractReaderInterceptorContext.java:66)
at
org.jboss.resteasy.core.interception.ServerReaderInterceptorContext.readFrom(ServerReaderInterceptorContext.java:61)
at
org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:56)
at
org.jboss.resteasy.security.doseta.DigitalVerificationInterceptor.aroundReadFrom(DigitalVerificationInterceptor.java:36)
at
...

Silly mistake on my side, it's
x = requests.put(url, headers=headers, json=params)

Related

HTTP error 422 in authentication responses

I have get an error for response 422. May i know how can i resolve this?
class FormsAPI:
def __init__(self, key):
self.authorization_key = personal_forms_authorization_key
def getFormInformation(self, formID):
'''
Get forms details.
return: list_form details
'''
url = 'https://api.bentley.com/forms/'
print(url)
try:
params = {'id': formID
}
headers = {'Accept': 'application/vnd.bentley.itwin-platform.v1+json',
'Authorization': self.authorization_key}
response = requests.get(url, headers=headers, params=params)
print(response)
if(response.status_code == 200):
content = jsonParser(response.text)
list_FormDetails = content
return list_FormDetails
else:
return "error"
except Exception as e:
print(e)
list_FormDetails = FormsAPI.getFormInformation(formID)
See answer from laurynasr for same question at https://github.com/imodeljs/imodeljs/discussions/1626:
422 is returned from the Forms API, not as part of the authentication -- it means that the client provided some parameters that could not be processed. The response payload contains more details.

Pipe request, resend request to another endpoint (make a common endpoint that lead to another endpoint

I want to create a common /me endpoint for all my roles (operators, managers, simple users, etc.) for all 4 methods, GET, POST, DELETE, UPDATE.
I found 2 methods to do it:
Call correspond function inside endpoint (requires to create a separate endpoint for every HTTP method).
Redirection (Allow to create a single function).
That is how it looks:
#router.get(path="/me", status_code=200) # Var 1
async def get_my_profile(
token: str = Depends(config.oauth2_scheme),
postgres_session: AsyncSession = Depends(database.get_db), ):
try:
token_payload = jose_jwt.get_unverified_claims(token=token)
if token_payload['role'] == config.USER_ROLE:
return await routers.users.get_user(user_id=int(token_payload['sub']),
token=token,
postgres_session=postgres_session)
except Exception as error:
services.error_handler(error)
#router.api_router(path="/me", status_code=200, methods=["GET", "POST", "DELETE", "PATCH"]) # Var 2
async def get_my_profile(request: Request, token: str = Depends(config.oauth2_scheme),):
try:
token_payload = services.get_token_payload(token=token)
scheme_ip_port = f'{request.url.scheme}://{request.url.hostname}:{request.url.port}'
urls = [f"{scheme_ip_port}/users/{token_payload['sub']}",
f"{scheme_ip_port}/operators/{token_payload['sub']}",
f"{scheme_ip_port}/clinics/employees/{token_payload['sub']}",
]
for i, url in enumerate(iterable=urls):
if i == token_payload['role']:
return responses.RedirectResponse(url=url)
except Exception as error:
services.error_handler(error)
Which one is preferred to use? What drawbacks every solution has?

Karate framework variable usage

I have this steps:
...
Then status 200
And match response.requests[0].request.url == "/endpoint"
And json body = response.requests[0].request.body
And match body == { "something": "something"}
To simplify, I tried to put response.requests[0].request in a variable called request:
...
Then status 200
And def request = response.requests[0].request
And match request.url == "/endpoint"
And json body = request.body
And match body == { "something": "something"}
I'm having the following error:
'request' is not a variable, use the form '* request <expression>' instead
I read the documentation and the use of request seems to be fine:
Given def color = 'red '
And def num = 5
Then assert color + num == 'red 5'
What am I doing wrong?
Thanks in advance.
Just make this change:
* def req = response.requests[0].request
# other steps
* request req
We simply disallow def request (using request as a variable name) because a lot of newbie users get confused. The error message has worked 99.9% of the time for users to understand what the problem is, but I guess you fall in the 0.1% :)

Getting an invalid token on an interpolated string sent from python/jinga2 backend

I'm sending a variable called apiID from a tornado/jinja2 python file to my vuejs template like this:
class SmartAPIUIHandler(BaseHandler):
def get(self, yourApiID):
doc_file = "smartapi-ui.html"
dashboard_template = templateEnv.get_template(doc_file)
dashboard_output = dashboard_template.render(apiID = yourApiID )
self.write(dashboard_output)
then in vuejs I'm interpolating the variable with no problem except it gives me an error
it says: Uncaught SyntaxError: Invalid or unexpected token
I checked on the python handler file and apipID is a string, so I don't see the problem. I'm quite new to python so maybe the answer is more obvious to one of you. I appreciate the help!!
Because of dashboard_output = dashboard_template.render(apiID = yourApiID ), you must have, in your template, something around the code:
this.apiID = {{ apiID }};
Due to the value being not a number but a string, add the 's:
this.apiID = '{{ apiID }}';

Posting another web query during render_GET or render_POST processing

I have a small web server written using Twisted. One of the things I want to do is have it return a result from another web server as the response to loading a page. That is, the response to render_GET() at server A (via http://A.com/resource) should be the content of a different URL at server B (via http://B.com/resource2). The content returned by server B is dynamic, so I can't just cache it.
Right now, server A can render pages just fine, it just can't render this remote resource. I've tried with Agent(), but I can't seem to get the response from B let alone forward it to A. I know that somewhere I have to take that request from the render_GET and later write() and finish() it. That's done in the cbBody callback, which get called but can't get to the original request to populate it.
Here's a piece of the code for server A's resource handler:
def render_GET(self,request):
# try with canned content just to test the whole thing
bmpServer = BMPServer(ServerBURL,
"xyzzy",
"plugh")
d= bmpServer.postNotification({"a":123},request)
print "Deferred", d
return NOT_DONE_YET
And this is the other code at server A:
theRequest = None
def cbRequest(response,args):
print "response called"
print response
print args
print 'Response version:', response.version
print 'Response code:', response.code
print 'Response phrase:', response.phrase
print 'Response headers:'
print pformat(list(response.headers.getAllRawHeaders()))
d = readBody(response)
d.addCallback(cbBody)
return d
def cbBody(body):
print "Response body:"
print body
theRequest.write(body)
theRequest.finish()
theRequest = None
def cbError(failure):
print type(failure.value), failure # catch error here
print failure.value.reasons[0].printTraceback()
class BMPServer(object):
def __init__(self,url,arg1,arg2):
self.url = url
self.arg1 = arg1
self.arg2 = arg2
def postNotification(self,message,request):
theRequest = request
bmpMessage = {'arg1':self.token,
'arg2':self.appID,
'message':message}
print "Sending request to %s"%self.url
print "Create agent"
agent = Agent(reactor)
print "create request deferred"
print "url = %s" % self.url
d = agent.request('POST', self.url,
Headers({'User-Agent': ['Twisted Web Client Example']}),
MessageProducer(bmpMessage))
print "adding callback"
d.addCallbacks(cbRequest,cbError)
print "returning deferred"
return d
When I run this as a standalone code (outside of the resource, using react() for example), it works fine. However, when I try to include it as shown above it just never seems to receive the data. I've got WireShark running so I can see the response is being returned from Server B, but the data never shows up in cbRequest().
For example, here's the output I see:
Sending request to http://localhost:8888/postMGCMNotificationService
Create agent
create request deferred
url = http://serverB:8888/postService
Message producer: body = {"arg2": "plugh", "arg1": "xyzzy", "message": {"a": 1}}
adding callback
returning deferred
testAgent: returning deferred
<Deferred at 0x10b54d290>
Writing body now
response called
<twisted.web._newclient.Response object at 0x1080753d0>
Response version: ('HTTP', 1, 1)
Response code: 200
Response phrase: OK
Response headers:
Response body:
{"result": false}
^CUnhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/web/_newclient.py", line 1151, in _bodyDataFinished_CONNECTED
self._bodyProtocol.connectionLost(reason)
File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/web/client.py", line 1793, in connectionLost
self.deferred.callback(b''.join(self.dataBuffer))
File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/internet/defer.py", line 382, in callback
self._startRunCallbacks(result)
File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/internet/defer.py", line 490, in _startRunCallbacks
self._runCallbacks()
--- <exception caught here> ---
File "/Library/Python/2.7/site-packages/Twisted-13.1.0_r39314-py2.7-macosx-10.8-intel.egg/twisted/internet/defer.py", line 577, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "AServer.py", line 85, in cbBody
print theRequest
exceptions.UnboundLocalError: local variable 'theRequest' referenced before assignment
Looking at this a little more, it seems that if I could figure out a way to get the request over to cbBody() this would all work just fine.
You can pass extra arguments to callbacks on a Deferred:
d.addCallback(f, x)
When d fires, the result is f(result of d, x). You can pass as many positional or keyword arguments as you like this way. See the API documentation for Deferred for more details.