When testing my Tridion content delivery web service using a web browser, I can successfully get a list of the available collections by invoking "http://webservice/odata.svc/", however when I try to access one of the collections, for example;
http://webservice/odata.svc/Publications
I get;
<message xml:lang="en-US">Unable to retrieve desired results.</message>
or a specific item
http://webservice/odata.svc/Publications(19)
I get:
<message xml:lang="en-US">Unable to build publication entry:
Unable to retrieve desired results.</message>
In the logs I get the following (I've removed timestamps etc. to make it a bit more readable):
ODataService - ODATA.NET: Resource retrieval: Publications
WebContext - setCurrentClaimStore: com.tridion.ambientdata.dotnet.DotNetClaimStore#576504fa, thread: Thread-5
ODataWebserviceHandler - Requested a OData feed/entry: Publications with type: application/atom+xml
ODataWebserviceHandler - Setting $top to 25
ResolverBase - Requested OData collection
StorageManagerFactory - Loading a non cached DAO for publicationId/typeMapping/itemExtension: 0 / Query / null
JPQLExecutor - Can not create JPAQueryDAO object
com.tridion.broker.StorageException: No Data Access Object for Query
at com.tridion.storage.filesystem.FSDAOFactory.getDAOForTypeMapping(FSDAOFactory.java:177) ~[cd_datalayer.jar:na]
at com.tridion.storage.StorageManagerFactory.getOriginalDAO(StorageManagerFactory.java:450) ~[cd_datalayer.jar:na]
at com.tridion.storage.StorageManagerFactory.getDAO(StorageManagerFactory.java:271) ~[cd_datalayer.jar:na]
at com.tridion.storage.StorageManagerFactory.getDefaultDAO(StorageManagerFactory.java:178) ~[cd_datalayer.jar:na]
at com.tridion.webservices.odata.input.jpql.JPQLExecutor.<init>(JPQLExecutor.java:61) [cd_webservice.jar:na]
at com.tridion.webservices.odata.input.jpql.JPQLExecutor.getExecutor(JPQLExecutor.java:103) [cd_webservice.jar:na]
at com.tridion.webservices.odata.input.resolver.PublicationsResolver.resolveCollection(PublicationsResolver.java:34) [cd_webservice.jar:na]
at com.tridion.webservices.odata.input.resolver.ResolverBase.resolve(ResolverBase.java:74) [cd_webservice.jar:na]
at com.tridion.webservices.odata.input.handler.ODataFeedRenderer.renderODataFeed(ODataFeedRenderer.java:45) [cd_webservice.jar:na]
at com.tridion.webservices.odata.input.handler.ODataWebserviceHandler.handleODataEntity(ODataWebserviceHandler.java:193) [cd_webservice.jar:na]
at com.tridion.webservices.odata.input.handler.ODataWebserviceHandler.handleResourceRequest(ODataWebserviceHandler.java:169) [cd_webservice.jar:na]
FilterValue - check if value: 25 is of Integer type
FilterValue - value: 25 is Integer
JPQLExecutor - JPAQueryDAO has not been instantiated. Probably FS storage type was used.
ResolverBase - Unable to build feed Unable to retrieve desired results.
This message points at my storage configuration, however I have not been able to find any clear guidance in the documentation as to how it should be set up to support the web service.
How should my storage be configured? Is it normal to expect to have a separate deployer for the service and the web site? What other issues should I be considering?
The CD Webservice requires all your content to be in the CD DB. This means nothing on the file system. If you still have stuff on the FS, some parts of the CD Webservice will not work. For example, think about pages that might be on the FS -- you will not be able to retrieve the PageContent via the CD Webservice.
To your problem, check that your CD Webservice cd_storage_conf.xml defines a database (JPA) connection. And of course it is functional. Check the usual suspects, db connection, user, pass, url, JARs...
Edit: Taking a closer look at your stack trace, you must have defined the FS as default storage medium (due to getOriginalDAO(...), yielding a FSDAOFactory.getDAOForTypeMapping(...)). So I think this is the root of the problem. Check also that your license is valid, and that your 'bindings' have not reverted to FS due to missing/expired CD license.
As additional input for others, I was also experiencing the 'Unable to retrieve desired results.' response, and in my case it was due to my cd_licenses.xml not being in the bin/config directory, with the other configuration files.
Related
When running amplify push -y in the CLI, my project errors with this message:
["Index: 0 State: {\"deploy\":\"waitingForDeployment\"} Message: Resource is not in the state stackUpdateComplete"]
How do I resolve this error?
The "Resource is not in the state stackUpdateComplete" is the message that comes from the root CloudFormation stack associated with the Amplify App ID. The Amplify CLI is just surfacing the error message that comes from the update stack operation. This indicates that the Amplify's CloudFormation stack may have been still be in progress or stuck.
Solution 1 – “deployment-state.json”:
To fix this issue, go to the S3 bucket containing project settings and deleted the “deployment-state.json” file in root folder as this file holds the app deployment states. The bucket should end with, or contain the word “deployment”.
Solution 2 – “Requested resource not found”:
Check the status of the CloudFormation stack and see if you can notice that the stack failed because of a “Requested resource not found” error indicating that the DynamoDB table “tableID” was missing and confirm that you have deleted it (possibly accidentally). Manually create the above DynamoDB table and retry to push again.
Solution 3A - “#auth directive with 'apiKey':
If you recieve an error stating that “#auth directive with 'apiKey' provider found, but the project has no API Key authentication provider configured”. This error appears when you define a public authorisation in your GraphQL schema without specifying a provider. The public authorization specifies that everyone will be allowed to access the API, behind the scenes the API will be protected with an API Key. To be able to use the public API you must have API Key configured.
The #auth directive allows the override of the default provider for a given authorization mode. To fix the issue specify “IAM” as the provider which allows to use an "Unauthenticated Role" from Cognito Identity Pools for public access instead of an API Key.
Below is the sample code for public authorisation rule:
type Todo #model #auth(rules: [{ allow: public, provider: iam, operations: [create, read, update, delete] }]) {
id: ID!
name: String!
description: String
}
After making the above changes, you can run “amplify update api” and add a IAM auth provider, the CLI generated scoped down IAM policies for the "UnAuthenticated" role automatically.
Solution 3B - Parameters: [AuthCognitoUserPoolId] must have values:
Another issue could occur here, where the default authorization type is API Key when you run the command “amplify add api” without specifying the API type. To fix this issue, follow these steps:
Deleted the the API
Recreate a new one by specifying the “Amazon Cognito user pool” as the authorization mode
Add IAM as an additional authorization type
Re-enable #auth directive in the newly created API Schema
Run “amplify push”
Documentation:
Public Authorisation
Troubleshoot CloudFormation stack issues in my AWS Amplify project
I deployed JDG on OpenShift Online with the following
- Image stream "jboss-datagrid71-openshift-rhel7.json" v1.2
- username 'admin' with role 'admin' and '___schema_manager'
- And given the permissions of READ, WRITE, EXEC, ADMIN, ALL for both the roles. Tried with just 'ALL' also.
- Refer images, Config-env-vars.png and Cache-env-vars.png within the Info.zip for the environment configurations done. (Available # https://drive.google.com/file/d/12EWF1AUB4d60mP_gmTkN4Qlh2pzzv6xi/view?usp=sharing)
While deploying client-side Java application (basically Hotrod with security enabled and with Protobuf based query feature), we are getting the following exception. Attached the logs from the DataGrid server and client application pods
Caused by: org.infinispan.client.hotrod.exceptions.HotRodClientException: java.lang.SecurityException: ISPN000287: Unauthorized access: subject 'Subject with principal(s): [SimpleUserPrincipal [name=admin], InetAddressPrincipal [address=10.131.14.124/10.131.14.124], admin#ApplicationRealm, admin#ApplicationRealm, ___schema_manager#ApplicationRealm, admin, ___schema_manager]' lacks 'WRITE' permission
FYI,
I use the following version of Infinispan from redhat repository
<version.org.infinispan>8.4.2.Final-redhat-1</version.org.infinispan>
In Java, while creating a Configuration Builder, I did in this way. Full code is available # https://github.com/techtantric/JDG-Remote-Hotrod-Secured
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.addServer()
.host(host)
.port(hotrodPort).security().authentication().serverName("jdg-server").saslMechanism("DIGEST-MD5").callbackHandler(new LoginHandler("admin", "password".toCharArray(), "ApplicationRealm")).enable()
.marshaller(new ProtoStreamMarshaller()); // The Protobuf based marshaller is required for query capabilities
cacheManager = new RemoteCacheManager(builder.build());
Please help us resolving this issue. Thanks in advance.
You should not be touching the ___schema_manager role.
Cosmos DB, API Azure Tables, gives you 2 endpoints in the Overview blade
Document Endpoint
Azure Table Endpoint
An example of (1) is
https://myname.documents.azure.com/dbs/tempdb/colls
An example of (2) is
https://myname.table.cosmosdb.azure.com/FirstTestTable?$filter=PartitionKey%20eq%20'car'%20and%20RowKey%20eq%20'124'
You can create the authorization code for (1) on the client using the prerequest code from this Postman script: https://github.com/MicrosoftCSA/documentdb-postman-collection/blob/master/DocumentDB.postman_collection.json
Which will give you a code like this:
Authorization: type%3Dmaster%26ver%3D1.0%26sig%3DavFQkBscU...
This is useful for playing with the rest urls
For (2) the only code I could find to generate a code that works was on the server side and gives you a code like this:
Authorization: SharedKey myname:JXkSGZlcB1gX8Mjuu...
I had to get this out of Fiddler
My questions
(i) Can you generate a code for case (2) above on the client like you can for case (1)
(ii) Can you securely use Cosmos DB from the client?
If you go to the Azure Portal for a GA Table API account you won't see the document endpoint anymore. Instead only the Azure Table Endpoint is advertised (e.g. X.table.cosmosdb.azure.com). So we'll focus on that.
When using anything but direct mode with the .NET SDK, our existing SDKs when talking to X.table.cosmosdb.azure.com endpoint are using the SharedKey authentication scheme. There is also a SharedKeyLight scheme which should also work. Both are documented in https://learn.microsoft.com/en-us/rest/api/storageservices/authentication-for-the-azure-storage-services. Make sure you read the sections specifically on the Table Service. The thing to notice is that a SharedKey header is directly tied to the request it is associated with. So basically every request needs a unique header. This is useful for security because it means that a leaked header can only be used for a limited time to replay a specific request. It can't be used to authorize other requests. But of course that is exactly what you are trying to do.
An alternative is the SharedKeyLight header which is a bit easier to implement as it just requires a date and the a URL.
But we don't have externalized code libraries to really help with either.
But there is another solution that is much friendly to things like Fiddler or Postman, which is to use a SAS URL as defined in https://blogs.msdn.microsoft.com/windowsazurestorage/2012/06/12/introducing-table-sas-shared-access-signature-queue-sas-and-update-to-blob-sas/.
There are at least two ways to get a SAS token. One way is to generate one yourself. Here is some sample code to do that:
var connectionString = "DefaultEndpointsProtocol=https;AccountName=tableaccount;AccountKey=X;TableEndpoint=https://tableaccount.table.cosmosdb.azure.com:443/;";
var tableName = "ATable";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference(tableName);
await table.CreateIfNotExistsAsync();
SharedAccessTablePolicy policy = new SharedAccessTablePolicy()
{
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(1000),
Permissions = SharedAccessTablePermissions.Add
| SharedAccessTablePermissions.Query
| SharedAccessTablePermissions.Update
| SharedAccessTablePermissions.Delete
};
string sasToken = table.GetSharedAccessSignature(
policy, null, null, null, null, null);
This returns the query portion of the URL you will need to create a SAS URL.
Another, code free way, to get a SAS URL is to go to https://azure.microsoft.com/en-us/features/storage-explorer/ and download the Azure Storage Explorer. When you start it up it will show you the "Connect to Azure Storage" dialog. In that case:
Select "Use a connection string or a shared access signature URI" and click next
Select "Use a connection string" and paste in your connection string from the Azure Portal for your Azure Cosmos DB Table API account and click Next and then click Connect in the next dialog
In the Explorer pane on the left look for your account under "Storage Accounts" (NOT Cosmos DB Accounts (Preview)) and then click on Tables and then right click on the specific table you want to explore. In the right click dialog you will see an entry for "Get Shared Access Signature", click on that.
A new dialog titled "Generate Shared Access Signature" will show up. Unfortunately so will an error dialog complaining about "NotImplemented", you can ignore that. Just click OK on the error dialog.
Now you can choose how to configure your SAS, I usually just take the defaults since that gives the widest access permission. Now click Create.
The result will be a dialog with both a complete URL and a query string.
So now we can take that URL (or create it ourselves using the query output from the code) and create a fiddler request:
GET https://tableaccount.table.cosmosdb.azure.com/ATable?se=2018-01-12T05%3A22%3A00Z&sp=raud&sv=2017-04-17&tn=atable&sig=X&$filter=PartitionKey%20eq%20'Foo'%20and%20RowKey%20eq%20'bar' HTTP/1.1
User-Agent: Fiddler
Host: tableaccount.table.cosmosdb.azure.com
Accept: application/json;odata=nometadata
DataServiceVersion: 3.0
To make the request more interesting I added a $filter operation. This is an OData filter that lets us explore the content. Note, btw, to make filter work both the Accept and DataServiceVersion headers are needed. But you can use the base URL (e.g. without the filter parameter) to make any of the REST API calls on a specific table.
Do be aware that the SAS token is scoped to an individual table. So higher level operations won't work with this SAS token.
I can get notes(real contents, not just metadata) from the evernote API. However, calling notestore->update() always gives me a EDAMUserException.
My php code is below, the arguments are self-explanatory:
//add text to note
//if append=true then the text will be appended to the end, else it will be appended to the start
public function addToNote($new_content, $access_token, $note_store, $note_guid, $append = true){
$note = $note_store->getNote($access_token, $note_guid, true, false, false, false);
$note->content +="<en-note>Note updated</en-note>";
$note_store->updateNote($access_token, $note);
}
I've already did a lot of searching before I asked here, and here are the things I know:
According to: https://dev.evernote.com/doc/articles/permissions.php it says that there are two types of api keys, one is the basic access and one is for full access, I have full access, this is proved by no exception was thrown during $note_store->getNote() call, and I did output the data from that call, I can actually get the contents of the note.
In the same page as 1: "Certain API functions are only available to official Evernote applications and services. These functions are described as such in the API Reference and will throw an EDAMUserException with the error code PERMISSION_DENIED if called by a third-party application." I read the API documentation here: https://dev.evernote.com/doc/reference/NoteStore.html#Fn_NoteStore_updateNote
It does not mention that it is blocked by default.
I think I figured out what was wrong. Evernote actually has its own DTD document format, if the "content" section of the note is not a valid document, then the request is denied. In my case it was not denied because my API key's access level, but because the "content" I gave was not a proper evernote format.
if I set:
$note->content='<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note><div>testing complete!!!</div></en-note>';
Then the note will be successfully updated.
However, for other users that are getting this exception and using the right format, it is most likely:
1.your api key does not have full access, choose the full access option while you request an api key.
2.usually you would start testing on the "sandboxed"(https://sandbox.evernote.com) version of their site, you need to register another account on the sandboxed site(you real evernote account doesn't carry over) and test with that account. If you do not do this, your account will not exist on the sandboxed account and anything you do will not work.
I have a file in my Alfresco (4.1.5) repository of which I want to read the content through the Alfresco services REST API.
For the lookup, I want to use the file path, not the UUID. However, the lookup by path does not work, only the lookup by UUID works. I cannot find the mistake.
This is the file path:
DisplayPath & File Name:
/Company Home/Data Dictionary/Cleaner Configs/cleaner.properties
QNamePath:
/app:company_home/app:dictionary/cm:Cleaner_x0020_Configs/cm:cleaner.properties
Lookup by UUID works with the following REST API url:
http://localhost:8080/alfresco/service/cmis/i/2391adf9-365c-4959-bf30-8f001154c100/content
However, lookup by path only does not work. Neither with the primary path nor the display path:
http://localhost:8080/alfresco/service/cmis/p/app:company_home/app:dictionary/cm:Cleaner_x0020_Configs/cm:cleaner.properties/content?a=false
http://localhost:8080/alfresco/service/cmis/p/Company%20Home/Data%20Dictionary/Cleaner%20Configs/cleaner.properties/content?a=false
I am getting a 404 error in both cases:
Message: 10080001 Unable to find ObjectPathReference[storeRef=workspace://SpacesStore,path=/app:company_home/app:company_home/app:dictionary/cm:Cleaner_x0020_Configs/cm:cleaner.properties]
Exception: org.springframework.extensions.webscripts.WebScriptException - 10080001 Unable to find ObjectPathReference[storeRef=workspace://SpacesStore,path=/app:company_home/app:company_home/app:dictionary/cm:Cleaner_x0020_Configs/cm:cleaner.properties]
Reference:
http://wiki.alfresco.com/wiki/CMIS_Web_Scripts_Reference#Get_Content_.28getContent.29
Gets the content stream for the specified document, or gets a
rendition stream for a specified rendition of a document.
GET /alfresco/service/cmis/p{path}/content{property}?a={attach?}
I found the problem, thanks to #Gagravarr for the hint:
I have to use the display path, but leave out /Company%20Home/ in the path, because the path used in the request url is taken as relative to the /Company%20Home node.
This works:
http://<host:port>/alfresco/service/cmis/p/Data%20Dictionary/Cleaner%20Configs/cleaner.properties/content?a=false