How to map variable from SPAppToken into AuthorizationCodeTokenRequest - java

I have registered my app engine app with my Office 365 environment and the callback URL is working, I receive an SPAppToken.
I want to get an Access Token using this java class:
http://javadoc.google-oauth-java-client.googlecode.com/hg/1.12.0-beta/com/google/api/client/auth/oauth2/AuthorizationCodeTokenRequest.html
My question is which of the values below map to the values I found in the SPAppToken ?
The credentials in ClientAuthentication are the applicationId and applicationSecret I asume. The redirectURI is to get back to my app.
I think the GenericURL should be populated with https://accounts.accesscontrol.windows.net/tokens/OAuth/2
But the I keep getting: Error: invalid_request
ACS90019: Unable to determine the tenant identifier from the request.
Below is the code xx means a variable that I need to replace and further below the SPAppToken (decoded from base64)
try {TokenResponse response = new AuthorizationCodeTokenRequest(new NetHttpTransport(), new JacksonFactory(), new GenericUrl(**"https://server.example.com/token"**), **"SplxlOBeZQQYbYS6WxSbIA"**).setRedirectUri("https://client.example.com/rd") .setClientAuthentication(new BasicAuthentication(**"s6BhdRkqt3"**, **"7Fjfp0ZBr1KtDRbnfVdmIw"**)).execute();
System.out.println("Access token: " + response.getAccessToken());
} catch (TokenResponseException e) {
if (e.getDetails() != null) {
System.err.println("Error: " + e.getDetails().getError());
if (e.getDetails().getErrorDescription() != null) {
System.err.println(e.getDetails().getErrorDescription());
}
if (e.getDetails().getErrorUri() != null) {
System.err.println(e.getDetails().getErrorUri());
}
} else {
System.err.println(e.getMessage());
}
}
SPAppToken decoded:
{"typ":"JWT","alg":"HS256"}{"aud":"e9e91cd9-0d95-46b7-8a05-f614a683e35d/eog-fire-ice.appspot.com#19d9feae-ba24-4c9e-831c-3132f2ea3974","iss":"00000001-0000-0000-c000-000000000000#19d9feae-ba24-4c9e-831c-3132f2ea3974","nbf":1353777617,"exp":1353820817,"appctxsender":"00000003-0000-0ff1-ce00-000000000000#19d9feae-ba24-4c9e-831c-3132f2ea3974","appctx":"{\"CacheKey\":\"hwqDPFbKDL9mIYpbReWYHeez1uES77UqEsxwienRA9g=\",\"SecurityTokenServiceUri\":\"https://accounts.accesscontrol.windows.net/tokens/OAuth/2\"}","refreshtoken":"IAAAAAi52NL58kY1UUpnmUJ9TPO7BpDSd6NqQGHbdfAEnOgioNbG8AwTGgf-3HPSNrdDexk5UUA3QFox_sky4_uon0XmLl6EfpqsC6RTpiatjJxXzB7EFJrqsiYI98MULyCubxjR5UyQwFzLvEjljEom7XcEXB2YCCWJQQdSRvFU4xo4NIPoUObhyjTK58TaCipUU3D4EiLJRSlkbcm_Y3VrVd8GMoQ8kx6BmJjeaGKZsJXWb7UJ8YTg6L4-HOoAiU3MymJl3oBxv_9rvHDmKb4FJ7vrN8AhJYUqlr9rZxOtG_BVeUX05E-umfoUU4PL2Cj-p7u4YOPo6rqVahovwGwYPn-pZbPfIcTj3TzKZdIk7OLemdR_S8_v0gASEM1Y_KTHsoQ6k-uZaa3QGZN4icu-Jp6Jh4UTRZuomLtkLmg7VVZL6VKpXUVW7RjUopoSEffb5RVmMVNOkNV4_r5NT7pjL0pWAk-uipTF0qLAMzEfr5M9YKNgBlbRbvjlePFz6co5_uOyY8VbfJsIqGhTr1dvW6o","isbrowserhostedapp":"true"}R?????XE??j?2??pZ?????0jLk
----- new info 2012-26-11 ------
After changing the "code" field to contain the refresh token and using the aud entire value instead of just the applicationID I get this message:
ACS50001: The required field 'resource' is missing.
The question is: am I getting closer or not ?
I have also asked this question here: https://groups.google.com/d/topic/google-oauth-java-client/EZtlwDbY_wk/discussion

I modified the com.google.api.client.json.JSONParser.java and put this code in my servlet:
JsonWebSignature jws = JsonWebSignature.parse(new JacksonFactory(), req.getParameter("SPAppToken"));
JsonParser jsonParser = new JacksonFactory().createJsonParser(jws.getPayload().get("appctx").toString());
//Create my own AppTxc that extends GenericJSON
AppCtx appCtx = jsonParser.parse(AppCtx.class, new CustomizeJsonParser());
String appctxsender=jws.getPayload().get("appctxsender").toString();
String[] splitApptxSender = appctxsender.split("#");
//sharepointhost name is part of the resource field
String sharepointServerHostName = new URL(req.getParameter("SPHostUrl")).getHost();
// create the resource field
String resource = splitApptxSender[0]+"/"+sharepointServerHostName+"#"+splitApptxSender[1];
try {
AuthorizationCodeTokenRequest tokenRequest = new AuthorizationCodeTokenRequest(new NetHttpTransport(), new JacksonFactory(),
new GenericUrl(appCtx.getSecurityTokenServiceUri()), jws.getPayload().get("refreshtoken").toString());
tokenRequest.setRedirectUri("https://eog-fire-ice.appspot.com/callback4fireandice");
tokenRequest.setClientAuthentication(
new ClientParametersAuthentication(jws.getPayload().getAudience(), SharePointAppSecret));
tokenRequest.setGrantType("refresh_token");
tokenRequest.set("resource", resource);
tokenRequest.set("refresh_token", jws.getPayload().get("refreshtoken").toString());
TokenResponse response =tokenRequest.execute();
String accesstoken=response.getAccessToken();
} catch (TokenResponseException e) {
if (e.getDetails() != null) {
pw.println("Error: " + e.getDetails().getError());
if (e.getDetails().getErrorDescription() != null) {
pw.println(e.getDetails().getErrorDescription());
}
if (e.getDetails().getErrorUri() != null) {
pw.println(e.getDetails().getErrorUri());
}
} else {
pw.println(e.getMessage());
}
}
I am not sure if all information (like the redirectURL is necessary, but now I have got an accesstoken from Azure ACS.
Thanks to Nick Swan (lightningtools.com) for the initial help based on Ruby on Rails.
On of course thanks to Yaniv Inbar (https://plus.google.com/+YanivInbar/) for providing the google oauth java client library.
I had to raise a bug report though: http://code.google.com/p/google-oauth-java-client/issues/detail?id=62&q=Type%3DDefect&sort=priority&colspec=ID%20Milestone%20Summary

Related

Optimize the code which Copying AWS S3 objects into DB

I have written a code which fetched the S3 objects from AWS s3 using S3 sdk and stores the same in our DB, the only problem is the task is repeated for three different services, the only thing is changed is the instance of service class.
I have copy and pasted code in each service layer just to changes the instance for an instance.
The task is repeated for service classes VehicleImageService, MsilLayoutService and NonMsilLayoutService, every layer is having its own repository.
I am trying to identify a way to accomplish the same by placing that snippet in one place and on an runtime using Reflection API I wish to pass the correct instance and invoke the method, but I want to achieve the same using best industry practices and pattern. I.e. I want to refactor into generic methods for other services, so instance can be passed at runtime.
So kindly assist me on the same.
public void persistImageDetails() {
log.info("MsilVehicleLayoutServiceImpl::persistImageDetails::START");
String bucketKey = null; //common param
String modelCode = null;//common param
List<S3Object> objList = new ArrayList<>(); //common param
String bucketName = s3BucketDetails.getBucketName();//common param
String bucketPath = s3BucketDetails.getBucketPrefix();//common param
try {
//the layoutRepository object can be MSILRepository,NonMSILRepository and VehilceImageRepository
List<ModelCode> modelCodes = layoutRepository.findDistinctAllBy(); // this line need to take care of
List<String> modelCodePresent = modelCodes.stream().map(ModelCode::getModelCode)
.collect(Collectors.toList());
List<CommonPrefix> allKeysInDesiredBucket = listAllKeysInsideBucket(bucketName, bucketPath);//common param
synchDB(modelCodePresent, allKeysInDesiredBucket);
if (null != allKeysInDesiredBucket && !allKeysInDesiredBucket.isEmpty()) {
for (CommonPrefix commonPrefix : allKeysInDesiredBucket) {
bucketKey = commonPrefix.prefix();
modelCode = new File(bucketKey).getName();
if (modelCodePresent.contains(modelCode)) {
log.info("skipping iteration for {} model code", modelCode);
continue;
}
objList = s3Service.getBucketObjects(bucketName, bucketKey);
if (null != objList && !objList.isEmpty()) {
for (S3Object object : AppUtil.skipFirst(objList)) {
saveLayout(bucketName, modelCode, object);
}
}
}
}
log.info("MSIL Vehicle Layout entries has been successfully saved");
} catch (Exception e) {
log.error("Error occured", e);
e.printStackTrace();
}
log.info("MsilVehicleLayoutServiceImpl::persistImageDetails::END");
}
private void saveLayout(String bucketName, String modelCode, S3Object object) {
log.info("Inside saveLayout::Start preparing entity to persist");
String resourceUri = null;
MsilVehicleLayout vehicleLayout = new MsilVehicleLayout();// this can be MsilVehicleLayout. NonMsilVehicleLayout, VehicleImage
vehicleLayout.setFileName(FilenameUtils.removeExtension(FilenameUtils.getName(object.key())));
vehicleLayout.setModelCode(modelCode);
vehicleLayout.setS3BucketKey(object.key());
resourceUri = getS3ObjectURI(bucketName, object.key());
vehicleLayout.setS3ObjectUri(resourceUri);
vehicleLayout.setS3PresignedUri(null);
vehicleLayout.setS3PresignedExpDate(null);
layoutRepository.save(vehicleLayout); //the layoutRepository object can be MSILRepository,NonMSILRepository and VehilceImageRepository
log.info("Exiting saveLayout::End entity saved");
}

Google API returning the server location, not user location

Hello so I though I was getting user location through this code but im actually getting the server's location, any idea how can I change it so I get the user location?
public void geolocate() {
try {
GeolocationPayloadBuilder payloadBuilder = new GeolocationPayload.GeolocationPayloadBuilder();
GeolocationPayload payload = payloadBuilder.createGeolocationPayload();
//GeoApiContext context = new GeoApiContext.Builder().apiKey("my api key").build();
// I guess the payload needs to be build in a different way but no clue how it should be :/
GeolocationApiRequest req = (GeolocationApiRequest) GeolocationApi.geolocate(context, payload);
GeolocationResult res = req.await();
String location = res.location.toString();
String[] latLngArray = location.split(",");
com.google.maps.model.LatLng latLng = new com.google.maps.model.LatLng(Double.parseDouble(latLngArray[0]),
Double.parseDouble(latLngArray[1]));
GeocodingApiRequest geoReq = GeocodingApi.reverseGeocode(context, latLng);
GeocodingResult[] geoRes = geoReq.await();
// Setting the user location for view
System.out.println(geoRes[0].formattedAddress);
origen.setValue(geoRes[0].formattedAddress);
} catch (Exception e) {
System.out.println("Exception in NetClientGet:- " + e);
}
}
this is the dependency where im getting the objects from:
<dependency>
<groupId>com.google.maps</groupId>
<artifactId>google-maps-services</artifactId>
<version>0.9.3</version>
</dependency>
hope somebody can help me with this, thanks in advance
EDIT:
I have been searching and found out how to build the payload with help of https://developers.google.com/maps/documentation/geolocation/intro#cell_tower_object
But I have a couple of question which is how will I get my users mac address to create the wifiAccessPoint and also where do I find info of cell towers in my city (Cali, Colombia)? Just an update will keep searching any help is appreciated..
#POST
#Path("/geolocate")
public String geolocate() {
try {
CellTower newCellTower = new CellTower.CellTowerBuilder().CellId(42).LocationAreaCode(415)
.MobileCountryCode(310).MobileNetworkCode(410).Age(0).createCellTower();
WifiAccessPoint newWifiAccessPoint = new WifiAccessPoint.WifiAccessPointBuilder()
.MacAddress("00:25:9c:cf:1c:ac").createWifiAccessPoint();
WifiAccessPoint newWifiAccessPoint2 = new WifiAccessPoint.WifiAccessPointBuilder()
.MacAddress("00:25:9c:cf:1c:ad").createWifiAccessPoint();
GeolocationPayloadBuilder payloadBuilder = new GeolocationPayload.GeolocationPayloadBuilder()
.HomeMobileCountryCode(310).HomeMobileNetworkCode(410).RadioType("gsm").Carrier("Vodafone")
.ConsiderIp(false).AddCellTower(newCellTower).AddWifiAccessPoint(newWifiAccessPoint)
.AddWifiAccessPoint(newWifiAccessPoint2);
GeolocationPayload payload = payloadBuilder.createGeolocationPayload();
GeoApiContext context = new GeoApiContext.Builder().apiKey("my api key")
.build();
GeolocationApiRequest req = (GeolocationApiRequest) GeolocationApi.geolocate(context, payload);
GeolocationResult res = req.await();
String location = res.location.toString();
String[] latLngArray = location.split(",");
com.google.maps.model.LatLng latLng = new com.google.maps.model.LatLng(Double.parseDouble(latLngArray[0]),
Double.parseDouble(latLngArray[1]));
GeocodingApiRequest geoReq = GeocodingApi.reverseGeocode(context, latLng);
GeocodingResult[] geoRes = geoReq.await();
// Setting the user location for view
return geoRes[0].formattedAddress;
} catch (Exception e) {
System.out.println("Exception in NetClientGet:- " + e);
}
return "XD";
}
The Geolocation API of Google Maps Platform is not intended for getting user location, what I can suggest is that you use the HTML5 Geolocation instead, there's also a sample of that in the Google Maps Platform documentation. But please note that this is not supported by Google as this is using HTML5 Geolocation and not Google APIs, if you wish to get the address of the user location as well, you may Geocode the coordinates that will be returned by the HTML5 Geolocation. You may see the sample below (without the Geocoding function). Here's a working sample - https://jsfiddle.net/w2sad5pn/
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
infoWindow.open(map);
map.setCenter(pos);
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
}

How can I update custom properties in alfresco workflow task using only Java?

First, I want to say thanks to everyone that took their time to help me figure this out because I was searching for more than a week for a solution to my problem. Here it is:
My goal is to start a custom workflow in Alfresco Community 5.2 and to set some custom properties in the first task trough a web script using only the Public Java API. My class is extending AbstractWebScript. Currently I have success with starting the workflow and setting properties like bpm:workflowDescription, but I'm not able to set my custom properties in the tasks.
Here is the code:
public class StartWorkflow extends AbstractWebScript {
/**
* The Alfresco Service Registry that gives access to all public content services in Alfresco.
*/
private ServiceRegistry serviceRegistry;
public void setServiceRegistry(ServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}
#Override
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException {
// Create JSON object for the response
JSONObject obj = new JSONObject();
try {
// Check if parameter defName is present in the request
String wfDefFromReq = req.getParameter("defName");
if (wfDefFromReq == null) {
obj.put("resultCode", "1 (Error)");
obj.put("errorMessage", "Parameter defName not found.");
return;
}
// Get the WFL Service
WorkflowService workflowService = serviceRegistry.getWorkflowService();
// Build WFL Definition name
String wfDefName = "activiti$" + wfDefFromReq;
// Get WorkflowDefinition object
WorkflowDefinition wfDef = workflowService.getDefinitionByName(wfDefName);
// Check if such WorkflowDefinition exists
if (wfDef == null) {
obj.put("resultCode", "1 (Error)");
obj.put("errorMessage", "No workflow definition found for defName = " + wfDefName);
return;
}
// Get parameters from the request
Content reqContent = req.getContent();
if (reqContent == null) {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing request body.");
}
String content;
content = reqContent.getContent();
if (content.isEmpty()) {
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Content is empty");
}
JSONTokener jsonTokener = new JSONTokener(content);
JSONObject json = new JSONObject(jsonTokener);
// Set the workflow description
Map<QName, Serializable> params = new HashMap();
params.put(WorkflowModel.PROP_WORKFLOW_DESCRIPTION, "Workflow started from JAVA API");
// Start the workflow
WorkflowPath wfPath = workflowService.startWorkflow(wfDef.getId(), params);
// Get params from the POST request
Map<QName, Serializable> reqParams = new HashMap();
Iterator<String> i = json.keys();
while (i.hasNext()) {
String paramName = i.next();
QName qName = QName.createQName(paramName);
String value = json.getString(qName.getLocalName());
reqParams.put(qName, value);
}
// Try to update the task properties
// Get the next active task which contains the properties to update
WorkflowTask wfTask = workflowService.getTasksForWorkflowPath(wfPath.getId()).get(0);
// Update properties
WorkflowTask updatedTask = workflowService.updateTask(wfTask.getId(), reqParams, null, null);
obj.put("resultCode", "0 (Success)");
obj.put("workflowId", wfPath.getId());
} catch (JSONException e) {
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
e.getLocalizedMessage());
} catch (IOException ioe) {
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"Error when parsing the request.",
ioe);
} finally {
// build a JSON string and send it back
String jsonString = obj.toString();
res.getWriter().write(jsonString);
}
}
}
Here is how I call the webscript:
curl -v -uadmin:admin -X POST -d #postParams.json localhost:8080/alfresco/s/workflow/startJava?defName=nameOfTheWFLDefinition -H "Content-Type:application/json"
In postParams.json file I have the required pairs for property/value which I need to update:
{
"cmprop:propOne" : "Value 1",
"cmprop:propTwo" : "Value 2",
"cmprop:propThree" : "Value 3"
}
The workflow is started, bpm:workflowDescription is set correctly, but the properties in the task are not visible to be set.
I made a JS script which I call when the workflow is started:
execution.setVariable('bpm_workflowDescription', 'Some String ' + execution.getVariable('cmprop:propOne'));
And actually the value for cmprop:propOne is used and the description is properly updated - which means that those properties are updated somewhere (on execution level maybe?) but I cannot figure out why they are not visible when I open the task.
I had success with starting the workflow and updating the properties using the JavaScript API with:
if (wfdef) {
// Get the params
wfparams = {};
if (jsonRequest) {
for ( var prop in jsonRequest) {
wfparams[prop] = jsonRequest[prop];
}
}
wfpackage = workflow.createPackage();
wfpath = wfdef.startWorkflow(wfpackage, wfparams);
The problem is that I only want to use the public Java API, please help.
Thanks!
Do you set your variables locally in your tasks? From what I see, it seems that you define your variables at the execution level, but not at the state level. If you take a look at the ootb adhoc.bpmn20.xml file (https://github.com/Activiti/Activiti-Designer/blob/master/org.activiti.designer.eclipse/src/main/resources/templates/adhoc.bpmn20.xml), you can notice an event listener that sets the variable locally:
<extensionElements>
<activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
<activiti:field name="script">
<activiti:string>
if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
</activiti:string>
</activiti:field>
</activiti:taskListener>
</extensionElements>
Usually, I just try to import all tasks for my custom model prefix. So for you, it should look like that:
import java.util.Set;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.apache.log4j.Logger;
public class ImportVariables extends AbstractTaskListener {
private Logger logger = Logger.getLogger(ImportVariables.class);
#Override
public void notify(DelegateTask task) {
logger.debug("Inside ImportVariables.notify()");
logger.debug("Task ID:" + task.getId());
logger.debug("Task name:" + task.getName());
logger.debug("Task proc ID:" + task.getProcessInstanceId());
logger.debug("Task def key:" + task.getTaskDefinitionKey());
DelegateExecution execution = task.getExecution();
Set<String> executionVariables = execution.getVariableNamesLocal();
for (String variableName : executionVariables) {
// If the variable starts by "cmprop_"
if (variableName.startsWith("cmprop_")) {
// Publish it at the task level
task.setVariableLocal(variableName, execution.getVariableLocal(variableName));
}
}
}
}

How to create user and group in aem6.2 programmatically with ACL permissions?

Is it possible to create Group and User in AEM6.2 by using Jackrabbit User Manager API with permissions.
I have just followed below URL's but the code is throwing some exception :
https://helpx.adobe.com/experience-manager/using/jackrabbit-users.html
https://stackoverflow.com/questions/38259047/how-to-give-permission-all-in-aem-through-programatically
ResourceResolverFactory getServiceResourceResolver throws Exception in AEM 6.1
As getAdministrativeResourceResolver(Map) method is deprecated then how can we use getServiceResourceResolver(Map) method instead.
Sharing my solution which will be helpful for others.
Following is the code using getServiceResourceResolver(Map) method for creating Group first and then User and then add user into group with ACL privileges and permission:
public void createGroupUser(SlingHttpServletRequest request) {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
String groupName = request.getParameter("groupName");
Session session = null;
ResourceResolver resourceResolver = null;
try {
Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "datawrite");
resourceResolver = resourceResolverFactory.getServiceResourceResolver(param);
session = resourceResolver.adaptTo(Session.class);
// Create UserManager Object
final UserManager userManager = AccessControlUtil.getUserManager(session);
// Create a Group
Group group = null;
if (userManager.getAuthorizable(groupName) == null) {
group = userManager.createGroup(groupName);
ValueFactory valueFactory = session.getValueFactory();
Value groupNameValue = valueFactory.createValue(groupName, PropertyType.STRING);
group.setProperty("./profile/givenName", groupNameValue);
session.save();
log.info("---> {} Group successfully created.", group.getID());
} else {
log.info("---> Group already exist..");
}
// Create a User
User user = null;
if (userManager.getAuthorizable(userName) == null) {
user = userManager.createUser(userName, password);
ValueFactory valueFactory = session.getValueFactory();
Value firstNameValue = valueFactory.createValue("Arpit", PropertyType.STRING);
user.setProperty("./profile/givenName", firstNameValue);
Value lastNameValue = valueFactory.createValue("Bora", PropertyType.STRING);
user.setProperty("./profile/familyName", lastNameValue);
Value emailValue = valueFactory.createValue("arpit.p.bora#gmail.com", PropertyType.STRING);
user.setProperty("./profile/email", emailValue);
session.save();
// Add User to Group
Group addUserToGroup = (Group) (userManager.getAuthorizable(groupName));
addUserToGroup.addMember(userManager.getAuthorizable(userName));
session.save();
// set Resource-based ACLs
String nodePath = user.getPath();
setAclPrivileges(nodePath, session);
log.info("---> {} User successfully created and added into group.", user.getID());
} else {
log.info("---> User already exist..");
}
} catch (Exception e) {
log.info("---> Not able to perform User Management..");
log.info("---> Exception.." + e.getMessage());
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resourceResolver != null)
resourceResolver.close();
}
}
public static void setAclPrivileges(String path, Session session) {
try {
AccessControlManager aMgr = session.getAccessControlManager();
// create a privilege set
Privilege[] privileges = new Privilege[] {
aMgr.privilegeFromName(Privilege.JCR_VERSION_MANAGEMENT),
aMgr.privilegeFromName(Privilege.JCR_MODIFY_PROPERTIES),
aMgr.privilegeFromName(Privilege.JCR_ADD_CHILD_NODES),
aMgr.privilegeFromName(Privilege.JCR_LOCK_MANAGEMENT),
aMgr.privilegeFromName(Privilege.JCR_NODE_TYPE_MANAGEMENT),
aMgr.privilegeFromName(Replicator.REPLICATE_PRIVILEGE) };
AccessControlList acl;
try {
// get first applicable policy (for nodes w/o a policy)
acl = (AccessControlList) aMgr.getApplicablePolicies(path).nextAccessControlPolicy();
} catch (NoSuchElementException e) {
// else node already has a policy, get that one
acl = (AccessControlList) aMgr.getPolicies(path)[0];
}
// remove all existing entries
for (AccessControlEntry e : acl.getAccessControlEntries()) {
acl.removeAccessControlEntry(e);
}
// add a new one for the special "everyone" principal
acl.addAccessControlEntry(EveryonePrincipal.getInstance(), privileges);
// the policy must be re-set
aMgr.setPolicy(path, acl);
// and the session must be saved for the changes to be applied
session.save();
} catch (Exception e) {
log.info("---> Not able to perform ACL Privileges..");
log.info("---> Exception.." + e.getMessage());
}
}
In code "datawrite" is a service mapping which is mapped with system user in "Apache Sling Service User Mapper Service" which is configurable in the OSGI configuration admin interface.
For more detail about system user check link - How to Create System User in AEM?
I am providing this code direcly from a training of an official Adobe channel, and it is based on AEM 6.1. So I assume this might be the best practice.
private void modifyPermissions() {
Session adminSession = null;
try{
adminSession = repository.loginService(null, repository.getDefaultWorkspace());
UserManager userMgr= ((org.apache.jackrabbit.api.JackrabbitSession)adminSession).getUserManager();
AccessControlManager accessControlManager = adminSession.getAccessControlManager();
Authorizable denyAccess = userMgr.getAuthorizable("deny-access");
AccessControlPolicyIterator policyIterator =
accessControlManager.getApplicablePolicies(CONTENT_GEOMETRIXX_FR);
AccessControlList acl;
try{
acl=(JackrabbitAccessControlList) policyIterator.nextAccessControlPolicy();
}catch(NoSuchElementException nse){
acl=(JackrabbitAccessControlList) accessControlManager.getPolicies(CONTENT_GEOMETRIXX_FR)[0];
}
Privilege[] privileges = {accessControlManager.privilegeFromName(Privilege.JCR_READ)};
acl.addAccessControlEntry(denyAccess.getPrincipal(), privileges);
accessControlManager.setPolicy(CONTENT_GEOMETRIXX_FR, acl);
adminSession.save();
}catch (RepositoryException e){
LOGGER.error("**************************Repo Exception", e);
}finally{
if (adminSession != null)
adminSession.logout();
}

Google App Engine. Stackdriver. Logging with Java

I want to POST Logs to "Custom Logs" of Stackdriver. These feature is beta, and maybe therefore it has no description, how to use Logging with Java API on App Engine. Anyway I want to describe my problem: I use this API version:
"com.google.apis:google-api-services-logging:v2beta1-rev10-1.21.0"
So, first I build the Logging Object like this (I hope this is right):
public static Logging createAuthorizedClient() throws IOException {
// Create the credential
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory);
if (credential.createScopedRequired()) {
credential = credential.createScoped(LoggingScopes.all());
}
return new Logging.Builder(transport, jsonFactory, credential).setApplicationName(SharedConstants.APPLICATION_ID).build();
}
After I get the Logging client, I try to push an Entry to the Log:
LogEntry lEntry = new LogEntry();
lEntry.setTextPayload("I want to see this log!");
WriteLogEntriesRequest writeLogEntriesRequest = new WriteLogEntriesRequest();
writeLogEntriesRequest.setLogName("My Super log");
List<LogEntry> listEntries = new ArrayList<>();
listEntries.add(lEntry);
writeLogEntriesRequest.setEntries(listEntries);
Logging logging = LoggingManager.createAuthorizedClient();
Write write = logging.entries().write(writeLogEntriesRequest);
WriteLogEntriesResponse writeLogResponse = write.execute();
But what I get is:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 OK
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid resource id",
"reason" : "badRequest"
} ],
"message" : "Invalid resource id",
"status" : "INVALID_ARGUMENT"
}
=== UPDATE: WORKING SOLUTION ===
Thanks to mshamma. Here is complete code, how to send the data to the logging:
public boolean send() {
WriteLogEntriesResponse response = null;
try {
final String now = getNowUtc();
final String insertId = "entry-at-" + now;
final Map<String, String> labels = ImmutableMap.of("project_id", SharedConstants.APPLICATION_ID, "name",
"projects/" + SharedConstants.APPLICATION_ID + "/logs/" + this.logName);
Logging service = createAuthorizedClient();
MonitoredResource ressource = new MonitoredResource();
ressource.setType("logging_log");
ressource.setLabels(labels);
LogEntry entry = new LogEntry().setInsertId(insertId).setResource(ressource).setTimestamp(now)
.setJsonPayload(this.entriesMap)
.setLogName("projects/" + SharedConstants.APPLICATION_ID + "/logs/" + this.logName)
.setSeverity(this.severity);
WriteLogEntriesRequest content = (new WriteLogEntriesRequest())
.setEntries(Collections.singletonList(entry));
response = service.entries().write(content).execute();
} catch (Exception e) {
}
return response != null;
}
private static String getNowUtc() {
SimpleDateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
return dateFormatUtc.format(new Date());
}
This code works fine with the last version of logging api
Thereby the EntriesMap is:
private Map<String, Object> entriesMap;
I ran into the same issue in the unmanaged Python environment. I got things working and I can see at least two issues in your code.
The log name needs to follow the pattern: "projects/<project-id>/logs/<log-id>". See the documentation of the field here: https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/LogEntry#SCHEMA_REPRESENTATION
You should add a resource descriptor both to the log entry (lEntry) and the write log entry request (writeLogEntriesRequest). In the case of GAE, the resource type field should be set to "gae_app" and you must add three labels to the resource that identify your GAE deployment: "project_id", "module_id" and "version_id".
I hope that will help resolve your issue!

Categories