Save createdByUserID and lastModifiedByUserID for group items
This commit is contained in:
		
					parent
					
						
							
								bb0a1dab13
							
						
					
				
			
			
				commit
				
					
						b54d4e78b7
					
				
			
		
					 9 changed files with 317 additions and 40 deletions
				
			
		| 
						 | 
					@ -38,6 +38,8 @@ Zotero.Item = function(itemTypeOrID) {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// loadPrimaryData (additional properties in dataObject.js)
 | 
						// loadPrimaryData (additional properties in dataObject.js)
 | 
				
			||||||
	this._itemTypeID = null;
 | 
						this._itemTypeID = null;
 | 
				
			||||||
 | 
						this._createdByUserID = null;
 | 
				
			||||||
 | 
						this._lastModifiedByUserID = null;
 | 
				
			||||||
	this._firstCreator = null;
 | 
						this._firstCreator = null;
 | 
				
			||||||
	this._sortCreator = null;
 | 
						this._sortCreator = null;
 | 
				
			||||||
	this._attachmentCharset = null;
 | 
						this._attachmentCharset = null;
 | 
				
			||||||
| 
						 | 
					@ -107,33 +109,19 @@ Zotero.defineProperty(Zotero.Item.prototype, 'itemID', {
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	enumerable: false
 | 
						enumerable: false
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
Zotero.defineProperty(Zotero.Item.prototype, 'libraryID', {
 | 
					
 | 
				
			||||||
	get: function() { return this._libraryID; },
 | 
					for (let name of ['libraryID', 'key', 'dateAdded', 'dateModified', 'version', 'synced',
 | 
				
			||||||
	set: function(val) { return this.setField('libraryID', val); }
 | 
							'createdByUserID', 'lastModifiedByUserID']) {
 | 
				
			||||||
});
 | 
						let prop = '_' + name;
 | 
				
			||||||
Zotero.defineProperty(Zotero.Item.prototype, 'key', {
 | 
						Zotero.defineProperty(Zotero.Item.prototype, name, {
 | 
				
			||||||
	get: function() { return this._key; },
 | 
							get: function () { return this[prop]; },
 | 
				
			||||||
	set: function(val) { return this.setField('key', val); }
 | 
							set: function (val) { return this.setField(name, val); }
 | 
				
			||||||
});
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Zotero.defineProperty(Zotero.Item.prototype, 'itemTypeID', {
 | 
					Zotero.defineProperty(Zotero.Item.prototype, 'itemTypeID', {
 | 
				
			||||||
	get: function() { return this._itemTypeID; }
 | 
						get: function() { return this._itemTypeID; }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
Zotero.defineProperty(Zotero.Item.prototype, 'dateAdded', {
 | 
					 | 
				
			||||||
	get: function() { return this._dateAdded; },
 | 
					 | 
				
			||||||
	set: function(val) { return this.setField('dateAdded', val); }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
Zotero.defineProperty(Zotero.Item.prototype, 'dateModified', {
 | 
					 | 
				
			||||||
	get: function() { return this._dateModified; },
 | 
					 | 
				
			||||||
	set: function(val) { return this.setField('dateModified', val); }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
Zotero.defineProperty(Zotero.Item.prototype, 'version', {
 | 
					 | 
				
			||||||
	get: function() { return this._version; },
 | 
					 | 
				
			||||||
	set: function(val) { return this.setField('version', val); }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
Zotero.defineProperty(Zotero.Item.prototype, 'synced', {
 | 
					 | 
				
			||||||
	get: function() { return this._synced; },
 | 
					 | 
				
			||||||
	set: function(val) { return this.setField('synced', val); }
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// .parentKey and .parentID defined in dataObject.js, but create aliases
 | 
					// .parentKey and .parentID defined in dataObject.js, but create aliases
 | 
				
			||||||
Zotero.defineProperty(Zotero.Item.prototype, 'parentItemID', {
 | 
					Zotero.defineProperty(Zotero.Item.prototype, 'parentItemID', {
 | 
				
			||||||
| 
						 | 
					@ -335,6 +323,8 @@ Zotero.Item.prototype._parseRowData = function(row) {
 | 
				
			||||||
			case 'attachmentSyncState':
 | 
								case 'attachmentSyncState':
 | 
				
			||||||
			case 'attachmentSyncedHash':
 | 
								case 'attachmentSyncedHash':
 | 
				
			||||||
			case 'attachmentSyncedModificationTime':
 | 
								case 'attachmentSyncedModificationTime':
 | 
				
			||||||
 | 
								case 'createdByUserID':
 | 
				
			||||||
 | 
								case 'lastModifiedByUserID':
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			case 'itemID':
 | 
								case 'itemID':
 | 
				
			||||||
| 
						 | 
					@ -668,6 +658,19 @@ Zotero.Item.prototype.setField = function(field, value, loadIn) {
 | 
				
			||||||
				value = !!value;
 | 
									value = !!value;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
 | 
								case 'createdByUserID':
 | 
				
			||||||
 | 
								case 'lastModifiedByUserID':
 | 
				
			||||||
 | 
									if (typeof value != 'number' || value != parseInt(value)) {
 | 
				
			||||||
 | 
										throw new Error(`${field} must be a number`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (!this._libraryID) {
 | 
				
			||||||
 | 
										throw new Error(`libraryID must be set before setting ${field}`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (Zotero.Libraries.get(this._libraryID).libraryType != 'group') {
 | 
				
			||||||
 | 
										throw new Error(`${field} is only valid for group library items`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				throw new Error('Primary field ' + field + ' cannot be changed in Zotero.Item.setField()');
 | 
									throw new Error('Primary field ' + field + ' cannot be changed in Zotero.Item.setField()');
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
| 
						 | 
					@ -1297,6 +1300,12 @@ Zotero.Item.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						if (this._changed.primaryData
 | 
				
			||||||
 | 
								&& (this._changed.primaryData.createdByUserID || this._changed.primaryData.lastModifiedByUserID)) {
 | 
				
			||||||
 | 
							let sql = "REPLACE INTO groupItems VALUES (?, ?, ?)";
 | 
				
			||||||
 | 
							yield Zotero.DB.queryAsync(sql, [itemID, this._createdByUserID || null, this._lastModifiedByUserID || null]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	// ItemData
 | 
						// ItemData
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
| 
						 | 
					@ -4783,13 +4792,6 @@ Zotero.Item.prototype.migrateExtraFields = function () {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Asynchronous load methods
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Return an item in the specified library equivalent to this item
 | 
					 * Return an item in the specified library equivalent to this item
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -4816,6 +4818,34 @@ Zotero.Item.prototype.addLinkedItem = Zotero.Promise.coroutine(function* (item)
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Update createdByUserID/lastModifiedByUserID, efficiently
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Used by sync code
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Zotero.Item.prototype.updateCreatedByUser = async function (createdByUserID, lastModifiedByUserID) {
 | 
				
			||||||
 | 
						this._createdByUserID = createdByUserID || null;
 | 
				
			||||||
 | 
						this._lastModifiedByUserID = lastModifiedByUserID || null;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						var sql = "REPLACE INTO groupItems VALUES (?, ?, ?)";
 | 
				
			||||||
 | 
						await Zotero.DB.queryAsync(sql, [this.id, this._createdByUserID, this._lastModifiedByUserID]);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (this._changed.primaryData) {
 | 
				
			||||||
 | 
							for (let x of ['createdByUserID', 'lastModifiedByUserID']) {
 | 
				
			||||||
 | 
								if (this._changed.primaryData[x]) {
 | 
				
			||||||
 | 
									if (Objects.keys(this._changed.primaryData).length == 1) {
 | 
				
			||||||
 | 
										delete this._changed.primaryData;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										delete this._changed.primaryData[x];
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//////////////////////////////////////////////////////////////////////////////
 | 
					//////////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Private methods
 | 
					// Private methods
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,9 @@ Zotero.Items = function() {
 | 
				
			||||||
				version: "O.version",
 | 
									version: "O.version",
 | 
				
			||||||
				synced: "O.synced",
 | 
									synced: "O.synced",
 | 
				
			||||||
				
 | 
									
 | 
				
			||||||
 | 
									createdByUserID: "createdByUserID",
 | 
				
			||||||
 | 
									lastModifiedByUserID: "lastModifiedByUserID",
 | 
				
			||||||
 | 
									
 | 
				
			||||||
				firstCreator: _getFirstCreatorSQL(),
 | 
									firstCreator: _getFirstCreatorSQL(),
 | 
				
			||||||
				sortCreator: _getSortCreatorSQL(),
 | 
									sortCreator: _getSortCreatorSQL(),
 | 
				
			||||||
				
 | 
									
 | 
				
			||||||
| 
						 | 
					@ -79,7 +82,8 @@ Zotero.Items = function() {
 | 
				
			||||||
		+ "LEFT JOIN items INoP ON (INo.parentItemID=INoP.itemID) "
 | 
							+ "LEFT JOIN items INoP ON (INo.parentItemID=INoP.itemID) "
 | 
				
			||||||
		+ "LEFT JOIN deletedItems DI ON (O.itemID=DI.itemID) "
 | 
							+ "LEFT JOIN deletedItems DI ON (O.itemID=DI.itemID) "
 | 
				
			||||||
		+ "LEFT JOIN publicationsItems PI ON (O.itemID=PI.itemID) "
 | 
							+ "LEFT JOIN publicationsItems PI ON (O.itemID=PI.itemID) "
 | 
				
			||||||
		+ "LEFT JOIN charsets CS ON (IA.charsetID=CS.charsetID)";
 | 
							+ "LEFT JOIN charsets CS ON (IA.charsetID=CS.charsetID)"
 | 
				
			||||||
 | 
							+ "LEFT JOIN groupItems GI ON (O.itemID=GI.itemID)";
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	this._relationsTable = "itemRelations";
 | 
						this._relationsTable = "itemRelations";
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3218,6 +3218,11 @@ Zotero.Schema = new function(){
 | 
				
			||||||
				yield Zotero.DB.queryAsync("CREATE INDEX deletedSearches_dateDeleted ON deletedSearches(dateDeleted)");
 | 
									yield Zotero.DB.queryAsync("CREATE INDEX deletedSearches_dateDeleted ON deletedSearches(dateDeleted)");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
 | 
								else if (i == 112) {
 | 
				
			||||||
 | 
									yield Zotero.DB.queryAsync("DROP TABLE IF EXISTS users");
 | 
				
			||||||
 | 
									yield Zotero.DB.queryAsync("CREATE TABLE users (\n    userID INTEGER PRIMARY KEY,\n    name TEXT NOT NULL\n)");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
			// If breaking compatibility or doing anything dangerous, clear minorUpdateFrom
 | 
								// If breaking compatibility or doing anything dangerous, clear minorUpdateFrom
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,6 +223,15 @@ Zotero.Sync.Data.Engine.prototype.start = Zotero.Promise.coroutine(function* ()
 | 
				
			||||||
		skipNotifier: true
 | 
							skipNotifier: true
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						if (this.library.libraryType == 'group') {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								yield this._updateGroupItemUsers();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (e) {
 | 
				
			||||||
 | 
								Zotero.logError(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	Zotero.debug("Done syncing " + this.library.name);
 | 
						Zotero.debug("Done syncing " + this.library.name);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1428,6 +1437,58 @@ Zotero.Sync.Data.Engine.prototype._uploadDeletions = Zotero.Promise.coroutine(fu
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Update createdByUserID/lastModifiedByUserID for previously downloaded group items
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * TEMP: Currently only processes one batch of items, but before we start displaying the names,
 | 
				
			||||||
 | 
					 * we'll need to update it to fetch all
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Zotero.Sync.Data.Engine.prototype._updateGroupItemUsers = async function () {
 | 
				
			||||||
 | 
						// TODO: Do more at once when we actually start showing these names
 | 
				
			||||||
 | 
						var max = this.apiClient.MAX_OBJECTS_PER_REQUEST;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						var sql = "SELECT key FROM items LEFT JOIN groupItems GI USING (itemID) "
 | 
				
			||||||
 | 
							+ `WHERE libraryID=? AND GI.itemID IS NULL ORDER BY itemID LIMIT ${max}`;
 | 
				
			||||||
 | 
						var keys = await Zotero.DB.columnQueryAsync(sql, this.libraryID);
 | 
				
			||||||
 | 
						if (!keys.length) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						Zotero.debug(`Updating item users in ${this.library.name}`);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						var jsonItems = await this.apiClient.downloadObjects(
 | 
				
			||||||
 | 
							this.library.libraryType, this.libraryTypeID, 'item', keys
 | 
				
			||||||
 | 
						)[0];
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (!Array.isArray(jsonItems)) {
 | 
				
			||||||
 | 
							Zotero.logError(e);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						for (let jsonItem of jsonItems) {
 | 
				
			||||||
 | 
							let item = Zotero.Items.getByLibraryAndKey(this.libraryID, jsonItem.key);
 | 
				
			||||||
 | 
							let params = [null, null];
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// This should almost always exist, but maybe doesn't for some old items?
 | 
				
			||||||
 | 
							if (jsonItem.meta.createdByUser) {
 | 
				
			||||||
 | 
								let { id: userID, username, name } = jsonItem.meta.createdByUser;
 | 
				
			||||||
 | 
								await Zotero.Users.setName(userID, name !== '' ? name : username);
 | 
				
			||||||
 | 
								params[0] = userID;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (jsonItem.meta.lastModifiedByUser) {
 | 
				
			||||||
 | 
								let { id: userID, username, name } = jsonItem.meta.lastModifiedByUser;
 | 
				
			||||||
 | 
								await Zotero.Users.setName(userID, name !== '' ? name : username);
 | 
				
			||||||
 | 
								params[1] = userID;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							await item.updateCreatedByUser.apply(item, params);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Zotero.Sync.Data.Engine.prototype._getJSONForObject = function (objectType, id, options = {}) {
 | 
					Zotero.Sync.Data.Engine.prototype._getJSONForObject = function (objectType, id, options = {}) {
 | 
				
			||||||
	return Zotero.DB.executeTransaction(function* () {
 | 
						return Zotero.DB.executeTransaction(function* () {
 | 
				
			||||||
		var objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(objectType);
 | 
							var objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(objectType);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1459,8 +1459,23 @@ Zotero.Sync.Data.Local = {
 | 
				
			||||||
			if (!options.skipData) {
 | 
								if (!options.skipData) {
 | 
				
			||||||
				obj.fromJSON(json.data, { strict: true });
 | 
									obj.fromJSON(json.data, { strict: true });
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if (obj.objectType == 'item' && obj.isImportedAttachment()) {
 | 
								if (obj.objectType == 'item') {
 | 
				
			||||||
				yield this._checkAttachmentForDownload(obj, json.data.mtime, options.isNewObject);
 | 
									// Update createdByUserID and lastModifiedByUserID
 | 
				
			||||||
 | 
									for (let p of ['createdByUser', 'lastModifiedByUser']) {
 | 
				
			||||||
 | 
										if (json.meta && json.meta[p]) {
 | 
				
			||||||
 | 
											let { id: userID, username, name } = json.meta[p];
 | 
				
			||||||
 | 
											obj[p + 'ID'] = userID;
 | 
				
			||||||
 | 
											name = name !== '' ? name : username;
 | 
				
			||||||
 | 
											// Update stored name if it changed
 | 
				
			||||||
 | 
											if (Zotero.Users.getName(userID) != name) {
 | 
				
			||||||
 | 
												yield Zotero.Users.setName(userID, name);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									if (obj.isImportedAttachment()) {
 | 
				
			||||||
 | 
										yield this._checkAttachmentForDownload(obj, json.data.mtime, options.isNewObject);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			obj.version = json.data.version;
 | 
								obj.version = json.data.version;
 | 
				
			||||||
			if (!options.saveAsUnsynced) {
 | 
								if (!options.saveAsUnsynced) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,10 +28,11 @@ Zotero.Users = new function () {
 | 
				
			||||||
	var _libraryID;
 | 
						var _libraryID;
 | 
				
			||||||
	var _username;
 | 
						var _username;
 | 
				
			||||||
	var _localUserKey;
 | 
						var _localUserKey;
 | 
				
			||||||
 | 
						var _users = {};
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	this.init = Zotero.Promise.coroutine(function* () {
 | 
						this.init = async function () {
 | 
				
			||||||
		let sql = "SELECT key, value FROM settings WHERE setting='account'";
 | 
							let sql = "SELECT key, value FROM settings WHERE setting='account'";
 | 
				
			||||||
		let rows = yield Zotero.DB.queryAsync(sql);
 | 
							let rows = await Zotero.DB.queryAsync(sql);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		let settings = {};
 | 
							let settings = {};
 | 
				
			||||||
		for (let i=0; i<rows.length; i++) {
 | 
							for (let i=0; i<rows.length; i++) {
 | 
				
			||||||
| 
						 | 
					@ -56,11 +57,16 @@ Zotero.Users = new function () {
 | 
				
			||||||
			let key = Zotero.randomString(8);
 | 
								let key = Zotero.randomString(8);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			sql = "INSERT INTO settings VALUES ('account', 'localUserKey', ?)";
 | 
								sql = "INSERT INTO settings VALUES ('account', 'localUserKey', ?)";
 | 
				
			||||||
			yield Zotero.DB.queryAsync(sql, key);
 | 
								await Zotero.DB.queryAsync(sql, key);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			_localUserKey = key;
 | 
								_localUserKey = key;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
							
 | 
				
			||||||
 | 
							rows = await Zotero.DB.queryAsync("SELECT userID, name FROM users");
 | 
				
			||||||
 | 
							for (let row of rows) {
 | 
				
			||||||
 | 
								_users[row.userID] = row.name;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	this.getCurrentUserID = function() { return _userID };
 | 
						this.getCurrentUserID = function() { return _userID };
 | 
				
			||||||
| 
						 | 
					@ -87,4 +93,18 @@ Zotero.Users = new function () {
 | 
				
			||||||
	this.getLocalUserKey = function () {
 | 
						this.getLocalUserKey = function () {
 | 
				
			||||||
		return _localUserKey;
 | 
							return _localUserKey;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						this.getName = function (userID) {
 | 
				
			||||||
 | 
							return _users[userID] || '';
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						this.setName = async function (userID, name) {
 | 
				
			||||||
 | 
							if (this.getName(userID) == name) {
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							await Zotero.DB.queryAsync("REPLACE INTO users VALUES (?, ?)", [userID, name]);
 | 
				
			||||||
 | 
							_users[userID] = name;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
-- 111
 | 
					-- 112
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- Copyright (c) 2009 Center for History and New Media
 | 
					-- Copyright (c) 2009 Center for History and New Media
 | 
				
			||||||
--                    George Mason University, Fairfax, Virginia, USA
 | 
					--                    George Mason University, Fairfax, Virginia, USA
 | 
				
			||||||
| 
						 | 
					@ -275,7 +275,7 @@ CREATE TABLE libraries (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE users (
 | 
					CREATE TABLE users (
 | 
				
			||||||
    userID INTEGER PRIMARY KEY,
 | 
					    userID INTEGER PRIMARY KEY,
 | 
				
			||||||
    username TEXT NOT NULL
 | 
					    name TEXT NOT NULL
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE groups (
 | 
					CREATE TABLE groups (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4046,6 +4046,85 @@ describe("Zotero.Sync.Data.Engine", function () {
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						describe("#_updateGroupItemUsers()", function () {
 | 
				
			||||||
 | 
							it("should update createdByUserID and lastModifiedByUserID", async function () {
 | 
				
			||||||
 | 
								var { id: groupID, libraryID } = await createGroup();
 | 
				
			||||||
 | 
								({ engine, client, caller } = await setup({ libraryID }));
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								var item1 = await createDataObject('item', { libraryID });
 | 
				
			||||||
 | 
								var item1DateModified = item1.dateModified;
 | 
				
			||||||
 | 
								var item2 = await createDataObject('item', { libraryID });
 | 
				
			||||||
 | 
								var responseJSON = [
 | 
				
			||||||
 | 
									item1.toResponseJSON(),
 | 
				
			||||||
 | 
									item2.toResponseJSON()
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
								responseJSON[0].meta.createdByUser = {
 | 
				
			||||||
 | 
									id: 152315,
 | 
				
			||||||
 | 
									username: "user152315",
 | 
				
			||||||
 | 
									name: "User 152315"
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								responseJSON[0].meta.lastModifiedByUser = {
 | 
				
			||||||
 | 
									id: 352352,
 | 
				
			||||||
 | 
									username: "user352352",
 | 
				
			||||||
 | 
									name: "User 352352"
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								responseJSON[1].meta.createdByUser = {
 | 
				
			||||||
 | 
									id: 346534,
 | 
				
			||||||
 | 
									username: "user346534",
 | 
				
			||||||
 | 
									name: "User 346534"
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								setResponse({
 | 
				
			||||||
 | 
									method: "GET",
 | 
				
			||||||
 | 
									url: `groups/${groupID}/items?itemKey=${item1.key}%2C${item2.key}&includeTrashed=1`,
 | 
				
			||||||
 | 
									status: 200,
 | 
				
			||||||
 | 
									headers: {
 | 
				
			||||||
 | 
										"Last-Modified-Version": 5
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									json: responseJSON
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								await engine._updateGroupItemUsers();
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								assert.equal(item1.createdByUserID, 152315);
 | 
				
			||||||
 | 
								assert.equal(item1.lastModifiedByUserID, 352352);
 | 
				
			||||||
 | 
								assert.equal(item1.dateModified, item1DateModified);
 | 
				
			||||||
 | 
								assert.equal(item2.createdByUserID, 346534);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							it("should use username if no name", async function () {
 | 
				
			||||||
 | 
								var { id: groupID, libraryID } = await createGroup();
 | 
				
			||||||
 | 
								({ engine, client, caller } = await setup({ libraryID }));
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								var item = await createDataObject('item', { libraryID });
 | 
				
			||||||
 | 
								var responseJSON = [
 | 
				
			||||||
 | 
									item.toResponseJSON()
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
								responseJSON[0].meta.createdByUser = {
 | 
				
			||||||
 | 
									id: 235235,
 | 
				
			||||||
 | 
									username: "user235235",
 | 
				
			||||||
 | 
									name: ""
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								setResponse({
 | 
				
			||||||
 | 
									method: "GET",
 | 
				
			||||||
 | 
									url: `groups/${groupID}/items?itemKey=${item.key}&includeTrashed=1`,
 | 
				
			||||||
 | 
									status: 200,
 | 
				
			||||||
 | 
									headers: {
 | 
				
			||||||
 | 
										"Last-Modified-Version": 6
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									json: responseJSON
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								await engine._updateGroupItemUsers();
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								assert.equal(item.createdByUserID, 235235);
 | 
				
			||||||
 | 
								assert.equal(Zotero.Users.getName(235235), 'user235235');
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	describe("#_upgradeCheck()", function () {
 | 
						describe("#_upgradeCheck()", function () {
 | 
				
			||||||
		it("should upgrade a library last synced with the classic sync architecture", function* () {
 | 
							it("should upgrade a library last synced with the classic sync architecture", function* () {
 | 
				
			||||||
			var userLibraryID = Zotero.Libraries.userLibraryID;
 | 
								var userLibraryID = Zotero.Libraries.userLibraryID;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -930,6 +930,69 @@ describe("Zotero.Sync.Data.Local", function() {
 | 
				
			||||||
				"SELECT COUNT(*) FROM items WHERE libraryID=? AND key=?", [libraryID, key2]
 | 
									"SELECT COUNT(*) FROM items WHERE libraryID=? AND key=?", [libraryID, key2]
 | 
				
			||||||
			), 0);
 | 
								), 0);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							it("should update createdByUser and lastModifiedBy when saving group item", async function () {
 | 
				
			||||||
 | 
								var { libraryID } = await getGroup();
 | 
				
			||||||
 | 
								let item = await createDataObject('item', { libraryID });
 | 
				
			||||||
 | 
								let data = item.toJSON();
 | 
				
			||||||
 | 
								data.key = item.key;
 | 
				
			||||||
 | 
								data.version = 10;
 | 
				
			||||||
 | 
								let json = {
 | 
				
			||||||
 | 
									key: item.key,
 | 
				
			||||||
 | 
									version: 10,
 | 
				
			||||||
 | 
									meta: {
 | 
				
			||||||
 | 
										createdByUser: {
 | 
				
			||||||
 | 
											id: 12345,
 | 
				
			||||||
 | 
											username: 'foo',
 | 
				
			||||||
 | 
											name: 'Foo Foo'
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										lastModifiedByUser: {
 | 
				
			||||||
 | 
											id: 23456,
 | 
				
			||||||
 | 
											username: 'bar',
 | 
				
			||||||
 | 
											name: 'Bar Bar'
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									data
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								await Zotero.Sync.Data.Local.processObjectsFromJSON(
 | 
				
			||||||
 | 
									'item', libraryID, [json], { stopOnError: true }
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								let localItem = Zotero.Items.getByLibraryAndKey(libraryID, item.key);
 | 
				
			||||||
 | 
								assert.isTrue(localItem.synced);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								assert.equal(localItem.createdByUserID, 12345);
 | 
				
			||||||
 | 
								assert.equal(localItem.lastModifiedByUserID, 23456);
 | 
				
			||||||
 | 
								assert.equal(Zotero.Users.getName(12345), 'Foo Foo');
 | 
				
			||||||
 | 
								assert.equal(Zotero.Users.getName(23456), 'Bar Bar');
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							it("should use username if empty name for createdByUser when saving group item", async function () {
 | 
				
			||||||
 | 
								var { libraryID } = await getGroup();
 | 
				
			||||||
 | 
								let item = await createDataObject('item', { libraryID });
 | 
				
			||||||
 | 
								let data = item.toJSON();
 | 
				
			||||||
 | 
								data.key = item.key;
 | 
				
			||||||
 | 
								data.version = 10;
 | 
				
			||||||
 | 
								let json = {
 | 
				
			||||||
 | 
									key: item.key,
 | 
				
			||||||
 | 
									version: 10,
 | 
				
			||||||
 | 
									meta: {
 | 
				
			||||||
 | 
										createdByUser: {
 | 
				
			||||||
 | 
											id: 12345,
 | 
				
			||||||
 | 
											username: 'foo',
 | 
				
			||||||
 | 
											name: ''
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									data
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								await Zotero.Sync.Data.Local.processObjectsFromJSON(
 | 
				
			||||||
 | 
									'item', libraryID, [json], { stopOnError: true }
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
								let localItem = Zotero.Items.getByLibraryAndKey(libraryID, item.key);
 | 
				
			||||||
 | 
								assert.isTrue(localItem.synced);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								assert.equal(localItem.createdByUserID, 12345);
 | 
				
			||||||
 | 
								assert.equal(Zotero.Users.getName(12345), 'foo');
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	describe("Sync Queue", function () {
 | 
						describe("Sync Queue", function () {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue