Customize Whitelabel Storefront

TensorDock offers a "whitelabel" service to select hosts. Organizations can setup storefronts powered by TensorDock's infrastructure, and take a %x commission off sales. Contact us for details.

Admin Panel

The admin panel is your interface for managing the storefront. TensorDock will take care of web hosting and all else under the hood. You must be the administrator of your organization to access the admin panel. To setup your site, simply save your frontend code, along with a subdomain address. We will go over how to do this in the following sections.

Edit Pages

First, you will be greeted by the edit pages section. If you do not have a storefront setup, there will be boilerplate code provided (as seen below). Each page is an HTML document, and we have two stylesheets (Theme, Custom CSS) you can edit. Edits are not live- you must click the "save" button to deploy your code to TensorDock's end. Additionally, the save button will save all the pages & CSS, so it does not matter which tab you're toggled on. You can also upload photos, which will be stored in static/img/.

Domain Management

The next section is domain management. Here, you can set the subdomain and custom domain of your frontend. For example, if you enter the subdomain "test", then anytime another user visits test.tensordock.com they will be served the frontend home page. If they visit test.tensordock.com/login, they will be served the login page of your saved frontend. If you own a custom domain, then you can also insert the domain here.

If its your first time setting up a whitelabel storefront, then after saving the page files and subdomain, you will have a custom storefront ready. All user purchases through your storefront site will earn a x% commission. With a custom domain, you must contact support to finish setting up.

User Management

Here, you can view information on registered users of your storefront.

Email: The email the user registered with

Date Created: The timestamp creation of the user

Email Verified: If the user's email is verified

Organization Name: The organization the user is registered under.

Organization Balance: Available funds of an organization

You can delete users (rendered unable to login). However, that will not delete their machines, as they are registered under organizations. Deleting an organization will delete all of its machines and remove their users.

When users create an account on the whitelabel storefront, that account is only valid on your storefront. They cannot login on the TensorDock marketplace.

Whitelabel API

Here, we will review critical code snippets of the boilerplate frontend, so you can make adjustments easier.

home.html

This simply your landing page; nothing to do here

signup.html

Aside from the standard markup, we have the following code for registration.

fetch(url, {
        method: 'POST',
        body: formData
      })
      .then((response) => response.json())
      .then((data) => {
        console.log(data);
        document.cookie = `whitelabelToken=${data.token}`;
        window.location.href = '/home';
      })
      .catch(error => console.error('Error:', error));

Here, we make a POST request to the /api/v0/client/whitelabel/register endpoint. Fields must be in form-data form, and has the fields email (string), password (string), confirm_password (string), organization_name (string), subdomain (string). After a successful request, the user will be generated on our end and a token will be send back in the response with the field token. This will be stored as a cookie on the client's browser, to be used for authentication later.

login.html

let formData = new FormData();
      formData.append('email', document.getElementById('email').value);
      formData.append('password', document.getElementById('password').value);
      formData.append('subdomain', window.location.hostname.split('.')[0]);

      fetch(url, {
        method: 'POST',
        body: formData
      })
      .then((response) => response.json())
      .then((data) => {
        console.log(data);

        if (data === undefined || data.token === undefined) {
          showMessage('Login failed');
        } else {
          document.cookie = `whitelabelToken=${data.token}`;
          window.location.href = '/deploy';
        }
      })
      .catch(error => {
        console.error('Error:', error);
        alert('Login failed');
      });

Here, we are using the /api/v0/client/whitelabel/login endpoint to simply post the email, password, and subdomain (which is uniquely linked to your storefront). If successful, we will get a token which will be stored as a cookie to be access later.

account.html

const response = await fetch(`${baseUrl}/api/vO/client/whitelabel/getUserInfo`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': whitelabelToken.split('=')[1]
          }
        });

        if (response.ok) {
          const userInquiryResponse = await response.json();
          console.log("RESPONSE WAS OK!")
          console.log("RESPONSE: ", userInquiryResponse)
          document.getElementById('account-funds').textContent = userInquiryResponse.balance;
          document.getElementById('user-id').textContent = userInquiryResponse.uuid;
          document.getElementById('user-email').textContent = userInquiryResponse.email;
          document.getElementById('organization-id').textContent = userInquiryResponse.organization;
          document.getElementById('organization-name').textContent = userInquiryResponse.organization_name;
          document.getElementById('organization-type').textContent = userInquiryResponse.organization_type;
          const membersList = document.getElementById('organization-members-list');
          const members = userInquiryResponse.members; 
          ...
        }else{
          window.location.href = './login.html';
        }

Here, we are doing a GET request to /api/vO/client/whitelabel/getUserInfo to get user information. In order to make authenticated requests, we put in the Authorization header our previous token. If the token is valid, then our response will have the user's balance, unique identifier, email, organization, organization name, organization type, as well as other users in the same organization. You can then display this information anywhere on the page for the user to view.

On an invalid token, the response will be an error code and we will simply redirect the user to the login screen.

const depositFunds = () => {
  const depositAmount = window.prompt("Please enter the deposit amount:");

  if (depositAmount !== null && Number(depositAmount) >= 0) {
    fetch(`http://localhost:5000/createDepositFundsSession/${depositAmount}`, {
      method: 'POST',
      headers: {
        'Authorization': document.cookie.split(';').find((elem) => elem.includes('whitelabelToken')).trim().split('=')[1],
      },
    })
    .then((response) => response.json())
    .then((session) => stripe.redirectToCheckout({ sessionId: session.id }))
    .then(function (result) {
      if (result.error) alert(result.error.message);
    })
    .catch(function (error) {
      console.error("Error:", error);
    });
  } else {
    alert("Invalid deposit amount");
  }
}

This function is used to open a Stripe deposit funds session. We make a POST request to /createDepositFundsSession/, with the deposit amount in the URI and the user's token in the Authorization header. In our boilerplate code, we have this method binded to a button press. When its ran successfully, it will open a Stripe tab on the user's browser to deposit money.

list.html

document.addEventListener("DOMContentLoaded", async () => {
        //const whitelabelToken = document.cookie.split('; ').find(row => row.startsWith('whitelabelToken='));
        if (whitelabelToken) {
            try {
            console.log("THIS RAN!")
            const response = await fetch(`${baseUrl}/api/v0/client/whitelabel/token_verify`, {
                method: 'POST',
                headers: {
                'Content-Type': 'application/json',
                'Authorization': whitelabelToken.split('=')[1]
                },
                //body: JSON.stringify({ whitelabelToken: whitelabelToken.split('=')[1] })
            });

            if (!response.ok) {
                window.location.href = './login.html';
            }
            } catch (error) {
            window.location.href = './login.html';
            }
        }else{
            window.location.href = './login.html';
        }
        })

Here, we do a POST request to the /api/v0/client/whitelabel/token_verify endpoint to verify if the user is logged in. As usual, we put the token in the Authorization header. On an unsuccessful response, we redirect them to login.

deploy.html

Most methods used here (deployServer, updateAvailableLocations, etc) are either using endpoints we covered above, or are using endpoints listed in our docs. If the endpoint is in our docs (start, stop, & delete VM, getting available hostnodes, get list of virtual machines), you can use it as described, but will have to include the token in the Authorization header. Without using the Authorization header, it will be treated as a "normal" TensorDock request as opposed to a whitelabel.

Last updated