Skip to main content

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.

NameTypeDescription
rowRecord<string, any>All data in the current row.
userRowy UserAll data in the current row.
refDocumentReferenceReference to the corresponding Firestore document of the current row.
dbFirestoreAccess to the full Cloud Firestore instance to access any collection or document.
authAuthAccess 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",
};
}
});