Action
Action columns allow you to run scripts in nodejs environment.
Actions expect to end by returning an ActionStatus object There two modes for action columns;
- Script
- Callable
Script
Action scripts are executed on Rowy Run and don't require any build process, However they can not use external npm packages.
API
Your code has access to the following parameters and can use the
await
keyword.
Name | Type | Description |
---|---|---|
row | Record<string, any> | All data in the current row. |
user | Rowy User | All data in the current row. |
ref | DocumentReference | Reference to the corresponding Firestore document of the current row. |
db | Firestore | Access to the full Cloud Firestore instance to access any collection or document. |
auth | Auth | Access to Firebase Auth via Admin SDK |
Examples
Setting User Roles in Firebase Auth Custom Claims
const action: Action = async ({ row, ref, db, storage, auth, actionParams, user, logging }) => {
logging.log("action started");
const { roles } = row;
const user = await auth.getUser(ref.id);
const customClaims = {
...user.customClaims,
roles,
};
await auth.setCustomUserClaims(ref.id, customClaims);
return {
success: true,
status: `updated roles:${roles.join(", ")}`,
message: `${row.firstName} has ${roles.join(", ")} roles now`,
cellValue: {
redo: true,
status: `updated roles:${roles.join(", ")}`,
completedAt: serverTimestamp(),
meta: { ranBy: context.auth.token.email },
undo: false,
},
};
};
export default action;
Sending an email via Sengrid
⚠️ Make sure to add your sendrid API key to Secret Manager, and verify the sender email address on Sengrid.
const action: Action = async ({ row, ref, db, storage, auth, actionParams, user }) => {
const sendgridSecret = await rowy.secrets.get("sendgrid")
const res = await fetch("https://api.sendgrid.com/v3/mail/send", {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + sendgridSecret,
'content-type': 'application/json'
},
body: JSON.stringify({
asm: {
// group_id: 0000 Unsubscribe group id
},
from: { name: "Sender Name", email: "you@company.com" },
personalizations: [
{
to: [{ name: row.name ? row.name : "", email: row.email }], // recipient
dynamic_template_data: {
}, // template parameters
},
],
template_id: "TEMPLATE_ID", // sendgrid template ID
//categories: [], // helper info to categorise sendgrid emails
custom_args: {
docPath: ref.path,
// optional, reference to be used for tracking email events
// add any other custom args you want to pass to sendgrid events here
}
})
})
if (res.ok) {
return {
success: true,
message: `Emailed ${row.name}`
}
}
const resData = await res.json()
if (resData.errors) {
return {
success: false,
message: resData.errors
}
}
}
export default action;
Callable
Callable mode requires you to build cloud functions that are compatible with
Rowy action columns, using the
Rowy Actions npm package, It's
used as an alternative to directly using functions.https.onCall function
, it
can be installed and used in an existing firebase cloud functions project, and
be used for more complex functionality that can not be achieved using
actionScripts.
Example
Example structure of how callable using rowy-actions package, the example illustrates how to disable a Firebase Auth user account with a callable.
import * as admin from "firebase-admin";
const auth = admin.auth();
import callableAction from "rowy-actions";
export const SuspendUser = callableAction(async ({ row, callableData }) => {
const { action } = callableData;
const { firstName, email } = row;
// switch statement can be used to perform different event based on the state of the action cell
const user = await auth.getUserByEmail(email);
switch (action) {
case "run":
case "redo":
// both run and redo preform the same action; disabling the user's account from firebase auth
await auth.updateUser(user.uid, { disabled: true });
return {
success: true, // return if the operation was success
message: `${firstName}'s account has been disabled`, // message shown in snackbar on the rowy ui after the completion of action
cellStatus: "disabled", // optional cell label, to indicate the latest state of the cell/row
newState: "undo", // "redo" | "undo" | "disabled" are options set the behavior of action button next time it runs
};
case "undo":
// re-enable user's firebase account
await auth.updateUser(user.uid, { disabled: false });
return {
success: true, // return if the operation was success
message: `${firstName}'s account has been re-enabled`, // message shown in snackbar on the rowy ui after the completion of action
cellStatus: "active", // optional cell label, to indicate the latest state of the cell/row
newState: "redo", // "redo" | "undo" | "disabled" are options set the behavior of action button next time it runs
};
default:
// return error message when no action is preformed
return {
success: false,
message: "Reached undefined state",
newState: "redo",
};
}
});