I think I need a little more adjustment to my sync function to get these documents out on the mobile.
Perhaps I just need to stop processing in the sync function earlier…?
I have this function:
function (doc, oldDoc) {
function _log(t) {
// Write to sg_info.log
console.log('' + t);
}
function _getUserKey(d) {
var key = null;
if (d) {
if (d.type == 'User') {
key = d.key;
} else {
key = d.userkey;
}
}
return key;
}
if (doc && doc._deleted) {
// Doc. deleted -> if public then require
if(oldDoc){
var userkey = _getUserKey(oldDoc);
_log('delete doc id: ' + doc._id + ', userkey=' + userkey);
if (userkey != null) {
requireUser(userkey);
} else {
requireAdmin();
}
}
_log('doc deleted, id: ' + (doc._id || 'no id!') + ', ' + (oldDoc ? ('old key=' + oldDoc.key + ', userkey=' + userkey) : 'no oldDoc'));
return;
}
_log('doc id: ' + (doc._id || 'no id!') + ', ispublic: ' + doc.ispublic + ', userkey=' + doc.userkey + ', ' + (oldDoc ? (oldDoc._deleted ? 'oldDoc is deleted' : ('old key=' + oldDoc.key + ', oldDoc.userkey=' + oldDoc.userkey + ' update')) : ' creation'));
// Document type is mandatory
if (typeof doc.type === 'undefined') {
_log('Document type missing: ' + JSON.stringify(doc));
throw ({ forbidden: "Document type is required. id=" + doc._id });
}
// Document key is mandatory
if (typeof doc.key === 'undefined') {
_log('Document key missing: ' + JSON.stringify(doc));
throw ({ forbidden: "Document key is required. id=" + doc._id });
}
// Update: Cannot allow change of type or key
if (oldDoc != null && !oldDoc._deleted) {
// Update
if (oldDoc.type != doc.type) {
throw ({ forbidden: "Can't change doc type" });
}
if (oldDoc.key != doc.key) {
throw ({ forbidden: "Can't change doc key" });
}
}
// Document sync is disabled (used for type Image - but generic implementation)
if (doc.issyncdisabled) {
throw ({ forbidden: "Sync. disabled for id=" + doc._id });
}
// All public docs are available in the app
if (doc.ispublic) {
_log('public, id: ' + (doc._id || 'no id!'));
channel('!');
}
// All fishing trips and catches from users AND external reporting are available (for stats or quotas)
if (doc.type == 'FishingTrip' || doc.type == 'Catch') {
if(typeof doc.userkey !== 'undefined'){
_log('Trip/catch for user: ' + doc.userkey + ', id: ' + (doc._id || 'no id!'));
}else{
_log('Externally reported trip/catch, id: ' + (doc._id || 'no id!'));
}
channel('!');
}
// All users are available (for stats)
if (doc.type == 'User' && doc.deleted != true) {
_log('User doc, id: ' + (doc._id || 'no id!'));
channel('!');
}
// Allow anyone to create a Feedback or Observation on the server
if (oldDoc == null && doc.userkey == null && (doc.type == 'Feedback' || doc.type == 'Observation')) {
_log('Created ' + doc.type + ': ' + (doc._id || 'no id!') + ', key: ' + doc.key + ' as anonymous user ');
return;
}
// Only non-public docs "owned" by user can be created/updated (and replicated)
var userkey = _getUserKey(doc);
if (userkey != null) {
if (oldDoc != null && ! oldDoc._deleted) {
// Update
if (oldDoc.userkey && oldDoc.userkey != doc.userkey) {
throw ({ forbidden: "Can't change user key" });
}
}
_log('User owned, id: ' + (doc._id || 'no id!') + ', type: ' + doc.type + ', user: ' + userkey);
if(doc.type != 'Image'){ // Do not send images TO mobile
channel('channel.' + userkey);
}
access(userkey, 'channel.' + userkey);
requireUser(userkey);
} else if (doc.ispublic) {
requireAdmin();
} else {
// Creation/update without user
_log('Document type cannot be created without user key: ' + (doc.type === 'Image' ? doc._id : JSON.stringify(doc)));
throw ({ forbidden: "This document type cannot be created without user key. id=" + doc._id });
}
}
And for a specific document that I want to send out to the mobile I have these loggings:
2020-03-31T08:41:32.222+02:00 [INF] Javascript: Sync doc id: FishingTrip:1A725F5366D5B833C125853C0024C2BA, ispublic: undefined, userkey=undefined, creation
> 2020-03-31T08:41:32.222+02:00 [INF] Javascript: Sync Externally reported trip/catch, id: FishingTrip:1A725F5366D5B833C125853C0024C2BA
> 2020-03-31T08:41:32.222+02:00 [INF] Javascript: Sync Document type cannot be created without user key: {"_deleted":false,"_id":"FishingTrip:1A725F5366D5B833C125853C0024C2BA","_rev":"1-ec336542807417badc34d9164bbd5457","anonymousemail":"ck@xyz.dk","anonymousname":"Christian XYZ","assockey":"3","assoczonekey":"2","catchkeys":["7E495104F4AA0BE4C125853C0024C2BD"],"cloudcover":"0","clubonlykey":"203","clubplacekey":"2C16DE9C74FAA24CC125853C002493DF","date":"2020-03-31T12:00:00+0200","humidity":"48","key":"1A725F5366D5B833C125853C0024C2BA","live":false,"locationlevel1":"9","locationlevel2":"9","locationlevel4":"203","locationtype":"2","month":3,"pressure":"1031","revisioninfo":{"created":"2020-03-31T08:41:32+0200","createdby":"Christian ZXyz/EBCED20047B25F42C1257CB2003360D3/Fangst","modifiedcount":1,"updates":[{"modified":"2020-03-31T08:41:32+0200","modifiedby":"Christian ZXyz/EBCED20047B25F42C1257CB2003360D3/Fangst"}]},"secret":false,"showsocioquestions":false,"statslocation":"9","statspublic":true,"temperature":"6","type":"FishingTrip","weather":"Skyfrit","windbearing":"256","winddirection":"247","windspeed":"4","year":2020,"zerotrip":false}
> 2020-03-31T08:41:32.222+02:00 [INF] Sync fn rejected doc "FishingTrip:1A725F5366D5B833C125853C0024C2BA" / "" --> 403 This document type cannot be created without user key. id=FishingTrip:1A725F5366D5B833C125853C0024C2BA
> 2020-03-31T08:41:32.222+02:00 [INF] Import: Error importing doc "FishingTrip:1A725F5366D5B833C125853C0024C2BA": 403 This document type cannot be created without user key. id=FishingTrip:1A725F5366D5B833C125853C0024C2BA
I want to make sure that I never receive a document of this type from the app - which is why I test for the userkey
field.
I think what I find difficult is to understand what parts of my sync function is used when the documents are being sent out to the app and what parts are used when receiving data from the app.
So far my understanding is that anything that is added to a channel will be available for the app.
And anything I want to update must have a requireUser(…) or requireAdmin() applied to it.
So how do I best obtain this?
- Sbould I stop processing in the sync function by issuing a
return;
once I have added the document to the channel("!")?
- Or should I call
requireAdmin()
to allow it to update on the mobile?
Thanks in advance for any clarification 