@contextualize/carta
v0.0.49
Published
Node wrapper for Carta API
Keywords
Readme
Installation
npm i @contextualize/cartaAbout
@contextualize/carta is a wrapper and utility for interfacing with Contextualize's Carta infrastructure. This package is designed to be used both on the front-end to build web application that seemlessly integrate with Carta, and on the back-end to create microservices that can leverage the Carta permissions system and user generated services made public through Carta.
Use Cases
- Handle user authentication through Carta
- Check permissions
- Interface with Carta Services
Configuration
Carta.configure() must be called before any part of the Carta class can be used.
|Option|Description|Type|Default|
|-----|--------|---|----|
|environment|The environment you are targetting. This should be "Production" unless otherwise instructed by Contextualize.| "Production" \| "Sandbox"| "Production"
|noCognito|Disable cognito functions. Useful for NodeJS microservices that ingest an existing user token.| boolean |false
Authenticate
You can authenticate a Carta session by either providing a token directly to the Carta constructor new Carta(token) or providing a username and password to await Carta.signIn(username, password).
In front-end applications, you can check for an existing session token by calling await Carta.session()
Token managment
Frontend applications
In frontend applications, the token is stored as a cookie to the *.contextualize[.us | -dev].com domain.
Tokens are automatically refreshed.
Stand-alone applications
The token is stored to RAM.
Tokens are automatically refreshed.
Microservices
Tokens will be provided to you by an accompanying frontend or stand-alone application.
Tokens should only be kept as long as the current user interaction. For example, with a REST API, the token should not be stored between requests.
Tokens cannot be refreshed by a microservice.
Use in Microservices
When using this package in microservices, a connection to Cognito is not recommended. Token validity is already checked by Carta.API, and creating user tokens in a microservice is bad practice.
Disable Cognito
Setting noCognito: true in your Carta configuration saves time by skipping Cognito User Pool configuration. Any functions labeled as "Cognito Dependent" will throw an error, such as Carta.signIn, Carta.session, and Carta.authenticatedUser
Carta.configure({
noCognito: true
});Carta Service Wrapper
@contextualize/carta simplifies the way you connect to Carta Services, automatically handling URL generation and Authorization tokens.
// Get an active session
const carta = await Carta.session();
// Create a service wrapper
const myService = carta.service.utilize(myNamespace, myService);
// Call your service endpoints as if you were fetching from it directly
const responseGet = await myService.get("my/resource/path");
const responsePost = await myService.post("my/resource/path", {
/*
json:
automatically serializes objects and sets Content-Type header
*/
json: myObjectPayload,
/*
query:
convert an object into a URL encoded querystring and appends it to the path i.e. ?my=query
*/
query: {'my': 'query'}
/*
headers:
Append additional headers to your request.
`Authorization` is automatically set by Carta.request
`Content-Type` is automatically set when `json` option is set
*/
headers: {
'X-Custom-Header': "custom header value"
}
});Examples
Test Bench NodeJS Application
index.ts
import Carta from "@contextualize/carta";
// Configure Carta
Carta.configure();
// Sign in using env variables
const carta = await Carta.signIn({
username: process.env['CARTA_USERNAME'],
password: process.env['CARTA_PASSWORD']
});
// Get projects
const projects = await carta.project.list();
// Print projects
console.log('My Projects:');
projects.forEach((project)=>{
console.log(`${project.id} ${project.name}`);
});
React App
src/index.tsx
import ReactDOM from "react-dom";
import App from "./app";
import Carta from "@contextualize/carta"
Carta.configure();
const rootElement = document.getElementById("root");
ReactDOM.render(
<App />,
rootElement
);src/App.tsx
import { FunctionComponent, useState, useEffect } from 'react'
import Carta from "@contextualize/carta"
import { Project } from "@contextualize/carta/dist/dto/Items"
export default function HomePage(): FunctionComponent {
const [projects, setProject] = useState<Project[]>([])
useEffect(()=>{
(async ()=>{
const carta = await Carta.session();
if(!carta){
// If the user isn't logged in, redirect them to Carta Portal
document.location = Carta.portalHost;
return;
}
// Get a list of projects the user has access to
const _projects = await carta.project.list();
// Update the projects state variable
setProjects(_projects);
})();
}, []);
return (
<div>
<h3>My Projects</h3>
<ul>
{ projects.map((project)=>(
<li key={project.id}>
{project.name}
</li>
)) }
</ul>
</div>
);
}Express Microservice
index.ts
const express = require('express');
const {default: Carta} = require("@contextualize/carta")
// Configure Carta with no cognito
Carta.configure({noCognito: true});
const app = express();
app.get('/projects', async (req, res)=>{
const carta = new Carta(req.headers['Authorization']);
const user = carta.userFromToken();
console.log(`Request received from ${user.name}`);
const projects = await carta.project.list();
res.status(200).json(projects);
})
const PORT = process.env.PORT || 3001;
app.listen(PORT, ()=>console.log(`App running on port ${PORT}`);Exceptions
The class heirachy of Carta exceptions is
CartaException(extendsError)All CartaExceptions will have a
messagesetCartaConfigurationExceptionCartaNoCognitoExceptionApplication attempted to call a Cognito Dependant function when Cognito was disabled in configuration
CartaIncompleteUserExceptionThe user has not completed the on-boarding process, and must be redirected to Carta Portal to complete the setup of their account
UnableToRefreshTokenExceptionToken is expired and then refresh token is missing or expired
CartaTokenExpiredExceptionThrown if a token is expired and Cognito is not available to refresh
CartaHttpExceptionAny HTTP error encountered when interfacing with the Carta API or service through the Carta API. CartaHttpException contains the response that caused the exception in case it contains any further valuable information in handling the exception. | Member Variable | Type | | --------------- | ---- | |
response|Response|CartaPermissionsExceptionCartaNotAuthenticatedException401 response from Carta
CartaPermissionDeniedException403 response from Carta
CartaServerErrorException500 response from Carta
CartaMalformedRequestException400 response from Carta
GenericHttpExceptionAny HTTP error response not explicitly handled previously. Will attempt to make a human readable
messageout of the response.
Examples
Incomplete User
import Carta from "@contextualize/carta"
import { CartaIncompleteUserException } from "@contextualize/carta/dist/exceptions/CartaException";
await Carta.configure();
try{
// Attempt to log into Carta
await Carta.signIn({username: "user", password: "pass"});
}catch(e){
// If the user's profile is incomplete, redirect them to Carta Portal
if(e instanceof CartaIncompleteUserException){
document.location = Carta.portalHost;
}
throw e;
}Permissions
import Carta from "@contextualize/carta";
import { CartaTokenExpiredException } from "@contextualize/carta/dist/exceptions/CartaException";
import { CartaNotAuthenticatedException, CartaPermissionDeniedException } from "@contextualize/carta/dist/exceptions/CartaPermissionException";
await Carta.configure();
const carta = new Carta(`[POTENTIALLY INVALID TOKEN]`);
try{
// The user might not have permission to the resource
await carta.project.get(`[RESOURCE UUID]`)
}catch(e){
if((e instanceof CartaNotAuthenticatedException)
|| (e instanceof CartaTokenExpiredException)){
// Prompt user to log in again
}
if(e instanceof CartaPermissionDeniedException){
// Alert the user that they do not have permission to access that resource
}
throw e;
}