Adds UsersController.SetAvatar and ClearAvatar

This commit is contained in:
Shannon
2017-05-26 00:02:32 +10:00
parent a8220e0f62
commit 528be48437
9 changed files with 201 additions and 88 deletions

View File

@@ -37,5 +37,10 @@ namespace Umbraco.Core.Models.Membership
/// The security stamp used by ASP.Net identity
/// </summary>
string SecurityStamp { get; set; }
/// <summary>
/// Will hold the media file system relative path of the users custom avatar if they uploaded one
/// </summary>
string Avatar { get; set; }
}
}

View File

@@ -95,6 +95,7 @@ namespace Umbraco.Core.Models.Membership
private string _name;
private string _securityStamp;
private string _avatar;
private int _sessionTimeout;
private int[] _startContentIds;
private int[] _startMediaIds;
@@ -124,6 +125,7 @@ namespace Umbraco.Core.Models.Membership
public readonly PropertyInfo LastPasswordChangeDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime>(x => x.LastPasswordChangeDate);
public readonly PropertyInfo SecurityStampSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.SecurityStamp);
public readonly PropertyInfo AvatarSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Avatar);
public readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.SessionTimeout);
public readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int[]>(x => x.StartContentIds);
public readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int[]>(x => x.StartMediaIds);
@@ -272,6 +274,13 @@ namespace Umbraco.Core.Models.Membership
set { SetPropertyValueAndDetectChanges(value, ref _securityStamp, Ps.Value.SecurityStampSelector); }
}
[DataMember]
public string Avatar
{
get { return _avatar; }
set { SetPropertyValueAndDetectChanges(value, ref _avatar, Ps.Value.AvatarSelector); }
}
/// <summary>
/// Gets or sets the session timeout.
/// </summary>

View File

@@ -79,6 +79,13 @@ namespace Umbraco.Core.Models.Rdbms
[NullSetting(NullSetting = NullSettings.NotNull)]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime UpdateDate { get; set; }
/// <summary>
/// Will hold the media file system relative path of the users custom avatar if they uploaded one
/// </summary>
[Column("avatar")]
[NullSetting(NullSetting = NullSettings.Null)]
public string Avatar { get; set; }
[ResultColumn]
public List<UserGroupDto> UserGroupDtos { get; set; }

View File

@@ -44,6 +44,7 @@ namespace Umbraco.Core.Persistence.Factories
user.LastPasswordChangeDate = dto.LastPasswordChangeDate ?? DateTime.MinValue;
user.CreateDate = dto.CreateDate;
user.UpdateDate = dto.UpdateDate;
user.Avatar = dto.Avatar;
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
@@ -74,7 +75,8 @@ namespace Umbraco.Core.Persistence.Factories
LastLoginDate = entity.LastLoginDate == DateTime.MinValue ? (DateTime?)null : entity.LastLoginDate,
LastPasswordChangeDate = entity.LastPasswordChangeDate == DateTime.MinValue ? (DateTime?)null : entity.LastPasswordChangeDate,
CreateDate = entity.CreateDate,
UpdateDate = entity.UpdateDate
UpdateDate = entity.UpdateDate,
Avatar = entity.Avatar
};
foreach (var startNodeId in entity.StartContentIds)

View File

@@ -9,7 +9,7 @@
(function () {
'use strict';
function usersResource($http, umbRequestHelper, $q) {
function usersResource($http, umbRequestHelper, $q, umbDataFormatter) {
function disableUsers(userIds) {
if (!userIds) {
@@ -121,15 +121,18 @@
throw "user not specified";
}
//need to convert the user data into the correctly formatted save data - it is *not* the same and we don't want to over-post
var formattedSaveData = umbDataFormatter.formatUserPostData(user);
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"userApiBaseUrl",
"PostSaveUser"),
user),
formattedSaveData),
"Failed to save user");
}
function getUserGroup() {
var deferred = $q.defer();
var user = {

View File

@@ -4,7 +4,7 @@ function versionHelper() {
return {
//see: https://gist.github.com/TheDistantSea/8021359
versionCompare: function(v1, v2, options) {
versionCompare: function (v1, v2, options) {
var lexicographical = options && options.lexicographical,
zeroExtend = options && options.zeroExtend,
v1parts = v1.split('.'),
@@ -61,15 +61,15 @@ angular.module('umbraco.services').factory('versionHelper', versionHelper);
function dateHelper() {
return {
convertToServerStringTime: function(momentLocal, serverOffsetMinutes, format) {
convertToServerStringTime: function (momentLocal, serverOffsetMinutes, format) {
//get the formatted offset time in HH:mm (server time offset is in minutes)
var formattedOffset = (serverOffsetMinutes > 0 ? "+" : "-") +
moment()
.startOf('day')
.minutes(Math.abs(serverOffsetMinutes))
.format('HH:mm');
.startOf('day')
.minutes(Math.abs(serverOffsetMinutes))
.format('HH:mm');
var server = moment.utc(momentLocal).utcOffset(formattedOffset);
return server.format(format ? format : "YYYY-MM-DD HH:mm:ss");
@@ -80,9 +80,9 @@ function dateHelper() {
//get the formatted offset time in HH:mm (server time offset is in minutes)
var formattedOffset = (serverOffsetMinutes > 0 ? "+" : "-") +
moment()
.startOf('day')
.minutes(Math.abs(serverOffsetMinutes))
.format('HH:mm');
.startOf('day')
.minutes(Math.abs(serverOffsetMinutes))
.format('HH:mm');
//convert to the iso string format
var isoFormat = moment(strVal).format("YYYY-MM-DDTHH:mm:ss") + formattedOffset;
@@ -121,30 +121,30 @@ angular.module('umbraco.services').factory('packageHelper', packageHelper);
function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, mediaHelper, umbRequestHelper) {
return {
/** sets the image's url, thumbnail and if its a folder */
setImageData: function(img) {
setImageData: function (img) {
img.isFolder = !mediaHelper.hasFilePropertyType(img);
if(!img.isFolder){
if (!img.isFolder) {
img.thumbnail = mediaHelper.resolveFile(img, true);
img.image = mediaHelper.resolveFile(img, false);
img.image = mediaHelper.resolveFile(img, false);
}
},
/** sets the images original size properties - will check if it is a folder and if so will just make it square */
setOriginalSize: function(img, maxHeight) {
setOriginalSize: function (img, maxHeight) {
//set to a square by default
img.originalWidth = maxHeight;
img.originalHeight = maxHeight;
var widthProp = _.find(img.properties, function(v) { return (v.alias === "umbracoWidth"); });
var widthProp = _.find(img.properties, function (v) { return (v.alias === "umbracoWidth"); });
if (widthProp && widthProp.value) {
img.originalWidth = parseInt(widthProp.value, 10);
if (isNaN(img.originalWidth)) {
img.originalWidth = maxHeight;
}
}
var heightProp = _.find(img.properties, function(v) { return (v.alias === "umbracoHeight"); });
var heightProp = _.find(img.properties, function (v) { return (v.alias === "umbracoHeight"); });
if (heightProp && heightProp.value) {
img.originalHeight = parseInt(heightProp.value, 10);
if (isNaN(img.originalHeight)) {
@@ -154,7 +154,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
},
/** sets the image style which get's used in the angular markup */
setImageStyle: function(img, width, height, rightMargin, bottomMargin) {
setImageStyle: function (img, width, height, rightMargin, bottomMargin) {
img.style = { width: width + "px", height: height + "px", "margin-right": rightMargin + "px", "margin-bottom": bottomMargin + "px" };
img.thumbStyle = {
"background-image": "url('" + img.thumbnail + "')",
@@ -162,10 +162,10 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
"background-position": "center",
"background-size": Math.min(width, img.originalWidth) + "px " + Math.min(height, img.originalHeight) + "px"
};
},
},
/** gets the image's scaled wdith based on the max row height */
getScaledWidth: function(img, maxHeight) {
getScaledWidth: function (img, maxHeight) {
var scaled = img.originalWidth * maxHeight / img.originalHeight;
return scaled;
//round down, we don't want it too big even by half a pixel otherwise it'll drop to the next row
@@ -173,7 +173,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
},
/** returns the target row width taking into account how many images will be in the row and removing what the margin is */
getTargetWidth: function(imgsPerRow, maxRowWidth, margin) {
getTargetWidth: function (imgsPerRow, maxRowWidth, margin) {
//take into account the margin, we will have 1 less margin item than we have total images
return (maxRowWidth - ((imgsPerRow - 1) * margin));
},
@@ -187,7 +187,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
targetHeight = optional;
*/
getRowHeightForImages: function(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, targetHeight) {
getRowHeightForImages: function (imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, targetHeight) {
var idealImages = imgs.slice(0, idealImgPerRow);
//get the target row width without margin
@@ -195,8 +195,8 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
//this gets the image with the smallest height which equals the maximum we can scale up for this image block
var maxScaleableHeight = this.getMaxScaleableHeight(idealImages, maxRowHeight);
//if the max scale height is smaller than the min display height, we'll use the min display height
targetHeight = targetHeight !== undefined ? targetHeight : Math.max(maxScaleableHeight, minDisplayHeight);
targetHeight = targetHeight !== undefined ? targetHeight : Math.max(maxScaleableHeight, minDisplayHeight);
var attemptedRowHeight = this.performGetRowHeight(idealImages, targetRowWidth, minDisplayHeight, targetHeight);
if (attemptedRowHeight != null) {
@@ -206,12 +206,12 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
if (attemptedRowHeight < minDisplayHeight) {
if (idealImages.length > 1) {
//we'll generate a new targetHeight that is halfway between the max and the current and recurse, passing in a new targetHeight
targetHeight += Math.floor((maxRowHeight - targetHeight) / 2);
return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow - 1, margin, targetHeight);
}
else {
else {
//this will occur when we only have one image remaining in the row but it's still going to be too wide even when
// using the minimum display height specified. In this case we're going to have to just crop the image in it's center
// using the minimum display height and the full row width
@@ -241,7 +241,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
//if we're already dealing with the ideal images per row and it's not quite wide enough, we can scale up a little bit so
// long as the targetHeight is currently less than the maxRowHeight. The scale up will be half-way between our current
// target height and the maxRowHeight (we won't loop forever though - if there's a difference of 5 px we'll just quit)
while (targetHeight < maxRowHeight && (maxRowHeight - targetHeight) > 5) {
targetHeight += Math.floor((maxRowHeight - targetHeight) / 2);
attemptedRowHeight = this.performGetRowHeight(idealImages, targetRowWidth, minDisplayHeight, targetHeight);
@@ -273,7 +273,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
},
performGetRowHeight: function(idealImages, targetRowWidth, minDisplayHeight, targetHeight) {
performGetRowHeight: function (idealImages, targetRowWidth, minDisplayHeight, targetHeight) {
var currRowWidth = 0;
@@ -285,7 +285,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
if (currRowWidth > targetRowWidth) {
//get the new scaled height to fit
var newHeight = targetRowWidth * targetHeight / currRowWidth;
return newHeight;
}
else if (idealImages.length === 1 && (currRowWidth <= targetRowWidth) && !idealImages[0].isFolder) {
@@ -303,7 +303,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
},
/** builds an image grid row */
buildRow: function(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, totalRemaining) {
buildRow: function (imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, totalRemaining) {
var currRowWidth = 0;
var row = { images: [] };
@@ -315,11 +315,11 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
for (var i = 0; i < imageRowHeight.imgCount; i++) {
//get the lower width to ensure it always fits
var scaledWidth = Math.floor(this.getScaledWidth(imgs[i], imageRowHeight.height));
if (currRowWidth + scaledWidth <= targetWidth) {
currRowWidth += scaledWidth;
currRowWidth += scaledWidth;
sizes.push({
width:scaledWidth,
width: scaledWidth,
//ensure that the height is rounded
height: Math.round(imageRowHeight.height)
});
@@ -352,17 +352,17 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
if (row.images.length === 1 && totalRemaining > 1) {
//if there's only one image on the row and there are more images remaining, set the container to max width
row.images[0].style.width = maxRowWidth + "px";
row.images[0].style.width = maxRowWidth + "px";
}
return row;
},
/** Returns the maximum image scaling height for the current image collection */
getMaxScaleableHeight: function(imgs, maxRowHeight) {
getMaxScaleableHeight: function (imgs, maxRowHeight) {
var smallestHeight = _.min(imgs, function(item) { return item.originalHeight; }).originalHeight;
var smallestHeight = _.min(imgs, function (item) { return item.originalHeight; }).originalHeight;
//adjust the smallestHeight if it is larger than the static max row height
if (smallestHeight > maxRowHeight) {
@@ -372,10 +372,10 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
},
/** Creates the image grid with calculated widths/heights for images to fill the grid nicely */
buildGrid: function(images, maxRowWidth, maxRowHeight, startingIndex, minDisplayHeight, idealImgPerRow, margin,imagesOnly) {
buildGrid: function (images, maxRowWidth, maxRowHeight, startingIndex, minDisplayHeight, idealImgPerRow, margin, imagesOnly) {
var rows = [];
var imagesProcessed = 0;
var imagesProcessed = 0;
//first fill in all of the original image sizes and URLs
for (var i = startingIndex; i < images.length; i++) {
@@ -384,7 +384,7 @@ function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, me
this.setImageData(item);
this.setOriginalSize(item, maxRowHeight);
if(imagesOnly && !item.isFolder && !item.thumbnail){
if (imagesOnly && !item.isFolder && !item.thumbnail) {
images.splice(i, 1);
i--;
}
@@ -449,7 +449,7 @@ function umbModelMapper() {
/** This converts the source model to a basic entity model, it will throw an exception if there isn't enough data to create the model */
convertToEntityBasic: function (source) {
var required = ["id", "name", "icon", "parentId", "path"];
var required = ["id", "name", "icon", "parentId", "path"];
_.each(required, function (k) {
if (!_.has(source, k)) {
throw "The source object does not contain the property " + k;
@@ -485,11 +485,11 @@ function umbSessionStorage($window) {
get: function (key) {
return angular.fromJson(storage["umb_" + key]);
},
set : function(key, value) {
set: function (key, value) {
storage["umb_" + key] = angular.toJson(value);
}
};
}
angular.module('umbraco.services').factory('umbSessionStorage', umbSessionStorage);
@@ -504,26 +504,26 @@ angular.module('umbraco.services').factory('umbSessionStorage', umbSessionStorag
*/
function updateChecker($http, umbRequestHelper) {
return {
/**
* @ngdoc function
* @name umbraco.services.updateChecker#check
* @methodOf umbraco.services.updateChecker
* @function
*
* @description
* Called to load in the legacy tree js which is required on startup if a user is logged in or
* after login, but cannot be called until they are authenticated which is why it needs to be lazy loaded.
*/
check: function() {
/**
* @ngdoc function
* @name umbraco.services.updateChecker#check
* @methodOf umbraco.services.updateChecker
* @function
*
* @description
* Called to load in the legacy tree js which is required on startup if a user is logged in or
* after login, but cannot be called until they are authenticated which is why it needs to be lazy loaded.
*/
check: function () {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"updateCheckApiBaseUrl",
"GetCheck")),
'Failed to retrieve update status');
}
$http.get(
umbRequestHelper.getApiUrl(
"updateCheckApiBaseUrl",
"GetCheck")),
'Failed to retrieve update status');
}
};
}
angular.module('umbraco.services').factory('updateChecker', updateChecker);
@@ -546,7 +546,7 @@ function umbPropEditorHelper() {
*
* @param {string} input the view path currently stored for the property editor
*/
getViewPath: function(input, isPreValue) {
getViewPath: function (input, isPreValue) {
var path = String(input);
if (path.startsWith('/')) {
@@ -582,7 +582,7 @@ angular.module('umbraco.services').factory('umbPropEditorHelper', umbPropEditorH
**/
function umbDataFormatter() {
return {
formatContentTypePostData: function (displayModel, action) {
//create the save model from the display model
@@ -594,7 +594,7 @@ function umbDataFormatter() {
//TODO: Map these
saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; });
saveModel.defaultTemplate = displayModel.defaultTemplate ? displayModel.defaultTemplate.alias : null;
var realGroups = _.reject(displayModel.groups, function(g) {
var realGroups = _.reject(displayModel.groups, function (g) {
//do not include these tabs
return g.tabState === "init";
});
@@ -621,9 +621,9 @@ function umbDataFormatter() {
return saveGroup;
});
//we don't want any null groups
saveModel.groups = _.reject(saveModel.groups, function(g) {
saveModel.groups = _.reject(saveModel.groups, function (g) {
return !g;
});
@@ -631,7 +631,7 @@ function umbDataFormatter() {
},
/** formats the display model used to display the data type to the model used to save the data type */
formatDataTypePostData: function(displayModel, preValues, action) {
formatDataTypePostData: function (displayModel, preValues, action) {
var saveModel = {
parentId: displayModel.parentId,
id: displayModel.id,
@@ -651,14 +651,23 @@ function umbDataFormatter() {
return saveModel;
},
/** formats the display model used to display the user to the model used to save the user */
formatUserPostData: function (displayModel, preValues, action) {
//create the save model from the display model
var saveModel = _.pick(displayModel, 'id', 'parentId', 'name', 'username', 'culture', 'email', 'startContentIds', 'startMediaIds', 'userGroups');
return saveModel;
},
/** formats the display model used to display the member to the model used to save the member */
formatMemberPostData: function(displayModel, action) {
formatMemberPostData: function (displayModel, action) {
//this is basically the same as for media but we need to explicitly add the username,email, password to the save model
var saveModel = this.formatMediaPostData(displayModel, action);
saveModel.key = displayModel.key;
var genericTab = _.find(displayModel.tabs, function (item) {
return item.id === 0;
});
@@ -679,7 +688,7 @@ function umbDataFormatter() {
saveModel.email = propEmail.value;
saveModel.username = propLogin.value;
saveModel.password = propPass.value;
var selectedGroups = [];
for (var n in propGroups.value) {
if (propGroups.value[n] === true) {
@@ -687,12 +696,12 @@ function umbDataFormatter() {
}
}
saveModel.memberGroups = selectedGroups;
//turn the dictionary into an array of pairs
var memberProviderPropAliases = _.pairs(displayModel.fieldConfig);
_.each(displayModel.tabs, function (tab) {
_.each(tab.properties, function (prop) {
var foundAlias = _.find(memberProviderPropAliases, function(item) {
var foundAlias = _.find(memberProviderPropAliases, function (item) {
return prop.alias === item[1];
});
if (foundAlias) {
@@ -709,7 +718,7 @@ function umbDataFormatter() {
saveModel.comments = prop.value;
break;
}
}
}
});
});
@@ -719,7 +728,7 @@ function umbDataFormatter() {
},
/** formats the display model used to display the media to the model used to save the media */
formatMediaPostData: function(displayModel, action) {
formatMediaPostData: function (displayModel, action) {
//NOTE: the display model inherits from the save model so we can in theory just post up the display model but
// we don't want to post all of the data as it is unecessary.
var saveModel = {
@@ -744,7 +753,7 @@ function umbDataFormatter() {
value: prop.value
});
}
});
});
@@ -760,8 +769,8 @@ function umbDataFormatter() {
var genericTab = _.find(displayModel.tabs, function (item) {
return item.id === 0;
});
var propExpireDate = _.find(genericTab.properties, function(item) {
var propExpireDate = _.find(genericTab.properties, function (item) {
return item.alias === "_umb_expiredate";
});
var propReleaseDate = _.find(genericTab.properties, function (item) {

View File

@@ -1,14 +1,17 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using AutoMapper;
using ClientDependency.Core;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
@@ -42,13 +45,89 @@ namespace Umbraco.Web.Editors
{
}
public IHttpActionResult SetAvatar(int id)
[FileUploadCleanupFilter(false)]
public async Task<HttpResponseMessage> SetAvatar(int id)
{
return Ok();
if (Request.Content.IsMimeMultipartContent() == false)
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var root = IOHelper.MapPath("~/App_Data/TEMP/FileUploads");
//ensure it exists
Directory.CreateDirectory(root);
var provider = new MultipartFormDataStreamProvider(root);
var result = await Request.Content.ReadAsMultipartAsync(provider);
//must have a file
if (result.FileData.Count == 0)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
//get the string json from the request
var userId = result.FormData["userId"];
int intUserId;
if (int.TryParse(userId, out intUserId) == false)
return Request.CreateValidationErrorResponse("The request was not formatted correctly, the userId is not an integer");
var user = Services.UserService.GetUserById(intUserId);
if (user == null)
return Request.CreateResponse(HttpStatusCode.NotFound);
var tempFiles = new PostedFiles();
if (result.FileData.Count > 1)
return Request.CreateValidationErrorResponse("The request was not formatted correctly, only one file can be attached to the request");
//get the file info
var file = result.FileData[0];
var fileName = file.Headers.ContentDisposition.FileName.Trim(new[] { '\"' }).TrimEnd();
var safeFileName = fileName.ToSafeFileName();
var ext = safeFileName.Substring(safeFileName.LastIndexOf('.') + 1).ToLower();
if (UmbracoConfig.For.UmbracoSettings().Content.DisallowedUploadFiles.Contains(ext) == false)
{
if (user.Avatar.IsNullOrWhiteSpace())
{
//we'll need to generate a new path!
//make it a hash of known data, we don't want this path to be guessable
user.Avatar = "UserAvatars/" + (user.Id + user.CreateDate.ToString("yyyyMMdd")).ToSHA1() + ext;
}
using (var fs = System.IO.File.OpenRead(file.LocalFileName))
{
FileSystemProviderManager.Current.MediaFileSystem.AddFile(user.Avatar, fs, true);
}
Services.UserService.Save(user);
//track the temp file so the cleanup filter removes it
tempFiles.UploadedFiles.Add(new ContentItemFile
{
TempFilePath = file.LocalFileName
});
}
return Request.CreateResponse(HttpStatusCode.OK, tempFiles);
}
public IHttpActionResult ClearAvatar(int id)
{
var found = Services.UserService.GetUserById(id);
if (found == null)
return NotFound();
var filePath = found.Avatar;
found.Avatar = null;
Services.UserService.Save(found);
if (FileSystemProviderManager.Current.MediaFileSystem.FileExists(filePath))
FileSystemProviderManager.Current.MediaFileSystem.DeleteFile(filePath);
return Ok();
}

View File

@@ -42,10 +42,7 @@ namespace Umbraco.Web.Models.ContentEditing
public int[] StartContentIds { get; set; }
[DataMember(Name = "startMediaIds")]
public int[] StartMediaIds { get; set; }
[DataMember(Name = "allowedSections")]
public IEnumerable<string> AllowedSections { get; set; }
public int[] StartMediaIds { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{

View File

@@ -19,6 +19,7 @@ namespace Umbraco.Web.Models.Mapping
//Used for merging existing UserSave to an existing IUser instance - this will not create an IUser instance!
config.CreateMap<UserSave, IUser>()
.ForMember(user => user.Language, expression => expression.MapFrom(save => save.Culture))
.ForMember(user => user.Avatar, expression => expression.Ignore())
.ForMember(user => user.SessionTimeout, expression => expression.Ignore())
.ForMember(user => user.SecurityStamp, expression => expression.Ignore())
.ForMember(user => user.ProviderUserKey, expression => expression.Ignore())
@@ -47,6 +48,7 @@ namespace Umbraco.Web.Models.Mapping
config.CreateMap<UserInvite, IUser>()
.ConstructUsing(invite => new User(invite.Name, invite.Email, invite.Email, Guid.NewGuid().ToString("N")))
.ForMember(user => user.Id, expression => expression.Ignore())
.ForMember(user => user.Avatar, expression => expression.Ignore())
.ForMember(user => user.SessionTimeout, expression => expression.Ignore())
.ForMember(user => user.StartContentIds, expression => expression.Ignore())
.ForMember(user => user.StartMediaIds, expression => expression.Ignore())