1.0.3 • Published 5 months ago

snowtools-session-context v1.0.3

Weekly downloads
-
License
ISC
Repository
-
Last release
5 months ago

snowtools-session-context

This React-Native library provides session context to your application. Upon authentication, a session token is issued and stored securely on the device. Your page logic can therefore inspect the session details to determine if someone is logged in and fetch their basic details. All API calls and WebSocket connections will automatically provide the session token as the AuthN strategy.

Installing

npm i snowtools-session-context

Declaring

The SessionContextProvider needs to be top-most element, so that anything underneath can access and make use of the Session Context provider.

import { SessionContextProvider } from "snowtools-session-context";

export default function Index() {
  return (
    <SessionContextProvider>
      <!-- your content goes here -->
    </SessionContextProvider>
  );
}

Usage

Inside your component functions that are declared wihtin the scope of the SessionContextProvider, you can make use of the Session Context by declaring the methods you wish to use:

import { useSessionContext } from "snowtools-session-context";

export default function MyComponent() {
  const { services, session, isOnline, isBiometricAuthenticated, isBiometricAuthenticatedOnce } = useSessionContext();
}

Methods Available

NameReturnsDescription
servicesServicesUseful service methods (see Service Methods below)
sessionSessionReturns the session context if the user is logged in or null if not
isOnlinebooleanWhether we have an active WebSocket to the application server
isBiometricAuthenticatedbooleanHas the user been authenticated by biometics in the past n seconds
isBiometricAuthenticatedOncebooleanHas the user been authenticated by biometics since opening the app

Service Methods

MethodDescription
callApi(params: ApiWrapperParams): Promise;Make a JSON request/response to the application server (see Calling APIs below)
isLoading(): boolean;Returns true when an API call is in progress. Useful for toggling UI functionality (see Calling APIs below)
goOnline(): void;Open the WebSocket connection to the application server (see Using WebSockets below)
goOffline(): void;Close the WebSocket connection to the application server (see Using WebSockets below)
sendMessage(message: string): void;Send a message over the WebSocket to the application server (see Using WebSockets below)
registerListener(name: string, callback: SetStateAction): void;Register a recipient of response messages from the application server via WebSocket (see Using WebSockets below)
isBiometricAuthenticated(timeout?: number): boolean;Check if the user has been authenticated biometricly since timeout seconds ago
authenticateBiometric(timeout?: number): Promise;Authenticate the user using biometrics if they haven't been autenticated since timeout seconds ago (or immediately if timeout is undefined)

Calling APIs

Define globally the base URL to use for API calls:

import { serviceDefaults } from "snowtools-session-context";
serviceDefaults.setBaseUrl("https://localhost/myapiservices");

The follow example shows a HTTP POST of credentials to the "/login" service:

const [userEnteredEmail, setUserEnteredEmail] = useState<string | null>(null);
const [userEnteredPassword, setUserEnteredPassword] = useState<string | null>(null);

...

services
    .callApi({
        url: "/login",
        body: {
            email: userEnteredEmail,
            password: userEnteredPassword,
        },
    })
    .then((response) => {
        if (response.err) Alert.alert(response.msg);
        // If all went well, then `callApi` did the setSession call
    })
    .catch((error) => {
        Alert.alert("Login Error", "Unknown Error");
        console.log(error);
    });

If url starts with /, then the default URL prefix will be used, which goes to the application server. To call an API outside of the application server, then put the full URL in url, for example: http://somewhere.com/api.

JSON Response Structure

Either the resposne will be what the caller expects, or it will contain the following attributes:

{
    "err": boolean,
    "msg": string,
    "session": Session
}

Session contains the following:

{
    "fn": string,
    "ln": string,
    "loc": string,
    "token": JWT,
    "sid": uuid,
    "uid": uuid
}
NameDescription
fnFirst name
lnLast name
locLocale (eg: en-US)
tokenJWT used for subsequent API calls and for creating a WebSocket connection
sidUUID of the user's current login session
uidUUID of the user

Using WebSockets

Define globally the base URL to use for API calls:

import { serviceDefaults } from "snowtools-session-context";
serviceDefaults.setBaseWebsocketUrl("https://localhost/mywebsocketapp");

The follow example shows a HTTP POST of credentials to the "/login" service: The following test component will automatically initiate a WebSocket using services.goOnline() and register the myclientservice recipient as a call to the setOutputText(string) function. There is an online/offline status bar (green/red respectively) that uses the isOnline flag. Finally messages are sent to the websocket using the services.sendMessage(message) function.

import { View, Text, StyleSheet, Button } from "react-native";
import { useSessionContext } from "snowtools-session-context";
import { TextInput } from "react-native";
import { useState } from "react";

function MyWebSocketTestComponent({ navigation }: { navigation: any }) {

  const { services, session, setSession, isOnline } = useSessionContext();

  const [inputText, setInputText] = useState();
  const [outputText, setOutputText] = useState();

  services.goOnline();
  services.registerListener("myclientservice", setOutputText);

  return (
    <>
      {isOnline && (
        <View style={{ backgroundColor: "green" }}>
          <Text>Online!</Text>
        </View>
      )}
      {!isOnline && (
        <View style={{ backgroundColor: "red" }}>
          <Text>Offline</Text>
        </View>
      )}
      <View style={styles.container}>
        <TextInput
          placeholder="Test"
          autoCorrect={false}
          autoCapitalize="none"
          value={inputText}
          onChangeText={setInputText}
        />
        <Text>Result: {outputText}</Text>
        <Button
          title="Test WebSocket"
          onPress={() => {
            services.sendMessage(
              '{"from": "myclientservice", "data": "sending ' + inputText + '"}'
            );
          }}
        />
      </View>
    </>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "column",
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#ccc",
  },
});

Using Localisations

It is best to feed your local translations into the Session Context Localisation as it will be switched automatically when the locale in user's context changes. To add your own translation files, do the following globally:

import { i18n } from "snowtools-session-context";
import en from "@/assets/languages/en";
import fr from "@/assets/languages/fr";

i18n.store({
  en: en,
  fr: fr,
});

You can still override the locale manually if needed:

i18n.locale = "en";
1.0.3

5 months ago

1.0.2

6 months ago

1.0.1

6 months ago

1.0.0

6 months ago