constcreationTime=data.creationTime||newDate();// allow tests to set the time
constmanifestJson=JSON.stringify(data.manifest);
constprefixId=data.type===exports.BACKUP_TYPE_APP?`${data.type}_${data.identifier}`:data.type;// type and identifier are same for other types
constid=`${prefixId}_v${data.packageVersion}_${hat(32)}`;// id is used by the UI to derive dependent packages. making this a UUID will require a lot of db querying
constresults=awaitdatabase.query(`SELECT ${BACKUPS_FIELDS} FROM backups WHERE identifier = ? AND state = ? ORDER BY creationTime DESC LIMIT ?,?`,[identifier,state,(page-1)*perPage,perPage]);
constresult=awaitdatabase.query(`SELECT ${BACKUPS_FIELDS} FROM backups WHERE id = ? ORDER BY creationTime DESC`,[id]);
if(result.length===0)returnnull;
returnpostProcess(result[0]);
}
asyncfunctiongetByTypePaged(type,page,perPage){
assert.strictEqual(typeoftype,'string');
assert(typeofpage==='number'&&page>0);
assert(typeofperPage==='number'&&perPage>0);
constresults=awaitdatabase.query(`SELECT ${BACKUPS_FIELDS} FROM backups WHERE type = ? ORDER BY creationTime DESC LIMIT ?,?`,[type,(page-1)*perPage,perPage]);
if(label.length>=200)returnnewBoxError(BoxError.BAD_FIELD,'label too long');
if(/[^a-zA-Z0-9._() -]/.test(label))returnnewBoxError(BoxError.BAD_FIELD,'label can only contain alphanumerals, space, dot, hyphen, brackets or underscore');
returnnull;
}
// this is called by REST API
asyncfunctionupdate(id,data){
assert.strictEqual(typeofid,'string');
assert.strictEqual(typeofdata,'object');
leterror;
if('label'indata){
error=validateLabel(data.label);
if(error)throwerror;
}
constfields=[],values=[];
for(constpindata){
if(p==='label'||p==='preserveSecs'){
fields.push(p+' = ?');
values.push(data[p]);
}
}
values.push(id);
constbackup=awaitget(id);
if(backup===null)thrownewBoxError(BoxError.NOT_FOUND,'Backup not found');
constresult=awaitdatabase.query('UPDATE backups SET '+fields.join(', ')+' WHERE id = ?',values);
if(result.affectedRows!==1)thrownewBoxError(BoxError.NOT_FOUND,'Backup not found');
if('preserveSecs'indata){
// update the dependancies
for(constdepIdofbackup.dependsOn){
awaitdatabase.query('UPDATE backups SET preserveSecs=? WHERE id = ?',[data.preserveSecs,depId]);
}
}
}
asyncfunctionsetState(id,state){
assert.strictEqual(typeofid,'string');
assert.strictEqual(typeofstate,'string');
constresult=awaitdatabase.query('UPDATE backups SET state = ? WHERE id = ?',[state,id]);
if(result.affectedRows!==1)thrownewBoxError(BoxError.NOT_FOUND,'Backup not found');
}
asyncfunctionlist(page,perPage){
assert(typeofpage==='number'&&page>0);
assert(typeofperPage==='number'&&perPage>0);
constresults=awaitdatabase.query(`SELECT ${BACKUPS_FIELDS} FROM backups ORDER BY creationTime DESC LIMIT ?,?`,[(page-1)*perPage,perPage]);