How to change schema using Cloud Code beforeSave - parse-server

Given the following schema
{
date: '2017-12-09',
amount: 10.00,
notify: true,
isInvoiceSent: false
}
Suppose that I decided to drop the column isInvoiceSent, how can I use Cloud Code and beforeSave to drop that column?
Parse.Cloud.beforeSave("Invoice", function(request, response) {
delete request.object.isInvoiceSent # <-- won't work
response.success();
});
The main reason is because after disabling column creation I get:
Permission denied for action addField on class Invoice

You can use the ‘req.object.unset(“isInvoiceSent”)’
See:
http://parseplatform.org/Parse-SDK-JS/api/v1.11.0/Parse.Object.html#unset For more infos!

Related

Sequelize: SequelizeUniqueConstraintError get conflicting row

I'm creating a backend using Sequelize. For best practices, I want to return Location header if the user tries to create an duplicated resource. Check my code:
try {
const resource = await Resource.create(data);
return res.status(201).send(resource);
} catch (error) {
// Error handling
switch (error.name) {
case 'SequelizeDatabaseError': return res.status(400).send(error);
case 'SequelizeUniqueConstraintError': {
// Resource location
res.location(`/${_location_}`)
return res.status(409).send(_resource_)
};
}
Obs: I'm not sure if check error.name is the best way to get the error. Please comment others if you know.
Printing the error on the console I found the error details:
{
// ...
ValidationErrorItem {
message: 'name must be unique',
type: 'unique violation',
path: 'name',
value: _value_,
origin: 'DB',
instance: [Resource],
validatorKey: 'not_unique',
validatorName: null,
validatorArgs: []
}
],
fields: { name: _value_ },
detail: 'Key (name)=(_value_) already exists.',
// ...
}
Obs: _value_ refers to duplicated value and name to column name.
There is a way to get the id (primary key, uuid, etc.) of the conflicting resource without do another query? If don't, should I really do the query just for return the Location header param?
I also tried it on my local server. I don't think it is possible to get Primary key of the conflicting row.
I would suggest before making .create() call you make .findOne() query so if you found already existing entry then you can return that row so it will also prevent error while creating new entry and it will also save create query on Database.

Dexie.js table.name isn't working even though the table is under the tables property

I'm wanting to fetch all items from a table into a collection but am getting an error that the table name is undefined. Here is my store:
db.version(1).stores({
users: '++id,',
orgs: '++id,',
applications: '++id'
})
Then later here is my call:
db.orgs.toCollection().count(function (count) {
console.log(count)
})
It gives the following error:
TypeError: Cannot read property 'toCollection' of undefined
But when I stop the debugger at the call and type in db.tables sure enough:
1:Table {name: "orgs", schema: TableSchema, _tx: undefined, …}
_tx:undefined
hook:function rv(eventName, subscriber) { … }
name:"orgs"
Any help is appreciated - thanks.
UPDATE
I noticed that when I seeded the database on initial creation I could fetch the data out. So I copied in that code into my template. It still fails however, so there must be something simple I'm missing, here is that code:
import Dexie from '#/dexie.es.js'
export default {
name: 'ListOrgs',
data: () => {
return {
orgs: []
}
},
methods: {
populateOrgs: async function () {
let db = await new Dexie('myDatabase').open()
db.orgs.toCollection().count(function (count) {
console.log(count)
})
}
},
mounted () {
this.populateOrgs()
}
}
Dexie has two modes
Static - the most common one used in most samples.
Dynamic - Schema is not specified in code.
Static Mode
//
// Static Mode
//
const db = new Dexie('myDatabase');
db.version(1).stores({myTable1: '++'});
db.version(2).stores({myTable1: '++, foo'});
db.myTable1.add({foo: 'bar'}); // OK - dexie knows about myTable1!
Dynamic Mode
//
// Dynamic Mode
//
const db = new Dexie('myDatabase');
// FAIL: db.myTable1.add({foo: 'bar'}); // myTable1 is unknown to the API.
// Here, you must wait for db to open, and then access tables using db.table() method:
db.open().then(db => {
const myTable = db.table('myTable');
if (myTable) {
myTable.add({foo: 'bar'});
}
}).catch(error => {
console.error(error);
});
If omitting any version() specification, Dexie will just try to open any existing database with the same name, no matter version or schema. But it won't create the implicit table properties onto the db instance.
When Dynamic Mode is Useful
Dynamic mode can be useful when building an arbritary database utility that should adapt to any indexedDB database - such as a DB explorer. Dynamic mode can also be useful when the javascript code is by design not aware of the schema (what tables are expected to be queried and what indexes there are).
Benefits with Static Mode
No need to wait for db.open() to complete.
Automatic DB creation when neeeded. No complex app code to deal with database versioning.
Automatic DB population when needed.
Design Patterns in Static Mode
db.js
import Dexie from 'dexie';
//
// Let this module do several things:
//
// * Create the singleton Dexie instance for your application.
// * Declare it's schema (and version history / migrations)
// * (Populate default data http://dexie.org/docs/Dexie/Dexie.on.populate)
//
export const db = new Dexie('myDatabase');
db.version(1).stores({
users: '++id,',
orgs: '++id,',
applications: '++id'
});
db.on('populate', () => {
return db.orgs.bulkAdd([
{'foo': 'bar'},
]);
});
app.js
import {db} from './db';
// Wherever you use the database, include your own db module
// instead of creating a new Dexie(). This way your code will
// always make sure to create or upgrade your database whichever
// of your modules that comes first in accessing the database.
//
// You will not have to take care of creation or upgrading scenarios.
//
// Let Dexie do that for you instead.
//
async function countOrgs() {
return await db.orgs.count();
}

Parse Server Dashboard Column validation like User class username

I just want to know if there's a way to make the columns for a class when creating from Parse Dashboard mandatory. Just like _User class has Username, password and email required.
I suggest you use Cloud Code's beforeSave triggers for this. These beforeSave triggers are similar to validators in Mongoose: they are automatically executed before any document of that specific type is saved.
On top of checking that some fields are required, you can use it to set default values, etc.
If the trigger returns an error, the document will not be saved. If it returns a success, the flow continues and the document is saved.
Here's a quick sample to create a beforeSave on the User class:
Parse.Cloud.beforeSave(Parse.User, function (request, response) {
if (request.object.get('favouriteAnimals') === undefined) {
request.object.set('favouriteAnimals', []);
}
if (!request.object.get('firstName') || !request.object.get('lastName')) {
response.error('Full name is required.');
}
else {
response.success();
}
});

how to create a task using SPService

I have used SPService to pull all the task that I have in my task list. I need to know how can I use SPService to create a task in standard SharePoint 2010 Task List.
I was able to create an item using sample code provided in a sample list but need to know what it takes to be able to create an item in Task list.
Thank you
The following example demonstrates how to create a Task item using SPServices:
function createTask(taskName,assignedToId, success,error) {
$().SPServices({
operation: "UpdateListItems",
batchCmd: "New",
listName: "Tasks",
valuepairs: [["Title", taskName],["AssignedTo", assignedToId]],
completefunc: function (xData, Status) {
if (Status == "success") success();
else error(xData.responseText);
}
});
}
Usage
var approverUserId = 10;
createTask('Approve order',approverUserId,
function(){
console.log('Task has been created');
},
function(error){
console.log('An error occurred while creating Task');
});
Key points:
UpdateListItems operation is used for creating list item
Title (TaskName) and AssignedTo field values are specified

Parse.com procedure for validating password requirements in Parse.Cloud.beforeSave(Parse.User

I am trying to find the best procedure for adding password requirements with Parse.com. It appears the easiest way would be to use a cloud function to execute right before user data is saved. My only caveat is that I want to validate user passwords only when the password is different from what is stored in the db or if the user does not exist in the db.
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
...
}
Couple of questions:
Does request.object.existed() work in beforeSave functions as it does with afterSave?
Can I access the user's password (using Parse.Cloud.useMasterKey()) via the request.object in the beforeSave functions? Or do I need to query the user's object inside the function.
In the log the input to the beforeSave function appears to have original and updated keys similar to the json below. However, I was not able to access the original and update json through the request.object. How would I access this data? It would be nice if the only check needed to be performed to verify whether a user's password as changed if a comparison between request.object.original.password !== request.object.updated.password
Sample cloudcode log output:
Input: {"original":{"email":"blah",
"firstname" : "blah",
"emailVerified":true,
"username":"blah",
"createdAt":"2014-04-28T23:05:47.452Z",
"updatedAt":"2014-0716T01:55:52.907Z",
"objectId":"blah",
"sessionToken":"blah"},
"update":{"firstname":"blah2"}}
Try something like this:
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
if (request.object.isNew()) {
// new object..
response.success();
} else {
if (request.object.dirtyKeys().indexOf("password") > -1) {
// Attempted to change the password.
response.error('No.');
}
}
});