Don't allow duplicate GCS folder names

pull/229/merge
Francis Lachapelle 2018-08-30 22:09:17 -04:00
parent 18df3bafb5
commit 3bdd90e2be
7 changed files with 75 additions and 33 deletions

View File

@ -614,19 +614,21 @@ static NSArray *childRecordFields = nil;
NSURL *folderLocation;
NSString *sql;
if ([[self container] hasLocalSubFolderNamed: newName])
[NSException raise: NSInvalidArgumentException
format: @"That name already exists"];
cm = [GCSChannelManager defaultChannelManager];
folderLocation
= [[GCSFolderManager defaultFolderManager] folderInfoLocation];
folderLocation = [[GCSFolderManager defaultFolderManager] folderInfoLocation];
fc = [cm acquireOpenChannelForURL: folderLocation];
if (fc)
{
#warning GDLContentStore should provide methods for renaming folders
sql
= [NSString stringWithFormat: (@"UPDATE %@ SET c_foldername = '%@'"
@" WHERE c_path = '%@'"),
[folderLocation gcsTableName],
[newName stringByReplacingString: @"'" withString: @"''"],
ocsPath];
sql = [NSString stringWithFormat: (@"UPDATE %@ SET c_foldername = '%@'"
@" WHERE c_path = '%@'"),
[folderLocation gcsTableName],
[newName stringByReplacingString: @"'" withString: @"''"],
ocsPath];
[fc evaluateExpressionX: sql];
[cm releaseChannel: fc];
// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'",

View File

@ -289,8 +289,18 @@
if ([folderName length] > 0)
{
clientObject = [self clientObject];
[clientObject renameTo: folderName];
response = [self responseWith204];
NS_DURING
{
[clientObject renameTo: folderName];
response = [self responseWith204];
}
NS_HANDLER
{
message = [NSDictionary dictionaryWithObject: [localException reason] forKey: @"message"];
response = [self responseWithStatus: 409 /* Conflict */
andString: [message jsonRepresentation]];
}
NS_ENDHANDLER;
}
else
{

View File

@ -1,6 +1,6 @@
/* UIxContactFolderProperties.m - this file is part of SOGo
*
* Copyright (C) 2015 Inverse inc.
* Copyright (C) 2015-2018 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,8 +21,10 @@
#import <Foundation/NSDictionary.h>
#import <Foundation/NSValue.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WORequest.h>
#import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/NSString+Utilities.h>
#import <Contacts/SOGoContactGCSFolder.h>
@ -59,21 +61,34 @@
- (WOResponse *) savePropertiesAction
{
WORequest *request;
NSDictionary *params;
WOResponse *response;
NSDictionary *params, *message;
id o;
request = [context request];
params = [[request contentAsString] objectFromJSONString];
response = [self responseWith204];
o = [params objectForKey: @"name"];
if ([o isKindOfClass: [NSString class]])
[addressbook renameTo: o];
NS_DURING
{
o = [params objectForKey: @"name"];
if ([o isKindOfClass: [NSString class]])
[addressbook renameTo: o];
o = [params objectForKey: @"synchronize"];
if ([o isKindOfClass: [NSNumber class]])
[addressbook setSynchronize: [o boolValue]];
o = [params objectForKey: @"synchronize"];
if ([o isKindOfClass: [NSNumber class]])
[addressbook setSynchronize: [o boolValue]];
}
NS_HANDLER
{
message = [NSDictionary dictionaryWithObject: [localException reason] forKey: @"message"];
response = [self responseWithStatus: 400 /* Bad Request */
andString: [message jsonRepresentation]];
return [self responseWith204];
}
NS_ENDHANDLER;
return response;
}
@end

View File

@ -581,15 +581,16 @@
* @returns a promise of the HTTP operation
*/
AddressBook.prototype.$rename = function(name) {
var i, list;
var _this = this, i, list;
list = this.isSubscription? AddressBook.$subscriptions : AddressBook.$addressbooks;
i = _.indexOf(_.map(list, 'id'), this.id);
this.name = name;
list.splice(i, 1);
AddressBook.$add(this);
return this.$save();
return this.$save().then(function() {
list.splice(i, 1);
_this.name = name;
AddressBook.$add(_this);
});
};
/**

View File

@ -17,6 +17,7 @@
vm.edit = edit;
vm.revertEditing = revertEditing;
vm.save = save;
vm.saving = false;
vm.confirmDelete = confirmDelete;
vm.importCards = importCards;
vm.showLinks = showLinks;
@ -98,13 +99,18 @@
function save(folder) {
var name = folder.name;
if (name && name.length > 0) {
if (!vm.saving && name && name.length > 0) {
if (name != vm.originalAddressbook.name) {
vm.saving = true;
folder.$rename(name)
.then(function(data) {
vm.editMode = false;
}, function(data, status) {
Dialog.alert(l('Warning'), data);
}, function() {
revertEditing(folder);
vm.editMode = folder.id;
})
.finally(function() {
vm.saving = false;
});
}
else {

View File

@ -498,18 +498,20 @@
* @returns a promise of the HTTP operation
*/
Calendar.prototype.$save = function() {
var _this = this;
var _this = this,
d = Calendar.$q.defer();
return Calendar.$$resource.save(this.id, this.$omit()).then(function(data) {
Calendar.$$resource.save(this.id, this.$omit()).then(function(data) {
// Make a copy of the data for an eventual reset
_this.$shadowData = _this.$omit();
return data;
return d.resolve(data);
}, function(data) {
Calendar.$log.error(JSON.stringify(data, undefined, 2));
// Restore previous version
_this.$reset();
return data;
return d.reject(data);
});
return d.promise;
};
/**

View File

@ -87,7 +87,7 @@
this.inputElement.value = this.calendar.name;
this.clickableElement.classList.add('ng-hide');
this.inputContainer.classList.remove('ng-hide');
if ($event.srcEvent.type == 'touchend') {
if ($event.srcEvent && $event.srcEvent.type == 'touchend') {
$timeout(function() {
$ctrl.inputElement.focus();
$ctrl.inputElement.select();
@ -115,6 +115,12 @@
$ctrl.inputContainer.classList.add('ng-hide');
$ctrl.clickableElement.classList.remove('ng-hide');
$ctrl.updateCalendarName();
}, function() {
$ctrl.editMode = true;
$timeout(function() {
$ctrl.inputElement.focus();
$ctrl.inputElement.select();
}, 200); // delayed focus for iOS
})
.finally(function() {
$ctrl.inputElement.disabled = false;