mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
User Profile enhancements:
- Upload of Avatar image - added as a child node via preferences aspect to the cm:person node for the current user - Ajax update of image in profile read/edit views - Auto generated thumbnail used for avatar immediately after upload Tweak of file-upload component to allow override of destination URL for POST of content Added new flag to thumbnail GET call to force thumbnail creation synchronously without waiting Fix to Person PUT API (Unit Test now executes correctly) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@10008 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
<webscript kind="org.alfresco.repository.content.stream">
|
<webscript kind="org.alfresco.repository.content.stream">
|
||||||
<shortname>Thumbnails</shortname>
|
<shortname>Thumbnails</shortname>
|
||||||
<description>Get a named thumbnail for a content resource</description>
|
<description>Get a named thumbnail for a content resource</description>
|
||||||
<url>/api/node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}?qc={queuecreate?}&ph={placeholder?}</url>
|
<url>/api/node/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}?qc={queuecreate?}&fc={forcecreate?}&ph={placeholder?}</url>
|
||||||
<url>/api/path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}?qc={queuecreate?}&ph={placeholder?}</url>
|
<url>/api/path/{store_type}/{store_id}/{id}/content{property}/thumbnails/{thumbnailname}?qc={queuecreate?}&fc={forcecreate?}&ph={placeholder?}</url>
|
||||||
<format default="">argument</format>
|
<format default="">argument</format>
|
||||||
<authentication>user</authentication>
|
<authentication>user</authentication>
|
||||||
<transaction>required</transaction>
|
<transaction>required</transaction>
|
||||||
|
@@ -4,12 +4,12 @@ function main()
|
|||||||
var pathSegments = url.match.split("/");
|
var pathSegments = url.match.split("/");
|
||||||
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
|
var reference = [ url.templateArgs.store_type, url.templateArgs.store_id ].concat(url.templateArgs.id.split("/"));
|
||||||
var node = search.findNode(pathSegments[2], reference);
|
var node = search.findNode(pathSegments[2], reference);
|
||||||
|
|
||||||
// 404 if the node to thumbnail is not found
|
// 404 if the node to thumbnail is not found
|
||||||
if (node == null)
|
if (node == null)
|
||||||
{
|
{
|
||||||
status.setCode(status.STATUS_NOT_FOUND, "The thumbnail source node could not be found");
|
status.setCode(status.STATUS_NOT_FOUND, "The thumbnail source node could not be found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the thumbnail name from the JSON content
|
// Get the thumbnail name from the JSON content
|
||||||
@@ -20,7 +20,7 @@ function main()
|
|||||||
{
|
{
|
||||||
status.setCode(status.STATUS_NOT_FOUND, "Thumbnail name was not provided");
|
status.setCode(status.STATUS_NOT_FOUND, "Thumbnail name was not provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the queue create flag
|
// Get the queue create flag
|
||||||
var qc = false;
|
var qc = false;
|
||||||
@@ -30,6 +30,14 @@ function main()
|
|||||||
qc = utils.toBoolean(qcString);
|
qc = utils.toBoolean(qcString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the force create flag
|
||||||
|
var fc = false;
|
||||||
|
var fcString = args.fc;
|
||||||
|
if (fcString != null)
|
||||||
|
{
|
||||||
|
fc = utils.toBoolean(fcString);
|
||||||
|
}
|
||||||
|
|
||||||
// Get the place holder flag
|
// Get the place holder flag
|
||||||
var ph = false;
|
var ph = false;
|
||||||
var phString = args.ph;
|
var phString = args.ph;
|
||||||
@@ -43,32 +51,39 @@ function main()
|
|||||||
if (thumbnail == null)
|
if (thumbnail == null)
|
||||||
{
|
{
|
||||||
// Queue the creation of the thumbnail if appropriate
|
// Queue the creation of the thumbnail if appropriate
|
||||||
if (qc == true)
|
if (fc)
|
||||||
{
|
{
|
||||||
node.createThumbnail(thumbnailName, true);
|
model.contentNode = node.createThumbnail(thumbnailName, false);
|
||||||
}
|
|
||||||
|
|
||||||
if (ph == true)
|
|
||||||
{
|
|
||||||
// Try and get the place holder resource
|
|
||||||
var phPath = thumbnailService.getPlaceHolderResourcePath(thumbnailName);
|
|
||||||
if (phPath == null)
|
|
||||||
{
|
|
||||||
// 404 since no thumbnail was found
|
|
||||||
status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found and no place holde resource set for '" + thumbnailName + "'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set the resouce path in the model ready for the content stream to send back to the client
|
|
||||||
model.contentPath = phPath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 404 since no thumbnail was found
|
if (qc)
|
||||||
status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found");
|
{
|
||||||
return;
|
node.createThumbnail(thumbnailName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ph == true)
|
||||||
|
{
|
||||||
|
// Try and get the place holder resource
|
||||||
|
var phPath = thumbnailService.getPlaceHolderResourcePath(thumbnailName);
|
||||||
|
if (phPath == null)
|
||||||
|
{
|
||||||
|
// 404 since no thumbnail was found
|
||||||
|
status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found and no place holde resource set for '" + thumbnailName + "'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set the resouce path in the model ready for the content stream to send back to the client
|
||||||
|
model.contentPath = phPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 404 since no thumbnail was found
|
||||||
|
status.setCode(status.STATUS_NOT_FOUND, "Thumbnail was not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -0,0 +1,8 @@
|
|||||||
|
<webscript>
|
||||||
|
<shortname>Avatar Upload</shortname>
|
||||||
|
<description>Upload avatar file content and apply to person preferences</description>
|
||||||
|
<format default="json" />
|
||||||
|
<authentication>user</authentication>
|
||||||
|
<transaction>required</transaction>
|
||||||
|
<url>/slingshot/profile/uploadavatar</url>
|
||||||
|
</webscript>
|
@@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* User Profile Avatar Upload method
|
||||||
|
*
|
||||||
|
* @method POST
|
||||||
|
* @param username {string}
|
||||||
|
* filedata {file}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function main()
|
||||||
|
{
|
||||||
|
var filename = null;
|
||||||
|
var content = null;
|
||||||
|
var username = null;
|
||||||
|
|
||||||
|
// locate file attributes
|
||||||
|
for each (field in formdata.fields)
|
||||||
|
{
|
||||||
|
if (field.name == "filedata" && field.isFile)
|
||||||
|
{
|
||||||
|
filename = field.filename;
|
||||||
|
content = field.content;
|
||||||
|
}
|
||||||
|
else if (field.name == "username")
|
||||||
|
{
|
||||||
|
username = field.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure all mandatory attributes have been located
|
||||||
|
if (filename == undefined || content == undefined)
|
||||||
|
{
|
||||||
|
status.code = 400;
|
||||||
|
status.message = "Uploaded file cannot be located in request";
|
||||||
|
status.redirect = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (username == null || username.length == 0)
|
||||||
|
{
|
||||||
|
status.code = 500;
|
||||||
|
status.message = "Username parameter not supplied.";
|
||||||
|
status.redirect = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = people.getPerson(username);
|
||||||
|
// ensure we found a valid user and that it is the current user or we are an admin
|
||||||
|
if (user == null || (people.isAdmin(person) == false && username != user.properties.userName))
|
||||||
|
{
|
||||||
|
status.code = 500;
|
||||||
|
status.message = "Failed to locate valid user to modify.";
|
||||||
|
status.redirect = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure cm:person has 'cm:preferences' aspect applied - as we want to add the avatar as
|
||||||
|
// the child node of the 'cm:preferenceImage' association
|
||||||
|
if (!user.hasAspect("cm:preferences"))
|
||||||
|
{
|
||||||
|
user.addAspect("cm:preferences");
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove old image child node if we already have one
|
||||||
|
var assocs = user.childAssocs["cm:preferenceImage"];
|
||||||
|
if (assocs != null && assocs.length == 1)
|
||||||
|
{
|
||||||
|
assocs[0].remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the new image node
|
||||||
|
var image = user.createNode(filename, "cm:content", "cm:preferenceImage");
|
||||||
|
image.properties.content.write(content);
|
||||||
|
image.properties.content.guessMimetype(filename);
|
||||||
|
image.properties.content.encoding = "UTF-8";
|
||||||
|
image.save();
|
||||||
|
|
||||||
|
// wire up 'cm:avatar' target association - backward compatible with JSF web-client avatar
|
||||||
|
assocs = user.associations["cm:avatar"];
|
||||||
|
if (assocs != null && assocs.length == 1)
|
||||||
|
{
|
||||||
|
user.removeAssociation(assocs[0], "cm:avatar");
|
||||||
|
}
|
||||||
|
user.createAssociation(image, "cm:avatar");
|
||||||
|
|
||||||
|
// save ref to be returned
|
||||||
|
model.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"nodeRef": "${image.nodeRef}",
|
||||||
|
"status":
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"name": "OK",
|
||||||
|
"description" : "File uploaded successfully"
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* User Profile Update method
|
* User Profile REST Update method
|
||||||
*
|
*
|
||||||
* @method POST
|
* @method POST
|
||||||
* @param json {string}
|
* @param json {string}
|
||||||
@@ -16,51 +16,66 @@
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
model.success = false;
|
function main()
|
||||||
var username = json.get("username");
|
|
||||||
if (username != null)
|
|
||||||
{
|
{
|
||||||
var person = people.getPerson(username);
|
model.success = false;
|
||||||
// ensure we found a valid person and that it is the current user or an admin
|
var username = json.get("username");
|
||||||
if (person != null && (username == person.properties.userName || people.isAdmin(person)))
|
if (username == null)
|
||||||
{
|
{
|
||||||
if (json.has("properties"))
|
status.code = 400;
|
||||||
|
status.message = "Failed to locate valid user to modify.";
|
||||||
|
status.redirect = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = people.getPerson(username);
|
||||||
|
// ensure we found a valid user and that it is the current user or we are an admin
|
||||||
|
if (user == null || (people.isAdmin(person) == false && username != user.properties.userName))
|
||||||
|
{
|
||||||
|
status.code = 500;
|
||||||
|
status.message = "Failed to locate valid user to modify.";
|
||||||
|
status.redirect = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.has("properties"))
|
||||||
|
{
|
||||||
|
var props = json.get("properties");
|
||||||
|
if (props != null)
|
||||||
{
|
{
|
||||||
var props = json.get("properties");
|
var names = props.names();
|
||||||
if (props != null)
|
for (var i=0; i<props.length(); i++)
|
||||||
{
|
{
|
||||||
var names = props.names();
|
var propname = names.get(i);
|
||||||
for (var i=0; i<props.length(); i++)
|
var propval = props.get(propname);
|
||||||
{
|
|
||||||
var propname = names.get(i);
|
// set simple text properties
|
||||||
var propval = props.get(propname);
|
user.properties[propname] = propval;
|
||||||
|
|
||||||
// set simple text properties
|
|
||||||
person.properties[propname] = propval;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (json.has("content"))
|
|
||||||
|
if (json.has("content"))
|
||||||
|
{
|
||||||
|
var props = json.get("content");
|
||||||
|
if (props != null)
|
||||||
{
|
{
|
||||||
var props = json.get("content");
|
var names = props.names();
|
||||||
if (props != null)
|
for (var i=0; i<props.length(); i++)
|
||||||
{
|
{
|
||||||
var names = props.names();
|
var propname = names.get(i);
|
||||||
for (var i=0; i<props.length(); i++)
|
var propval = props.get(propname);
|
||||||
{
|
|
||||||
var propname = names.get(i);
|
// set content property
|
||||||
var propval = props.get(propname);
|
user.properties[propname].content = propval;
|
||||||
|
|
||||||
// set content property
|
|
||||||
person.properties[propname].content = propval;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: AVATAR?
|
// TODO: AVATAR?
|
||||||
|
|
||||||
person.save();
|
user.save();
|
||||||
model.success = true;
|
model.success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main();
|
@@ -33,12 +33,12 @@ import org.alfresco.repo.jscript.ScriptNode;
|
|||||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
import org.alfresco.service.cmr.security.AccessStatus;
|
|
||||||
import org.alfresco.service.cmr.security.PermissionService;
|
|
||||||
import org.alfresco.service.cmr.security.PersonService;
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.Content;
|
import org.alfresco.util.Content;
|
||||||
import org.alfresco.web.scripts.DeclarativeWebScript;
|
import org.alfresco.web.scripts.DeclarativeWebScript;
|
||||||
import org.alfresco.web.scripts.Status;
|
import org.alfresco.web.scripts.Status;
|
||||||
@@ -46,6 +46,7 @@ import org.alfresco.web.scripts.WebScriptException;
|
|||||||
import org.alfresco.web.scripts.WebScriptRequest;
|
import org.alfresco.web.scripts.WebScriptRequest;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Web Script to update a person's details
|
* Web Script to update a person's details
|
||||||
*
|
*
|
||||||
@@ -75,35 +76,25 @@ public class PersonPut extends DeclarativeWebScript
|
|||||||
{
|
{
|
||||||
// get references to services
|
// get references to services
|
||||||
NodeService nodeService = PersonPut.this.serviceRegistry.getNodeService();
|
NodeService nodeService = PersonPut.this.serviceRegistry.getNodeService();
|
||||||
PermissionService permissionService = PersonPut.this.serviceRegistry.getPermissionService();
|
|
||||||
|
|
||||||
// Can only update the given person node's properties if the
|
// Update the given person node's properties
|
||||||
// currently logged in user is the system user or,
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>(16);
|
||||||
// already has write permissions on the person node or,
|
props.put(ContentModel.PROP_USERNAME, (Serializable) personProps.get("userName"));
|
||||||
// matches the user name property of that person node
|
props.put(ContentModel.PROP_TITLE, (Serializable) personProps.get("title"));
|
||||||
String currentUserName = AuthenticationUtil.getCurrentUserName();
|
props.put(ContentModel.PROP_FIRSTNAME, (Serializable) personProps.get("firstName"));
|
||||||
String personUserName = (String) nodeService.getProperty(person,
|
props.put(ContentModel.PROP_LASTNAME, (Serializable) personProps.get("lastName"));
|
||||||
ContentModel.PROP_USERNAME);
|
props.put(ContentModel.PROP_ORGANIZATION, (Serializable) personProps.get("organisation"));
|
||||||
if (PersonPut.this.authenticationComponent.isSystemUserName(currentUserName) == true
|
props.put(ContentModel.PROP_JOBTITLE, (Serializable) personProps.get("jobtitle"));
|
||||||
|| (permissionService.hasPermission(
|
props.put(ContentModel.PROP_EMAIL, (Serializable) personProps.get("email"));
|
||||||
this.person, PermissionService.WRITE) == AccessStatus.ALLOWED)
|
try
|
||||||
|| personUserName.equals(currentUserName) == true)
|
|
||||||
{
|
{
|
||||||
nodeService.setProperty(
|
nodeService.setProperties(this.person, props);
|
||||||
this.person, ContentModel.PROP_TITLE, (Serializable) personProps.get("title"));
|
|
||||||
nodeService.setProperty(
|
|
||||||
this.person, ContentModel.PROP_FIRSTNAME, (Serializable) personProps.get("firstName"));
|
|
||||||
nodeService.setProperty(
|
|
||||||
this.person, ContentModel.PROP_LASTNAME, (Serializable) personProps.get("lastName"));
|
|
||||||
nodeService.setProperty(
|
|
||||||
this.person, ContentModel.PROP_ORGANIZATION, (Serializable) personProps.get("organisation"));
|
|
||||||
nodeService.setProperty(
|
|
||||||
this.person, ContentModel.PROP_JOBTITLE, (Serializable) personProps.get("jobtitle"));
|
|
||||||
nodeService.setProperty(
|
|
||||||
this.person, ContentModel.PROP_EMAIL, (Serializable) personProps.get("email"));
|
|
||||||
}
|
}
|
||||||
else
|
catch (AccessDeniedException err)
|
||||||
{
|
{
|
||||||
|
// catch security exception if the user does not have permissions
|
||||||
|
String currentUserName = AuthenticationUtil.getCurrentUserName();
|
||||||
|
String personUserName = (String)nodeService.getProperty(person, ContentModel.PROP_USERNAME);
|
||||||
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Current user: "
|
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "Current user: "
|
||||||
+ currentUserName + " does not have the appropriate permissons to update "
|
+ currentUserName + " does not have the appropriate permissons to update "
|
||||||
+ " person node with userName: " + personUserName);
|
+ " person node with userName: " + personUserName);
|
||||||
|
Reference in New Issue
Block a user