I'm getting the following error when trying to create a hold using the Google Vault API:
HttpError 500 when requesting
https://vault.googleapis.com/v1/matters/{matterId}/holds?alt=json
returned "Internal error encountered."
from google.oauth2 import service_account
import googleapiclient.discovery
SCOPES = ['https://www.googleapis.com/auth/ediscovery']
SERVICE_ACCOUNT_FILE = './serviceaccount.json'
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
delegated_credentials = credentials.with_subject('delegateuser#example.com')
client = googleapiclient.discovery.build('vault', 'v1', credentials=delegated_credentials)
data = { 'name': 'test', 'accounts': [{'email': 'testuser#example.com' }], 'corpus': 'MAIL', 'query': { 'mailQuery': {'terms': 'to:ceo#company.com'} }}
results = client.matters().holds().create(matterId='{matterId}', body=data).execute()
I've replaced the actual matterId string with {matterId}.
Creating matters, listing matters and listing holds work just fine.
I've tried different combinations of fields to include in the request body but the docs are not clear as to which are required...
It turns out you can't use 'email' in holds().create() - you must use accountId, or the 'id' number for the gmail user.
You can use emails to create holds
https://developers.google.com/vault/guides/holds#create_a_hold_for_mail_on_specific_user_accounts_with_a_search_query
Related
When my application runs in the Development environment, the Account ID that Plaid returns will result in an "INVALID_ACCOUNT_ID" error when applied in an Options object that is sent along with the request. The example code is a simple flow that I expect my application to support. It loads in Accounts from Plaid based on the access token and captures the account IDs, and then randomly chooses an account to query Plaid for the current balance.
import os
import random
from typing import Any
import plaid
from plaid.api import plaid_api
from plaid.model.accounts_balance_get_request import AccountsBalanceGetRequest
from plaid.model.accounts_get_request import AccountsGetRequest
from plaid.model.accounts_get_request_options import AccountsGetRequestOptions
# Load in from environ
plaid_env = os.environ.get("PLAID_ENV", "sandbox").title()
client_id = os.environ["PLAID_CLIENT_ID"]
secret = os.environ["PLAID_SECRET"]
access_token = os.environ["ACCESS_TOKEN"]
# Initialize Plaid Client
configuration = plaid.Configuration(
host=getattr(plaid.Environment, plaid_env),
api_key={
"clientId": client_id,
"secret": secret,
},
)
api_client = plaid.ApiClient(configuration)
plaid_client = plaid_api.PlaidApi(api_client)
# Request for all account balances
account_balance_request = AccountsBalanceGetRequest(access_token=access_token)
account_balance_response = plaid_client.accounts_balance_get(account_balance_request)
# Data structure for accounts
accounts = [
{
"account_name": a["official_name"],
"account_id": a["account_id"],
}
for a in account_balance_response["accounts"]
]
# Pick one account to operate on
test_account = random.choice(accounts)
# Request for Account Balance this account's balance
try:
test_account_balance_request = AccountsGetRequest(
access_token=access_token,
options=AccountsGetRequestOptions(account_ids=[test_account["account_id"]]),
)
test_account_balance_response = plaid_client.accounts_get(
test_account_balance_request
)
print(
f"Balance of {test_account['account_name']} is "
f"{test_account_balance_response['accounts'][0]['balances']['current']}"
)
except Exception as e:
print(f"Unable to update balance of account. Error = {e}")
When operating in the Sandbox, this works perfectly fine:
Balance of Plaid Gold Standard 0% Interest Checking is 110.0
When operating in the Development environment, it returns:
Unable to update balance of account. Error = (400)
Reason: Bad Request
HTTP response headers: HTTPHeaderDict({'Server': 'nginx', 'Date': 'Wed, 05 Oct 2022 02:58:30 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': '308', 'Connection': 'keep-alive', 'plaid-version': '2020-09-14'})
HTTP response body: {
"display_message": null,
"documentation_url": "https://plaid.com/docs/?ref=error#invalid-input-errors",
"error_code": "INVALID_ACCOUNT_ID",
"error_message": "one or more of the account IDs is invalid",
"error_type": "INVALID_INPUT",
"request_id": "",
"suggested_action": null
}
While this sample code is redundant, I am experiencing the INVALID_ACCOUNT_ID error on any function that supports account_ids in the options. If I remove the Options objects from offending requests in my application, the requests works. I have reviewed the causes that are cited in the documentation and I'm not convinced any of them relate to this issue. Would anyone be able to help?
I'm trying to implement the EPIC FHIR SMART Backend Services (Backend OAuth 2.0)
on go programming language.
I've created my dev account, uploaded the public key there, and selecting the backend system as the application audience.
I'm pretty sure my jwt token is correct. I've inspected it on jwt.io, the signature is correct. However, I always get this error:
{ "error": "invalid_client", "error_description": null }
I've tried other possible solutions as well such as:
ensuring the expiration date within the jet claim is below 5 minutes
placing the payload in the body with the correct content type, which is application/x-www-form-urlencoded
ensuring to use the sandbox client_id
using the correct jwt sign in method (RS384)
What should I do to resolve this issue?
Btw, I also saw several discussions on the google groups saying that it's worth to wait for one or two days after the dev account is created.
Below is my code. Appreciate the help!
var (
oauth2TokenUrl = "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token"
sandboxClientID = "..."
privateKey = "..."
)
// load private key
signKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(privateKey))
So(err, ShouldBeNil)
// construct jwt claims
now := time.Now()
claims := jwt.MapClaims{
"iss": sandboxClientID,
"sub": sandboxClientID,
"aud": oauth2TokenUrl,
"jti": uuid.New().String(), // fill with reference id
"exp": now.Add(1 * time.Minute).Unix(), // cannot be more than 5 minutes!
}
log.Info(" => claims:", utility.ToJsonString(claims))
// generate signed token using private key with RS384 algorithm
alg := jwt.SigningMethodRS384
signedToken, err := jwt.NewWithClaims(alg, claims).SignedString(signKey)
So(err, ShouldBeNil)
log.Info(" => signed token", signedToken)
// prepare api call payload
payload := map[string]string{
"grant_type": "client_credentials",
"client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
"client_assertion": signedToken,
}
// dispatch the api call
req := resty.New().
R().
EnableTrace().
SetFormData(payload)
res, err := req.Post(oauth2TokenUrl)
So(err, ShouldBeNil)
log.Info(" => response status:", res.StatusCode())
log.Info(" => response header:", res.Header())
log.Info(" => response body:", string(res.Body()))
// parse response
resBody := make(map[string]interface{})
err = json.Unmarshal(res.Body(), &resBody)
So(err, ShouldBeNil)
Fantastic, I got it working now.
The solution is simply waiting! it was confusing because I can't find any explanation about this on the doc, and also the error message is not quite friendly.
in summary, after creating dev app and the public key is uploaded there, we have to wait for a few hours/days, and then the credentials will eventually be usable.
The waiting part is applied to both open epic and app orchard dev accounts.
It seems that Epic has some kind of synchronising mechanism which runs once a day. So waiting after account create is the only solution. Please also note that, in app settings after Endpoint URI change you also have to wait some time.
Error { "error": "invalid_client", "error_description": null } also shows up when redirect_uri param is set to something like localhost:3000.
I encountered this problem too. In my case, I was using "Patients" as the "Application Audience" selected for the Epic SMART on FHIR app. I was able to successfully obtain an authorization code on the test server, but when I attempted to exchange it for an access token I received "invalid_client" error message.
The mistake I made is that the redirect_uri in the HTTP POST must be an absolute URL and must match a redirect URI you have specified for your app. If the redirect URI is invalid, the resulting error message will say "invalid client" (which is misleading).
Here is a sample of the Python code I was using...
data = {
'grant_type': 'authorization_code',
'code': request.GET.get('code'),
'redirect_uri': 'http://127.0.0.1:8000/ehr_connection_complete/', # THIS MUST BE AN ABSOLUTE URL
'client_id': '11111111-2222-3333-4444-555555555555',
}
response = post(url, data)
It felt odd to me that an error with the redirect_uri parameter generates an error message about invalid_client, but it's true with Epic's test FHIR server.
I hope this information helps others.
I am using Python Google Classroom API to retrieve announcements data.
Here is my code.
from fetch import Fetch
from googleapiclient.discovery import build
cred = 'catp.json'
get_credits = Fetch(cred) #fetching credential data
credit = get_credits()
service = build('Classroom', 'v1', credentials=credit)
setup = service.courses()
data = setup.list().execute()['courses']
course_names = []
course_ids = []
for i in range(len(data)):
course_names.append(data[i]['name'])
course_ids.append(data[i]['id'])
announcement_data = setup.announcements().list(courseId=course_ids[0]).execute()
But I receive the following Traceback Error:
Additional Information:
My project is registered under service account.
My role is Owner.
I have students account on Google Classroom.
To check whether the same error would be called if I tried to access announcements from a teachers account I created a Course in Classroom, using my Students account and posted some demo announcements.
The result was the same TracebackError. I also tried getting access to the data using API Explorer from Google, passing the same course ID as an argument. The data was received normally without any errors.
[Edit]
Here is the code for fetching credentials, Fetch(cred):
import os
import pickle
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
class Fetch:
def __init__ (self, credential_filename):
self.scopes = ['https://www.googleapis.com/auth/classroom.courses.readonly',
'https://www.googleapis.com/auth/classroom.announcements',
]
self.path = 'C:/frank/programs/python/google api'
self.credential_file = credential_filename
def __call__(self):
os.chdir(self.path)
token = open('token.pickle', 'rb')
creds = pickle.load(token)
if creds.valid == False:
if creds.expired == True:
creds.refresh(Request())
else:
try:
flow = InstalledAppFlow.from_client_secrets_file(self.credential_file, self.scopes)
creds = flow.run_local_server(port=0)
except FileNotFoundError:
print(f'{self.credential_file} does not exist')
token = open(self.token_file, 'wb')
pickle.dump(creds, token)
return creds
I'm unable to a folder by providing an id to that folder using Boxr gem. Previously I didn't has the enterprise settings as shown in this post which I have now fixed. I'm creating a token using JWT authentication get_user_token method the following way.
token = Boxr::get_user_token("38521XXXX", private_key: ENV.fetch('JWT_PRIVATE_KEY'), private_key_password: ENV.fetch('JWT_PRIVATE_KEY_PASSWORD'), public_key_id: ENV.fetch('JWT_PUBLIC_KEY_ID'), client_id: ENV.fetch('BOX_CLIENT_ID'), client_secret: ENV.fetch('BOX_CLIENT_SECRET'))
I then pass this this token when creating a client.
client = Boxr::Client.new(token)
when I check the current user on client this is what I get:
client.current_user
=> {"type"=>"user",
"id"=>"60853XXXX",
"name"=>"OnlineAppsPoC",
"login"=>"AutomationUser_629741_06JgxiPtPj#boxdevedition.com",
"created_at"=>"2018-10-04T08:41:32-07:00",
"modified_at"=>"2018-10-04T08:41:50-07:00",
"language"=>"en",
"timezone"=>"America/Los_Angeles",
"space_amount"=>10737418240,
"space_used"=>0,
"max_upload_size"=>2147483648,
"status"=>"active",
"job_title"=>"",
"phone"=>"",
"address"=>"",
"avatar_url"=>"https://app.box.com/api/avatar/large/6085300897"}
When I run client.methods I see there is folder_from_id however when I call that method I get the following error:
pry(#<FormsController>)> client.folder_from_id("123456", fields: [])
Boxr::BoxrError: 404: Not Found
from /usr/local/bundle/gems/boxr-1.4.0/lib/boxr/client.rb:239:in `check_response_status'
I have the following settings:
I also authorize the application. Not sure what else to do.
token = Boxr::get_user_token(user_id,
private_key: ENV.fetch('JWT_PRIVATE_KEY'),
private_key_password: ENV.fetch('JWT_PRIVATE_KEY_PASSWORD'),
public_key_id: ENV.fetch('JWT_PUBLIC_KEY_ID'),
client_id: ENV.fetch('BOX_CLIENT_ID'),
client_secret: ENV.fetch('BOX_CLIENT_SECRET'))
client = Boxr::Client.new(token.access_token)
folder = client.folder_from_id(folder_id)
client.upload_file(file_path, folder)
For anybody using C# and BOXJWT.
You just need to have a boxManager set up and will get you with anything you need, say BoxFile, Folder etc.
If you have the folderID, well & good, but if you need to retrieve, this can be done as shown below:
string inputFolderId = _boxManager.GetFolder(RootFolderID).Folders.Where(i => i.Name == boxFolder).FirstOrDefault().Id; //Retrieves FolderId
Folder inputFolder = _boxManager.GetFolder(inputFolderId);
I'm setting up a rocket chat server in an air gapped testbed where I'll have thousands of automated users talking to each other to generate network traffic. I had seen the user import via CSV documented here. That lets me create my users, but not with pre-assigned passwords. Looking in programs/server/packages/rocketchat_importer-csv.js I see that it is setting the password to a formulaic string including the current date.
That's as good as a random password for my needs.
Is there a way to, say, include another column in the CSV where I can assign the password for each user?
I installed it via snaps on Ubuntu 16.04.4 if that affects anything.
In the end, I wrote a python script to do the job making a web request for each line of the CSV. Here's what I came up with:
import csv
import json
import requests
def main(csv_path, admin_user, admin_pass, base_url):
"""
Read the given CSV of the format:
loginname, email, real name, password
and create all the users described in it in the Rocket.Chat server
available at `base_url`
"""
login_json = json.dumps({'username': admin_user, 'password': admin_pass})
response = requests.post(base_url + '/api/v1/login', data=login_json)
data = response.json()['data']
token = data['authToken']
userid = data['userId']
headers = {
'X-Auth-Token': token,
'X-User-Id': userid,
'Content-type': 'application/json',
}
with open(csv_path) as raw:
reader = csv.reader(raw)
for user in reader:
request = {
'username': user[0],
'email': user[1],
'name': user[2],
'password': user[3],
}
ret = requests.post(base_url + '/api/v1/users.create',
data=json.dumps(request), headers=headers)