Alliance Business Suite

Version Documentation License: ABS EULA Twitter: fenixalliance

Welcome to the Alliance Business Suite Documentation!

Aiming to help organizations reach beyond expectations, the Alliance Business Suite is designed to augment businesses across industries worldwide through a low-code, and fully customizable business development platform.

At a very high level, the Alliance Business Suite is a set of powerful, extensible, multi-tenant applications built to enable businesses to jumpstart their digitalization process through powerful business applications built to cover the core processes of any given business.

The Alliance Business Suite provides customers with a Full-Stack, Low-Code, Modular, and Multi-Tenant Business Application Framework built on top of the Alliance Business Platform.

The Alliance Business Suite relies on five major components designed to separate different functionalities into layers; these components are:

The Alliance Core Libraries contain the core abstractions and default implementations required by the Alliance Business Model and dependent components. It is also the external dependency source for the entire Alliance Business Suite, which means that external dependencies, which are dependencies outside the FenixAlliance.* namespace, are referenced by the FenixAlliance.ACL.Deps Package, which is the base ACL Package and, therefore, it could be referred to as the Core Package.

For more information on the dependency tree, design overview, and external dependencies, please refer to Advanced Topics.

The Alliance Business Model is a declarative specification and definition of standard entities that represent commonly used concepts and activities across business and productivity applications and is being extended to observational and analytical data as well. ABM provides well-defined, modular, and extensible business entities such as Accounts, Business Units, cases, Contact, Leads, Opportunity, and Items (Products/Services) and interactions with vendors, workers, and customers, such as activities and service level agreements. that serve as the dynamic data layer for the entire Alliance Business Suite.

Anyone can build on and extend ABM definitions to capture additional business-specific scenarios.

The Alliance Passport Service enables developers and non-developers alike The Alliance Passport Service is an Authentication/Authorization Engine designed to enable customers to easily configure and manage business identity scenarios by assigning (or connecting) a digital identity to their contacts, whether they are customers, employees, partners, guests, and more.

It also provides common features for managing authentication, authorization, data protection, HTTPS enforcement, app secrets, XSRF/CSRF prevention, and CORS management. These security features allow you to build robust, yet secure Alliance Business Suite apps.

The Alliance Business Platform is a Modular API Framework. It leverages .NET 5.0 with the best of REST, SignalR, GraphQl y gRPCto transact with the Alliance Business Model Schema (AMB). The Alliance Business Platform is an open-source and cross-platform framework for integrating next-generation functionalities into your applications. It allows you to build spectacular single-page apps using .NET and C# with or without JavaScript. ABP apps can connect and transact to the data layer (The Alliance Business Modal Schema) using any language through standard requests through the various GrPC, HTTP, and GraphQL Endpoints.

To capture additional business-specific scenarios, you can easily build on and extend The Alliance Business Platform through ASP.NET + Angular / React (And pretty much any Web Stack Framework).

The Alliance Business Studio is the Graphical Administration Engine for the Alliance Business Suite. It allows users to manage their implementations, transact data through the Alliance Business Platform, generate and consume views, and reports, customize and extend the system, and much more.

You can build on top of, and extend The Alliance Business Studio to capture additional business-specific scenarios.

How to build applications on top of the Alliance Business Suite?

Client and server code are written in C#, allowing users to extend the product with their code through Module libraries. It builds upon next-generation technologies such as Blazor, SignalR, Razor Pages, and MVC through .NET, an open-source and cross-platform framework for building web-mobile apps using C#, with or without the use of JavaScript.

The power of the Alliance Business Suite can be leveraged from small personal blogs, eCommerce platforms, and professional portfolios to the infrastructure of large corporations.

User Guide

Getting Started

For Business Use.

  • Download or Clone the latest Alliance Business Suite release. Decompress the downloaded .zip on a folder on your PC, navigate to that folder and execute the FenixAlliance.ABS.Web.exe file.

A console window will pop up, providing information about the initialization process. Open your server on the provided URL, go through the installation wizard, and start using the Alliance Business Suite. For more information about hosting your Alliance Business Suite instance, please refer to Hosting your Alliance Business Suite.

For Developer Users

  • Install the latest edition (v16.8 or higher) of Visual Studio 2019 (Community, Professional, or Enterprise Editions) with the ASP.NET and web development workload enabled. Alliance Business Suite works with ALL editions of Visual Studio from Community to Enterprise. If you do not have a SQL Server installation available already and you wish to use LocalDB for development, you must also install the .NET desktop development workload.

  • Download a release or Clone the ABS. Portal repository to your local system using Git. Open the FenixAlliance.ABS.Portal.sln solution file and Build the solution. Make sure you specify FenixAlliance.ABS.Portal as the Startup Project and then Run the application.

Installing an official release:

Additional Instructions

  • If you have already installed a previous version of Alliance Business Suite and you wish to do a clean database install, simply point the DefaultConnection value in the ABS Portal Settings Manager to a fresh database record. This will trigger a re-install when you run the application which will execute the database installation scripts.

  • Every ABS Repo ignores appsettings.json by default, so as long as you don't delete the directive from .gitignore, you're cleared to submit a pull request.

Video Series

  • If you are getting started with Alliance Business Suite, a series of videos are available that explain how to install the product, interact with the user interface, and develop custom modules.

Documentation

There is a separate Documentation repository, which contains various types of documentation for the Alliance Business Suite, including the C# API documentation for every class on every library. The contents of the repository are available at https://docs.absuite.net as interactive documentation.


Easy Install

The Easy Way: As a Docker Container.

docker pull FenixAlliance.ABS:latest

Conventional Install

git clone https://github.com/FenixAlliance/ABS.Bin
cd ABS.Bin
./FenixAlliance.ABS.Web.exe

or

dotnet FenixAlliance.ABS.Web.dll

Installing as an application dependency

dotnet nuget add source https://nuget.absuite.net/nuget -n absuite.net
dotnet add package FenixAlliance.ABS.Hub --version latest
dotnet add package FenixAlliance.ABS.Assets --version latest
using FenixAlliance.ABS.Hub.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

namespace FenixAlliance.ABS
{
    public class Startup
    {
        public IHostEnvironment Environment { get; set; }
        public IConfiguration Configuration { get; }

        // Constructor
        public Startup(IConfiguration Configuration, IHostEnvironment Environment)
        {
            this.Environment = Environment;
            this.Configuration = Configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
          services.AddAllianceBusinessSuite(Configuration, Environment);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
          app.UseAllianceBusinessSuite(Configuration, Environment);
        }
    }
}
using FenixAlliance.ABS.Hub.Extensions;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAllianceBusinessSuite(builder.Configuration, builder.Environment);

var app = builder.Build();

app.UseAllianceBusinessSuite(builder.Configuration, builder.Environment);

app.Run();

Release Announcements

Alliance Business Suite v1.2

Example Screenshots

ABS Studio Dashboard:

image.png

ABS Extensions:

The ABS is modular. Whether you need to add pages, products, or posts with no code at all (using the ABS Web Designer), modify the style or layout, or add your Types, Controllers, Pages, Views, Components, or Tag Helpers

ABS Extensions

ABS Commander Terminal:

The ABS Commander Terminal is a Built-In functionality that allows users to execute commands against the ABP set of APIs.

ABS Commander Terminal

ABS WOPI Connector:

The ABS Workplace Module allows users to create, view, and edit Office files with Office for the web, right from their ABS Instances. It also allows users to manage files for pretty much every entity type.

ABS WOPI Connector

ACS Bot Maker:

The Alliance Conversational Services Bot Maker Platform is an ABS extension that allows users to create conversational flows using NLP and a graphical UI.

ABS Bot Maker

Versioning

Maintaining forward and backward compatibility is a key goal of the ABS. Therefore, the ABS now uses only additive versioning, which means any revision of the ABM following the "2.0" release will not:

  • Introduce new mandatory attributes on previously published entities, or change an optional attribute to be mandatory
  • Rename previously published attributes or entities
  • Remove previously published attributes

🤝 Contributing

Contributions, issues, and feature requests are welcome!
Feel free to check issues page. You can also take a look at the contributing guide.

  1. Issue Guidelines
  2. Report Security Vulnerabilities
  3. Pull Request Requirements
  4. Translations
  5. Chart of Accounts

Show your support

Give this project a ⭐️ if this project helped you!

Author

👤 Fenix Alliance Inc.

Logo and Trademark

The brand name Alliance Business Suite and its logos are trademarks of Fenix Alliance S.A.S in Colombia and Fenix Alliance Inc in other countries ("Fenix Alliance").

Fenix Alliance owns and oversees the trademarks for the ABS name and logos. We have developed this trademark usage policy with the following goals in mind:

  • We’d like to make it easy for anyone to use the ABS name or logo for community-oriented efforts that help spread and improve ABS.
  • We’d like to make it clear how ABS-related businesses and projects can (and cannot) use the ABS name and logo.
  • We’d like to make it hard for anyone to use the ABS name and logo to unfairly profit from, trick, or confuse people who are looking for official ABS resources.

Licensing and Contributions

Your access to and use of the Alliance Business Suite's source code is governed by the Fenix Alliance's End User License Agreement "EULA". If you don't agree to those terms, as amended from time to time, you are not permitted to access or use the Alliance Business Suite.

We welcome any contributions to the Alliance Business Suite development through pull requests on GitHub. Most of our active development is in the development branch, so we prefer to take pull requests there (particularly for new features). We try to make sure that all new code adheres to the Fenix Alliance coding standards. All contributions are governed by the terms of the EULA.

Legal Notices

Fenix Alliance and any contributors grant you a license to the documentation and other content in this repository under the Creative Commons Attribution 4.0 International Public License and grant you a license to any code or binary form Fenix Alliance through the ABS EULA.

Fenix Alliance, Alliance Business Suite, Infinity Comex, and/or other Fenix Alliance products and services referenced in the documentation may be trademarks or registered trademarks of Fenix Alliance Inc. in the United States/or other countries. The licenses for this project do not grant you rights to use any of Fenix Alliance's names, logos, or trademarks. Fenix Alliance's general trademark guidelines can be found at http://docs.fenix-alliance.com.

Privacy information can be found at https://fenix-alliance.com/legal/policies/privacypolicy

Fenix Alliance and any contributors reserve all other rights, whether under their respective copyrights, patents, or trademarks, whether by implication, estoppel, or otherwise.

Alliance Business Suite - Low-Code Next-Generation Business Development Platform. | Product Hunt

About this Documentation

Welcome to the Alliance Business Suite documentation! We are on the mission to create the Ultimate Business Development Platform to provide you an unprecedented suite of capabilities to ensure your business can exceed customer's expectations through next-generation experiences.

We believe that knowing your customers and your business enables you to personalize each experience and optimizes efficiencies so you can earn customers for life.

This documentation is constantly being developed and adapted to the latest version of the Alliance Business Suite and its goal is to provide an extensive guide for technical and non-technical audiences alike. At a very high level, this documentation provides guides on how to perform common tasks within the Alliance Business Suite, but it also digs deeper, sometimes, into technical details; but don't worry, we'll let you know the technical difficulty at the beginning of every guide.

Some guides contained in this documentation require special Business Permissions or installable software. Requirements, if any, will be highlighted at the beginning of each guide.

Some parts of this documentation are still being developed and changes are made to it every day, so please feel free to request further explanation or provide feedback about features you would like us to explain in more detail.

Contributing to the Alliance Business Suite and/or its documentation

Woohoo! You've decided to contribute? That's amazing! We want to make contributions to the Alliance Business Suite as easy and frictionless as we can. Contributing requires a GitHub account. If you don't have an account, follow the instructions for the GitHub account setup.

Then, you just need to create an Issue to report bugs, propose APIs, request features and tooling, propose designs and improvements.

All of these contributions will be filled as Issues on the Alliance Business Suite Documentation Repository and they adhere to the Issue Management Policy.

Roadmap

This project is a work in progress and the schedule for implementing enhancements is dependent upon the availability of community members who are willing/able to assist. For a more comprehensive look at our roadmap, please visit our Progess Board.

Proposed:

  • Node.js SDK
  • PowerShell SDK
  • Agreement Template Definitions
  • Email Signature Template Definitions
  • Document Template Definitions
  • Article Template Definitions
  • gRPC Modularization
  • Reporting Dashboard
  • Dynamic Dashboards
  • gRPC Modularization
  • ACS Modularization
  • UBL 2.1 Support
  • Process Canvas.
  • Granular Property Set Access
  • Custom Includes Definitions
  • Virtual Entity Data Sources
  • In-Portal Live Chat Widget
  • ML-Based Search Results Ranking Engine
  • ML-Based Fraud Detection Engine (Anomaly Detection), (Binary Classification)
  • ML-Based Price Prediction Engine
  • ML-Based Sales Spike Detection Engine (Anomaly Detection)
  • ML-Based Sales Forecasting Engine (Regression), (Time Series)
  • ML-Based Sentiment Analysis Engine
  • ML-Based Customer Segregation Engine (Clustering)

Planned:

  • Node Package for Static Assets distribution & version management
  • New IService interface & Default Implementation as an optional base for Service Interfaces.

Achieved:

  • ✅ MudBlazor Integration is now available for Studio Modules
  • ✅ Fluent UI Integration is now available for Studio Modules
  • ✅ FAST Design Integration is now available for Studio Modules
  • ✅ New IDateTimeService interface & Default Implementation for Date/Time Localization.
  • ✅ New IServicesService interface & Default Implementation for service resolution helpers through DI.
  • ✅ New IService interface & Default Implementation as an optional base for Service Interfaces.
  • ✅ .NET 6.0 LTS Update
  • ✅ Studio Layout Localization
  • ✅ Code Editor: Razor Syntax Highlighting
  • ✅ ML-Based Natural Language Processing Engine
  • ✅ ML-Based eCommerce Recommendation Engine
  • ✅ Template Definitions
  • ✅ ML-Based Spam Detection Engine
  • ✅ In-Studio Live Chat Manager
  • ✅ Code Editor: Diagnostics Highlighting
  • ✅ Workflow Manager Engine (Experimental)
  • ✅ Workflow Visual Designer (Experimental)
  • ✅ ML-Based Language Detection Engine
  • ✅ Fluid Support (Experimental)
  • ✅ Email Template Definitions
  • ✅ Blazor Support (Experimental)
  • ✅ Options & Settings API
  • ✅ .NET SDK
  • ✅ Custom Options Manager
  • ✅ Custom Portal Option Definitions
  • ✅ Virtual SPA Support (Angular/React)
  • ✅ Razor Templating Engine
  • ✅ Live Web Designer Integration
  • ✅ Dynamic Entity Views
  • ✅ Content Live Builder
  • ✅ Custom Controller Definitions
  • ✅ Portal Settings Manager UI
  • ✅ Custom Option Definitions
  • ✅ Custom Service Endpoint Definitions
  • ✅ Custom Web Portal Resources
  • ✅ Alliance Passport Services (Auth Engine)
    • ✅ TOTP MFA Enabled
    • ✅ Local Account Support
    • ✅ Microsoft Identity Integration
    • ✅ Twitter Identity Integration
    • ✅ Facebook Identity Integration
    • ✅ Google Identity Integration
    • ✅ Azure AD Identity Integration
    • ✅ Azure AD B2C Identity Integration
    • ✅ Okta Identity Integration (Preview)
    • ✅ AWS Cognito Identity Integration
    • ✅ Default Identity Management
  • ✅ Module Manager Dashboard
    • ✅ Trusted Publisher Rules
    • ✅ Module Assembly Manager
    • ✅ Managed Module Support
    • ✅ Unmanaged Module Support
  • ✅ Authentication / User Management / Profile Management
  • ✅ Authorization / Roles Management / Granular Permissions
  • ✅ Blazor Support
  • ✅ Cross-Platform Database Support ( MySQL, MSSQL )
  • ✅ Dynamic CSS/Lazy Loading
  • ✅ Dynamic Page Compositing Model / Site & Page Management
  • ✅ Dynamic Routing
  • ✅ Dynamic Swagger Specs
  • ✅ EF Core Migrations for Database Installation / Upgrade
  • ✅ Enabled for Infinity Comex (eCommerce Extension)
  • ✅ Event Logging / Audit Trail
  • ✅ Extensibility via Custom Modules
  • ✅ Extensibility via Custom Themes
  • ✅ Folder / File Management (Azure Storage, File System)
  • ✅ GraphQl API with Voyager, GraphiQl y GraphQl Playground
  • ✅ Headless API with Swagger Support
  • ✅ HealthCheck Rules with UI Support
  • ✅ i18n Enabled (Based on GeoAPI and Custom Settings)
  • ✅ Improved JavaScript reference support
  • ✅ In-App CLI (Studio Commander)
  • ✅ Infinity Comex Support (ABS' eCommerce Engine)
  • ✅ JavaScript Lazy Loading
  • ✅ Modular Architecture
  • ✅ Multi-Currency Support
  • ✅ Multi-Portal ( Monolith & Microservice Distributed )
  • ✅ Multi-Tenant ( Shared Database & Isolated Database )
  • ✅ Notifications / Email Delivery
  • ✅ Notifications / SMTP Delivery
  • ✅ Progressive Web Application Support
  • ✅ Recycle Bin
  • ✅ REST API with Swagger Support
  • ✅ Scheduled Flows ( Background Processing )
  • ✅ Scheduled Jobs ( Background Processing )
  • ✅ Seamless Upgrade Experience
  • ✅ Slack integration (OAuth)
  • ✅ Support For Additional Authentication Providers (OAuth)

Constant Considerations

  • ✅ Code Annotations
  • ✅ A11y Improvements
  • ✅ i18n Improvements
  • ✅ UI/UX Improvements
  • ✅ 100% Code Coverage
  • ✅ Security Improvements
  • ✅ SOLID Code Improvements
  • ✅ Performance Improvements
  • ✅ Scalability Improvements
  • ✅ Extensibility Improvements
  • ✅ Generic Integrations Improvements
  • ✅ Developer productivity enhancements
  • ✅ Separation of Concerns Improvements
  • ✅ Bug fixes & core Dependency Management

Alliance Business Suite API References

System requirements

The following browsers are supported:

  • Google Chrome
  • Microsoft Edge (supported on Windows 10)
  • Apple Safari 11
  • Internet Explorer 11
  • Quad-core x64 2 GHz CPU or higher (x64 compatible dual-core 1.5 GHz processor)
  • 16GB Memory (8GB Memory)
  • 40GB free hard disk space (10GB free hard disk) SSD Recommended

Supported Operating Systems

The following operating systems are supported with the recommendation that the latest Windows updates are applied.

  • Windows Server 2012 R2 x64 Datacenter / Standard
  • Windows Server 2016 x64 Datacenter w/ Containers
  • Windows Server 2016 x64 Datacenter w/ Containers

Supported SQL Server Editions

The following SQL Server Editions are supported with the recommendation that the latest Windows updates are applied.

  • SQL Server 2019
  • SQL Server 2017
  • SQL Server 2016
  • Azure SQL Service

Internet Information Services (IIS)

  • IIS 10, Windows Server 2016
  • IIS 10.0, Windows 10 & Windows Server 2019

Optional Software Components

  • SQL – SQL Word Breakers
  • SQL – SQL Server Agent Service
  • SQL – Server Full-Text Indexing

Getting Started with the Alliance Business Suite

Data is at the center of every modern business, unlocking new paths and ideas for operational performance and customer experience, but gathering and analyzing data is rather a complicated, time-consuming task. In an increasingly globalized world, technology is a key differentiator between those who stay ahead and those who don't.

To help businesses across the world to harness this promise, we've created a digital solution aimed to give organizations the ability to cover their main operations without constraining our customers with opinionated business development platforms.

The Alliance Business Suite lets you build outstanding and secure web and mobile apps. This is what you need to get started:

  1. Get an Alliance Business Suite license:

  2. Install the Alliance Business Suite

  3. Start building your business

Alliance Business Suite Fundamentals

This article provides an overview of key topics for understanding how to develop Alliance Business Suite apps.

Tutorial: Get started with the Alliance Business Suite

This tutorial shows how to create and run your first Alliance Business Suite instance.

You'll learn how to:

  • [✔] Install an Alliance Business Suite instance.
  • [✔] (optional) Trust the development certificate.
  • [✔] Run the app.

In the end, you'll have a working Alliance Business Suite instance running on your local machine.

Prerequisites

  • .NET Core 6.0 SDK or later
  • MySQL Server 8.0 or later

Installation

Conventional Install

git clone https://github.com/FenixAlliance/ABS.Bin
cd ABS.Bin
./FenixAlliance.ABS.Studio.exe

or

dotnet FenixAlliance.ABS.Studio.dll

Development Install

Install as a Docker Container.

docker pull FenixAlliance.ABS:latest

Install as an Application Extension

There are certain cases where customers prefer to install the Alliance Business Suite so that they can extend the standard functionalities, create modules, integrations, SPAs, or really, any kind of extensions without having to worry about all the required wiring for it to work properly.

In these cases, the best approach is to install the Alliance Business Suite as an application extension into a new or existing ASP.NET Application.

To do this:

  1. Add the NuGet package
dotnet add package FenixAlliance.ABS.Hub --version latest
  1. Register Services and Configuration
using FenixAlliance.ABS.Hub.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

namespace FenixAlliance.ABS
{
    public class Startup
    {
        public IHostEnvironment Environment { get; set; }
        public IConfiguration Configuration { get; set; }

        // Constructor
        public Startup(IConfiguration Configuration, IHostEnvironment Environment)
        {
            this.Environment = Environment;
            this.Configuration = Configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
          services.AddAllianceBusinessSuite(Configuration, Environment);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
          app.UseAllianceBusinessSuite(Configuration, Environment);
        }
    }
}
  1. Trust the HTTPS development certificate:

cert.png

Select Yes if you agree to trust the development certificate.

Installation wizard

The Alliance Business Suite uses the suitesettings.json configuration file to determine whether or not the Alliance Business Suite instance is already configured to work. The Status section of the configuration file is used to instruct the system on the current configuration step.

The first step towards having an operational instance is to set up the basic options such as Database Connections Strings, seeding the database, create the primary Business Tenant, and the root account holder.

Customers can achieve this installation through a web wizard aimed to beat WordPress's 5 Minutes installation.

On this wizard, you'll be prompted with a few configuration steps:

1. Primary Database Options

Primary Database Options

2. Business Tenant Basic Information

Business Tenant Basic Information

3. Primary Portal Basic Information

Primary Portal Basic Information

4. Identity Provider Options

Identity Provider Options

5. Root Account Credentials

Root Account Credentials

Fill in the required information on each step and click on "Install". This will create the ABM Scheme to the Database, seed data such as countries, currencies, states, cities, timezones, the selected COA, and other important, standardized data. The creation and seeding process might take up to 5 minutes, depending on your connection and system's specifications.

Seeding Process

Let the application finish this process, reload the page & log in with the Root Account credentials defined in previous steps.

Configuring an Alliance Business Suite Instance

Short Notation for this page

  • Acting Business Tenant ("ABT")
  • Current Web Portal ("CWP")

The Alliance Business Suite is designed to be as easy to use as it can be by abstracting complexity through a clean UI and multiple navigation features designed to take you where you need to perform.

Once installed, your instance will be functional, but not quite yet ready for production. For this reason, new instances are created with a Not Operational Status. This Status means that even new users can be created and pretty much every functionality will work right out of the box, several unconfigured functionalities won't be available until proper setup.

In order to get your instance to an Operational State, you should first configure for the first time the Alliance Passport Service, perform some internal configurations, and properly set up your Root Web Portal.

Configuring your instance

One of the most important files in your Alliance Business Suite instance is the suitesettings.json file. This file is located in the root of your instance's file directory and contains your website’s base configuration details, such as database-connection information.

When you first download the Alliance Business Suite, this file does not exist, as it will be created during the initial setup process.

Although you can manually provide a suitesettings.json file for your instance (bypassing like so the initial setup process), you will be required to run this initial setup process at least once to create your initial database schema and insert required records.

Once this installation process has been completed, multiple instances can retrieve their configuration files through the ABS Management API from the root instance, and thus sharing the data layer, allowing customers to scale both the data and application layer independently, depending on their specific requirements.

Each Alliance Business Suite instance contains its own administrator portal. Instances are bounded each a Business Tenant's Primary Web Portal's configuration.

The first towards configuring your Root Web Portal is to finish creating information for your Business Tenant. The amount of configuration required will depend on the number of Modules included in your instance.

Note: Although currently possible, it is not recommended to edit the suitesettings.json file directly unless required.

Administration Flow Optimization

Due to the massive amount of different types of data that the Alliance Business Suite is built to manage, and the tremendous amount of control given to our customers, it can be easy to get lost among all the different options and configurations available. We understand this and We want your workflow to be as fluid as possible, so we've been tackling this issue through several shortcuts and UI optimizations that will help you manage your business tenant's with an incredibly high APM ("Actions per Minute") rate.

These optimizations include:

  1. Drastically reducing the number of page loads required to manage everything inside the Alliance Business Suite: Our goal is to bring this number to 1, meaning that once you're into the Alliance Business Studio,
  2. Drastically reducing the number of clicks required to get from point A to point B inside the application: Our goal is to provide multiple ways to get you where you need to be across your business tenants.
  3. Optimizing performance and improving both UX/UI to deliver clear, readable interfaces to manage data across Business Tenants.
  4. Including accessibility features to improve the way people with limitations interact with the application.
  5. Delivering additional interfaces other than the Studio to help Customers to automate and extend

Understanding the GenericOption Table and the Options API.

The GenericOption Table

To maximize your ability to extend the Alliance Business Suite, we've created the a generic data persistance mechanism, which is a table containing a few columns to store optional and configuration data for external applications without the need to modify nor extend the Alliance Business Model Schema, not to bring another data persistence mechanism.

The options table stores data as encrypted JSON data. Data is written to the options table using the Options API, both of which consist of a set of functions used to add, update and delete data from this table.

The Options API

To make it easier for developers to create custom configurations, we've created a set of methods specified into the IOptionsService interface. This interface comes configured with its default implementation right out of the box, but custom implementations could override this default implementation.

As the GenericOption table stores data which is related to the setup and administration of the site as a whole, access to it is restricted. The Alliance Business Studio gives users the ability to modify the value of each configuration given the proper permissions to do so.

To be able to amend settings and options, users will need to have the manage_options Business Permission. The only default user role with this capability is the root role.

This means that if you need to add options that other user roles have access to, you'll have to assign the manage_options capability to them. This carries risks, so only do it if you're sure!

Structure of the GenericOption Table

The options table has a similar structure to the three metadata tables. It has the following fields:

  • ID: The Global Unique Identifier for every option.
  • Name: The Option Name for Friendly Access
  • Value: The option value, usually stored in JSON format.
  • Autoload: (boolean) whether or not this option would be loaded on memory cache.
  • Timestamp: The time for the last option update.
  • Transient: whether or not this option is a temporal option.
  • WebPortalID: The ID for the Web Portal who owns this option.
  • Discriminator: The Option Type.

Option Types.

GenericOptins have different types (also called scopes). As of v1.3.0, the following types are available:

  • AccountHolderOption: An option that's bound to an account holder and, optionally, to a Web Portal.
  • BusinessOption: An option that's bound to a Business Tenant and, optionally, to a Web Portal.
  • BusinessApplicationOption: An option that's bound to a Business Application and, optionally, to a Web Portal.

Aditional considerations

One of the important things to understand about the GenericOption table is the autoload field. This contains a boolean value (yes or a no). This essentially controls whether or not it is loaded on cached memory by the OptionsService.LoadOptions() function. Autoloaded data is data that is loaded on every page of your Alliance Business Suite instance. Just like we showed you how to disable certain scripts from loading sitewide, the same idea applies here. The autoload attribute is set to “yes” by default for developers, but not every option should be loaded on every page.

Hosting the Alliance Business Suite

You can deploy the Alliance Business Suite on-premises (self-hosted). Unlike cloud deployments, when you choose an on-premises deployment, different system requirements like hardware type, sizing, and functionality needs to be considered. This chapter contains guides on self-hosted/on-premise deployments.

Getting Started

Hosting the Alliance Business Suite on IIS

Internet Information Services (IIS) is a flexible, secure and manageable Web Server for hosting web apps, including ASP.NET Core.

Supported platforms

The following operating systems are supported:

  • Windows 10 or later
  • Windows Server 2012 R2 or later

The Alliance Business Suite is a 64-bit (x64) for the following reasons:

  • Requires the larger virtual memory address space available to a 64-bit app.
  • Requires the larger IIS stack size.
  • Has 64-bit native dependencies.

Install the ASP.NET Core Module/Hosting Bundle

Download the installer using the following link:

Current .NET Core Hosting Bundle installer (direct download)

For more detailed instructions on how to install the ASP.NET Core Module, or installing different versions, see Install the .NET Core Hosting Bundle.

Publish an Alliance Business Suite instance to IIS

Create the IIS site

  1. On the IIS server, create a folder to contain the Alliance Business Suite folders and files. In a further step, the folder's path is provided to IIS as the physical path to the app. For more information on an app's deployment folder and file layout, see ASP.NET Core directory structure.

  2. In IIS Manager, open the server's node in the Connections panel. Right-click the Sites folder. Select Add Website from the contextual menu.

  3. Provide a Site name and set the Physical path to the app's deployment folder that you created. Provide the Binding configuration and create the website by selecting OK.

  4. Confirm the process model identity has the proper permissions: If the default identity of the app pool (Process Model > Identity) is changed from ApplicationPoolIdentity to another identity, verify that the new identity has the required permissions to access the app's folder, database, and other required resources. For example, the app pool requires read and write access to folders where the app reads and writes files.

Warning

Top-level wildcard bindings (http://*:80/ and http://+:80) should not be used. Top-level wildcard bindings can open up your app to security vulnerabilities. This applies to both strong and weak wildcards. Use explicit hostnames rather than wildcards. Subdomain wildcard binding (for example, *.mysub.com) doesn't have this security risk if you control the entire parent domain (as opposed to *.com, which is vulnerable).

Clone the Alliance Business Suite Distributable

The best way to manage the Alliance Business Suite Update Flow is to clone the Alliance Business Suite to the publish directory using Git.

  1. Navigate to the Publish Directory, make sure is empty, and open a CLI into it.
  2. Run the following command: git clone https://github.com/fenixalliance/abs.bin .
    • If you're unable to deploy directly to the IIS site folder on the IIS server, pick your desired ring from the Releases Repo and clone on removable media and physically move them to the IIS site folder on the server, which is the site's Physical path in IIS Manager. Move the contents of the cloned repository to the IIS site folder on the server, which is the site's Physical path in IIS Manager.
    • If you're unable to use git, you'll face additional considerations regarding the Update Process.
  3. Restart the IIS Site.

Browse the website

The app is accessible in a browser after it receives the first request. Make a request to the app at the endpoint binding that you established in IIS Manager for the site.

Logging across the Alliance Business Suite

The Alliance Business Suite contains a powerful logging engine based on Serilog, a popular .NET library that provides diagnostic logging that's built with powerful structured event data in mind.

using Serilog;

var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;

Log.Information("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);

This example records two properties, Position and Elapsed along with the log event. The properties captured in the example, in JSON format, would appear like:

{"Position": {"Latitude": 25, "Longitude": 134}, "Elapsed": 34}

The @ operator in front of Position tells Serilog to serialize the object passed in, rather than convert it using ToString().

The :000 segment following Elapsed is a standard .NET format string that affects how the property is rendered. The console sink included with Serilog will display the above message as:

09:14:22 [Information] Processed { Latitude: 25, Longitude: 134 } in 034 ms.

Through the Alliance Business Studio, customers are able to manage these logs without the need to access the server directly.

To manage logs for your Alliance Business Suite instance, navigate to the /Studio/Network/Logs route on any configured Web Portal.

Understanding Request Routing through the Alliance Business Suite

The Alliance Business Suite contains a powerful routing engine based on .NET's Routing System.

At a high level, routing is responsible for matching incoming HTTP requests and dispatching those requests to the Alliance Business Suite's executable endpoints. Endpoints are the app's units of executable request-handling code. Endpoints are defined in the app and configured when the app starts. The endpoint matching process extracts values from the request's URL and provides those values for request processing. Using endpoint information from the app, routing is also able to generate URLs that map to endpoints.

The Alliance Business Suite's routing configurations abstract the complexities out of the routing process through several techniques depending on the execution context. This means that routing is as simple as providing a relative URL ("Slug") when creating a page.

In cases where customers might want to create a custom Module, they can expose custom endpoints while still taking advantage of the Routing Engine, meaning they can create and manage routing rules through the Alliance Business Studio and apply them to their custom endpoints.

Rate limiting

The Alliance Business Platform contains a rate-limiting solution designed to control the rate of requests that clients can make to a Web API or MVC app based on IP address or client ID. Through the Alliance Business Studio, you can configure the rate-limiting middleware and set multiple limits for different scenarios like allowing an IP or Client to make a maximum number of calls in a time interval. You can define these limits to address all requests made to an API or you can scope the limits to each executable API URL or HTTP verb and path.

Working with static files.

This topic describes the overall functionality for the Alliance Business Platform | File System Engine, how to upload static files into an Alliance Business Suite instance, and how to retrieve the URL and file name that can be used to request that file.

About Uploading Files on Studio

The Alliance Business Platform contains a powerful file system engine called ABP-FS. Through ABP-FS, users can upload files and relate them to almost any ABM Record. By exposing several API endpoints on both code and REST APIs, users can upload files of any kind. Default restrictions are provided for security purposes, and files can also be uploaded through FTP or through the Alliance Business Studio (using the GUI file manager).

File Upload Scopes

By leveraging the ABP-FS APIs, customers and developers can upload files scoped to an Alliance Business Model Record; this allows customers to access, manage, and share files related to, for example, an Account, a Contact, or a Portal, in one place.

Public Files.

Scoped Public Files

The ABP-FS allows customers to upload public files within the scope of a Web Portal. These files are exposed through the /Public/{PortalID} endpoint available to every portal.

Unscoped Public Files

When developing single or multiple portals, customers might want to share common files between them. To do so, they can now upload Unscoped Public Files that will be available through the /Public endpoint.

Unscoped files are marked as read-only files by default and can only be uploaded by an Account Holder with global_admin Business Permission.

Public Files URL

Regardless of how you upload a file, you can retrieve the file URL by using the Alliance Business Studio File Manager or by recomposing the URL from the File Path by prepending the /Public/ endpoint to it, so that it is relative to the /AppData/Public folder where both Scoped and Unscoped Public Files are uploaded.

Accessing data from the Alliance Business Model engine.

If you've ever had to bring data from multiple systems and applications together, you know what an expensive and time-consuming task that can be. Without being able to share and understand the same data easily, each application or data integration project requires a custom implementation.

The Alliance Business Model simplifies this process by providing a common data model that includes entities that represent commonly used business concepts and activities, such as Contact, Invoice, and Account, to simplify the creation, aggregation, and analysis of data.

Why use the Alliance Business Model?

Commonly, businesses have more than one application to cover specific business operations such as eCommerce, Accounting, Sales, Marketing, CRM, and more. These are a lot of applications and they consume time and money, but that's not it! they all have different representations for the Contact Entity. This can be frustrating when trying to integrate these applications together to produce better and automated outcomes. To solve this issue, you can build those apps on top of a standardized data schema, allowing you to share the same entities across applications. Of course, your application might have different data requirements between them, so you can extend the predefined schemas and even create new schemas!

One cool thing about this is that when it comes the time to create a new business application, your data schemas will be ready to provide the required data infrastructure for your application and share this data with every other application.

Alliance Business Model simplifies data management and app development by unifying data into a known form and applying structural and semantic consistency across multiple apps and deployments. To summarize the benefits:

  • A unified shape, where data integrations can combine existing enterprise data with other sources and use that data holistically to develop apps or derive insights.
  • Structural and semantic consistency across applications and deployments.
  • Simplified integration and disambiguation of data that's collected from processes, digital interactions, product telemetry, people interactions, and so on.
  • The ability to extend the Alliance Business Model schema standard entities to tailor the model to your organization. This is enabled thanks to both the ABM Mongo Interop Service and the ABS Virtual Entities functionalities.

Alliance Business Model in action

The Alliance Business Model is influenced by data schemas that are present in both UBL Schema and Common Data Model, covering a range of business areas. If you are a customer or a partner of Fenix Alliance Group, you are already using the Alliance Business Model.

Businesses, institutions, Partners, and independent software vendors (ISVs) use the Alliance Business Model to extend and interoperate with any given Alliance Business Suite instance.

Organizations from industries such as manufacturing, government, and education are working closely with Fenix Alliance Group to extend the Alliance Business Model to their specific business scenarios, and the dynamic ABM Engine allows seamless data integration even when schemas are not exactly the same. This allows customers from an unlimited range of industries to leverage the benefit of the Alliance Business Model's standard entities and extend to their specific verticals so that industry solutions can interoperate more easily.

// Get all the contacts from the configured ABM Provider.
var contacts = await DataContext.Contact.ToListAsync();

foreach(var contact in contacts){
    Console.WriteLine(contact.ID);
}

Introduction to Razor Templating Engine

Portal Pages can make coding page-focused scenarios easier and more productive than using controllers and views.

This document provides an introduction to the Alliance Business Suite - Razor Templating Engine

#Rendering HTML The default Razor language is HTML. Rendering HTML from Razor markup is no different than rendering HTML from an HTML file. HTML markup in .cshtml Razor files is rendered by the server unchanged.

#Razor syntax Razor supports C# and uses the @ symbol to transition from HTML to C#. Razor evaluates C# expressions and renders them in the HTML output.

When an @ symbol is followed by a Razor reserved keyword, it transitions into Razor-specific markup. Otherwise, it transitions into plain C#.

To escape an @ symbol in Razor markup, use a second @ symbol:

<p>@@Username</p>

The code is rendered in HTML with a single @ symbol:

<p>@Username</p>

HTML attributes and content containing email addresses don't treat the @ symbol as a transition character. The email addresses in the following example are untouched by Razor parsing:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

Implicit Razor expressions

Implicit Razor expressions start with @ followed by C# code:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

With the exception of the C# await keyword, implicit expressions must not contain spaces. If the C# statement has a clear ending, spaces can be intermingled:

<p>@await DoSomething("hello", "world")</p>

Getting Started with Alliance Business Suite Web Portals

The Alliance Business Suite includes a powerful multi-portal CMS to help businesses to offer external-facing websites that allow users outside their organizations to sign in with a wide variety of identities, create and view data in and from the Alliance Business Model, or even browse content anonymously. The full capabilities of Alliance Business Suite Portals are available as of Version 1.2.

You have the ability to create a Portals Web Portals Network ("WPN") for each Business Tenant by using the multi-portal feature. Business tenants can create as many Web Portals under the same instance as they need.

Web Portals are scoped to a Business Tenant to allow customers to deliver experiences that directly transact data with the Alliance Business Model and additional Data Sources. This means that users can perform a controlled (yet extensible) number of actions (like adding products to their cart, update their profile, create addresses, generate orders, access quotes, invoices and so much more)

How do Portals Work?

Web Portals are content sets that belong to a Business Tenant. Portals make use of the powerful Alliance Business Suite Razor Engine to group Web Content under a single domain.

Configuring Domains

Compared with a typical single-portal ABS instance, a WPN installation has additional considerations.

Every fresh Alliance Business Suite instance comes with one default Portal owned by the Business Tenant that was created through the installation process. This Root Portal must exist and is defined by your instance's settings file.

Alliance Business Suite Portals can have additional related domains/subdomains.

Domains should resolve to your instance's public IP Address. Also, domains should be related to a portal for the multi-tenant data router to work properly.

Themes and Modules

When you enable a WPN Instance: each Web Portal of a network can activate both modules and themes individually, but installation is done at an instance scope, which means they are available to every Web Portal present on your instance.

You must have access to your domain's DNS settings.

Configuring a Multi-Portal Network

1. Preparing your instance

Unless this is a fresh install and you have no data to lose, please backup your database and file system.

2. Select a Business Tenant

When you create a new portal, you do so under the scope of a Business Tenant. This means that you should have permissions from the Business Tenant to access the Studio and "create_portals" at the very least.

3. Create Web Portal

To create a Web Portal, login as an authorized user and select the Business Tenant that will own the Web Portal.

Acting as the selected Business Tenant, click on the cogs icon on the top-right hand side of the Studio Header.

Click on Portals and provide a Title and a root domain (the Root Domain should be a Subdomain of the Root Portal's Root Domain. This means that every portal's Root Domain is relative to the domain that you used to install your instance).

E.g: If you installed your instance under the https://example.com domain, each subsequent Web Portal will have a Root Domain that's scoped to the Root Portal's domain, like so: https://NewPortalRootDomain.example.com

4. Create a Primary Domain (optional)

In order to set up another domain that's not related to the Root PortalDomain, you should create a security rule to allow traffic through certain domains and then map the rule to your new Web Portal.

5. Create Additional Domains (optional)

You can have more than one domain mapping to the same Web Portal. You can choose whether or not this mapping should be performed through an HTTP redirection. To create and map an additional domain to a Web Portal, create the new domain under the Admin section for your Business Tenant, under Admin > Security > Domains. Then, navigate to the portal that this Domain should map to and select it from the domains tab.

Working with Web Pages

Web pages are meant to represent content located at a particular URL, scoped to a Web Portal (and therefore to a Business Tenant), and is based on one of the core tables of the Alliance Business Model Schema.

Web Pages are related through parent and child relationships to other web pages, this structure forms the hierarchy of a website, and therefore, its site map is automatically generated.

Web pages also form the basis for including other, specialized table types in the portal site map – web files, shortcuts, forums, advanced forms, and blogs are all situated in the portal site map through – and thus derive their URLs from – a relationship to a parent web page.

Manage web pages

Web pages can be created, edited, and deleted from the Alliance Business Platform REST API. However, the Media Portals Module provides advanced customization that can be performed from the Alliance Business Studio.

  • Open the Alliance Business Studio.

  • Go to Modules > Media Portals > Web Pages.

    • To edit an existing web page using the standard editor, select the "Edit" option below the web page name.
    • To edit an existing web page using the Visual WYSIWYG editor, select the "Live Edit" option below the web page name.
    • To create a new Web Page, click on the Create Button.
  • Enter appropriate values in, at least, the required fields.

  • Select Save & Close.

Content Engines

The Alliance Business Suite contains a powerful content engine to provide the level of customizability required to give the highest level of control over every bit that's to be presented to a user on a Web Page. These engines are meant to work with Web Content records and they have several capability sets.

Razor Engine:

The Razor Engine is a derivate from .NET's Server Side Markup Language. Web Content marked as .razor will be compiled and rendered using a Service Abstraction which means that its default can be replaced by a custom implementation.

Razor is a markup syntax that lets you embed server-based code (Visual Basic and C#) into web pages at a very high level.

Server-based code can use every available service inside any given Alliance Business Suite instance to dynamically generate web content on the fly, while a web page is written to the browser.

When a web page is called (either by slug or id), the server executes the server-based code inside the page before it returns the page to the browser. The code can perform complex tasks by running on the server, like accessing the Alliance Business Model or leveraging our extensive set of APIs.

Razor is based on ASP.NET and designed for creating web applications. The ABS Razor Engine has the power of traditional Razor, but it is easier to use.

Blazor Engine

The Alliance Business Suite lets you build interactive web UIs using C# instead of JavaScript. By using Blazor under the hood, apps are composed of reusable web UI components implemented using C#, HTML, and CSS. Both client and server code is written in C#, allowing you to share code and libraries already present.

Liquid Engine (Experimental)

The Alliance Business Suite supports Liquid template language, which is a secure template language that is also very accessible for non-programmer audiences.

HTML Engine

In cases where customers decide to use plain HTML5, the Alliance Business Suite contains the ability to bypass all Content Engines and render HTML fragments whenever they are called. This is also the most efficient type of Web Content.

Markdown Engine

The last Content Engine, and therefore the least privileged, is the Markdown Engine, which is a lightweight markup language for creating formatted plain text using an embedded markdown-text editor.

Razor Pages Introduction

Pages are very important components for the Alliance Business Suite. They allow customers to implement unique, visually outstanding web pages by using a templating engine that's based on .NET's Razor Syntax.

Pages in the Alliance Business Suite can be added through the Admin Portal of your ABS instance and live edited through the ABS Web Builder.

Pages are WebContent Components, which makes them extremely powerful. They are stored in the Alliance Business Model Database provider and C# is server-side evaluated to then render the output as HTML, CSS, and JavaScript.

Although pages can inject services and even interact with the ABM Database Provider through the DataContext instance present at every page, pages can optionally contain a caller method. This method's responsibility is to produce the model that's going to be used to fill the page's Model property, sort of like a controller method passing a Model to a view.

Creating a Web Page

To create a Web Page in the Alliance Business Suite you must have Studio Access (access_studio) permission and the create WebContent entities permission (create_webcontent).

  • Head to your ABS Instance's Admin Portal at https://{yourdomain}/admin
  • Select the Business Tenant for which you want to create a Web Page.
  • Click on the Add button of your Command Bar and Select Web Page
  • Give the entry a Title, a Slug, and (optionally) select a template and parent page to use on the page.
  • Write some code using the Razor Syntax and the Code Editor.
  • Validate your code for errors.
  • Save Changes.

Once you've saved changes for your Web Page, the system will automatically redirect you to the Edition page. Here you will be able to edit everything about your page, and new options will be available, such as categorization and tags.

Page Routing

Pages must define a "Slug". This relative route gets combined with the parent's page slug to produce the Absolute Slug of the page and defines the route over which your page will be located and invoked. It can be changed at any time.

Currently, Pages other than the Home Page are available at the /Pages/{AbsoluteSlug} route.

Home Page

Each portal on the Alliance Business Suite must be provided with a Home Page. this can be any page you've created and it will allow each portal to find the page that will be rendered at the root of the portal. Customers can mark a page as the Home Page by ticking the respective option on a portal-related or by setting the page on each Portal's Options Manager.

If you set a portal-related page as the home page by ticking the "Is Home Page" option, that will replace any other Home Page related to that specific portal, becoming, like so, the Active Home Page.

The above is a legacy method for Home page discovery. To improve consistency across portals, we've implemented a new method to select the Home Page on the Portal's Options Manager. To use the new method, head to your Instance's administration portal and over General Settings, select the page you would like to render at the root of each portal.

Client-Side UI Frameworks

The Alliance Business Suite is configured to allow customers to use, right out of the box, several UI Frameworks such as:

These frameworks can be enabled or disabled on a template basis to allow customers to create and combine unique experiences with the tools they already use and love.

ABS Razor Syntax

Razor is a markup syntax for embedding server-based code into web pages. The Razor syntax consists of Razor markup, C#, and HTML. Files containing Razor generally have a .cshtml file extension. Razor is also found in Razor components files (.razor).

Razor syntax

Razor supports C# and uses the @ symbol to transition from HTML to C#. Razor evaluates C# expressions and renders them in the HTML output.

When an @ symbol is followed by a Razor reserved keyword, it transitions into Razor-specific markup. Otherwise, it transitions into plain C#.

To escape an @ symbol in Razor markup, use a second @ symbol:

<p>@@Username</p>

The code is rendered in HTML with a single @ symbol:

<p>@Username</p>

HTML attributes and content containing email addresses don't treat the @ symbol as a transition character. The email addresses in the following example are untouched by Razor parsing:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

Implicit Razor expressions

Implicit Razor expressions start with @ followed by C# code:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

With the exception of the C# await keyword, implicit expressions must not contain spaces. If the C# statement has a clear ending, spaces can be intermingled:

<p>@await DoSomething("hello", "world")</p>

Implicit expressions cannot contain C# generics, as the characters inside the brackets (<>) are interpreted as an HTML tag. The following code is not valid:

<p>@GenericMethod<int>()</p>

The preceding code generates a compiler error similar to one of the following:

  • The "int" element wasn't closed. All elements must be either self-closing or have a matching end-tag.
  • Cannot convert method group 'GenericMethod' to non-delegate type 'object'. Did you intend to invoke the method?`

Generic method calls must be wrapped in an explicit Razor expression or a Razor code block.

Templated Razor delegates

Razor templates allow you to define a UI snippet with the following format:

Explicit Razor expressions

Explicit Razor expressions consist of an @ symbol with balanced parenthesis. To render last week's time, the following Razor markup is used:

<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>

Any content within the @() parenthesis is evaluated and rendered to the output.

Implicit expressions, described in the previous section, generally can't contain spaces. In the following code, one week isn't subtracted from the current time:

<p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>

The code renders the following HTML:

<p>Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)</p>

Explicit expressions can be used to concatenate text with an expression result:

@{
    var joe = new Person("Joe", 33);
}

<p>Age@(joe.Age)</p>

Without the explicit expression, <p>Age@joe.Age</p> is treated as an email address, and <p>Age@joe.Age</p> is rendered. When written as an explicit expression,

Age33

is rendered.

Explicit expressions can be used to render output from generic methods in .cshtml files. The following markup shows how to correct the error shown earlier caused by the brackets of a C# generic. The code is written as an explicit expression:

<p>@(GenericMethod<int>())</p>

Expression encoding

C# expressions that evaluate to a string are HTML encoded. C# expressions that evaluate to IHtmlContent are rendered directly through IHtmlContent.WriteTo. C# expressions that don't evaluate to IHtmlContent are converted to a string by ToString and encoded before they're rendered.

@("<span>Hello World</span>")

The preceding code renders the following HTML:

&lt;span&gt;Hello World&lt;/span&gt;

The HTML is shown in the browser as plain text: Hello World

HtmlHelper.Raw output isn't encoded but rendered as HTML markup.

Warning: Using HtmlHelper.Raw on unsanitized user input is a security risk. User input might contain malicious JavaScript or other exploits. Sanitizing user input is difficult. Avoid using HtmlHelper.Raw with user input.

@Html.Raw("<span>Hello World</span>")

The code renders the following HTML:

<span>Hello World</span>

Razor code blocks

Razor code blocks start with @ and are enclosed by {}. Unlike expressions, C# code inside code blocks isn't rendered. Code blocks and expressions in a view share the same scope and are defined in order:

@{
    var quote = "The future depends on what you do today. - Mahatma Gandhi";
}

<p>@quote</p>

@{
    quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
}

<p>@quote</p>

The code renders the following HTML:

<p>The future depends on what you do today. - Mahatma Gandhi</p>
<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>

In code blocks, declare local functions with markup to serve as templating methods:

@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }

    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

The code renders the following HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

Implicit transitions

The default language in a code block is C#, but the Razor Page can transition back to HTML:

@{
    var inCSharp = true;
    <p>Now in HTML, was in C# @inCSharp</p>
}

Explicit delimited transition

To define a subsection of a code block that should render HTML, surround the characters for rendering with the Razor tag:

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <text>Name: @person.Name</text>
}

Use this approach to render HTML that isn't surrounded by an HTML tag. Without an HTML or Razor tag, a Razor runtime error occurs.

The <text> tag is useful to control whitespace when rendering content:

  • Only the content between the tag is rendered.
  • No whitespace before or after the tag appears in the HTML output.

Explicit line transition

To render the rest of an entire line as HTML inside a code block, use @: syntax:

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    @:Name: @person.Name
}

Without the @: in the code, a Razor runtime error is generated.

Extra @ characters in a Razor file can cause compiler errors at statements later in the block. These compiler errors can be difficult to understand because the actual error occurs before the reported error. This error is common after combining multiple implicit/explicit expressions into a single code block.

Control structures

Control structures are an extension of code blocks. All aspects of code blocks (transitioning to markup, inline C#) also apply to the following structures:

Conditionals @if, else if, else, and @switch

@if controls when code runs:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

else and else if don't require the @ symbol:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
else if (value >= 1337)
{
    <p>The value is large.</p>
}
else
{
    <p>The value is odd and small.</p>
}

The following markup shows how to use a switch statement:

@switch (value)
{
    case 1:
        <p>The value is 1!</p>
        break;
    case 1337:
        <p>Your number is 1337!</p>
        break;
    default:
        <p>Your number wasn't 1 or 1337.</p>
        break;
}

Looping @for, @foreach, @while, and @do while

Templated HTML can be rendered with looping control statements. To render a list of people:

@{
    var people = new AccountHolder[]
    {
          new AccountHolder(){...},
          new AccountHolder(){...},
          ...
    };
}

The following looping statements are supported:

@for

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@foreach

@foreach (var person in people)
{
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@while

@{ var i = 0; }
@while (i < people.Length)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
}

@do while

@{ var i = 0; }
@do
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
} while (i < people.Length);

Compound @using

In C#, a using statement is used to ensure an object is disposed. In Razor, the same mechanism is used to create HTML Helpers that contain additional content. In the following code, HTML Helpers render a

tag with the @using statement:

@using (Html.BeginForm())
{
    <div>
        Email: <input type="email" id="Email" value="">
        <button>Register</button>
    </div>
}

@try, catch, finally

Exception handling is similar to C#:

@try
{
    throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
    <p>The exception message: @ex.Message</p>
}
finally
{
    <p>The finally statement.</p>
}

@lock

Razor has the capability to protect critical sections with lock statements:

@lock (SomeLock)
{
    // Do critical section work
}

Comments

Razor supports C# and HTML comments:

@{
    /* C# comment */
    // Another C# comment
}
<!-- HTML comment -->

The code renders the following HTML:

<!-- HTML comment -->

Razor comments are removed by the server before the webpage is rendered. Razor uses @* *@ to delimit comments. The following code is commented out, so the server doesn't render any markup:

@*
    @{
        /* C# comment */
        // Another C# comment
    }
    <!-- HTML comment -->
*@

Directives

Razor directives are represented by implicit expressions with reserved keywords following the @ symbol. A directive typically changes the way a view is parsed or enables different functionality.

Understanding how Razor generates code for a view makes it easier to understand how directives work.

@{
    var quote = "Getting old ain't for wimps! - Anonymous";
}

<div>Quote of the Day: @quote</div>

The code generates a class similar to the following:

public class _Views_Something_cshtml : RazorPage<dynamic>
{
    public override async Task ExecuteAsync()
    {
        var output = "Getting old ain't for wimps! - Anonymous";

        WriteLiteral("/r/n<div>Quote of the Day: ");
        Write(output);
        WriteLiteral("</div>");
    }
}

@functions

The @functions directive enables adding C# members (fields, properties, and methods) to the generated class:

@functions {
    // C# members (fields, properties, and methods)
}

For example:


@functions {
    public string GetHello()
    {
        return "Hello";
    }
}

<div>From method: @GetHello()</div> 

The code generates the following HTML markup:

<div>From method: Hello</div>

The following code is the generated Razor C# class:


using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;

public class _Views_Home_Test_cshtml : RazorPage<dynamic>
{
    // Functions placed between here 
    public string GetHello()
    {
        return "Hello";
    }
    // And here.
#pragma warning disable 1998
    public override async Task ExecuteAsync()
    {
        WriteLiteral("\r\n<div>From method: ");
        Write(GetHello());
        WriteLiteral("</div>\r\n");
    }
#pragma warning restore 1998
}

@functions methods serve as templating methods when they have markup:


@{
    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

@functions {
    private void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }
}

The code renders the following HTML:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

@implements

The @implements directive implements an interface for the generated class.

The following example implements System.IDisposable so that the Dispose method can be called:


@implements IDisposable

<h1>Example</h1>

@functions {
    private bool _isDisposed;

    ...

    public void Dispose() => _isDisposed = true;
}

@inherits

The @inherits directive provides full control of the class the view inherits:

@inherits TypeNameOfClassToInheritFrom

The following code is a custom Razor page type:

using Microsoft.AspNetCore.Mvc.Razor;

public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
{
    public string CustomText { get; } = 
        "Gardyloo! - A Scottish warning yelled from a window before dumping" +
        "a slop bucket on the street below.";
}

The CustomText is displayed in a view:

@inherits CustomRazorPage<TModel>

<div>Custom text: @CustomText</div>

The code renders the following HTML:

<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

The following code is an example of a strongly-typed view:

@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>
<div>Custom text: @CustomText</div>

If "rick@contoso.com" is passed in the model, the view generates the following HTML markup:


<div>The Login Email: rick@contoso.com</div>
<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@model

The @model directive specifies the type of the model passed to a view or page:

@model TypeNameOfModel

The class generated inherits from DynamicComponentBase:

public class Template : DynamicComponentBase<TypeNameOfModel>

Razor exposes a Model property for accessing the model passed to the view:

<div>The Login Email: @Model.Email</div>

The @model directive specifies the type of the Model property. The directive specifies the T in RazorPage that the generated class that the view derives from. If the @model directive isn't specified, the Model property is of type dynamic. For more information, see C# Strongly typed models and the @model keyword.

@namespace

The @namespace directive:

Sets the namespace of the class of the generated Razor page

@namespace Your.Namespace.Here

@using

The @using directive adds the C# using directive to the generated view:

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

Templated Razor delegates

@<tag>...</tag>

The following example illustrates how to specify a templated Razor delegate as a Func<T,TResult>. The dynamic type is specified for the parameter of the method that the delegate encapsulates. An object type is specified as the return value of the delegate. The template is used with a List of Pet that has a Name property.

@using FenixAlliance.ABM.Models.Logistics.Stock.Item
@{
    Func<dynamic, object> itemTemplate = @<p>Item SKU: <strong>@item.SKU</strong>.</p>;

    var items = new List<Item>
    {
        new Item { SKU = "AAD_BASIC" },
        new Item { SKU = "RIGHTSMANAGEMENT" },
        new Item { SKU = "MCOPSTNC" }
    };
}

The template is rendered with items supplied by a foreach statement:

@foreach (var item in items)
{
    @itemTemplate(item)
}

Rendered output:

<p>Item SKU: <strong>AAD_BASIC</strong>.</p>
<p>Item SKU: <strong>RIGHTSMANAGEMENT</strong>.</p>
<p>Item SKU: <strong>MCOPSTNC</strong>.</p>

You can also supply an inline Razor template as an argument to a method. In the following example, the Repeat method receives a Razor template. The method uses the template to produce HTML content with repeats of items supplied from a list:

@using Microsoft.AspNetCore.Html

@functions {
    public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
        Func<dynamic, IHtmlContent> template)
    {
        var html = new HtmlContentBuilder();

        foreach (var item in items)
        {
            for (var i = 0; i < times; i++)
            {
                html.AppendHtml(template(item));
            }
        }

        return html;
    }
}

Using the list of items from the prior example, the Repeat method is called with:

  • List of Items.
  • Number of times to repeat each item.
  • Inline template to use for the list items of an unordered list.
<ul>
    @Repeat(items, 3, @<li>@item.SKU</li>)
</ul>

Rendered output:

<p>Item SKU: <strong>AAD_BASIC</strong>.</p>
<p>Item SKU: <strong>AAD_BASIC</strong>.</p>
<p>Item SKU: <strong>AAD_BASIC</strong>.</p>
<p>Item SKU: <strong>RIGHTSMANAGEMENT</strong>.</p>
<p>Item SKU: <strong>RIGHTSMANAGEMENT</strong>.</p>
<p>Item SKU: <strong>RIGHTSMANAGEMENT</strong>.</p>
<p>Item SKU: <strong>MCOPSTNC</strong>.</p>
<p>Item SKU: <strong>MCOPSTNC</strong>.</p>
<p>Item SKU: <strong>MCOPSTNC</strong>.</p>

Razor reserved keywords

Razor keywords

  • namespace
  • functions
  • inherits
  • model
  • section

Razor keywords are escaped with @(Razor Keyword) (for example, @(functions)).

C# Razor keywords

  • case
  • do
  • default
  • for
  • foreach
  • if
  • else
  • lock
  • switch
  • try
  • catch
  • finally
  • using
  • while

C# Razor keywords must be double-escaped with @(@C# Razor Keyword) (for example, @(@case)). The first @ escapes the Razor parser. The second @ escapes the C# parser.

Reserved keywords not used by Razor

  • class

Getting started with ABS Blazor Pages

The Alliance Business Suite Portals include Blazor Support (Server-Side). ABS Blazor Pages are based on components. A component in Blazor is an element of UI, such as a page, dialog, or data entry form.

To the Alliance Business Suite, Blazor Components are .NET C# classes built into .NET assemblies that:

  • Define flexible UI rendering logic.
  • Handle user events.
  • Can be nested and reused.
  • Live scoped to a Web Portal, therefore, to a Business Tenant.
  • Are stored in the Alliance Business Model as Web Pages / Web Components.
  • Can be shared and distributed as Razor class libraries or NuGet packages.

Creating a Blazor Component inside the Alliance Business Suite requires some basic knowledge of how traditional Blazor Components work.

The component class is usually written in the form of a Razor markup page. Components in Blazor are formally referred to as Razor components and their only difference with ABS Components is the way they are compiled.

Razor is a syntax for combining HTML markup with C# code designed for developer productivity. Razor allows you to switch between HTML markup and C# in the same file with IntelliSense programming support in Visual Studio. Razor Pages and MVC also use Razor. Unlike Razor Pages and MVC, which are built around a request/response model, components are used specifically for client-side UI logic and composition.

Blazor uses natural HTML tags for UI composition. The following Razor markup demonstrates a Blazor Page that displays a list of Stock Items stored into the Alliance Business Model:

@page "/Pages/test"

@using Microsoft.EntityFrameworkCore
@inject FenixAlliance.ABM.Data.DataContext db

@foreach(var item in Model){
    <h1>@item.Title</h1>
}

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>


@code {
    List<FenixAlliance.ABM.Models.Logistics.Stock.Item.Item> Model {get;set;} = new();

    private void GetProducts()
    {
        Model = db.Item.ToList();
    }

}

In this example, GetProducts is a C# method triggered by the button's onclick event. This method queries the Alliance Business Model for Stock items and then projects the results onto a List of Stock Items.

Fundamentals

Enabling Blazor Support

Enabling Blazor Support is a process that's done at the Template/Page Level. This means that to enable Blazor Support, both Web Page and Web Template should meet certain conditions.

Initializing Blazor at the Template level:

To enable Blazor support on a Web Template, you should add at least these two tags to it, as following:

<!DOCTYPE html>

<html class="no-js" lang="en">

<head>
    <!-- This tag is required to enable blazor support -->
    <base href="/" />
    ....
</head>
<body>
    ....

    @Body

    ....

    <!-- This tag is required to enable blazor support -->
    <script src="_framework/blazor.server.js"></script>

</body>

</html>


Initialize Blazor when the document is ready

The following example starts Blazor when the document is ready:

<body>
    ....

    @Body

    ....

    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
      document.addEventListener("DOMContentLoaded", function() {
        Blazor.start();
      });
    </script>
</body>

Initializing Blazor at the Page/Component level:

To enable Blazor for a page or component, you just need to select .razor as the Code Type for any WebPage/WebComponent. If .razor Code Type is selected, the Templating Engine will compile that Web Content as a Blazor Component, enabling syntaxis and diagnostics.

Difference between ABS Blazor Pages and ABS Blazor Components.

At a fundamental level, pages and components differ in that pages contain the @page directive. The Templating Engine will enforce this directive on WebPages marked as .razor Code Type and disallow components containing this directive.

Web Pages/Components marked as .razor Code Type provides data binding features with the @bind Razor directive attribute with a field, property, or Razor expression value.

The following example component binds:

  • An <input> element value to the C# inputValue field.
  • A second <input> element value to the C# InputValue property.

When an <input> element loses focus, its bound field or property is updated.


<p>
    <input @bind="inputValue" />
</p>

<p>
    <label>
        Demonstration of equivalent HTML binding: 
        <input value="@InputValue"
            @onchange="@((ChangeEventArgs __e) => InputValue = __e.Value.ToString())" />
    </label>
</p>


<ul>
    <li><code>inputValue</code>: @inputValue</li>
    <li><code>InputValue</code>: @InputValue</li>
</ul>

@code {
    private string inputValue;

    private string InputValue { get; set; }
}

The text box is updated in the UI only when the component is rendered, not in response to changing the field's or property's value. Since components render themselves after event handler code executes, field and property updates are usually reflected in the UI immediately after an event handler is triggered.

As a demonstration of how data binding composes in HTML, the following example binds the InputValue property to the second <input> element's value and onchange attributes. The second <input> element in the following example is a concept demonstration and isn't meant to suggest how you should bind data in Razor components.


@using Microsoft.AspNetCore.Components.Web


<p>
    <label>
        Normal Blazor binding: 
        <input @bind="InputValue" />
    </label>
</p>

<p>
    <label>
        Demonstration of equivalent HTML binding: 
        <input value="@InputValue"
            @onchange="@((ChangeEventArgs __e) => InputValue = __e.Value.ToString())" />
    </label>
</p>

<p>
    <code>InputValue</code>: @InputValue
</p>

@code {
    private string InputValue { get; set; }
}

When the previous component is rendered, the value of the HTML <input> element comes from the InputValue property. When the user enters a value in the text box and changes element focus, the onchange event is fired and the InputValue property is set to the changed value. In reality, code execution is more complex because @bind handles cases where type conversions are performed. In general, @bind associates the current value of an expression with a value attribute and handles changes using the registered handler.

Bind a property or field on other Document Object Model (DOM) events by including an @bind:event="{EVENT}" attribute with a DOM event for the {EVENT} placeholder. The following example binds the InputValue property to the <input> element's value when the element's oninput event is triggered. Unlike the onchange event, which fires when the element loses focus, oninput fires when the value of the text box changes.


<p>
    <input @bind="InputValue" @bind:event="oninput" />
</p>

<p>
    <code>InputValue</code>: @InputValue
</p>

@code {
    private string InputValue { get; set; }
}

Razor attribute binding is case sensitive:

  • @bind and @bind:event are valid.
  • @Bind/@Bind:Event (capital letters B and E) or @BIND/@BIND:EVENT (all capital letters) are invalid.

Unparsable values

When a user provides an unparsable value to a data-bound element, the unparsable value is automatically reverted to its previous value when the binding event is triggered.

Consider the following component, where an <input> element is bound to an int type with an initial value of 123.

@using Microsoft.AspNetCore.Components.Web

<p>
    <input @bind="inputValue" />
</p>

<p>
    <code>inputValue</code>: @inputValue
</p>

@code {
    private int inputValue = 123;
}

By default, data binding applies to the element's onchange event. If the user updates the value of the text box's entry to 123.45 and changes the focus, the element's value is reverted to 123 when onchange fires. When the value 123.45 is rejected in favor of the original value of 123, the user understands that their value wasn't accepted.

For the oninput event (@bind:event="oninput"), a value reversion occurs after any keystroke that introduces an unparsable value. When targeting the oninput event with an int-bound type, a user is prevented from typing a dot (.) character. A dot (.) character is immediately removed, so the user receives immediate feedback that only whole numbers are permitted. There are scenarios where reverting the value on the oninput event isn't ideal, such as when the user should be allowed to clear an unparsable <input> value. Alternatives include:

  • Don't use the oninput event. Use the default onchange event, where an invalid value isn't reverted until the element loses focus.
  • Bind to a nullable type, such as int? or string and provide custom get and set accessor logic to handle invalid entries.
  • Use a form validation component, such as InputNumber or InputDate. Form validation components provide built-in support to manage invalid inputs. Form validation components:
    • Permit the user to provide invalid input and receive validation errors on the associated EditContext.
    • Display validation errors in the UI without interfering with the user entering additional webform data.

Format strings

Data binding works with a single DateTime format string using @bind:format="{FORMAT STRING}", where the {FORMAT STRING} placeholder is the format string. Other format expressions, such as currency or number formats, aren't available at this time but might be added in a future release.

@using Microsoft.AspNetCore.Components.Web

<p>
    <label>
        <code>yyyy-MM-dd</code> format:
        <input @bind="startDate" @bind:format="yyyy-MM-dd" />
    </label>
</p>

<p>
    <code>startDate</code>: @startDate
</p>

@code {
    private DateTime startDate = new(2020, 1, 1);
}

In the preceding code, the <input> element's field type (type attribute) defaults to text.

Nullable System.DateTime and System.DateTimeOffset are supported:

private DateTime? date;
private DateTimeOffset? dateOffset;

Specifying a format for the date field type isn't recommended because Blazor has built-in support to format dates. In spite of the recommendation, only use the yyyy-MM-dd date format for binding to function correctly if a format is supplied with the date field type:

<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">

Custom binding formats

C# get and set accessors can be used to create custom binding format behavior, as the following DecimalBinding component demonstrates. The component binds a positive or negative decimal with up to three decimal places to an <input> element by way of a string property (DecimalValue).

@using System.Globalization

<p>
    <label>
        Decimal value (&plusmn;0.000 format):
        <input @bind="DecimalValue" />
    </label>
</p>

<p>
    <code>decimalValue</code>: @decimalValue
</p>

@code {
    private decimal decimalValue = 1.1M;
    private NumberStyles style = 
        NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
    private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");

    private string DecimalValue
    {
        get => decimalValue.ToString("0.000", culture);
        set
        {
            if (Decimal.TryParse(value, style, culture, out var number))
            {
                decimalValue = Math.Round(number, 3);
            }
        }
    }
}

Additional resources

Blazor Data Binding

ABS Web event handling

Specify delegate event handlers in Razor component markup with @on{DOM EVENT}="{DELEGATE}" Razor syntax:

For event handling:

  • Asynchronous delegate event handlers that return a Task are supported.
  • Delegate event handlers automatically trigger a UI render, so there's no need to manually call StateHasChanged.
  • Exceptions are logged.

The following code:

  • Calls the UpdateHeading method when the button is selected in the UI.
  • Calls the CheckChanged method when the checkbox is changed in the UI.
<h1>@currentHeading</h1>

<p>
    <label>
        New title
        <input @bind="newHeading" />
    </label>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

<p>
    <label>
        <input type="checkbox" @onchange="CheckChanged" />
        @checkedMessage
    </label>
</p>

@code {
    private string currentHeading = "Initial heading";
    private string newHeading;
    private string checkedMessage = "Not changed yet";

    private void UpdateHeading()
    {
        currentHeading = $"{newHeading}!!!";
    }

    private void CheckChanged()
    {
        checkedMessage = $"Last changed at {DateTime.Now}";
    }
}

In the following example, UpdateHeading:

  • Is called asynchronously when the button is selected.
  • Waits two seconds before updating the heading.
<h1>@currentHeading</h1>

<p>
    <label>
        New title
        <input @bind="newHeading" />
    </label>
    <button @onclick="UpdateHeading">
        Update heading
    </button>
</p>

@code {
    private string currentHeading = "Initial heading";
    private string newHeading;

    private async Task UpdateHeading()
    {
        await Task.Delay(2000);

        currentHeading = $"{newHeading}!!!";
    }
}

Event Arguments

For events that support an event argument type, specifying an event parameter in the event method definition is only necessary if the event type is used in the method. In the following example, MouseEventArgs is used in the ReportPointerLocation method to set message text that reports the mouse coordinates when the user selects a button in the UI.


@for (var i = 0; i < 4; i++)
{
    <p>
        <button @onclick="ReportPointerLocation">
            Where's my mouse pointer for this button?
        </button>
    </p>
}

<p>@mousePointerMessage</p>

@code {
    private string mousePointerMessage;

    private void ReportPointerLocation(MouseEventArgs e)
    {
        mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
    }
}


Supported EventArgs are shown in the following table.

Lambda expressions

Lambda expressions are supported as the delegate event handler.


@page "/Pages/EventHandlerExample4"

<h1>@heading</h1>

<p>
    <button @onclick="@(e => heading = "New heading!!!")">
        Update heading
    </button>
</p>

@code {
    private string heading = "Initial heading";
}

It's often convenient to close over additional values using C# method parameters, such as when iterating over a set of elements. The following example creates three buttons, each of which calls UpdateHeading and passes the following data:

  • An event argument (MouseEventArgs) in e.
  • The button number in buttonNumber.

@page "/event-handler-example-5"

<h1>@heading</h1>

@for (var i = 1; i < 4; i++)
{
    var buttonNumber = i;

    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@i
        </button>
    </p>
}

@code {
    private string heading = "Select a button to learn its position";

    private void UpdateHeading(MouseEventArgs e, int buttonNumber)
    {
        heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
    }
}

EventCallback

A common scenario with nested components executes a parent component's method when a child component event occurs. An onclick event occurring in the child component is a common use case. To expose events across components, use an EventCallback. A parent component can assign a callback method to a child component's EventCallback.

The following Child component demonstrates how a button's onclick handler is set up to receive an EventCallback delegate from the sample's ParentComponent. The EventCallback is typed with MouseEventArgs, which is appropriate for an onclick event from a peripheral device.

<p>
    <button @onclick="OnClickCallback">
        Trigger a Parent component method
    </button>
</p>

@code {
    [Parameter]
    public string Title { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}

The Parent component sets the child's EventCallback (OnClickCallback) to its ShowMessage method.

@page "/Pages/parent"

<h1>Parent-child example</h1>

<Child Title="Panel Title from Parent" OnClickCallback="@ShowMessage">
    Content of the child component is supplied by the parent component.
</Child>

<p>@message</p>

@code {
    private string message;

    private void ShowMessage(MouseEventArgs e)
    {
        message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
    }
}

When the button is selected in the ChildComponent:

  • The Parent component's ShowMessage method is called. the message is updated and displayed in the Parent component.

  • A call to StateHasChanged isn't required in the callback's method (ShowMessage). StateHasChanged is called automatically to rerender the Parent component, just as child events trigger component rerendering in event handlers that execute within the child.

EventCallback and EventCallback<TValue> permit asynchronous delegates. EventCallback is weakly typed and allows passing any type of argument in InvokeAsync(Object). EventCallback<TValue> is strongly typed and requires passing a T argument in InvokeAsync(T) that's assignable to TValue.

<ChildComponent 
    OnClickCallback="@(async () => { await Task.Yield(); messageText = "Blaze It!"; })" />

Invoke an EventCallback or EventCallback with InvokeAsync and await the Task:

await OnClickCallback.InvokeAsync(arg);

Use EventCallback and EventCallback<TValue> for event handling and binding component parameters.

Prefer the strongly typed EventCallback<TValue> over EventCallback. EventCallback<TValue> provides enhanced error feedback to users of the component. Similar to other UI event handlers, specifying the event parameter is optional. Use EventCallback when there's no value passed to the callback.

Prevent default actions

Use the @on{DOM EVENT}:preventDefault directive attribute to prevent the default action for an event, where the {DOM EVENT} placeholder is a Document Object Model (DOM) event.

When a key is selected on an input device and the element focus is on a text box, a browser normally displays the key's character in the text box. In the following example, the default behavior is prevented by specifying the @onkeydown:preventDefault directive attribute. When the focus is on the <input> element, the counter increments with the key sequence Shift + +. The + character isn't assigned to the <input> element's value. For more information on keydown, see MDN Web Docs: Document: keydown event.

<p>
    <input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>

@code {
    private int count = 0;

    private void KeyHandler(KeyboardEventArgs e)
    {
        if (e.Key == "+")
        {
            count++;
        }
    }
}

Specifying the @on{DOM EVENT}:preventDefault attribute without a value is equivalent to @on{DOM EVENT}:preventDefault="true".

An expression is also a permitted value of the attribute. In the following example, shouldPreventDefault is a bool field set to either true or false:

<input @onkeydown:preventDefault="shouldPreventDefault" />

...

@code {
    private bool shouldPreventDefault = true;
}

Stop event propagation

Use the @on{DOM EVENT}:stopPropagation directive attribute to stop event propagation, where the {DOM EVENT} placeholder is a Document Object Model (DOM) event.

In the following example, selecting the checkbox prevents click events from the second child <div> from propagating to the parent <div>.

Since propagated click events normally fire the OnSelectParentDiv method, selecting the second child <div> results in the parent <div>message appearing unless the checkbox is selected.

@page "/Pages/EventHandlerExample7"

<label>
    <input @bind="stopPropagation" type="checkbox" />
    Stop Propagation
</label>

<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
    <h3>Parent div</h3>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
        Child div that doesn't stop propagation when selected.
    </div>

    <div class="m-1 p-1 border" @onclick="OnSelectChildDiv" 
            @onclick:stopPropagation="stopPropagation">
        Child div that stops propagation when selected.
    </div>
</div>

<p>
    @message
</p>

@code {
    private bool stopPropagation = false;
    private string message; 

    private void OnSelectParentDiv() =>
        message = $"The parent div was selected. {DateTime.Now}";

    private void OnSelectChildDiv() =>
        message = $"A child div was selected. {DateTime.Now}";
}

Focus an element

Call FocusAsync on an element reference to focus an element in code. In the following example, select the button to focus the <input> element.

razor

Copy
@page "/Pages/EventHandlerExample8"

<p>
    <input @ref="exampleInput" />
</p>

<button @onclick="ChangeFocus">
    Focus the Input Element
</button>

@code {
    private ElementReference exampleInput;

    private async Task ChangeFocus()
    {
        await exampleInput?.FocusAsync();
    }
}

Forms and validation

The Blazor framework supports web forms with validation using the EditForm component bound to a model that uses data annotations.

To demonstrate how an EditForm component works with data annotations validation, consider the following ExampleModel type. The Name property is marked required with the RequiredAttribute and specifies a StringLengthAttribute maximum string length limit and error message.


using System.ComponentModel.DataAnnotations;

public class ExampleModel
{
    [Required]
    [StringLength(10, ErrorMessage = "Name is too long.")]
    public string Name { get; set; }
}

A form is defined using the Blazor framework's EditForm component. The following Razor component demonstrates typical elements, components, and Razor code to render a webform using an EditForm component, which is bound to the preceding ExampleModel type.


<EditForm Model="@exampleModel" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <InputText id="name" @bind-Value="exampleModel.Name" />

    <button type="submit">Submit</button>
</EditForm>

@code {
    private ExampleModel exampleModel = new();

    private void HandleValidSubmit()
    {
        Console.WriteLine("HandleValidSubmit called");

        // Process the valid form
    }
}

In the preceding component:

  • The EditForm component is rendered where the element appears.
  • The model is created in the component's @code block and held in a private field (exampleModel). The field is assigned to EditForm.Model's attribute (Model) of the element.
  • The InputText component (id="name") is an <input> component for editing string values. The @bind-Value directive attribute binds the exampleModel.Name model property to the InputText component's Value property.
  • The HandleValidSubmit method is assigned to OnValidSubmit. The handler is called if the form passes validation.
  • The data annotations validator (DataAnnotationsValidator component†) attaches validation support using data annotations:
    • If the <input> form field is left blank when the Submit button is selected, an error appears in the validation summary (ValidationSummary component‡) ("The Name field is required.") and HandleValidSubmit is not called.
    • If the <input> form field contains more than ten characters when the Submit button is selected, an error appears in the validation summary ("Name is too long.") and HandleValidSubmit is not called.
    • If the <input> form field contains a valid value when the Submit button is selected, HandleValidSubmit is called.

†The DataAnnotationsValidator component is covered in the Validator component section. ‡The ValidationSummary component is covered in the Validation Summary and Validation Message components section. For more information on property binding, see data binding.

Theming Engine

This article contains information about developing themes for the Alliance Business Suite. The product includes a powerful theming engine that allows customers to customize every portal's look and feel.

Introduction

Alliance Business Suite Themes are groups of files that work together to create the design and functionality of an Alliance Business Suite portal. Each Theme may be different, offering many choices for site owners to instantly change their portal look.

We're building the theme engine to allow customers to create themes for their own use, for a client project or to submit to the ABS Theme Directory.

Capabilities

The ABS Theming Engine is built on top of the ABS Razor Templating Engine, which allows themes to use a combination of C# + HTML, CSS, and JavaScript to build amazing experiences.

  • Use a powerful component architecture to avoid code repetition and improve maintainability
  • Provide alternative templates for fixed platform functionalities such as the Store & Dashboard.
  • Themes can be updated through a mirror URL (which can perform things like license validation and much more).

Benefits

  • Themes can keep your Business Logic separated from your UI.
  • Themes are easily portable to other Alliance Business Suite instances.
  • Themes can be enabled on many portals running on the same instance.
  • Theme files can be overridden by child theme files and Dynamic Web Content (pulled from the database).

Anatomy of a Theme

Alliance Business Suite themes are just files living on a specific folder inside your instance's file system (/AppData/Themes/{ThemeName}). Each Theme Folder contains static files (such as JavaScript, CSS, Images, SVGs...) as well as a collection of C#, Razor, and Cshtml files.

The Alliance Business Suite includes a default theme in each new installation. Examine the files in the default theme carefully to get a better idea of how to build your own Theme files.

Child Themes

A child theme allows you to change small aspects of each theme's appearance while still preserving your theme’s look and functionality. To understand how child themes work it is first important to understand the relationship between parent and child themes.

A parent theme is a regular theme that includes every needed file the theme needs to properly work. This includes static files and business logic (dependencies should be installed through a Module).

Therefore, a Child Theme is just a subset of the parent's files which overrides a small subset of the parent's theme style and/or functionality.

Benefits of using a Child Theme

  • make your modifications portable and replicable;
  • keep customization separate from parent theme functions.
  • allow parent themes to be updated without destroying your modifications.
  • allow you to take advantage of the effort and testing put into the parent theme.
  • save on development time as you are not reinventing the wheel; and
  • are a great way to start learning about theme development.

The anatomy of a Theme

Themes contain a specific folder structure used to override the content defaults

- /Pages/
- /Components/
- /Public/
- /Templates/

Using these template files you can poll dynamic web content within the Main.cshtml master file to include these other files where you want them to appear in the final generated page.

  • To include the body, use @Body.
  • To include the header, use @await ViewService.InvokeAsync("Header").
  • To include the sidebar, use @await ViewService.InvokeAsync("Sidebar").
  • To include the footer, use @await ViewService.InvokeAsync("Footer").
  • To include the search bar, use @await ViewService.InvokeAsync("Search").

Here is an example of a basic Template File:

@{Name = "Turing Main Template";}

@await ViewService.InvokeAsync("Header")
@Body
@await ViewService.InvokeAsync("Footer")

For more on how these various Templates work and how to generate different information within themes, read the Templates documentation.

Theme Configuration File

In addition to your theme, the theme.json file provides details about the Theme in the form of a JSON Object. The file MUST exist and provide details about the Theme in a specific format. No two Themes are allowed to have the same details listed in the properties, as this will lead to problems in the Theme selection process. If you make your own Theme by copying an existing one, make sure you change this information first.

{
    "ID": "Turing",
    "Name": "Turing",
    "Domain": "Turing",
    "Version": "0.0.1",
    "AuthorName": "Fenix Alliance Inc.",
    "AuthorUrl": "https://fenix-alliance.com",
    "ThemeUrl": "https://fenix-alliance.com",
    "Tags": "mega-menu, translation-ready",
    "License": "GNU General Public License v2 or later",
    "LicenseUrl": "http://www.gnu.org/licenses/gpl-2.0.html",
    "Description": "Default theme for the Alliance Business Suite Portal."
}

NB: The name used for the Author is suggested to be the same as the Theme Author's github.com username, in which case it should start with an "@", although it can be the author's real or business name as well.

Template Files

Templates are ABS Razor source files used to generate the pages requested by visitors and are output as HTML. Template files are made up of HTML, C# and are rendered through ABS Templating Engine.

The Alliance Business Suite defines several template files that control the look and feel of certain parts of each portal.

Templates are rendered based upon the Web Component Hierarchy, which depends on the files that are present on the portal's enabled theme.

Template files should exist inside the Templates folder on your theme.

At the very minimum, an Alliance Business Suite Theme consists of two files:

  • theme.json
  • /Public/style.css

Both of these files go into the Theme directory. The Main.cshtml template file is very flexible. It can be used to include references to the header, sidebar, footer, body, categories, archives, search, error, and any other components both present in the theme's filesystem or pulled from the Alliance Business Model as Dynamic Web Content.

Or, it can be divided into several template files, each one taking on part of the workload. If you do not provide other template files, the Alliance Business Suite may have default files or functions to perform their jobs. For example, if you do not provide a SearchForm.cshtml template file, the Alliance Business Suite has a default View Component to display the search form.

Core Templates

  • Main.cshtml: The main template. If your Theme provides its own template, Main.cshtml must be present.

  • Blog.cshtml: The Blog template.

  • Forum.cshtml: The Forum template.

  • Store.cshtml: The Store template.

  • Dashboard.cshtml: The Dashboard template.

Core Pages

  • Page.cshtml: The page template. Used when an individual Page is queried.

  • Home.cshtml: The home page template, which is the front page by default. If you use a static front page this is the template for the page with the latest posts.

  • ForumHome.cshtml: The home page template, which is the front page by default. If you use a static front page this is the template for the page with the latest posts.

  • BlogHome.cshtml: The home page template, which is the front page by default. If you use a static front page this is the template for the page with the latest posts.

  • StoreHome.cshtml: The home page template, which is the store front page by default. If you use a static store front page this is the template for the page with the latest posts.

  • {PluralizedEntityType}.cshtml: The content template used when the records from any given Entity type are queried. For example, Courses.cshtml used for displaying posts from the Entity named "Course". Archive.cshtml is used if the query template for the custom post type is not present.

  • Single{EntityType}.cshtml: The single post template used when a single post from a custom post type is queried. For example, SingleItemCategory.cshtml used for displaying single records from the "ItemCategory" Entity. Single.cshtml is used if the query template for the custom post type is not present.

  • Category.cshtml: The category template. Used when a category is queried.

  • Tag.cshtml: The tag template. Used when a tag is queried.

  • Currencies.cshtml: The currency selector page template. Used to change the default currency is queried.

  • User.cshtml: The account page template. Used on the User Profile Page.

  • Login.cshtml: The login page template. Used on the User Login Page.

  • Register.cshtml: The register page template. Used on the User Registration Page.

  • Taxonomy.cshtml: The taxonomy template. Used when a taxonomy is queried.

  • SocialProfile.cshtml: The Social Profile template page. Used when a social profile is queried.

  • Date.cshtml: The date/time template. Used when a date or time is queried. Year, month, day, hour, minute, second.

  • Archive.cshtml: The archive template. Used when a category, author, or date is queried. Note that this template will be overridden by Category.cshtml, SocialProfile.cshtml, and Date.cshtml for their respective query types.

  • Search.cshtml: The search results template. Used when a search is performed.

  • Attachment.cshtml: Attachment template. Used when viewing a single attachment.

  • Image.cshtml: Image attachment template. Used when viewing a single image attachment. If not present, attachment.php will be used.

  • E404.cshtml: The 404 Not Found template. Used when the ABS cannot find a post or page that matches the query.

  • E401.cshtml: The 404 Not Authorized template. Used when the ABS cannot allow a user to query some endpoint.

  • E500.cshtml: The 500 Error template. Used when the ABS cannot perform some action due to some internal error.

Core Components

  • Head.cshtml: The head component.

  • Footer.cshtml: The footer component.

  • Header.cshtml: The header component.

  • StoreFooter.cshtml: The store footer component.

  • StoreHeader.cshtml: The store header component.

Layout Pages on the Alliance Business Suite

Pages and views frequently share visual and programmatic elements. This article demonstrates how to:

  • Use common layouts.
  • Share directives.
  • Run common code before rendering pages or views.

This document discusses layouts for the two different approaches to building Alliance Business Suite Apps: Razor Pages and controllers with views. For this topic, the differences are minimal:

Razor Pages are database records according to the Alliance Business Model Schema. Controllers with views are sets of precompiled code living on the Alliance Business Model.

What is a Layout

Most web apps have a common layout that provides the user with a consistent experience as they navigate from page to page. The layout typically includes common user interface elements such as the app header, navigation or menu elements, and footer.

Page Layout example

Common HTML structures such as scripts and stylesheets are also frequently used by many pages within an app. All of these shared elements may be defined in a layout file, which can then be referenced by any view used within the app. Layouts reduce duplicate code in views.

page-layout.png

Common HTML structures such as scripts and stylesheets are also frequently used by many pages within an app. All of these shared elements may be defined in a layout file, which can then be referenced by any view used within the app. Layouts reduce duplicate code in views.

By convention, the default layout for an Alliance Business Suite app is named MainLayout.

The layout defines a top-level template for views in the app. Apps don't require a layout. Apps can define more than one layout, with different views specifying different layouts.

The following code shows the layout file for a template created a project with a controller and views:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApplication1</title>

    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />

</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-page="/Index" class="navbar-brand">WebApplication1</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/Index">Home</a></li>
                    <li><a href="/About">About</a></li>
                    <li><a href="/Contact">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <partial name="_CookieConsentPartial" />

    <div class="container body-content">
        @Body
        <hr />
        <footer>
            <p>&copy; 2020 - WebApplication1</p>
        </footer>
    </div>


        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
                crossorigin="anonymous"
                integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
        </script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
                crossorigin="anonymous"
                integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
        </script>

        <script src="~/js/site.min.js" ></script>

</body>
</html>

Specifying a Layout

Razor views have a Layout property. Individual views specify a layout by setting this property:

LayoutOptionShowcase.png

View components are similar to page views, but they're much more powerful. View components don't use model binding and only depend on the data provided when calling into it.

A view component:

  • Renders a chunk rather than a whole response.
  • Includes the same separation-of-concerns and testability benefits found between a controller and view.
  • Can have parameters and business logic.
  • Is typically invoked from a layout page.

View components are intended anywhere you have reusable rendering logic that's too complex for a partial view, such as:

  • Dynamic navigation menus
  • Tag cloud (where it queries the database)
  • Login panel
  • Shopping cart
  • Recently published articles
  • Sidebar content on a typical blog
  • A login panel that would be rendered on every page and show either the links to log out or log in, depending on the login state of the user

A view component consists of two parts: the class (typically derived from ViewComponent) and the result it returns (typically a view). Like controllers, a view component can be a POCO, but most developers will want to take advantage of the methods and properties available by deriving from ViewComponent.

Creating a view component

A view component class can be created on your ABS Instance administration dashboard, under Appearance > Components.

View component methods

A view component defines its logic in an InvokeAsync method that returns a Task<IViewComponentResult> or in a synchronous Invoke method that returns an IViewComponentResult. Parameters come directly from the invocation of the view component, not from model binding. A view component never directly handles a request. Typically, a view component initializes a model and passes it to it's corresponding view by calling the View method. In summary, view component methods:

  • Define an InvokeAsync method that returns a Task<IViewComponentResult> or a synchronous Invoke method that returns an IViewComponentResult.
  • Typically initializes a model and passes it to a view by calling the ViewComponent View method.
  • Parameters come from the calling method, not HTTP. There's no model binding.
  • Are not reachable directly as an HTTP endpoint. They're invoked from your code (usually in view). A view component never handles a request.
  • Are overloaded on the signature rather than any details from the current HTTP request.

View search path

The Alliance Business Suite searches for ViewComponents using the Alliance Business Model Schema. It will use case insensitive search by Name and Id for the ViewComponent.

Note: If the View Component is not rendered, no errors will be thrown and only an empty markup string will be rendered.

Perform synchronous work

The framework handles invoking a synchronous Invoke method if you don't need to perform asynchronous work. The following method creates a synchronous Invoke view component:

public class Template : DynamicComponentBase
{
    public dynamic Invoke(int maxPriority, bool isDone)
    {
        var items = new List<string> { $"maxPriority: {maxPriority}", $"isDone: {isDone}" };
        return items;
    }
}

A view component class:

  • Fully supports constructor dependency injection

  • Doesn't take part in the controller lifecycle, which means you can't use filters in a view component

@model List<string>

<h3>Priority Items</h3>
<ul>
    @foreach (var item in Model)
    {
        <li>@item</li>
    }
</ul>

Invoking a Web Component

To use a component inside a Page, template, or another component, call ViewService.InvokeAsync from anywhere in your view:

@await ViewService.InvokeAsync("Component Name or Id", {Anonymous Type Containing Parameters}, (optional) recompile = false)
@await ViewService.InvokeAsync("Component Name or Id", new { maxPriority = 1, isDone = false  })

All view component parameters are required

Each parameter in a view component is a required attribute. See this GitHub issue. If any parameter is omitted:

  • The InvokeAsync method signature won't match, therefore the method won't execute.
  • The ViewComponent won't render any markup.
  • No errors will be thrown.

[[TOC]]

The Alliance Business Suite contains a simple, yet powerful engine for enabling seamless Client-Side Single Page Application development using Angular or React/React+Redux, or really any Client-Side framework.

The ABS SPA Service provides a convenient template to act as a starting point for Client-Side Applications both using Angular or React/React+Redux to implement a rich, client-side user interface (UI) while still taking advantage of the tremendous power of the Alliance Business Suite without the hustle of creating and connecting independent application components, managing authentication and more.

ABS SPA applications offer the convenience of hosting several custom applications inside a single Alliance Business Suite instance, Consequently, your business applications can be perceived, managed, and operated as a single unit.

There are slight differences between the Angular/React/React+Redux app created for the Alliance Business Suite and the one traditionally created by each respective SPA framework tool (via ng new or npx create-react-app ); however, the app's capabilities are unchanged. The app created by each template contains a Bootstrap-based layout and a basic routing example.

Each ABS SPA template is configured to use the Alliance Business Platform as an API backend and the SPA project to act as a UI.

Creating a Single Page Application.

To create a new Client-Side application for the Alliance Business Suite, head over to your ABS Studio, click on integrations from the top right-hand side corner of your state bar. Select Alliance Business Suite > Applications > Create Application.

There, fill out the form, select a name for your application and mark your new application as a Single Page Application. There, you will be prompted with additional required properties for your application.

image.png You can customize things like:

  • The Application Name
  • The NPM Publish Script
  • The NPM Start Script
  • The SPA Engine

Managing your Angular Application

Managing your React Application

The template is equivalent to creating both an ASP.NET Core project to act as an API backend, and a standard CRA React project to act as a UI, but with the convenience of hosting both in a single app project that can be built and published as a single unit.

Managing your React + Redux Application

Add pages, images, styles, modules, etc.

The Alliance Business Suite offers an in-app code editor and file manager to allow you to add static files and code changes to your SPA application. However, sometimes customers do prefer to realize extension development using tools like Visual Studio and VS Code on their development desktops.

This is why the Alliance Business Suite allows customers to connect a public/private git repo to each SPA and pull/push updates with the click of a button.

To enable Git Management for your SPA application, head to your application page and Enable Git Repo Management. Provide a Git Repo URL and a personal access token if the repo is private.

image.png

Install npm packages

To install third-party npm packages, use a command prompt on the application page and run the following command:

spa -id packages install --save <package_name> or just add it to your package.json and request the application to execute the publish script, (which will execute npm install first) by clicking on the Re-Publish Files button.

image.png

Publish and deploy

In development, ABS SPAs run in a mode optimized for developer convenience. For example, JavaScript bundles include source maps (so that when debugging, you can see your original TypeScript code). The app watches for TypeScript, HTML, and CSS file changes on the SPA Root Files Path and automatically recompiles and reloads when it sees those files change.

In production, the Alliance Business Suite serves the version of your app that's optimized for performance. This is configured to happen automatically. When you publish, the build configuration emits a minified, ahead-of-time (AoT) compiled build of your client-side code. Unlike the development build, the production build doesn't require Node.js to be installed on the server (unless you have enabled server-side rendering (SSR)).

Run the SPA independently

The project is configured to start its own instance of the SPA in the background when the Alliance Business Suite starts in development mode. This is convenient because you don't have to run a separate server manually.

There's a drawback to this default setup. Each time you modify your C# code and your Alliance Business Suite instance needs to restart, the SPA server restarts. Around 10 seconds is required to start back up. If you're making frequent updates to your Alliance Business Suite instance (Like installing new applications or modules) and don't want to wait for each SPA process to restart, run the Angular CLI server externally, independently of the ASP.NET Core process. To do so:

image.png

Provide a URL for the running ABS SPA and the Alliance Business Suite will establish a proxy To the SPA Development Server.

Current limitations

The React project template isn't meant for server-side rendering (SSR). For SSR with React and Node.js, consider Next.js or Razzle.

Session and state management in the Alliance Business Suite

HTTP is a stateless protocol. By default, HTTP requests are independent messages that don't retain user values. This article describes several approaches to preserve user data between requests.

State management

State for the Alliance Business Suite can be stored using several approaches. Each approach is described later in this topic.

Storage approachStorage mechanism
CookiesHTTP cookies. May include data stored using server-side app code.
Session stateHTTP cookies and server-side app code
TempDataHTTP cookies or session state
Query stringsHTTP query strings
Hidden fieldsHTTP form fields
HttpContext.ItemsServer-side app code
CacheServer-side app code

Cookies

Cookies store data across requests. Because cookies are sent with every request, their size should be kept to a minimum. Ideally, only an identifier should be stored in a cookie with the data stored by the ABS Instance. Most browsers restrict cookie size to 4096 bytes. Only a limited number of cookies are available for each domain.

Because cookies are subject to tampering, they must be validated by the app. Cookies can be deleted by users and expire on clients. However, cookies are generally the most durable form of data persistence on the client.

Cookies are often used for personalization, where content is customized for a known user. The user is only identified and not authenticated in most cases. The cookie can store the user's name, account name, or unique user ID such as a GUID. The cookie can be used to access the user's personalized settings, such as their preferred website background color.

See the European Union General Data Protection Regulations (GDPR) when issuing cookies and dealing with privacy concerns. For more information, see General Data Protection Regulation (GDPR) support for the Alliance Business Suite.

Session state

Session state is an Alliance Business Suite Instance scenario for the storage of user data while the user browses a web app. Session state uses a store maintained by the app to persist data across requests from a client. The session data is backed by a cache and considered ephemeral data. The site should continue to function without the session data. Critical application data should be stored in the Account Holder database entity and cached in session only as a performance optimization.

The session isn't supported in SignalR functionalities because a SignalR Hub may execute independently of an HTTP context. For example, this can occur when a long polling request is held open by a hub beyond the lifetime of the request's HTTP context.

The Alliance Business Suite maintains the session state by providing a cookie to the client that contains a session ID. The cookie session ID:

  • Is sent to the app with each request.
  • Is used by the app to fetch the session data.

Session state exhibits the following behaviors:

  • The session cookie is specific to the browser. Sessions aren't shared across browsers.
  • Session cookies are deleted when the browser session ends.
  • If a cookie is received for an expired session, a new session is created that uses the same session cookie.
  • Empty sessions aren't retained. The session must have at least one value set to persist the session across requests. When a session isn't retained, a new session ID is generated for each new request.
  • The app retains a session for a limited time after the last request. The app either sets the session timeout or uses the default value of 20 minutes. Session state is ideal for storing user data:
  • That's specific to a particular session.
  • Where the data doesn't require permanent storage across sessions.
  • Session data is deleted either when the ISession.Clear implementation is called or when the session expires.
  • There's no default mechanism to inform app code that a client browser has been closed or when the session cookie is deleted or expired on the client.
  • Session state cookies aren't marked essential by default. Session state isn't functional unless tracking is permitted by the site visitor. For more information, see General Data Protection Regulation (GDPR) support across the Alliance Business Suite

Don't store sensitive data in session state. The user might not close the browser and clear the session cookie. Some browsers maintain valid session cookies across browser windows. A session might not be restricted to a single user. The next user might continue to browse the app with the same session cookie.

The in-memory cache provider stores session data in the memory of the server where the app resides. In a server farm scenario:

Use sticky sessions to tie each session to a specific app instance on an individual server. Azure App Service uses Application Request Routing (ARR) to enforce sticky sessions by default. However, sticky sessions can affect scalability and complicate web app updates. A better approach is to configure the Alliance Business Suite to a Redis or SQL Server by enabling distributed cache, which doesn't require sticky sessions. For more information, see Distributed caching in the Alliance Business Suite.

The session cookie is encrypted via IDataProtector. Data Protection must be properly configured to read session cookies on each machine. For more information, see Alliance Business Suite Data Protection and Key storage providers.

Warning

Don't store sensitive data in session state. The user might not close the browser and clear the session cookie. Some browsers maintain valid session cookies across browser windows. A session might not be restricted to a single user. The next user might continue to browse the app with the same session cookie.

The in-memory cache provider stores session data in the memory of the server where the app resides. In a server farm scenario:

Use sticky sessions to tie each session to a specific app instance on an individual server. Alliance Business Cloud uses Application Request Routing (ARR) to enforce sticky sessions by default. However, sticky sessions can affect scalability and complicate web app updates. A better approach is to enable Redis or SQL Server distributed cache, which doesn't require sticky sessions. For more information, see Distributed caching in the Alliance Business Suite.

Configure session state

To configure session state you'll need to visit your portal's configuration dashboard. The Alliance Business Suite handles the configuration required to add session management through the in-memory session provider with a default in-memory implementation of a Distributed Cache.

You can set the timeout in both development and production environments to simplify testing.

  • HttpContext.Session is available after session state is configured.
  • HttpContext.Session can't be accessed before UseSession has been called.

A new session with a new session cookie can't be created after the Alliance Business Suite has begun writing to the response stream. The exception is recorded in the web server log and not displayed in the browser.

Load session state asynchronously

The default session provider in the Alliance Business Suite loads session records from the underlying IDistributedCache backing store asynchronously only if the ISession.LoadAsync method is explicitly called before the TryGetValue, Set, or Remove methods. If LoadAsync isn't called first, the underlying session record is loaded synchronously, which can incur a performance penalty at scale.

To have apps enforce this pattern, wrap the DistributedSessionStore and DistributedSession implementations with versions that throw an exception if the LoadAsync method isn't called before TryGetValue, Set, or Remove. Register the wrapped versions in the services container.

Session options

To override session defaults, visit your Portal Administration Dashboard.

Query strings

A limited amount of data can be passed from one request to another by adding it to the new request's query string. This is useful for capturing the state in a persistent manner that allows links with the embedded states to be shared through email or social networks. Because URL query strings are public, never use query strings for sensitive data.

In addition to unintended sharing, including data in query strings can expose the app to Cross-Site Request Forgery (CSRF) attacks. Any preserved session state must protect against CSRF attacks. For more information, see Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in the Alliance Business Suite.

Hidden fields

Data can be saved in hidden form fields and posted back on the next request. This is common in multi-page forms. Because the client can potentially tamper with the data, the app must always revalidate the data stored in hidden fields.

HttpContext.Items

The HttpContext.Items collection is used to store data while processing a single request. The collection's contents are discarded after a request is processed. The Items collection is often used to allow components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters.

Cache

Caching is an efficient way to store and retrieve data. The app can control the lifetime of cached items. For more information, see Response caching in the Alliance Business Suite.

Cached data isn't associated with a specific request, user, or session. Do not cache user-specific data that may be retrieved by other user requests.

To cache application-wide data, see Cache in-memory in the Alliance Business Suite.

The Alliance Business Suite supports creating RESTful services, also known as web APIs, using C#. To handle requests, a web API uses controllers. Controllers in the Alliance Business Suite can be added from several approaches, some of which will allow you to access every Alliance Business Suite feature that's available. Controllers are classes that derive from ControllerBase and can be added as Modules to the Alliance Business Suite by installing them as a Nuget Package or uploading them through your instance or File System.

This article shows how to use controllers for handling web API requests.

ControllerBase class

The Alliance Business Suite is written in C# using .NET, and several interfaces have been set in place to make it as extensible as it can be.

The Alliance Business Suite allows customers to develop their own API Sets (which consists of one or more controller classes that derive from ControllerBase) just as if they were building a .NET API, with one main difference. You don't need to worry about wiring features and managing complicated stuff such as authentication processes, dependency injection, and application startup. Also, you can use the ABS SDK to build amazing custom functionalities with just a few lines of code.

Please consider the following class as an example of the most basic custom API Controller for the Alliance Business Suite:


[ApiController]
[Route("api/v2/[controller]")]
public class LicensesController : ControllerBase {

        // Constructor
        public LicensesController(){
        }

        [HttpGet("validate/{LicenceID}")]
        public async Task<ActionResult> Get(string LicenceID)
        {
            await Task.Delay(1000);
            return Ok(LicenceID);
        }

}

The previous controller will be available at /api/v2/licenses and the Get method can be invoked by making an HTTP GET request to /api/v2/licenses/validate/{LicenseID}

Also, it is worth pointing out that the Alliance Business Suite DOES have support for the MVC Pattern, so you should not create a web API controller by deriving from the Controller class. Controller derives from ControllerBase and adds support for views, so it's for handling web pages, not web API requests. There's an exception to this rule: if you plan to use the same controller for both views and web APIs, derive it from Controller."

In essence, creating an Alliance Business Suite compatible Controller is just as straightforward as creating a .NET API Controller with a few additions:

  • You can inject, through dependency injection, any registered Alliance Business Suite Service. This includes every interface provided with the following schema: I{ServiceName}Service (e.g: IAuthService, IHolderService, IViewRenderingService, ICodeCompilationService, and other 100+).

Please consider the following class as an example of a Custom Complex Controller for the Alliance Business Suite:


using FenixAlliance.ABM.Data;
using FenixAlliance.ABM.Data.Interfaces.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace FenixAlliance.Areas.Licensing.Controllers
{
    [ApiController]
    [Route("api/v2/CustomMe")]
    [ApiExplorerSettings(IgnoreApi = true)]
    public class HolderController : ControllerBase {

        public DataContext DataContext { get; set; }
        public IAuthService AuthService { get; set; }
        public IStoreService StoreService { get; set; }
        public IConfiguration Configuration { get; set; }
        public IHostEnvironment Environment { get; set; }
        public IHolderService HolderService { get; set; }
        public ITenantService TenantService { get; set; }
        public IStorageService StorageService { get; set; }

        public LicensesController(
            DataContext DataContext,
            IConfiguration Configuration,
            IHostEnvironment Environment,
            IStoreService StoreService,
            ITenantService TenantService,
            IHolderService HolderService,
            IAuthService AuthService,
            IStorageService StorageService
        )
        {
            this.AuthService = AuthService;
            this.DataContext = DataContext;
            this.Environment = Environment;
            this.StoreService = StoreService;
            this.Configuration = Configuration;
            this.HolderService = HolderService;
            this.TenantService = TenantService;
            this.StorageService = StorageService;
        }

        /// <summary>
        /// Get the current user profile
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Produces("application/json")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(Holder), StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ResponseStatus), StatusCodes.Status401Unauthorized)]
        public async Task<ActionResult<APIResponse>> GetMe()
        {
            var apiResponse = JsonConvert.DeserializeObject<APIResponse>(
                JsonConvert.SerializeObject(
                    await AuthService.BindApiBaseResponse(
                        DataContext,
                        HttpContext,
                        Request,
                        HolderService,
                        User
                        )
                    )
                );

            if (apiResponse == null || !apiResponse.Status.Success || apiResponse.Holder == null)
            {
                return Unauthorized(apiResponse?.Status);
            }

            return Ok(apiResponse.Holder);
        }
    }
}

Installing a Custom Controller

To install a custom controller you just need to build the Razor Class Library containing your custom Controllers as a NuGet Package and then upload it into your Alliance Business Suite instance.

If your RCL depends on other Nuget Packages, those DLLs will need to be copied into your Module's NuGet Package for your custom functionality to work.

To do this, you can extract the .nupkg file using something like 7-Zip (NuGet Packages are just Zipped files with a different extension), and then copy into the lib/ folder every non-ABS Dll required for your RCL to work properly. Then, re-compress the files, and change the re-compressed file extension to .nupkg to be uploaded into your Alliance Business Suite Instance as a Module. (The actual path of the dlls into the lib folder makes no difference whatsoever on the discovery process, so feel free to set up your own structure.)

To install a module into your Alliance Business Suite:

  • Upload your NuGet Package to the Alliance Business Suite Gallery and then install it through the Modules Manager. (This method will make your Module available to every Alliance Business Suite installation out there, and is best suited for those who create commercial modules and integrations)

  • Upload the NuGet package right into your Alliance Business Suite instance using your instance's Modules Manager.

  • Copy the NuGet Package into the Modules folder at the root of your Alliance Business Suite installation. (If the folder does not exist yet, you can confidently create it) and then enable it through your instance's admin portal.

Developing Modules for the Alliance Business Suite

The Alliance Business Suite is a modular application platform. This means that you can create custom functionalities in the form of modules and add them to your ABS instance.

Modules are pieces of software that are designed to perform a specific set of functions or add a specific kind of feature, to any Alliance Business Suite instance. ABS Modules work only with self-hosted ABS instances. Hosted versions such as absuite.net typically offer theme options for customizing portals, but it isn’t possible to install plugins freely to customize portals on this platform.

ABS Modules are written in C#, the programming language for the Alliance Business Suite itself. When using ABS Modules, you can easily install or “plugin” the one you want to an existing ABS instance with no coding knowledge required. The power of ABS Modules makes it possible to extend the functionality of the Alliance Business Suite sites while creating customer experiences that are completely unique.

The Alliance Business Platform provides an essential framework for building a basic website. Some specialized functions can be added to each module and integrated with every theme but those features usually relate to customizing the structure of the site itself. For example, a theme designed for photographers might include options for a gallery or slideshow, and an eCommerce theme might have basic functionality for setting up product pages. Plugins incorporate a fully developed set of functions into your Alliance Business Suite instance site and can include options for customization and configuration.

Creating Modules

To create a Module for the Alliance Business Suite, you'll need to create a new Razor Class Library with DotNet. Then add a reference to the FenixAlliance.ABP.SDK Nuget package to your project and implement the IModule interface.

This will give you access to the entire dependency tree of the Alliance Business Suite, which includes things like Internal Services, Database Access, and Initialization Middleware Entrypoints (to register your own custom services or InternalServices implementations). From there, is just like developing any other ASP.NET Class Library, but without having to worry about things like StartUp processes or complex application dependency wiring.

Once your Module is ready for production, you can build it as a Nuget Package and install it into any ABS instance by uploading the .nupkg file to the Modules folder on the Root content path of your ABS instance or by uploading it to the ABS Public Modules Gallery and install it through your Admin Portal..

What Can Modules Do?

Modules make it easy to convert a basic Alliance Business Suite instance into a fully functioning online storefront, a membership site, a blog, or a website capable of handling the complex professional needs of a multinational corporation. Generally, Modules can add essential functions that are useful for any Alliance Business Suite instance, as well as features for specific needs.

Modules can enhance your Alliance Business Suite instance by:

  • Adding Custom Functionalities. Modules are extremely powerful when it comes to building custom functionalities on top of the Alliance Business Suite. Even when it is super easy to static assets and server-side logic to the Alliance Business Suite through Pages, Components, and Templates, and even SPA applications can be added with the click of a button, Modules allow customers to add fully functional sets of components for the ABS instance. Modules can contain Static Assets, MVC sets, Blazor Components, Tag Helpers, API Controllers, Bot Dialogs, Middlewares, and more.
  • Improving user experience. Modules can add features to help users navigate through a portal, find content, leave comments, subscribe for updates, and contact site administrators.
  • Adding essential security features. The core Alliance Business Suite install comes with a great set of security features, but Modules can add sophisticated firewalls, alerts, user verifications, authentication providers, and spam blockers for greater site security.
  • Speeding up site loading time. Modules can speed up an Alliance Business Suite portal by enabling caching and optimizing static files such as images and even videos.
  • Streamlining your workflow. Modules can help optimize your site for searchability, add server-side logic and API endpoints.
  • Improving the site’s appearance. Modules can add designer fonts, galleries, sliders, and media players to your site. Some themes require certain Modules to perform properly.
  • Adding needed features for your site’s goals. Modules can add features like product pages and shopping carts to eCommerce sites, landing pages, paywalls, and a long list of other features to support the site’s intended purpose.

Best practices for ABS Module Development

  • To reduce possible incompatibilities, it is recommended to create all your functionality inside an ASP.NET Area named after your Module. This will reduce the possibility to collide with other module namespaces and routes.
  • Whenever possible, use the default provided service interfaces under the FenixAlliance.ABM.Data.Interfaces.Services namespace.
  • If you need to add a custom implementation for any service, it is recommended not to do so and instead create a new service; but in cases when there is no other choice, please consider inheriting from the Internal implementation and overriding the required virtual methods.

Security Considerations

Due to the power of Modules, they can be used to add incredible functionalities to your ABS instance, but they can also result in breaking functionalities and even security breaches.

Keep in mind some general ideas while considering security for each aspect of your system:

Reduce exposure

First of all, make sure your Modules are always updated. Also, if you are not using a specific Module, delete it from the system.

Limit access

Making smart Instance/Module/Theme configurations can drastically reduce possible entry points available to a malicious person.

Containment

Your system should be configured to minimize the amount of damage that can be done in the event that it is compromised.

Preparation and knowledge

Keeping backups and knowing the state of your Alliance Business Suite instance at regular intervals. Having a plan to backup and recover your installation in the case of catastrophe can help you get back online faster in the case of a problem.

Trusted Sources

Do not get plugins/themes from untrusted sources. Restrict yourself to the Alliance Business Suite Gallery repository or well-known companies. Trying to get modules/themes from the outside may lead to issues.

Internationalization in the Alliance Business Suite

A multilingual website allows the site to reach a wider audience. The Alliance Business Suite provides convenient, easy-to-use solutions for localizing portals into different languages and cultures.

Internationalization involves Globalization and Localization. Globalization is the process of designing apps that support different cultures. Globalization adds support for the input, display, and output of a defined set of language scripts that relate to specific geographic areas.

Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. For more information see Globalization and localization terms near the end of this document.

How to make the app's content localizable

The Alliance Business Suite was architected to allow customers to obtain this functionality right out of the box. Through simple front-end settings for each portal, customers can select a default language for each portal and localize strings and HTML fragments by just calling the _() method available through code on every web content entry. (e.g: _("Hello World"))

Once your localizable strings have been placed in code using the String Localizer function. you can create localization resources using your instance's admin portal.

Implement a strategy to select the language/culture for each request

Localization is already set up using the ACL. Additional supported languages, as well as the primary content language for each portal, can be selected on each's portal configuration manager.

QueryStringRequestCultureProvider

Portals can use a query string to set the Culture Info. For apps that use the cookie or Accept-Language header approach, adding a query string to the URL is useful for debugging and testing code. By default, the QueryStringRequestCultureProvider is registered as the first localization provider in the RequestCultureProvider list. You pass the query string parameters culture and UI-culture. The following example sets the specific culture (language and region) to Spanish/Mexico:

http://yourdomain/?culture=es-MX&ui-culture=es-MX

If you only pass in one of the two (culture or ui-culture), the query string provider will set both values using the one you passed in. For example, setting just the culture will set both the Culture and the UICulture:

http://localhost:5000/?culture=es-MX

CookieRequestCultureProvider

Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. Use the MakeCookieValue method to create a cookie.

The CookieRequestCultureProvider DefaultCookieName returns the default cookie name used to track the user's preferred culture information. The default cookie name is .AspNetCore.Culture.

The cookie format is c=%LANGCODE%|uic=%LANGCODE%, where c is Culture and uic is UICulture, for example:

c=en-UK|uic=en-US

If you only specify one of culture info and UI culture, the specified culture will be used for both culture info and UI culture.

The Accept-Language HTTP header

The Accept-Language header is settable in most browsers and was originally intended to specify the user's language. This setting indicates what the browser has been set to send or has inherited from the underlying operating system. The Accept-Language HTTP header from a browser request isn't an infallible way to detect the user's preferred language (see Setting language preferences in a browser). A production app should include a way for a user to customize their choice of culture.

Set the Accept-Language HTTP header in IE

  1. From the gear icon, tap Internet Options.

  2. Tap Languages.

  3. Internet Options

  4. Tap Set Language Preferences.

  5. Tap Add a language.

  6. Add the language.

  7. Tap the language, then tap Move Up.

Set the culture programmatically

You can easily create a component to allow your users to select their preferred culture from the list of supported cultures:

This sample, present on the Header Component for the Turing Theme shows you how to do so:

@{
	var requestCulture = Context.Features.Get<IRequestCultureFeature>();
	var cultureItems = RequestLocalizationOptions.Value.SupportedUICultures
		.Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
		.ToList();
	var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}

<li class="nav-item dropdown">
	<div class="dropdown-menu" aria-labelledby="SelectLang">
		<!-- Current Language -->
		<h6 class="dropdown-header">
			<b>  <i class="fas fa-globe-americas"></i>&nbsp;  @_("Current Language"): </b>
			<b id="CurrencyTip">
				@requestCulture.RequestCulture.Culture.TwoLetterISOLanguageName
			</b>
		</h6>
		<div class="dropdown-divider"></div>
		@foreach (var item in cultureItems)
		{
			var value = @item.Value;
			<a href="#" onclick="SelectLang('@(value.Replace(" ", ""))')" class="dropdown-item">
				<i class="fas fa-language"></i>&nbsp; @item.Text
			</a>
		}
	</div>

	<script>
		//Select Language
		function SelectLang(value) {
			cookie = "c=" + value.trim() + "|uic=" + value.trim();
			Cookies.set('.AspNetCore.Culture', cookie);
			window.location.reload();
		}
	</script>
</li>

Globalization and localization terms

The process of localizing your portals also requires a basic understanding of relevant character sets commonly used in modern software development and an understanding of the issues associated with them. Although all computers store text as numbers (1's and 0's), different systems store the same text using different numbers. The localization process refers to translating the portal user interface (UI) for a specific culture/locale.

Localizability is an intermediate process for verifying that a globalized app is ready for localization.

The RFC 4646 format for the culture name is {languagecode2}-{country/regioncode2}, where {languagecode2} is the language code and {country/regioncode2} is the subculture code. For example, es-CO for Spanish (Colombia), en-US for English (United States), and en-AU for English (Australia). RFC 4646 is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region.

Internationalization is often abbreviated to "I18N". The abbreviation takes the first and last letters and the number of letters between them, so 18 stands for the number of letters between the first "I" and the last "N". The same applies to Globalization (G11N), and Localization (L10N).

Terms:

  • Globalization (G11N): The process of making a piece of software to support different languages and regions.
  • Localization (L10N): The process of customizing an app for a given language and region.
  • Internationalization (I18N): Describes both globalization and localization.
  • Culture: It's a language and, optionally, a region.
  • Neutral culture: A culture that has a specified language, but not a region. (for example "en", "es")
  • Specific culture: A culture that has a specified language and region. (for example "en-US", "en-GB", "es-CL")
  • Parent Culture: The neutral culture that contains a specific culture. (for example, "en" is the parent culture of "en-US" and "en-GB")
  • Locale: A locale is the same as a culture.

A multilingual portal allows the site to reach a wider audience. The Alliance Business Suite provides services and middleware for localizing into different languages and cultures.

Internationalization involves Globalization and Localization. Globalization is the process of designing apps that support different cultures. Globalization adds support for input, display, and output of a defined set of language scripts that relate to specific geographic areas.

Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. For more information see Globalization and localization terms near the end of this document.

App localization involves the following:

  1. Make the app's content localizable
  2. Provide localized resources for the languages and cultures you support
  3. Implement a strategy to select the language/culture for each request

Make the app's content localizable

The ABS Razor Engine was architected to improve productivity when developing localized apps. DynamicComponentBase uses the ResourceManager and ResourceReader to provide culture-specific resources at run time. The interface has an easy-to-use method and an IEnumerable for returning localized strings. DynamicComponentBase retrieves the portal default language from the suite configuration file and then loads localized resources from the Alliance Business Model provider. You can develop an app targeted for localization right out of the box by adding LocalizationStrings and LocalizedStrings through the portal admin center. The code below shows how to wrap the string "About Title" for localization.

@{ 
    var localizedString = _("Hello World!");
}
@localizedString 
@_("Hello World!")

Creating Localizable/Localized Strings

The Alliance Business Suite offers a convenient way to create localizable resources like strings or HTML fragments. Localizable/Localized Strings are retrieved and formatted if you need to insert the value of an object, variable, or expression into the localized resource. For example, you can insert the value of a Decimal value into a paragraph to display it to the user as a single string:

@{
    var pricePerOunce = 17.36m;
    var localizedString = _("The current price is {0} per ounce.", pricePerOunce); 
}
<!-- Result: The current price is 17.36 per ounce. -->
@localizedString 

To create a Localization Resource:

  1. Go to your Suite Admin Center,
  2. Select Internationalization > Strings from the left-hand menu.
  3. Select your base language and target language.
  4. Create or select a new Localization String by selecting the base language variation, providing a Base Value, and optionally leaving a comment for future reference.
  5. With your Localization String selected, refer to the Translations panel and there create a new translation by selecting the target language variation, providing a Target Value, and optionally leaving a comment for future reference.

image.png

@{ 
 var localizedString = __["Hello World!"];
}
@localizedString 

Alliance Business Suite Components

The Alliance Business Suite is composed out of 5 Components.

The Alliance Business Suite was architected as a modular Application Framework. This means that components are able to work without their higher-level components. The lowest Component is the Alliance Core Libraries Component and the highest Component is the Alliance Business Studio Component.

ABS Components.jpg

Alliance Core Libraries

The Alliance Core Libraries contains the core abstractions and default implementations required by the Alliance Business Model and dependent components. It is also the external dependency source for the entire Alliance Business Suite, which means that external dependencies, which are dependencies outside the FenixAlliance.* namespace are referred to by the FenixAlliance.ACL.Deps Package, which is the base ACL Package and, therefore, it could be referred to as the Core Package.

For more information on the dependency tree, design overview and external dependencies, please refer to Advanced Topics.

Alliance Business Model

The Alliance Business Model is a declarative specification and definition of standard entities that represent commonly used concepts and activities across business and productivity applications and is being extended to observational and analytical data as well. ABM provides well-defined, modular, and extensible business entities such as Account, Business Unit, Case, Contact, Lead, Opportunity, and Items (Products/Services), as well as interactions with vendors, workers, and customers, such as activities and service level agreements. that serve as the dynamic data layer for the entire Alliance Business Suite.

Anyone can build on and extend ABM definitions to capture additional business-specific scenarios.

Alliance Passport Service

The Alliance Passport Service enables developers and non-developers alike The Alliance Passport Service is an Authentication/Authorization Engine designed to enable customers to easily configure and manage businesses identity scenarios by assigning (or connecting) a digital identity to their contacts, whether they are customers, employees, partners, guests, and more.

It also provides common features for managing authentication, authorization, data protection, HTTPS enforcement, app secrets, XSRF/CSRF prevention, and CORS management. These security features allow you to build robust, yet secure Alliance Business Suite apps.

Alliance Business Platform

The Alliance Business Platform is a Modular API Framework. It leverages .NET 5.0 with the best of REST, SignalR, GraphQl y gRPCto transact with the Alliance Business Model Schema (AMB). The Alliance Business Platform is an open-source and cross-platform framework for integrating next-generation functionalities into your applications. It allows you to build spectacular single-page apps using .NET and C# with or without JavaScript. ABP apps can connect and transact to the data layer (The Alliance Business Modal Schema) using any language through standard requests through the various GrPC, HTTP, and GraphQL Endpoints.

Anyone can build on and extend The Alliance Business Platform through ASP.NET + Angular / React (And pretty much any Framework), to capture additional business-specific scenarios.

Alliance Business Studio

The Alliance Business Studio is the Graphical Administration Engine for the Alliance Business Suite. It allows users to manage their implementations, transact data through the Alliance Business Platform, generate and consume views, reports, customize and extend the system, and much more.

Anyone can build on and extend The Alliance Business Studio to capture additional business-specific scenarios.

Alliance Business Cloud

The Alliance Business Cloud is an HTTP-based service for hosting Alliance Business Suite Instances and other kinds of applications. These can be developed in your favorite language, be it .NET, .NET Core, Java, Ruby, Node.js, PHP, or Python. Applications run and scale with ease on both Windows-based environments.

The Alliance Business Cloud not only adds the power of Microsoft Azure to your Alliance Business Suite instance, such as security, load balancing, autoscaling, and automated management features; You can also take advantage of its DevOps capabilities, such as continuous deployment from Azure DevOps, GitHub, Docker Hub, and other sources, package management, staging environments, custom domain, and free/paid TLS/SSL certificates.

With Alliance Business Cloud, you pay for the compute resources you use. The compute resources you use are determined by the Service plan that you run your Alliance Business Suite instance on.

Understanding the Alliance Core Libraries.

The Alliance Core Libraries contains the core abstractions and default implementations required by the Alliance Business Model and dependent components. It is also the external dependency source for the entire Alliance Business Suite, which means that external dependencies, which are dependencies outside the FenixAlliance.* namespace are referred to by the FenixAlliance.ACL.Deps Package, which is the base ACL Package and, therefore, it could be referred to as the Core Package.

Dependant components of the Alliance Core Libraries can make use of external dependencies referred by the Core Package thanks to .NET's Waterfall dependency resolution mechanism.

For more information on the dependency tree, design overview, and external dependencies, please refer to Advanced Topics.

Referred External Dependencies

PackageVersion
Amazon.AspNetCore.Identity.Cognito3.0.0
Amazon.Extensions.CognitoAuthentication2.2.2
AngleSharp0.16.0
AspNetCore.HealthChecks.SqlServer5.0.3
AspNetCore.HealthChecks.UI.Client5.0.1
AspNetCore.HealthChecks.UI.InMemory.Storage5.0.1
AspNetCore.HealthChecks.UI5.0.1
AspNetCore.Proxy4.2.0
AspNetCoreRateLimit4.0.1
Autofac.Extensions.DependencyInjection7.1.0
Autofac6.2.0
AutoMapper.Collection.EntityFrameworkCore7.0.1
AutoMapper.Extensions.Microsoft.DependencyInjection8.1.1
AutoMapper10.1.1
Azure.Storage.Blobs12.9.1
Blazor.Extensions.Canvas1.1.1
Blazor.Extensions.SignalR1.0.0
Blazor.Extensions.Storage1.0.0
Blazor.Extensions.WebUSB1.0.0
Blazor.Extensions.XTerm0.1.0
BlazorFluentUI.ListComponents5.5.3
BotSharp.Core0.4.0
ByteSize2.0.0
Catalyst.Models.English1.0.18055
Catalyst1.0.19323
ChartJs.Blazor.Fork2.0.2
CsvHelper27.1.1
Dapper2.0.90
DnsClient1.5.0
DotLiquid2.2.541
Elsa.Activities.UserTask2.2.1
Elsa2.2.1
Emitter1.0.41
FlexLabs.EntityFrameworkCore.Upsert5.0.0
FluentEmail.Core3.0.0
FluentEmail.Smtp3.0.0
FluentValidation.AspNetCore10.3.1
FluentValidation10.3.1
Fluid.Core2.0.13
Flurl.Http3.2.0
GraphQL.Server.Transports.AspNetCore5.0.2
GraphQL.Server.Transports.WebSockets4.4.1
GraphQL.Server.Ui.GraphiQL5.0.2
GraphQL.Server.Ui.Playground5.0.2
GraphQL.Server.Ui.Voyager5.0.2
GraphQL4.6.0
HtmlAgilityPack1.11.36
Humanizer2.11.10
IdentityServer4.EntityFramework.Storage4.1.2
IdentityServer4.EntityFramework4.1.2
IdentityServer44.1.2
JWT8.2.3
LiteDB5.0.11
MailKit2.15.0
MassTransit7.2.2
MatBlazor2.8.0
MediatR.Extensions.Autofac.DependencyInjection7.3.0
MediatR.Extensions.Microsoft.DependencyInjection9.0.0
MediatR9.0.0
MetadataExtractor2.7.0
Microsoft.ApplicationInsights.AspNetCore2.18.0
Microsoft.AspNet.WebApi.Client5.2.7
Microsoft.AspNetCore.Authentication.Abstractions2.2.0
Microsoft.AspNetCore.Authentication.AzureAD.UI5.0.9
Microsoft.AspNetCore.Authentication.AzureADB2C.UI5.0.9
Microsoft.AspNetCore.Authentication.Facebook5.0.9
Microsoft.AspNetCore.Authentication.Google5.0.9
Microsoft.AspNetCore.Authentication.JwtBearer5.0.9
Microsoft.AspNetCore.Authentication.MicrosoftAccount5.0.9
Microsoft.AspNetCore.Authentication.OpenIdConnect5.0.9
Microsoft.AspNetCore.Authentication.Twitter5.0.9
Microsoft.AspNetCore.Authentication2.2.0
Microsoft.AspNetCore.Blazor0.7.0
Microsoft.AspNetCore.Components.Web5.0.9
Microsoft.AspNetCore.Components5.0.9
Microsoft.AspNetCore.DataProtection5.0.9
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore5.0.9
Microsoft.AspNetCore.Hosting.Server.Abstractions2.2.0
Microsoft.AspNetCore.Hosting2.2.7
Microsoft.AspNetCore.Http.Abstractions2.2.0
Microsoft.AspNetCore.Http.Features5.0.9
Microsoft.AspNetCore.Http2.2.2
Microsoft.AspNetCore.Identity.EntityFrameworkCore5.0.9
Microsoft.AspNetCore.Identity.UI5.0.9
Microsoft.AspNetCore.Mvc.Core2.2.5
Microsoft.AspNetCore.Mvc.NewtonsoftJson5.0.9
Microsoft.AspNetCore.Mvc.Razor.Extensions5.0.9
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation5.0.9
Microsoft.AspNetCore.Mvc.WebApiCompatShim2.2.0
Microsoft.AspNetCore.Mvc2.2.0
Microsoft.AspNetCore.Razor.Language5.0.9
Microsoft.AspNetCore.SignalR.Core1.1.0
Microsoft.AspNetCore.SpaServices.Extensions5.0.9
Microsoft.Azure.KeyVault.Core3.0.5
Microsoft.Bot.Builder.AI.Luis4.14.1
Microsoft.Bot.Builder.Dialogs4.14.1
Microsoft.Bot.Builder.integration.AspNet.Core4.14.1
Microsoft.CSharp4.7.0
Microsoft.EntityFrameworkCore.Design5.0.9
Microsoft.EntityFrameworkCore.Proxies5.0.9
Microsoft.EntityFrameworkCore.Relational5.0.9
Microsoft.EntityFrameworkCore.Sqlite5.0.9
Microsoft.EntityFrameworkCore.SqlServer5.0.9
Microsoft.EntityFrameworkCore.Tools5.0.9
Microsoft.EntityFrameworkCore5.0.9
Microsoft.Extensions.Caching.Abstractions5.0.0
Microsoft.Extensions.Caching.Memory5.0.0
Microsoft.Extensions.Caching.SqlServer5.0.1
Microsoft.Extensions.Configuration.Abstractions5.0.0
Microsoft.Extensions.DependencyInjection.Abstractions5.0.0
Microsoft.Extensions.DependencyInjection5.0.2
Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions5.0.9
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore5.0.9
Microsoft.Extensions.Hosting.Abstractions5.0.0
Microsoft.Extensions.Hosting5.0.0
Microsoft.Extensions.Http5.0.0
Microsoft.Extensions.Localization.Abstractions5.0.9
Microsoft.Extensions.Localization5.0.9
Microsoft.Extensions.Logging.Abstractions5.0.0
Microsoft.Extensions.Logging.Console5.0.0
Microsoft.Extensions.Logging.Debug5.0.0
Microsoft.Extensions.Logging5.0.0
Microsoft.Extensions.Primitives5.0.1
Microsoft.Graph4.3.0
Microsoft.Identity.Client4.35.1
Microsoft.Identity.Web.UI1.16.0
Microsoft.Identity.Web1.16.0
Microsoft.IdentityModel.Tokens6.12.2
Microsoft.ML.AutoML0.18.0
Microsoft.ML.CpuMath1.6.0
Microsoft.ML.DataView1.6.0
Microsoft.ML.EntryPoints0.18.0
Microsoft.ML.Recommender0.18.0
Microsoft.ML1.6.0
Microsoft.OpenApi1.2.3
Microsoft.Rest.ClientRuntime.Azure.Authentication2.4.1
Microsoft.TestPlatform16.11.0
Microsoft.VisualBasic10.3.0
Microsoft.VisualStudio.Web.BrowserLink2.2.0
Microsoft.VisualStudio.Web.CodeGeneration.Design5.0.2
Mobsites.Blazor.SignaturePad1.1.7
MongoDB.Bson2.13.1
MongoDB.Driver2.13.1
MudBlazor.ThemeManager1.0.5
MudBlazor5.1.1
Newtonsoft.Json13.0.1
NodaTime.Serialization.JsonNet3.0.0
NodaTime3.0.5
NReco.LambdaParser1.0.12
NuGet.Packaging5.11.0
NuGet.Protocol5.11.0
Okta.AspNetCore3.5.0
Polly.Caching.Memory3.0.2
Polly7.2.2
Pomelo.EntityFrameworkCore.MySql5.0.1
QRCoder1.4.1
RabbitMQ.Client6.2.2
Radzen.Blazor3.9.2
Razor.Templating.Core1.5.0
RazorLight1.1.0
ReactiveUI.Blazor15.1.1
reCAPTCHA.AspNetCore3.0.10
RestSharp106.12.0
Sendgrid9.24.2
Seq.Extensions.Logging6.0.0
Serilog.AspNetCore4.1.0
Serilog.Enrichers.Environment2.2.0
Serilog.Enrichers.Process2.0.2
Serilog.Enrichers.Thread3.1.0
Serilog.Settings.Configuration3.2.0
Serilog.Sinks.AzureBlobStorage3.0.2
Serilog2.10.0
SixLabors.ImageSharp.Web1.0.3
SixLabors.ImageSharp1.0.3
StackifyMiddleware3.0.5.2
Standard.Licensing1.1.5
Swashbuckle.AspNetCore.SwaggerGen6.1.5
Swashbuckle.AspNetCore.SwaggerUI6.1.5
Swashbuckle.AspNetCore.Swagger6.1.5
System.ComponentModel.Annotations5.0.0
System.IdentityModel.Tokens.Jwt6.12.2
System.IO.FileSystem.AccessControl5.0.0
System.Reactive5.0.0
System.Security.Permissions5.0.0
System.ServiceModel.Duplex4.8.1
System.ServiceModel.Http4.8.1
System.ServiceModel.NetTcp4.8.1
System.ServiceModel.Primitives4.8.1
System.ServiceModel.Security4.8.1
System.Text.Json5.0.2
Toolbelt.Blazor.HotKeys10.0.1
UnitConversion1.0.41
Unity5.11.10
Z.EntityFramework.Plus.EFCore5.2.7
ZXing.Net0.16.6
ZXingBlazor0.1.6

Alliance Business Model (ABM) Schema

In a nutshell, the Alliance Business Model serves as the main dynamic data layer for the entire Alliance Business Suite.

The Alliance Business Model is a declarative schema definition of standard entities representing commonly used concepts and activities across business and productivity applications and is being extended to observational and analytical data.

The Alliance Business Model provides well-defined, modular, and extensible business entities such as Account, Deal Unit, Case, Contact, Lead, Opportunity, and Product, as well as interactions with suppliers, employees, and customers, such as activities and service level agreements.

Configurations

When installing the Alliance Business Suite on a given server, you'll be required to provide the Connection Strings to the Database that will host the Alliance Business Model Schema.

You can change several configurations using these connections strings too, for example, increase/decrease certain default values or even to point to another database (when migrating, for example) and, Although not recommended, you can even change the Database Engine that's providing SQL services to your running instance.

Providers

The Alliance Business Model was designed to work with several SQL Database providers such as Oracle SQL, Microsoft SQL Server, MySQL, MariaDB, PostgreSQL.

The SQL engine that your Alliance Business Suite's instance is going to use can be selected on the installation process.

Extensions

We're currently working to let anyone extend the Alliance Business Model definitions to capture additional business-specific scenarios.

As of 1.2.0, Custom engines can be supported by generating the appropriate migrations required for the Alliance Business platform in order to work properly.

When building custom engines, you'll be required to manage these migrations yourself, which is kind of a pain, so we're experimenting on in-Database-Database Engine as well as NoSQL interoperability to allow customers to easily extend the Alliance Business Model Schema Specification. Also, we're working on providing Per-Record SQL File-Databases with Distributed File System Support.

We're also currently working on providing even more convenient interfaces for customers extending the Alliance Business Model procedurally or through the Alliance Business Studio.

Entities

Use the Alliance Business Suite's API reference to explore and learn about all the available Alliance Business Model entity definitions, their attributes, and purposes. These entities span several business domains and describe data in different applications and solutions. For example, you can find entity definitions related to Accounting, Learning, Human Resources, and more.

We also maintain a Visual Reference Diagram on GitHub to allow customers to easily identify entities on the Alliance Business Model.

Understanding Alliance Business Model Records

In a nutshell, Alliance Business Records are records stored into the Alliance Business Model Schema. These records contain the structured, relational data scoped to a Business Tenant and might be composed of one or more related database registries.

Work with data using web services

There are two different access methods, each using a different protocol, to manage the Alliance Business Model: a set of Web and Code APIs. Your code can access the Alliance Business Model through either the Web Service endpoints or using the SDK API.

Alliance Passport Services Overview

Overview

The Alliance Business Suite contains a powerful and extensible Authentication and Authorization engine called the Alliance Passport Service ("APS").

How to get started?

The Alliance Passport Service enables developers and non-developers alike to easily configure and manage identity scenarios. The Alliance Passport Service Engine contains features for managing authentication, authorization, data protection, HTTPS enforcement, app secrets, XSRF/CSRF prevention, and CORS management. These security features allow you to build robust, yet secure Alliance Business Suite apps.

Common Terms

Learn more about APS + IAM terms.

  • Permission Sets: refer to the ABM record objects that are used to grant access to resources. You can attach Permission Sets to Identities. These include BusinessProfileRecord, BusinessPermission, SecurityGroup, and SecurityRole.

  • Identities: The ABM record objects that APS uses to authenticate and group. These include AccountHolder, BusinessTenant, BusinessApplication and BusinessDomain.

  • Users A person or application that uses an Identity. Although AccountHolder is the most common type of Identity, BusinessApplication can also be used to sign in and make requests to the Alliance Business Platform's APIs within the scope of a BusinessTenant or a BusinessDomain.

Managing Identity

With the Alliance Business Suite, you can easily manage Authentication and Authorization flows.

Understanding how APS works

Before you create Account Holders or Business Tenants, you should understand how APS enables IAM workflows.

Alliance Passport Services (commonly known as "APS") is an Identity Engine that provides the infrastructure necessary to control authentication and authorization for the Alliance Business Suite.

The Identity and Access Management Module ("IAM") is an extension built on top of the Alliance Passport Services Framework to allow users and applications to connect to certain Alliance Business Suite instances.

Authentication vs. Authorization

Authentication is a process in which a user provides credentials that are then compared to those stored by an operating system, database, app, or resource. If they match, users are authenticated successfully, and can then perform actions that they're authorized for, during an authorization process. The authorization refers to the process that determines what a user is allowed to do.

Another way to think of authentication is to consider it as a way to enter a space, such as a server, database, app, or resource, while authorization is which actions the user can perform to which objects inside that space (server, database, or app).

Authentication fundamentals

An Account Holder must be authenticated (signed in to the Alliance Business Suite) using their credentials to send a request to any Alliance Business Platform API. Some modules, such as Media Portals, ICX Stores, and ABS Workplace, allow a few requests from anonymous users. However, they are the exception to the rule.

Users

A User is a person or application that can make a request for an action or operation on an ABM resource. The User is authenticated as a Security Identity to make requests to allowed resources through the Alliance Business Platform set of APIs.

Note: As a best practice, do not use your root user credentials for your daily work. Instead, create an additional Account Holder with a more limited Permission Set. You can also support federated users or programmatic access by allowing a Business Application to access your ABS instance.

Root Users

To authenticate from the root user, you must sign in with the email address and password you provided when installing the instance. As any other regular IAM user, root users can set up multi-factor authentication through an authenticator app such as Google Authenticator, Microsoft Authenticator, or really any MFA TOTP (Time-based One-time Password Algorithm) application.

API Users

To authenticate from the API or ABS Commander CLI (Bash or Powershell), you must create and provide an access key and secret key. You can get these keys by installing and navigating to the ABS Self-integration.

Users might also be required to provide additional security information. For example, Fenix Alliance recommends that you use multi-factor authentication (MFA) to increase the security of your account and to enforce it on Privileged Account Holders. To learn more about the IAM entities that the Alliance Passport Service can authenticate, see APS Identity Holders and APS Security Roles.

Authentication Middleware

The Alliance Business Suite uses two primary middlewares for authentication. A Cookie-based authentication engine and standard Token-based authentication.

When a user authenticates into an Alliance Business Suite instance using their username and password (or any other authentication provider, for that matter), they're issued a cookie, containing an authentication token that can be used for authentication and authorization. The token is stored in the browser as a cookie that accompanies every request the client makes to the application. Generating and validating this cookie is performed by the APS Cookie Authentication Middleware. The middleware serializes a user principal into an encrypted cookie. On subsequent requests, the middleware validates the cookie, recreates the principal, and assigns the principal to the User property present on controllers, views, components, and more.

Token-based authentication

When a user is authenticated, they're issued a token (not an anti-forgery token). The token contains user information in the form of claims or a reference token that points the app to the user state maintained in the app. When a user attempts to access a resource requiring authentication, the token is sent to the app with an additional authorization header in form of a "Bearer token".

"Bearer tokens" make the app stateless. In each subsequent request, the token is passed in the request for server-side validation. This token isn't encrypted; it's encoded. On the server, the token is decoded to access its information. To send the token on subsequent requests, the token is saved in the browser's local storage. This design prevents CSRF vulnerability as the token is stored in the browser's local storage. CSRF is a concern when the token is stored in a cookie.

Identity Providers:

Although but you can use third-party identity services such as Facebook, Twitter, and LinkedIn, or even enterprise services such as Azure AD, Azure AD B2C, AWS Cognito (preview), Okta (preview), and many more, the Alliance Business Suite provides many tools and libraries to secure your apps including built-in identity providers, TOTP MFA (Time-based One-time Password Algorithm Multi-Factor Authentication) support.

Authorization Fundamentals

Users must also be authorized (allowed) to complete any request. During authorization, the APS Engine uses values from the request context to check for policies that apply to the request. It then uses the policies to determine whether to allow or deny the request. Most policies are stored in the ABS as ABM Records and specify the permissions for principal entities. There are several types of policies that can affect whether a request is authorized. To provide your users with permissions to access any layer of the Alliance Business Suite, you need only identity-based ABM records. Resource-based policies are popular for granting cross-account access. The other policy types are advanced features and should be used carefully.

The APS Engine checks each policy that applies to the context of any given request. If a single permissions policy is missing, a denied action will be returned, APS denies the entire request and stops evaluating. This is called an explicit deny. Because requests are denied by default, APS authorizes your request only if every part of your request is allowed by the applicable permissions policies. The evaluation logic for a request within a single account follows these general rules:

  • By default, all requests are denied. (In general, requests made using the ABS root user credentials for resources in the instance are always allowed.)

  • An explicit allow in any permissions policy (identity-based or resource-based) overrides this default.

  • The existence of a Parent Tenant' IAM permissions boundary or a session policy overrides the allow. If one or more of these policy types exists, they must all allow the request. Otherwise, it is implicitly denied.

  • An explicit deny in any policy overrides any allows.

To learn more about how all types of policies are evaluated, please refer to Authorization evaluation logic. If you need to make a request in a different account, a policy in the other account must allow you to access the resource, and the Identity Entity that you use to make the request must have an identity-based policy that allows the request.

Security Permissions

After your request has been authenticated and authorized, the Alliance Passport Service approves the actions or operations in your request. Operations are defined by service and include things that you can do to a resource, such as reading, creating, editing, and deleting that resource. For example, APS supports several actions for each ABM Record, including the following actions:

  • Create
  • Read
  • Update
  • Delete

To allow an Identity to perform an operation, you must include the necessary actions in a role and then assign to the Identity the Role that grants action access to the affected resource type.

Resources

After the Alliance Passport Service Engine approves the operations in your request, it can be performed on the related ABM Records within the Alliance Business Model. A resource is an object that exists within an Alliance Business Suite instance. Examples include a Financial Account Record in the ABM, an IAM user, and a Storage File. The service defines a set of actions that can be performed on each resource through its exposed API Methods through either the REST Application Programming Interface or a GUI, like the Alliance Business Studio or a Portal. If you create a request to perform an unrelated action on a resource, that request is denied. For example, if you request to delete an IAM role but provide an IAM group resource, the request fails. Please refer to the BusinessPermission tables that identify which resources are affected by an action, see Actions, Resources, and Business Permissions for Alliance Business Suite Resources.

Introduction to Account Holder Entities

An Account Holder is a CredentialsPrincipal for the APS Engine. It represents a human user identified by a username/password. (Unless using some kind of federated identity service like Azure Active Directory, Google, Facebook, Microsoft Identity, etc...)

The "Credentials" aspect of APS Identity and Access Management (IAM) helps you with the question "Who is that user?", often referred to as authentication. Instead of sharing your root user credentials with others, you can create individual Account Holders within your instance that correspond to users in your organization.

In the following figure, the users Sebastien, Fernando, Camila, Alejandro, Ana, and Julianna have been added to a single ABS Instance. Each Account Holder will have their own credentials.

First-time access only: Your root user credentials

When you create an ABS Instance, you create an APS Account Holder root identity, which you will use to sign in to the instance. You can sign in to the ABS Studio and the ABS Portal Admin using this root user identity; that is, the email address and password that you provided when installing the instance. This combination of your email address and password is also called your root user credentials.

When you use your root user credentials, you have complete, unrestricted access to all resources in your ABS instance, including access to your billing and licensing information and the ability to change your password and set multi-factor authentication. This level of access is necessary when you first set up your account. However, we recommend that you don't use root user credentials for everyday access. We especially recommend that you do not share your root user credentials with anyone because doing so gives them unrestricted access to your instance. Only service control policies (SCPs) in tenants can restrict the permissions that are granted to the root user.

We recommend that you create an Account Holder for yourself and then assign yourself administrative permissions for your account. You can then sign in as the new user to add more users and transact over resources as needed.

The following sections explain how you can use APS to create and manage user identity and permissions to provide secure, limited access to your ABS instance, both for yourself and for others who need to work with your ABS instance.

Create an Account Holder

Creating an Account through a local account.


Account Holders are not unrelated records; they are users within your ABS Portals, Contacts within your CRM, Students within your LMS, Account Owners within your Accounting Management Engine, Business Employees within a given Business Tenant, and much more.

Each Account Holder can have their own password for access to the ABS. You can also create an individual access key for each user so that the user can make programmatic requests to work with resources in your account.

By default, ABS Portals are configured to allow Guest Users and Customer Users. These Guest Users are unauthenticated portal visitors granted with a limited set of permissions, like store_read, cart_view, cart_update, while Customer Accounts are allowed for more extensive permissions such as account_read, account_delete, account_update, wallet_read, and others.

If the Enable New User Option is marked to true, Guest Users can quickly create and manage their Account Holder credentials by themselves. The APS Engine is configured to allow local or federated accounts by enabling and configuring additional identity providers such as Google, Facebook, Microsoft, LinkedIn, Twitter, and more.

When creating a local account, you will be asked to verify your email address through a code.

The IAM module contains all the access logic to the Alliance ID account, It is composed of roles capable of assuming a certain set of permissions to act on behalf of a Business Tenant.

image.png

Federating existing users

If the users in your organization already have a way to be authenticated, such as by signing in to your corporate network, you don't have to create separate IAM users for them. Instead, you can federate those user identities into the APS Engine.

Federation is particularly useful in these cases:

Your users already have identities in a corporate directory: If your corporate directory is compatible with Security Assertion Markup Language 2.0 (SAML 2.0), you can configure your corporate directory to provide single-sign-on (SSO) access to the APS Engine for your users. For more information, refer to Common scenarios for temporary credentials.

If your corporate directory is not compatible with SAML 2.0, you can create an identity broker extension to provide single-sign-on (SSO) access to the APS Engine for your users. For more information, see Enabling custom identity broker access into an ABS Instance.

If your corporate directory is Microsoft Active Directory, you can use Azure Active Directory to establish trust between your corporate directory and your ABS instance.

Your users already have Internet identities: If you are creating a mobile app or web-based app that can let users identify themselves through an Internet identity provider like Login with Amazon, Facebook, Google, or any OpenID Connect (OIDC) compatible identity provider, the app can use federation to access ABS resources. For more information, see About web identity federation.

Enabling supported identity providers

To enable an external identity provider into your Alliance Business Suite instance you'll need to use the following topics to configure your instance to use the respective providers:

image.png

Optionally set password

When you register with an external login provider, you don't have a password registered with the app. This alleviates you from creating and remembering a password for the site, but it also makes you dependent on the external login provider. If the external login provider is unavailable, you won't be able to sign in to the website.

To create a password and sign in using your email that you set during the sign-in process with external providers: Select the Hello link at the top-right corner to navigate to the Manage view.

Creating your Alliance ID through an identity provider: (e.g. Amazon, Facebook, LinkedIn, Google...)


If you don’t already have an Alliance ID account, you can get it for free by using those accounts that you already own and use (like your social media accounts). For this matter, you will need to select the identity provider of your choice when you create your Account Holder.

You will need to log in to your Alliance ID account through your chosen identity provider to get access to your account and resources.

Enabled Identity Providers


description: >- To create a new business you will need to be legally authorized to act on the name of that business, as you will need to sign the terms and conditions for our business network on its behalf.

Business Tenant Accounts

Once a user has an Alliance ID account, they will be able to create one or more Business Tenants. There is currently a creation limit of 5 Business Tenants per Alliance ID Holder.

An Alliance ID Holder can request the Alliance support service to raise the tenant quota given the need.

Create a new business account

Prerequisites: In order for you to follow this tutorial, you need to make sure you already own an Alliance ID Account.

How to create a business tenant?

To create a business tenant, login to your Alliance ID Account. Make click on your name and select "My Alliance ID Profile" from the dropdown list. This will take you to you Accounts Principal Page.

Place your mouse on the right-hand side corner of your screen, over your name and you will see a dropdown list containing your authorized businesses. Then, select "Create a business".

This step will take you to the Business Creation Form. Fill the form and make sure that you are legally authorized to act on the name of that business, as you will need to provide documentation to support that claim.

Business creation form. v1.0.0

Note that creating a business can sometimes take a few seconds.

Once your form has been correctly filled, your business' information will be submitted for review, but your business tenant account will be created successfully and your Alliance ID Holder will be added as the root account for that business.

You have now successfully created a business tenant account and only your current Alliance ID Account will be able to select it as root.

Security Roles


When an identity is created it may belong to one or more roles. For example, Daniel may belong to the Administrator and User roles, while Ana may only belong to the User role.

How these roles are created and managed depends on the backing store of the authorization process. Roles are exposed to the developer through the IsInRole method on the IAuthService class.

You can use roles to delegate access to APS Identities like Account Holders, applications, or services that don't normally have access to your ABS resources. For example, you might want to grant users in your Alliance Business Suite instance access to resources they don't usually have, or grant users in one server instance access to resources in another instance. Or you might want to allow a mobile app to use Alliance Business Suite resources, but not want to embed access keys within the app (where they can be difficult to rotate and where users can potentially extract them). Sometimes you want to give access to users who already have identities defined outside of your server instance, such as in your corporate directory. Or, you might want to grant access to your account to third parties so that they can perform an audit on your resources.

For these scenarios, you assign them a Security Role that provides the permissions they need. For example, you can assign roles to allow adding or changing users, resetting user passwords, managing user licenses or managing domain names.

Default Account Holder permissions

In Alliance Passport Services , every Account Holder is granted a set of default permissions. An Account Holder’s access consists of the type of user, their role assignments, and their ownership of individual records. This article describes those default permissions and contains a comparison of the member and guest user defaults. The default user permissions can be changed only in user settings in Alliance Business Studio.

Member and Guest Account Holders

The set of default permissions received depends on whether the user is a native member of the tenant (member user) or if the user is unrelated to the acting tenant or brought over from another tenant as a guest (guest user).

  • Member Account Holders can access the Alliance Business Studio, create and update owned Alliance Business Model records, register applications, manage their own profile photo and mobile phone number, change their own password, and invite guests.

  • Guest users have restricted permissions. They can manage their own profile, view related records, change their own password and retrieve some information about other users, products, groups, and apps, however, they cannot read Alliance Business Model records. For example, guest users cannot enumerate the list of all users, groups, and other directory objects. Guests can be added to administrator roles, which grant them full read and write permissions contained in the role. Guests can also invite other guests.

Security Groups

There are two forms of common security identities in Alliance Passport Services: Account Holders and Business Tenants. These accounts represent an entity (a person or an organization).

Account Holders can also be used as dedicated service accounts for some applications. Security groups are used to collect user accounts, service accounts, and other groups into manageable units.

Security groups can provide an efficient way to assign access to resources on your Alliance Business Suite. By using security groups, you can:

Assign Business Permissions to security groups.

Business Permissions can be assigned to a security group to determine what members of that group can do within the scope of a Business Tenant. Business Permissions are automatically assigned to some security groups when the Alliance Business Suite is installed to help administrators define a person’s administrative role.

For example, a user who is added to the Global Administrators group in Alliance Passport Services has the ability to access the Alliance Business Studio Manager. This is possible because, by default, the Business Permission studio_access is automatically assigned to the Global Administrators group through the "Admin" Security Role being assigned to that group. Therefore, members of this group inherit the Business Permissions that are assigned to that Security Group.

You can use Group Policy to assign user rights to security groups to delegate specific tasks. For more information about using Group Policy, see User Rights Assignment.

Assign Roles to security groups.

Like Business Permissions, Security Roles are assigned to Identities to grant access to certain resources. Business Permissions determine who can access the resource and the level of access, such as Full Control.

A Security Role is a group of permissions that grant access to various levels of access, such as the Account Operators Role or the Domain Admins group. When assigning permissions for resources to a Security Role, administrators assign those permissions to a Security Role rather than to individual users.

The permissions are assigned once to the Security Role, instead of several times to each individual user. Each account that is added to a Security Role receives the Business Permissions that are assigned to that Security Role in Alliance passport Services, and the user receives the permissions that are defined for that group.

Security groups can be assigned with an Email Address so that sending an email message to the group forwards the message to all the members of the group.

Working with Business Permissions

After your request has been authenticated and authorized, the Alliance Passport Service approves the actions or operations in your request. Operations are defined by service and include things that you can do to a resource, such as reading, creating, editing, and deleting that resource. For example, APS supports several actions for each ABM Record, including the following actions:

  • Create
  • Read
  • Update
  • Delete

To allow an Identity to perform an operation, you must include the necessary actions in a role and then assign to the Identity the Role that grants action access to the affected resource type.

Granting Business Permissions

Business Permissions can be assigned to any APS Identity either as a single permission or through a role that contains the specified permission.

Business Permissions can be granted through the Alliance Business Studio on the Security Trail Module.

OAuth 2.0 and OpenID Connect protocols on the Alliance Passport Service

The Alliance Passport Service implements authentication and authorization with industry-standard protocols such as:

  • OpenID Connect (OIDC)
  • OAuth 2.0.

APS offers built-in support for all the standard flows defined by the OAuth 2.0 and OpenID Connect core specifications:

  • Authorization code flow
  • Implicit flow
  • Hybrid flow (which is basically a mix between the first two flows)
  • Resource owner password credentials grant
  • Client credentials grant

The information here will be useful if you choose to write your code by directly sending and handling HTTP requests or using a third-party open-source library, rather than using one of our open-source SDKs.

Note: While the service is standards-compliant, there can be subtle differences between any two implementations of these protocols.

The basics

In nearly all OAuth 2.0 and OpenID Connect flows, there are four parties involved in the exchange:

  • The Authorization Server is the Alliance Passport Service and is responsible for ensuring the user's identity, granting and revoking access to resources, and issuing tokens. The authorization server is also known as the identity provider - it securely handles anything to do with the user's information, their access, and the trust relationships between parties in a flow.
  • The Resource Owner is typically the end-user. It's the party that owns the data and has the power to allow clients to access that data or resource.
  • The OAuth Client is your app, identified by its application ID. The OAuth client is usually the party that the end-user interacts with, and it requests tokens from the authorization server. The client must be granted permission to access the resource by the resource owner.
  • The Resource Server is where the resource or data resides. It trusts the Authorization Server to securely authenticate and authorize the OAuth Client and uses Bearer access tokens to ensure that access to a resource can be granted.

App registration

Every app that wants to connect to the Alliance Passport Service must be registered through the App registrations experience in the Alliance Business Studio before it can sign these users in using OAuth 2.0 or OpenID Connect. The app registration process will collect and assign a few values to your app:

  • An Application ID that uniquely identifies your app
  • A Redirect URI (optional) that can be used to direct responses back to your app
  • A few other scenario-specific values.

For more details, learn how to register an app.

Endpoints

Once registered, the app communicates with the Alliance Passport Service by sending requests to the endpoint:

Service ProviderEndpoints
ABS Onlinehttps://fenix-alliance.com/connect/authorize
https://fenix-alliance.com/connect/token
ABS Serverhttps://{server-endpoint}/connect/authorize
https://{server-endpoint}/connect/token

Tokens

OAuth 2.0 and OpenID Connect make extensive use of bearer tokens, generally represented as JWTs (JSON Web Tokens). A bearer token is a lightweight security token that grants the "bearer" access to a protected resource. In this sense, the "bearer" is anyone that gets a copy of the token. Though a party must first authenticate with the Alliance Passport Service to receive the bearer token, if the required steps are not taken to secure the token in transmission and storage, it can be intercepted and used by an unintended party.

While some security tokens have a built-in mechanism for preventing unauthorized parties from using them, bearer tokens do not have this mechanism and must be transported in a secure channel such as transport layer security (HTTPS). If a bearer token is transmitted over plain HTTP, a malicious party can use a man-in-the-middle attack to acquire the token and use it for unauthorized access to a protected resource.

The same security principles apply when storing or caching bearer tokens for later use. Always ensure that your app transmits and stores bearer tokens in a secure manner. For more security considerations on bearer tokens, see RFC 6750 Section 5.

There are primarily 3 types of tokens used in OAuth 2.0 / OIDC:

  • Access tokens - tokens that a resource server receives from a client, containing permissions the client has been granted.
  • ID tokens - tokens that a client receives from the authorization server, used to sign in a user and get basic information about them.
  • Refresh tokens - used by a client to get new access and ID tokens over time. These are opaque strings and are only understandable by the authorization server.

External resources

Alliance Business Platform (ABP)


The Alliance Business Platform is a Modular Application Framework built on .NET with the best of REST, SignalR, GraphQl y gRPC capabilities and it's built on top of the the Alliance Business Model Schema (ABM).

The Alliance Business Platform is also a Mobile Backend framework for integrating next-generation functionalities into your mobile applications.

It allows you to build spectacular single-page apps using .NET and C# with or without JavaScript. ABP apps can connect and transact to the data layer (The Alliance Business Modal Schema) using any language through standard requests through the various GrPC, HTTP, and GraphQL Endpoints.

The Alliance Business Platform provides a unified programmability model that you can use to build apps for organizations and consumers that interact with the data on the Alliance Business Model.

You can use the Alliance Business Platform APIs to access data stored on your Alliance Business Model, scoped to any given Business Tenants; Explore our documentation to learn more about how to use Fenix Alliance's ABP APIs.

Anyone can build on and extend The Alliance Business Platform through ASP.NET + Angular / React (And pretty much any Framework), to capture additional business-specific scenarios.

Explorers

The Alliance Business Platform integrates a comprehensive API Specification for every HTTP, GrapghQL or gRPC request that's available on every Alliance Business Suite instance. These specifications follow well stablished standards to give customers the flexibility and support required to extend the system with their own custom functionalities to easily build breathtaking business applications.

API Explorers

HTTP

  • https://{yourinstancedomain}/api/v2/documentation

GraphQL

  • https://{yourinstancedomain}/api/v3/playground
  • https://{yourinstancedomain}/api/v3/voyager
  • https://{yourinstancedomain}/api/v3/GraphiQL

Security

The Alliance Business Platform provides many tools and solutions to secure your apps including built-in identity providers, third-party identity services interoperability (such as Facebook, Twitter, LinkedIn, Google and More).

With Alliance Business Platform, you can easily manage app secrets, which are a way to store and use confidential information and it also provides protection against common vulnerabilities in software to help you secure your apps and prevent security breaches. The following list of techniques are forecefuly prevented to avoid the most common security vulnerabilities in web apps:

  • Cross-Site Scripting (XSS) attacks
  • SQL injection attacks
  • Cross-Site Request Forgery (XSRF/CSRF) attacks
  • Open redirect attacks

You should be aware there are more vulnerabilities that you should be aware of. For more information on tooling and further considerations, see the other articles in the Security and Identity sections of the table of contents.

Extensibility

You can extend the Alliance Business platform through Modules, which are nothing more than Razor Class Libraries built with or without the use of the Alliance Business Suite's SDK.

Welcome to the Alliance Business Platform REST API reference for the v2.0 endpoint.

[[TOC]]

API sets on the ABS REST endpoint v2.0 are in general availability (GA) status, and have gone through a review-and-feedback process with customers to meet practical, production needs. Updates to APIs on this endpoint are additive in nature and do not break existing app scenarios.

Representational State Transfer (REST) APIs are service endpoints that support sets of HTTP operations (methods), which provide create, retrieve, update, or delete access to the service's resources. This section will give you an overall overview of processes like:

  • How to call ABP REST APIs with Postman, CURL and the Powershell SDK.
  • Common use cases for the ABP REST API.
  • The basic components of a REST API request/response pair.
  • How to register your client application with ABP Identity and access management (IAM) to secure your REST requests.
  • Overviews of creating and sending a REST request, and handling the response.
  • Additional resources about versioning and support contact information.

How to call the ABP REST APIs with Postman

The following video will show you how to quickly authenticate with the ABP REST API Authentication Endpoints via the client id/secret method. We encourage you to continue reading below to learn about what constitutes a REST operation, but if you need to quickly call the APIs, this video is for you.

// TODO: ADD Video explaining Postman process.
// TODO: ADD Video explaining CURL process.
// TODO: ADD Video explaining Powershell SDK process.

Available Endpoint Sets - REST API Reference Browser

The Alliance Business Platform REST API has been decoupled into modular, consumable REST Endpoint Sets as follows:

The ABP REST API Browser – is a tool to allow internal and external developers to get the most out of the REST APIs from Fenix Alliance. If you have any feedback, create a new issue in the FenixAlliance/feedback repo on GitHub.

OData Support

OData (Open Data Protocol) is an ISO/IEC approved, OASIS standard that defines a set of best practices for building and consuming REST APIs. It enables creation of REST-based services which allow resources identified using Uniform Resource Locators (URLs) and defined in a data model, to be published and edited by Web clients using simple HTTP messages.

OData is fully integrated ont the Alliance Business Platform to help developers to focus on business logic without worrying about the various API approaches to define request and response headers, status codes, HTTP methods, URL conventions, media types, payload formats, query options, etc. It provides guidance for tracking changes, defining functions/actions for reusable procedures, and sending asynchronous/batch requests.

About the OData Protocol

The OData Protocol is an application-level protocol for interacting with data via RESTful interfaces. It supports the description of data models, editing and querying of data according to those models. REST APIs that are based on OData are easy to discover and consume due to the OData metadata, a machine-readable description of the data model which renders in a human readable format and enables the creation of powerful generic client proxies and tools.

OData improves semantic interoperability between systems and follows these design principles:

  • Follow REST principles.
  • Keep it simple. Address the common cases and provide extensibility where necessary.
  • Build incrementally. A very basic, compliant service should be easy to build, with additional work necessary only to support additional capabilities.
  • Extensibility is important. Services should be able to support extended functionality without breaking clients unaware of those extensions.
  • Prefer mechanisms that work on a variety of data sources. In particular, do not assume a relational data model.

The OData Protocol is different from other REST-based web service approaches in that it provides a uniform way to describe both the data and the data model. This improves semantic interoperability between systems and allows an ecosystem to emerge. It follows these design principles:

Common use cases

The power of the Alliance Business Platform REST API Engine lies in being able to easily extend the Alliance Business Suite across different business-cases through services exposed on several REST endpoints.

A number of these services are designed to enable rich scenarios around Alliance ID Tenants and around Business Contexts.

User-centric use cases in v2.0

  1. Get the profile and photo of Anna, an Alliance ID Holder.
  2. Get the profile information about Anna's Business Enrollments (BPRs) and IDs of her direct relations.
  3. Access Anna's files on Alliance ID User Storage, find the identity of the last person who modified a file on Anna's enrolled businesses, and navigate to that person's social profile.
  4. Access Anna's follows and followers on the Alliance ID Network, get information and manage their relationships and navigate to their profile endpoint.
  5. Manage Subscriptions and communication options and track changes in Anna's change-log.
  6. Set automatic replies and social statuses when Lisa is away from the office.
  7. Get the people who are most relevant to Lisa, based on communication, collaboration, social activity, and business relationships.
  8. Get Anna's projects and assigned tasks.
  9. Get Anna's cart status, place and manage products, services, and cloud resource orders.
  10. Navigate through Anna's wallet endpoints, which allow developers to extend their Anna's experience and easily conduct transactions directly trough their Alliance ID Wallet's secure federated payment capabilities.
  11. Get Anna's notifications and filter the output through query parameters.
  12. Set automatic reminder's on Anna's calendar. (Soon at Winter Update)

Business use cases in v2.0

  1. Run a report on an organization Anna belongs to and identify the group with the most communication among group members.
  2. Run a report on the amounts of unpaid invoices, filtering through data using OData (Open Data Protocol).

Other API versions

There are currently 2 versions of the Alliance ID REST APIs - v2.0 and v2.1 (still in beta). Be aware that APIs in beta status is subject to change, and may break existing scenarios without notice. Don't take a production dependency on APIs in the beta endpoint. Be aware that V1.x endpoints and SDKs were deprecated as of 31/12/2015 and are no longer functional.

Find more information about versioning and support.

Connect with us

Are there additional APIs or features you'd like to see in the AiD API? Post new feature requests on UserVoice.

Have feedback for existing Fenix Alliance API Endpoints? Connect with us on Github.

Working with the Alliance Business Suite SDK

This topic provides information about where you can download the developer tools, assemblies, and code samples that are shipped as part of the Software Development Kit (SDK) for the Alliance Business Suite.

SDK assemblies

The SDK assemblies are available as NuGet packages that you can directly use in your Visual Studio projects. For information about using a NuGet package in Visual Studio, see Install and use a package in Visual Studio

The following SDK assemblies are available:

Package NameTop AssemblyPackage Location
FenixAllaince.ABS.SDKFenixAllaince.ABS.SDK.dllhttps://www.nuget.org/packages/FenixAlliance.ABS.SDK/
FenixAllaince.ABP.SDKFenixAllaince.ABP.SDK.dllhttps://www.nuget.org/packages/FenixAlliance.ABP.SDK/
FenixAllaince.APS.SDKFenixAllaince.APS.SDK.dllhttps://www.nuget.org/packages/FenixAlliance.APS.SDK/
FenixAllaince.ABM.SDKFenixAllaince.ABM.SDK.dllhttps://www.nuget.org/packages/FenixAlliance.ABM.SDK/

Using the Alliance Business Suite SDK.

The Alliance Business Suite SDK provides several interfaces and default implementations designed to speed up business application development. By leveraging the SDK, developers can create outstanding personalized experiences for their customers, employees, providers, and more.

Although it is possible to combine programming models, the first step towards developing Alliance Business Suite Applications/Extensions is to decide the Programming Model to use.

Note: Alliance business Suite Applications/Extensions can be created using .NET or Node.js. This article focuses on the ABS SDK for .NET. As of version 1.2.x, the ABS SDK for Node.js hasn't been published, and requests have to be performed against the Alliance Business Platform Web APIs.

By using .NET and Visual Studio and the ABS SDK for .NET, developers can easily create extensions either by using ASP.NET MVC or Blazor to cover specific business needs while leveraging the power of C# and the Alliance Business Suite.

Overriding Default Service Implementations.

Customers can also use the Alliance Business Suite to override the default Interface Implementations present on every Alliance Business Suite instance. To do so, just implement the desired interface and register it as a Service Override on the ConfigureServices method present on the IModule Interface.

Alliance Business Studio (ABS Studio)


The Alliance Business Studio is the Graphical Administration Engine for the Alliance Business Suite. It allows users to manage their instances, transact data, generate and consume views, reports, customize and extend the system, and much more.

We're building the Alliance Business Studio to help you manage your entire Alliance Business Suite trough an intuitive, user-friendly interface designed to increase your productivity by using cutting-edge technologies such as Blazor on .NET, allowing us to deliver bazing-fast functionalities.

Accessing the Studio

The Alliance Business Studio can be used by navigating to the /Studio route on an existing Alliance Business Suite installation. To access the Alliance Business Studio, Account Holders are required to, at least, have the studio_access permission.

By default, business tenant administrators can access the studio independently of whether or not they have the studio_access permission.

We recommend customers to enforce Multi-Factor Authentication on Administrator Accounts to increase security on privileged account holders.

Extending the Studio

The Alliance Business Studio is built on top of the Alliance Business platform and extends it's functionality through pluggable modules and integrations. In fact, the Alliance Business Studio itself is an Alliance Business Platform Module.

Modules can be hooked to the Alliance Business Studio to allow instance owners to interact with data and functionalities exposed by such module. This is convenient for developers looking to extend the Alliance Business Platform as it provides a clean interface and thousands of ready to use UI components and tools to create data-driven business applications.

Working with Alliance Business Suite Portals

The Alliance Business Suite contains the tools and resources you need to create customer-facing business applications such as websites, intranets & extranets, content delivery platforms, service administration dashboards, and much more.

ABS Portals can use any number of NuGet/npm libraries as well as any UI Framework such as Blazor, ASP.NET, Bootstrap, Angular, VUE.js, React + Redux to create spectacular experiences for business users built on top of your line of business applications.

Use cases for Alliance Business Suite Portals

Is exists a virtually infinite number of use cases for the Alliance Business Suite Portals. Portals are designed to provide basic (yet extremely powerful) building blocks for your business applications. These building blocks are known as the Alliance Business Suite Components, and they work together to provide you with a fluent development experience when creating internet-exposed applications that directly connect to your internal systems such as your CRM & ERP Solutions.

Understanding the IPortalContext Interface

A Portal is just a .NET Razor Class Library containing the views and services required by that portal to work properly. Portals extend the Alliance Business Suite to allow you to run multiple portals off a single Alliance Business Suite instance.

This makes it possible to control a network of portals (MultiPortal Network) under a single Alliance Business Studio dashboard. You can manage everything including the number of sites, businesses, users, features, themes, and more. It is possible to manage hundreds, thousands, and (theoretically) millions of sites that extend or modify the behavior of any Component, Module, or Integration.

The best example of a MultiPortal Alliance Business Suite Network is fenix-alliance.com, which hosts Fenix Alliance's services such as Alliance Pay Platform, Infinity Comex, Propietarios.net, Alliance Business Cloud, and many more.

Portals can start taking advantage of the Alliance Business Suite components just by injecting and initializing an instance of the IPortalContext interface. This interface contains an abstraction for several methods user Authentication/Authorization, Business Tenant Routing, Forex Services, eCommerce & Wallet Management, as well as Social Profile Data for internal B2B, B2C, C2C networks.

Injecting and Initializing an IPortalContext Instance

The Alliance Business Suite comes with a default implementation of the IPortalContext Interface whose instance can easily be obtained as a Scoped Service through Dependency Injection.

File _Imports.razor:

@inject IPortalContext PortalContext

File Layout.razor:

@inherits LayoutComponentBase
<CascadingValue Value="this">

    @if (PortalContextis not null && PortalContext.Ready)
    {
        @Body
    }

</CascadingValue>

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    protected override async Task OnInitializedAsync()
    {
        PortalContext.Layout = this;

        var User = (await authenticationStateTask).User;

        await PortalContext.Init(User, NavManager, JS);
        this.StateHasChanged();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {

        }
    }

    public async Task RefreshLayout(string BusinessID)
    {
        this.StateHasChanged();
    }


    public async Task CallStateHasChanged()
    {
        this.StateHasChanged();
    }

}

Use the Alliance Business Pocket as a Mobile Application Framework (Experimental)

Alliance Business Suite Mobile Apps is a set of client and server libraries aimed to create mobile/desktop applications that integrate to the Alliance Business Suite using Blazor on .NET MAUI.

Currently, we support:

  • .NET + Blazor on the server-side (for security)
  • .NET MAUI + Blazor Client-side (Access to Native APIs)

General Services Overview

The Alliance Business Suite provides a wide set of functionalities wrapped as services specially designed to provide our customers with enterprise-class capabilities for common business processes in small and mid-sized companies across industries, enabling them to manage more complex processes, such as assembly, manufacturing, service, and warehouse management.

Default Services Manifest

Working with the BlockChains Service on the Alliance Business Suite.

Built-in to the Alliance Business Platform is the ability to connect your business applications to both public/private Ethereum nodes while simplifying smart contract management and interaction with nodes like Geth, Parity, Quorum, Besu, and more.

Features

  • [New, Alpha] NFTs Support.
  • ABS Wallet Service integration.
  • HD Wallet creation and management.
  • Alliance Business Model integration.
  • JSON RPC / IPC Ethereum core methods.
  • Geth management API (admin, personal, debugging, miner).
  • Parity management API.
  • Quorum integration.
  • Besu integration.
  • Simplified smart contract interaction for deployment, function calling, transaction, and event filtering and decoding of topics.
  • Blockchain processing.
  • ABI to .Net type encoding and decoding, including attribute-based for complex object deserialisation (nethereum-abi-encoding.md).
  • Rules engine.
  • HD Wallet integration.
  • Transaction, RLP, and message signing, verification, and recovery of accounts.
  • Integrated TestRPC testing to simplify TDD and BDD (Specflow) development.
  • Key storage using Web3 storage standard, compatible with Geth and Parity.
  • Simplified account life cycle for both managed by a third-party client (personal) or stand-alone (signed transactions).
  • Low-level Interception of RPC calls.
  • Code generation of smart contracts services.

Roadmap

The following features are to be expected in the near future:

  • ABS SDK Support.
  • Smart Contract Management Pages.
  • Unity 3D Integration (ABS SDK).

Working with Smart Contract Support

We are currently working to provide a complete Smart Contract management experience for the Alliance Business Suite. As of now, Smart Contracts should be created and deployed outside the Alliance Business Suite, and then imported as a Contract Address to be exposed to the BlockChains Service.

Working with NFT Support

NFT stands for non-fungible token. This quote from ethereum.org explains it well:

"NFTs are tokens that we can use to represent ownership of unique items. They let us tokenize things like art, collectibles, even real estate. They can only have one official owner at a time and they're secured by the Ethereum blockchain – no one can modify the record of ownership or copy/paste a new NFT into existence."

What is an NFT standard or ERC-721?

The ERC-721 is the most common NFT standard. If your Smart Contract implements certain standardized API methods, it can be called an ERC-721 Non-Fungible Token Contract.

These methods are specified in the EIP-721. Open-sourced projects like OpenZeppelin have simplified the development process by implementing the most common ERC standards as a reusable library.

Minting NFTs

"Minting an NFT" is the act of publishing a unique instance of your ERC721 token on the blockchain.

By minting an NFT, you publish a unique token on a blockchain. This token is an instance of your Smart Contract.

Each token has a unique token URI, which contains metadata of your asset in a JSON file that conforms to a certain schema. The metadata is where you store information about your NFT, such as name, image, description, and other attributes.

An example of the JSON file for the "ERC721 Metadata Schema" looks like this:

{
	"attributes": [
		{
			"trait_type": "Shape",
			"value": "Circle"
		},
		{
			"trait_type": "Mood",
			"value": "Sad"
		}
	],
	"description": "A sad circle.",
	"image": "https://i.imgur.com/Qkw9N0A.jpeg",
	"name": "Sad Circle"
}

How is NFT's metadata stored?

There are three main ways to store an NFT's metadata.

First, store the information on-chain. In other words, you can extend your ERC-721 and store the metadata on a blockchain, which can be costly.

The second method is to use IPFS. And the third way is to simply have your API return the JSON file.

The Alliance Business Suite can use a combination of these methods when creating NFTs, preventing actors to temper the underlying JSON file.

How to View the NFT in your Metamask Wallet

You need to start by downloading the mobile version of Metamask. Then, log into your account.

Your Wallet Account should be connected to MetaMask to view your NFTs, and the network should point to the main network configured on your Alliance Business Suite's settings.

You should see an NFTs tab along with an add NFT button. Click on the button and enter the address of your Smart Contract along with the ids that you have minted.

IMG_0376

Multi-Tenancy Service

The Alliance Business Suite isolates into business tenants a set of functionalities such as data access, web portals scoping, record scoping, user enrollment, among others, to allow several businesses to live into the same Alliance Business Suite server. These capabilities also enable customers to create multi-business experiences such as marketplaces, social networks, and more!

Multi-Currency Functionality

Built-in to the very heart of the Alliance Business Suite is the capability of managing multi-currency operations with live and historical foreign exchange data. The powerful Forex Service is designed to help businesses who manage operations in multiple currencies, giving them the ability to introduce amounts any currency for records such as products, invoices, payments, and more, even accounting records, while still being able to perfectly balance financial statements and accounting reports, displaying records on each user's favorite currency and even creating multi-currency or even multi-national fintech portal capabilities.

Multi-Currency is extremely powerful given its inner behavior: it converts each amount into United States Dollars and takes a snapshot of live forex exchange data on each record upsert. This forex snapshot might or might not be bound to a particular day, and might be regularly updated for the purpose of displaying up to date currency conversions, met the following criteria:

  • Forex Shapshots on Accounting Records such as Invoices, Payments, Account Records, Ledger Records and more won´t be updated unless explicitly requested by a user with "invoice_manage" permission.
  • Forex Snapshots on Sales & Logistics Records such as Deal Units, Stock Items (Courses, Licenses, Products, Services, Subscriptions, etc.) will be kept up to date with the latest Forex Exchange data for the purpose of allowing businesses to keep their prices up to date with the current exchange rate, regarding the currency they've selected to input any given financial amount.

Understanding the Alliance Business Suite Pricing Service

Pricing is an important part of every business. Commonly, pricing presents challenges such as keeping up to date with provider price updates, calculating discounts, surcharges, taxes, shipping costs, profit margins, and more. This turns pricing into a complex process when a business trades with several commodities, goods, and services.

The Pricing Service is a middleware service designed to calculate prices based on several criteria that can be automated and applied to every Item. It takes a snapshot of the appropriate Forex Exchange Data (Live or Stored, depending on preferences) and it converts values to United States Dollars. This snapshot is linked with each record to ensure proper recalculation of exchanged values for the purpose of accounting balances and reports.

How is calculated the price of an Item?

When you create or update an Item using the Logistics Module, you will be asked to provide the Regular Price of an Item, as well as the currency you are providing this value in. The Regular Price refers to the price it takes for your business to acquire or manufacture a product or a service. This value is commonly known as the Cost of Goods (COG).

This value will be used as the base amount for the calculations ahead.

Understanding Policy-Based Calculations

The Alliance Business Model provides a convenient structure to help businesses to overcome the complexity of the Pricing Process. It contains Policies that can be applied to each Item to automatically calculate the final pricing amounts of each item.

Pricing Amounts

Calculated Item Price without Discounts, Surcharges nor Policies. Identical to Regular Price.

Calculated Total Discounts Amount. It's calculated depending on the On Discount Flag; if checked, logic will cascade to assert if the discount is either a Fixed Discount or not, (in which case it will be a percentual discount, which is the default behavior)

If the Fixed Discount flag is marked, you will need to enter the discounted amount in the same currency you've selected for the Regular Price, so be subtracted from the Regular Price, otherwise, you will need to input a percentage to be subtracted off the Regular Price.

Once the discounts have been applied, the Price After Discounts value is generated and passed to the following calculation step as the base for the Surcharges Calculation.

It refers to the Calculated Total Surcharges Amount.

It is calculated by receiving the Price After Discounts value from the previous step and applying first every default Pricing Rule Policy registered to the Passing Item's Owner and then every Pricing Rule Policy registered to the passing Item.

Calculated Total Profit Amount It is calculated by receiving the Price After Surcharges value from the previous step and applying first every default Selling Margin Policy registered to the Passing Item's Owner, and then Selling Margin Policy registered to the Passing Item.

Calculated Total Return Cost Amount

It is calculated by receiving the Price After Profit value from the previous step and applying first every default Return Policy registered to the Passing Item's Owner, and then every Return Policy registered to the Passing Item.

Calculated Total Refund Cost Amount

It is calculated by receiving the Price After Return Policies value from the previous step and applying first every default Refund Policy registered to the Passing Item's Owner, and then every Return Policy registered to the Passing Item.

Calculated Total Warranty Cost Amount

It is calculated by receiving the Price After Refund Policies value from the previous step and applying first every default Warranty Policy registered to the Passing Item's Owner, and then every Warranty Policy registered to the Passing Item.

Calculated Total Taxes Amount

It is calculated by receiving the Price After Warranty Policies value from the previous step and applying first every default Tax Policy registered to the Passing Item's Owner, and then every Tax Policy registered to the Passing Item.

Calculated Total Withholding Taxes Amount It is calculated at the Order & Invoice Level.

Calculated Total Shipping Cost Amount

It is calculated at the Order & Invoice Level.

Calculated Total Shipping Taxes Amount

It is calculated at the Order & Invoice Level.

Calculated Total Price Amount (Revenue)

It is calculated by the following Formula:

Detail Amount: Da

Discounts Amount: D

Surcharges Amount: S

Profit Amount: P

Total Taxes Amount: TT

Total Withholding Taxes Amount: TWT

Total Warranty Cost Amount: TWC

Total Refund Cost Amount: TRfC

Total Return Cost Amount: TRtC

Total Shipping Cost Amount: SC

Total Shipping Tax Amount: ST

Total Amount: (Da - D) + S + P + (TT - TWT) + (SC + ST) + TRfC + TRtC + TWC

Working with the Wallets Service on the Alliance Business Suite

Wallets across the Alliance Business Suite are designed to serve several purposes depending on the server's configuration.

At a high level, Wallets are accounts are related to an Account Holder or a Contact Record. These accounts are then used to create a unified network where transactions are possible in any direction within these three types of records.

Wallet Accounts serve the purpose of storing and transacting value across said networks, enabling customers to easily create commercial and financial services ready to grow and scale.

Wallet accounts are also related to an Accounting Account, which is a group of accounting records used to produce Accounting and Financial Reports.

Transactions across Wallets

Transactions across Wallets serve the purpose of transferring value amounts across the network. On each transaction, there are at least two Wallet Accounts involved. A transaction starts with a Wallet Owner (either an Account Holder, a Business Tenant, or a Contact Record) defining an amount and a destination account registered to their wallet.

Upon proper Waller Decryption (which might require re-authentication), the transaction will be processed and signed by the Alliance Business Platform using dynamically generated signing keys.

Multi-Currency Support

Because of the Alliance Business Suite's multi-currency capability, transactions across wallets are made on United States Dollars, but transaction amounts and logs are always historically exchanged using conversion rate snapshots to display and balance the exact conversion rates as of the Transaction's timestamp.

This is convenient for accounting purposes as well as to provide a great experience to end-users, allowing them to input and view amounts on their preferred currency without having to perform any conversions themselves.

Understanding Contact Wallets

Contact Wallets are Regular Wallet Accounts that instead of being related to an Account Holder or a Business Tenant, are related to a Contact Record on the CRM Section of the Alliance Business Model.

This might seem odd, given that to either a B2B or a B2C Scenario, only two types of wallets are required: A Business-Related Wallet and a Customer-Related Wallet. So, what's the purpose of Contact Wallets?

Like Social Profiles, Contact Wallets are designed to Allow Customers to create their own multi-tenant business applications through the Wallet services on top of the Alliance Business Suite, simplifying the process of creating Financial Applications ready for Web 3.0.

Understanding CryptoWallets

CryptoWallets is the name of the functionality that allows each Wallet Account to interact with any number of BlockChains. Each Waller Account is assigned by the Alliance Business platform with an Ethereum Address. This Ethereum Address uniquely identifies a Wallet Account across any ABS BlockChain. This enables customers to create services such as crypto-currencies and exchanges, NFT marketplaces, apps (distributed/decentralized applications), and even their own Web 3.0 & metaverse-enabled experiences.

Connecting a Wallet to MetaMask

Through the Alliance Business Studio, Wallet Owners can connect their Wallet Accounts to MetaMask. To do this, head to the wallet configuration and click on the "Connect to MetaMask" button, then open MetaMask on your browser toolbar, click on your avatar and select "Import Account".

Copy your Wallet's Private Key and paste it into Metamask, or scan the QR Code using MetaMask Mobile.

Once your Wallet Identifier has been linked to MetaMask, click on the "Finish Connection" button to finalize the synchronization.

Troubleshooting Wallets

Descripción:

Identity and Access Manager

The ABP Identity and Access Manager (IAM) enables you to manage access to Business Tenant services and resources securely. Using IAM, you can create and manage ABP users and groups, and use permissions to allow and deny their access to Tenant owned resources.

IAM is a feature of the Alliance Passport Service offered at no additional charge. You will be charged only for use of other ABS services consumed by your users or ABP Services consumed by your applications.

To get started using IAM you will need to have administrator access over a Business Tenant. If you have already registered a Business Tenant, go to the Alliance Business Studio and get started with these IAM Best Practices.

ABP IAM has a list of best practices to help Alliance ID Holders to manage access to Business Tenant resources.

  • Users – Create individual users.
  • Groups – Manage permissions with groups.
  • Permissions – Grant least privilege.
  • Auditing – Turn on ABS SecTrail.
  • Password – Configure a strong password policy.
  • MFA – Enable MFA for privileged users.
  • Roles – Use IAM roles for custom integrations.
  • Sharing – Use IAM roles to share access.
  • Rotate – Rotate security credentials regularly.
  • Conditions – Restrict privileged access further with conditions.
  • Rooting – Reduce or remove the use of overprivileged users.

Use cases

Fine-grained access control to ABP resources

IAM enables your users to control access to ABP service APIs and to specific resources. IAM also enables you to add specific conditions such as time of day to control how a user can use ABP, their originating IP address, whether they are using SSL, or whether they have authenticated with a multi-factor authentication device.

Multi-factor authentication for highly privileged users

Protect your ABP environment by using ABP MFA, a security feature available at no extra cost that augments user name and password credentials. MFA requires users to prove physical possession of a hardware MFA token or MFA-enabled mobile device by providing a valid MFA code.

Analyze access

IAM helps you analyze access across your ABP environment. Your security teams and administrators can quickly validate that your policies only provide the intended public and cross-account access to your resources. You can also easily identify and refine your policies to allow access to only the services being used. This helps you to better adhere to the principle of least privilege.

Integrate with your corporate directory

IAM can be used to grant your employees and applications federated access to the ABP Management Console and ABP service APIs, using your existing identity systems such as Microsoft Active Directory. You can use any identity management solution that supports SAML 2.0, or feel free to use one of our federation samples (ABP Console SSO or API federation).

How it works

IAM assists in creating roles and permissions ABP IAM allows you to:

  • Manage IAM users and their access – You can create users in IAM, assign them individual security credentials (in other words, access keys, passwords, and multi-factor authentication devices), or request temporary security credentials to provide users access to ABP services and resources. You can manage permissions in order to control which operations a user can perform.

  • Manage IAM roles and their permissions – You can create roles in IAM and manage permissions to control which operations can be performed by the entity, or ABP service, that assumes the role. You can also define which entity is allowed to assume the role. In addition, you can use service-linked roles to delegate permissions to ABP services that create and manage ABP resources on your behalf.

  • Manage federated users and their permissions – You can enable identity federation to allow existing identities (users, groups, and roles) in your enterprise to access the ABP Management Console, call ABP APIs, and access resources, without the need to create an IAM user for each identity. Use any identity management solution that supports SAML 2.0, or use one of our federation samples (ABP Console SSO or API federation).

Get started with ABP IAM

Step 1 - Sign up for an Alliance ID account

Step 2 - Explore and learn with simple tutorials by instantly get access to the ABS Free Tier.

Step 3 - Accelerate, build and expand your business while taking advantage of being a part of our global Alliance Network.

What Is a Ledger Account?

The ledger account contains a listing of business transaction records. It is a separate record a ledger that is assigned to a specific asset, liability, equity item, revenue type, or expense type.

Here are the primary general ledger accounts:

  • Asset accounts
  • Liability accounts
  • Stockholders’ equity accounts
  • Revenue accounts
  • Expense accounts
  • Revenue and loss accounts

Transactions are recorded throughout the year by debiting and crediting ledger accounts. The transactions are caused by normal business activities such as billing customers or through adjusting entries.

How to write to a Ledger?

The Alliance Business Suite Accounting Module uses the double-entry bookkeeping method. So writing to a ledger means recording transactions into it. Each transaction is recorded into at least two ledger accounts. The entries have debit as well as credit transactions and are posted in two columns.

The Alliance Business Suite Accounting Module exposes a general ledger to each business tenant in the system. This ledger employs the double-entry bookkeeping method, which means that each financial transaction affects at least two general ledger accounts and each entry has a debit and a credit transaction. Double-entry transactions are posted in two columns, with debit postings on the left and credit entries on the right, and the total of all debit and credit entries must balance before recording the transaction.

Ledgers break up the financial information from the journals into specific accounts such as Cash, Accounts Receivable, and Sales, on their own sheets. This allows you to see the details of all your transactions.

What’s the Difference Between a Journal and a Ledger?

The journal and ledger both play an important role in the accounting process. The business transactions are primarily recorded in the journal and thereafter posted into the ledger under respective heads. While many financial transactions are posted in both the journal and ledger, there are significant differences in the purpose and function of each of these accounting books.

MEANING

The financial transactions are summarized and recorded as per the double-entry system in a journal. It’s also known as the primary book of accounting or the book of original entry.

The ledger, on the other hand, is known as the principal book of accounting. It records the information from the journal in the “T” format. It is used to create the trial balance which is also the source of the financial statements such as the income statement and the balance sheet

RECORDING TRANSACTIONS

The process of recording transactions in a journal is called journalizing while the process of transferring the entries from the journal to the ledger is known as posting.

The transactions in a journal are recorded in chronological order making it easy to identify the transactions are associated with a given business day, week, or another billing period. By contrast, the arrangement of entries within a ledger has more to do with grouping like transactions together into specific accounts for purposes of assessing the data for internal financial and accounting purposes.

FORMAT

The format of a journal is simple. It includes the transaction date, particulars of the transaction, folio number, debit amount, and credit amount. There is no scope for balancing in a journal.

The format of a journal:

DateParticularsL.F.DebitCredit
Transaction dateAccount title and detailsLedger folio numberAmt.Amt.

The ledger uses the “T” format where the date, particulars, and amount are recorded on each side.

The format of a ledger:

DateParticularsFolio NumberAmountDateParticularsFolio NumberAmount
Transaction dateAccount nameAmt.Transaction dateAccount nameAmt.

Unlike a journal, some ledger accounts start with an opening balance that is the closing balance of the previous year. Also, in the end, the ledger amounts should be balanced.

Preparing a ledger is important as it serves as a master document for all your financial transactions. Since it reports revenue and expenses in real-time, it can help you stay on top of your spending. The general ledger also helps you compile a trial balance, spot unusual transactions, and aids in the creation of financial statements.

Managing the Billing Process

The Alliance Business Model contains records to store sales and billing information. Billing records establish a cascading flow designed to suit the business process of any given business around the world.

The Alliance Business Suite | Accounting Module contains several tools built to help customers to harness the power of the Alliance Business Model by adding several Platform API Endpoints and Studio Views to the Alliance Business Suite, enabling customers to:

  • Outline Billing Records using Logistics and Sales Data.
  • Relate Billing Records to Holders, Accounts, Contacts, and more.
  • Expose Billing Records into Web Portals.
  • Interoperate with ABS E-Commerce stores.
  • Connect several payment gateways.

Note: Deal Units belong to the Sales Scope and can be managed on the Sales Manager Module.

SalesPlusBilling.jpg

Managing Orders on Account Manager

Working with Invoices on Accounting Manager.

When a Contact places an order, you can create an invoice to bill them for the upcoming sale.

Creating Invoices

Typically, you convert an order into an invoice; however, you can also create an invoice that does not originate from an order. To create an Invoice, you can either navigate to your sales orders, select an existing Order and create an Invoice from it, or you can also create a new invoice that's not related to any order by navigating to Accounting > Billing > Invoices > Create.

Assigning Invoices to Contacts

As an Accounting Record, Invoices can be related to any Individual/Organization (or both) present on your Contact Sight CRM. To assign an Invoice to a Contact, simply select it from the dropdown list when outlining your new invoice.

Remarks: By default, every Individual/Organization on your CRM will be available to be selected as the owner for an Invoice; however, when you select an Individual, the Organizations Dropdown List will be filtered to display only those organizations that are somehow related to the selected Individual. Likewise, if you select an Organization first, the Individuals Dropdown List will be filtered to display only those Individuals that are somehow related to the selected Organization.

Assigning Invoices to Identities

You can also decide whether or not to relate an identity to your invoices. Identities such as Account Holders or Business Tenants are users within the Alliance Business Model which can access business applications built with Alliance Business Suite.

When you select an Individual as the Owner for an Invoice, you will be able to select its related Account Holder if you want your invoice to be available through the Studio/API for that particular user. Likewise, when you select an Organization as the owner for your invoice, its related Business Tenant will become available on the Business Dropdown to be selected. (See Contact Relations)

Adding Invoice Lines

One of our goals is to make it as easy and intuitive as possible to outline Invoices, Debit Notes & Credit Notes. To add an invoice Line, click on the Add Invoice Line button on your Invoice Outliner & fill out the form.

By default, you will only have to select the Stock Item you want to sell and introduce a quantity. The Accounting Engine will automatically calculate the total amounts depending on the Invoice's Price List (if any) for the invoice line, but total control over these values is made possible through Custom Calculations.

Customizing Invoice Line Calculations

By default, when you add a new Invoice Line to an Invoice, automatic calculations are made based on the selected Stock Item and the Invoice's Price List. However, you can switch to custom calculations to control the values that contribute to the Total Line's Amount. To learn more about price calculations, refer to Billing Item Records

Understanding Tax Calculations

Applied Tax Policies contribute to the Total Amount of each Line by their respective percentages. e.g If a Tax Policy named VAT with a 19% value is added to a Line, it will increase the Tax Amount by 19& of the Tax Base, therefore increasing the Total Amount for that Line.

Updating Invoices

Updating Invoices is as simple as creating them. If an invoice is marked as a draft (hasn't been closed, signed, or reported) every change is allowed (including changing its owner, date, Forex Rate, and more). Nevertheless, once that invoice is no longer a draft, the Accounting Manager won't allow updates or recalculations. Reopening an Invoice requires Global Administrator Privileges.

Closing Invoices

Once your invoice is perfectly outlined, you will be able to close it. Closed Invoices become permanent, unmutable records. Once you have closed your Invoice, you can export it to multiple formats like JSON, XML, PDF, HTML, UML. Closed Invoices also become available to its Related Identities via the Studio & APIs.

Deleting Invoices

To delete an invoice, head to the Invoice Details Page and select Delete from the Actions Bar. Only Draft Invoices can be deleted.

Getting Payments for Invoices

Once your invoice is closed, you can collect payment for your invoice using any of the Alliance Business Suite's integrations for Payment Gateways.

Send an Invoice through Email

Once your invoice is marked as closed, a new option to send an email containing a representation for your invoice will become visible. To send an email, simply click on that button, enter an email and click send.

Reporting Invoices to Fiscal Authorities

In some cases, Invoices need to be reported to their respective fiscal identities, either in a statement or through a digital service. Althousg Accounting Manager itself does not contain the capabilities to automatically report Invoices to their Fiscal Authority, several integrations have been created to do so with fiscal entities from several countries such as Colombia, Costa Rica, México & more.

Adjusting Forex Rates for Invoices

Forex Rates serve to calculate the Foreign Exchange Conversion over which a particular invoice was outlined, when it was outlined. If the currency in which either an Invoice or an Invoice Line was created us equal to USD, the Forex Rate will be 1.0. Otherwise, it will contain the total amount (in the selected currency) needed to exchange 1 USD as of the Invoice's Date.

Working with Billing Item Records

Billing Records are designed to allow businesses to better manage their billing process by helping them to easily manage their billing process.

A Billing Item Record represents a line item on a Billing Record, such as a single entry on a quote, order, or invoice. This means it connects one Item to a Billing Record.

Types of Billing Item Records

When you add an item to a Deal Unit, you are creating a Deal Unit Item Record. Each one of these records represents an item that's possible to sell on a given Deal Unit.

When you add an item to a Quote, you are creating a Quote Item Record. Each one of these records represents an item that's being quoted to present to a customer.

When you add an item to an Order, you are creating an Order Item Record. Each one of these records represents an item that's being ordered by a customer.

When you add an item to an Invoice, you are creating an Invoice Item Record. Each one of these records represents an item that's being invoiced to a customer.

Coupon Item Records are a special type of Billing Item Records designed to allow customers to apply global coupons to their cart, scoped coupons to each product on their cart, and then pass those records to an Order on the Checkout process.

Pricing of Billing Item Records

Billing Item Records are also used to calculate critical values of each Billing Record such as the price of goods (Detail Price), taxes, shipping costs, discounts, surcharges, profit margins, and others.

Calculations can be overridden by providing a custom value using your preferred currency. To do this, you will need to select "Custom" on the Price Calculation Method of each Billing Item Record in order to provide your custom values.

When overriding calculations, you are responsible for the whole price calculation process, meaning you will have full control over the amounts that will produce the final Billing Record's Total Amount.

As every Item Billing Record (the base record for Invoice Lines, Order Lines, Quote Lines, and more). Calculations are made using a segregated approach where several values come into play.

The equation is the following:

  • Currency: The Currency in which you are entering custom values.

  • Forex Rate: The total amount used for conversion between the currency you're entering values and United States Dollars. You can enter a custom value or auto-calculate using the Historical Exchange Feature.

  • Base Amount: It represents the base price for a single product unit, without profit, discounts, surcharges, or taxes.

  • Total Profit: The Total Profit Amount for a single product unit.

  • Total Detail (Auto calculated): Total Amount over which Discounts will be calculated.

  • Total Discounts: Total Discounts for a single product unit.

  • Total Surcharges: Total Discounts for a single product unit.

  • Tax Base (Auto calculated): Represents the Base Amount for Tax Calculations. Tax Base Calculation depends on Total Detail minus Total Discounts + Total Surcharges.

  • Tax Amount (Auto calculated): Tax Amounts can be automatically calculated by adding Tax Policies to every Line. Tax Policies can be synced from the selected Stock Item, or manually added to a Line.

  • Global Discounts: Global Discounts are discounts made outside the scope of the Taxable values. Those discounts are suitable for operational discounts such as Tax Discounts (for whatever reason).

  • Global Surcharges: Global Surcharges are surcharges made outside the scope of the Taxable values. Those surcharges are suitable for operational surcharges such as shipping costs or payment processing fees which need to be covered but outside your fiscal domain.

  • Total Amount (Auto Calculated): The total Amount for the Line. Is calculated by Adding the Tax Amount to the Tax Base, then applying Global Discounts/Surcharge.

Adding Tax Policies to Billing Item Records

To add a Tax Policy to a Billing Item Record, the new Policy needs to exist the Accounting Manager. Once it exists, it will be available to be selected when you click on the "Add Tax" button on the Line Outliner Form.

Once you add the tax policy, it will be automatically calculated having as tax base the current Billing Item Records' Tax Base Amount.

Understanding Tax Calculations

Applied Tax Policies contribute to the Total Amount of each Billing Item Record by their respective percentages. e.g If a Tax Policy named VAT with a 19% value is added to a Billing Item Record, it will increase the Tax Amount by 19& of the Tax Base, therefore increasing the Total Amount for that Billing Item Records.

What Is a Ledger?

The accounting ledger contains a listing of all general accounts in the accounting system’s chart of accounts.

A ledger represents the record-keeping system for a company’s financial data, with debit and credit account records validated by trial balances. Ledgers contain a record of each financial transaction that takes place during the life of an operating company and holds account information that is needed to prepare the company’s financial statements. Transaction data is segregated, by type, into Ledger Accounts for assets, liabilities, owners’ equity, revenues, and expenses.

Performing Trial Balances

// TODO: Document

Contact Sight Module (CRM)

Welcome to the Alliance Business Suite | Contact Sight Module Documentation. These articles will enable you to work with the module to get the most out of your Alliance Business Suite instance.

At the very core of the Alliance Business Suite, a wide range of CMS capabilities have been built to give you the greatest extent of flexibility while supporting your business core cases to enable your organization to manage every relationship it has, to exponentially increase the value you deliver to your customers.

Types of Records

Types of records

Contact Records: In ABS ContactSight, most of the information service requests are typically managed in relation to an existing contact record. These contacts can represent both an Individual or an Organization (company or group of people) and they are also used by other modules, like accounting, sales, and marketing.

Contacts are the heart of the Alliance Business Suite. ABS ContactSight's customer management capabilities are designed to help you grow your business and make it easy to have a strong contact management strategy embedded in your operations to help increase your business income and accelerate productivity.

Although these are the typical uses of Individuals and Organizations, different deployments might use these record types differently. But they're both typically referred to as Contacts.

This common root between individuals and organizations allows you to set the related contact on any record, to either an individual or an organization contact record.

Contact Profile Records: Contact Profiles are records designed to isolate contact capabilities that could be used by other modules. For example, a Student Profile will allow a Contact to own course enrollments, grades, homework deliveries, completion certificates, and everything that's related to this type of profile. Likewise, Supplier Profiles will allow Contact Records to have work orders and purchase requests/invoices, and so on.

Managing Contact Records on Alliance Business Suite Contact Sight

Contact records store much of the information that your business collects from its customers. Contacts are one of the main records on the Alliance Business Model as they relate to pretty much every other record on the Database Schema, Contacts are required to create records such as Entitlements, Quotes, Orders, Invoices, Payments, Support Tickets and more.

Contact Types

There are two types of Contacts.

  • Individuals: Individuals are records used to store information about the people you know and work with.
  • Organizations: Organizations are records used to store data about companies you do business with.

Creating Contacts

To create either an Individual or an Organization using ABS Contact Sight, navigate to the module, click on the type of contact you wish to create. Select "Create New" and fill out, at the very least, the name and email for the new individual/organization.

Note: There are values you will only be able to create/modify within a contact only after this contact has been created.

Editing Contacts

To edit a Contact, navigate to Contact Sight Module on the Alliance Business Studio, click on the type of contact you wish to edit, find the contact on the Contacts Grid and click on it to open it on the Contact Edition View.

Deleting Contacts

To Delete a Contact, navigate to the contact you wish to delete and open it on the Contact Edition View. Under the Actions Bar, click on delete and confirm your intention by typing the contact's email. Contact Deletion requires special permissions to execute. Deleted contacts will remain hidden, but available for up to 30 days (depending on your Contact Deletion Policy) before permanent and unrecoverable deletion.

NOTE: Deleting Contacts will delete all their related data, like files, profiles, tasks, schedules, and more. Contacts with related Orders, Invoices, and Payments can't be deleted.

Welcome to the iCommerce Engine Documentation

Infinity Comex Engine builds on top of the proven Alliance Business Suite Retail capabilities to help businesses to deliver a comprehensive omnichannel solution that unifies back-office, in-store, call center, and digital experiences. Infinity Comex Engine enables you to build brand loyalty through a white-labeled store built to deliver personalized customer engagements, increase revenue, boost employee productivity, optimize operations to reduce costs, and drive supply chain efficiencies, ultimately delivering better business outcomes.

The Infinity Comex engine is constantly evolving to harness the entire power of the Alliance Business Model by extending through modular and fully customizable capabilities the Alliance Business Suite to deliver:

  • Everything you need to build and operate your eCommerce business.

The Alliance Business Suite and the infinity Comex engine are meant to be together! They work side-by-side to help businesses optimize their operations by cutting off inefficiencies and helping them to deliver spectacular omnichannel experiences. The Alliance Business Suite enables seamless content management, assets, promotions, inventory, and pricing across all channels.

  • Everything you need to protect your customers and your business.

The Alliance Business Platform's and Alliance Passport Services' security features and standards are deeply integrated into the Infinity Comex Engine. Authentication and Authorization flows are defined at a platform level by configuring (or extending) the APS Engine. Then, also at a platform level, security features like HTTPS enforcement, Encryption, HSTS, CORS, and others can be enabled, disabled, or configured through the Alliance Business Suite - Admin Portal. Also, EU General Data Protection Regulation (GDPR) support is enabled for both ABP and ICX Engines.

To learn more about Data Protection across the Alliance Business Suite, please visit this link.

  • Everything you need to streamline your logistics and operations.

The Infinity Comex Engine is built on top of the Logistics module of the Alliance Business Suite. This allows the engine to read and write data directly from your logistic operations platform. The Infinity Comex engine also connects to several modules like ABS Subscriptions, ABS Marketing, ABS Accounting, and ABS Partners to help your business to deliver Amazon Quality-like Experiences to your customers.

  • Everything you need to build your brand and expose your business online.

Besides the fact that Infinity Comex Stores are fully customizable/white-label Customer-Facing solutions (which means your customers won't even know we're there), hundreds of external integrations allow users to connect and configure their favorite channels and applications through standard authentication protocols exposed by third-party developers.

Carts

Carts are a core part of our application. Carts allow guests, users, and businesses to navigate and customize our offers for their specific needs and preferences through Cart Registrations.

Overview

Carts define the currency and localization for the entire interface. This means that it will control the display currency for things like offers pricing, CRM, and accounting suite records, and personalize our offers based on your country.

Keep in mind that currency exchange rates are only for display purposes and you will be able to select the base price for every "Price Input". This will allow us to make conversions based on current and historical exchange rates, depending on the record type.

Products in your cart.

Adding products from Infinity Comex to your cart is as easy as clicking a button, but that's not the end of the story. we have designed a simple, yet powerful engine to help you select from a set of available options per product for things like Shipping, warranty, assurance, returns and refund policies and more.

Services in your cart.

When you register a service to your cart, it will be linked to your account through a Service Cart Registration. Service cart registrations let you pick from a set of available options like Project Management Methodology, Frontend Stacks, Framework, Programming Language (Based on the selected Framework), Operating System, and more.

Cloud Resources in your cart.

Once you have successfully created your Alliance ID, you will automatically get access to your Tenant Cart. Use it to store products before your checkout process.

Guest Carts

Guest carts are carts provisioned based on your current IP address. Its lifespan is 24 hours and is aimed to help you navigate your platform even when you are not logged in.

How is it different from my Guest Cart from my Tenant Cart?

The main difference is that your Tenant Shopping Cart has a slot for your Account ID, while your guest cart contains a slot for your IP address.

Another difference is that guest carts are just for instant navigation for our offerings, but they are actually not suited to place an order through your guest cart.

Also, Andy, our support bot, is programmed to empty every guest cart on our database ant midnight every two days.

In order to prevent cart deletion, you can log in to your Alliance ID Account to use your Tenant Cart for pre-order adjustments. Tenant carts have a time span of 31 days.

Guest Cart timespan policy.

Your guest cart will be deleted every 48 hours, which means that products on your guest cart might need to be added to your cart again if an old cart has already been deleted.

Tenant Carts

Have you had a chance to answer the previous question?

Yes, after a few months we finally found the answer. Sadly, Mike is on vacation right now so I'm afraid we are not able to provide the answer at this point.

Registrations Timespan Policy

When you add a product, a service, or a managed cloud resource to your cart, it will create a Cart Registration. These registrations will be available for you to customize your order preferences and place orders or provisioning requests with just a click. Cart registrations for your Alliance ID Tenant Cart won't be deleted until the first day of each month.

Business Carts

Business Carts get provisioned when you create a business account. They are intended for you to place Product Orders, Service Orders, and Cloud Resource Provisioning Requests.

Please note that access to business services depends on your granted capabilities and you will only be able to access our marketplaces if you are registered as a business owner or administrator, an acquisition manager or an advisor for your currently selected business.

What is the purpose of Business Carts?

Business' carts are aimed to provide the same functionality as a Tenant or Guest cart, with the difference that every order made from this chart will be processed using it's attached business Tax ID. This allows business owners/administrators and acquisition managers to quickly place orders on behalf of their business,

Welcome to the Alliance Business Suite | Logistics Manager

Supply Chain Management is at the core of every business. By delivering tools to effectively manage Stock, Warehouses, Suppliers, and a wide range of Logistics-Related Records, we're enabling businesses to achieve efficient Supply Chain Management without the hustle.

Inventory Management

The Logistics Manager Module was designed to help businesses to conduct effective inventory management while increasing ROI by making it easier to get a holistic view of your products through comprehensive views and tools, and valuable insights to make sure you're ordering the right inventory, at the right time and in right amounts,

Warehousing Management

The key to an efficient and profitable business is total visibility into the inventory process from start to finish and management tools to help you maintain optimal stock levels year-round. An effective inventory management system helps you streamline all the moving parts of your warehouse: From recommending optimal stock levels all the way to keeping your supply chain organized and running smoothly.

Shipping Management

We are making it easier than ever before to sell physical products by offering integrations and extensibility capabilities to connect your favorite shipping carriers, showing live rates, or adding custom solutions.

Logistics API

Through the Logistics Module API, developers can create custom solutions that extend its capabilities. Our goal is to create secure CRUD RESTfull Endpoints for almost every possible Record Type on the Logistics section of the Alliance Business Model.

Working with Stock Items in the Alliance Business Suite | Logistics Module

At the most basic level, Stock items are goods that you manufacture or trade (sell and purchase). Stock Items are highly inter-related ABM Records, they can be added to Carts, Quotes, Orders, Invoices, Wishlists, and more, as well as related to one or more Categories, Tags, Brands, Price Lists, Suppliers, Warehouses, and more.

Stock Items Manager

Some organizations have the need to manage hundreds or even thousands of Stock Items. This process is usually boring and time-consuming. For this reason, we're constantly investing our efforts in building efficient, automatable tools to help customers infuse efficiency into their operations.

The Stock Items Manager is an Alliance Business Studio view designed to make managing stock items as fast and efficient as possible.

Infused with inline and on-page editing tools, customers can create and manage Stock Items and related records without the need for page reloads.

To access the Stock Items Manager View, head to the Studio endpoint on any Web Portal, and navigate to Modules > Logistics > Stock Items.

Creating Stock Items

Stock Items can be created from the Stock Items Manager View. To do so, clock on the "Quick Create" button. This will open a panel containing the Stock Item Management Form, which contains all the fields available for Stock Items on the Alliance Business Model.

At the very least, Stock Items require a Title as well as a Stock Keeping Unit ("SKU").

qp9IJQI6Gy.gif

Updating Stock Items

Stock Items can be filtered and updated either by using the Stock Item Management Form or the In-Line Editing capabilities built into the Stock Items Grid. You can execute any of those through the Action Buttons on every Stock Item Record displayed on the Stock Items Grid.

Updating Stock Items is as straightforward as creating them. In fact, if you use the Stock Item Management Form to update a Stock Item, you'll be using exactly the same form you've used to create it.

Stock Item Identifiers

Stock Items are identified, at the lowest level, by a Globally Unique Identifier ("Guid") generated by the Alliance Business Model. Nevertheless, the Stock Item Record contains several fields to help customers to correlate this "Guid" with their own standards.

FieldDescription
BarcodeUPN, EAN or ISBN Barcode
SKUStock Keeping unit represents the code for a distinct type of item for sale. It must be unique for each Business Tenant
ISBN(ISBN-10 or ISBN-13) International Standard Book Number (ISBN)
UPCUniversal Product Code consists of 12 numeric digits that are uniquely assigned to each trade item.
EANInternational Article Number (also known as European Article Number or EAN) consists of a thirteen-digit code.
ASINAmazon Standard Identification Number (ASIN) is a ten-digit alphanumeric code that identifies products on Amazon.
UNSPSCUnited Nations Standard Products and Services Code is a taxonomy of products and services for use in eCommerce. It is a four-level hierarchy coded as an eight-digit number, with an optional fifth level adding two more digits.
GTINGlobal Trade Item Number (GTIN) GTINs consists of eight, 12, 13, or 14 digits
MPNManufacturer Part Number. It is a unique number that is issued by manufacturers to identify individual products.
Supplier CodeSupplier Code represents the Primary Supplier Code used to correlate each Stock Item with the Primary Supplier Standard.

Filtering

The Stock Items Grid contains powerful filtering capabilities.

Barcoding

The Stock Items Manager contains Barcoding Capabilities, meaning you can generate and update barcodes for Stock Items and then filter them out using their barcode.

To create or update a barcode, use the Stock Item Management Form and click on the "Scan Barcode" button. This will ask you permission to use your device's camera to start scanning. Once a valid barcode is recognized, the system will automatically fill out the proper fields on the Stock Item Management Form.

Barcoding in the Logistics module enables other Modules such as Sales, Accounting, POS, and even custom modules to filter out Stock Items using either a desktop or a smartphone camera.

Bulk Actions

The Stock Items Management View allows customers to perform bulk actions on Stock Items, such as adding or removing pricing policies (discounts, surcharges, price adjustments), Taxes, Relations, and more.

To perform a bulk action, select the Stock Items you want to update by ticking the checkbox on the left side of each Stock Item. You can check and filter stock items without losing your current selection state. Then click on the "Bulk Actions" button.

A Modal Prompt will appear. Select the bulk action you want to perform, configure your action and click on the Execute Button.

Bulk actions are blazing fast (executed in the order of seconds for hundreds of records), but performing bulk actions on thousands of records can take a little while.

Working with Sales Flows on Alliance Business Suite - Sales Hub Module

Using Sales Flows in Alliance Business Suite Sales Manager can help you ensure your data follows a set of pre-defined steps to increase data consistency across your business operations.

At its most basic level, a Sales Flow is a Business Process stored inside the Alliance Business Model. As a Business Process, a Sales Flow contains a set of logical steps designed to define a path to follow for each Sales Record.

Working with Sales Hub Records on the Alliance Business Suite

Built on top of the powerful Alliance Business Model capabilities for sales, the Alliance Business Suite - Sales Hub Module is being built to cover every stage of your sales process.

Types of Sales Records

There are three types of sales records across the Alliance Business Model:

Deal Units:

Deal Units are the first step towards managing your business opportunities since they come to life, to their final state. Deal Units allow you to link several Stock Items from which automatically calculates estimated revenues, profits, taxes, totals, and more.

A Deal unit represents a business opportunity, a deal that you want to start tracking. With a Deal Unit, you can forecast sales revenue, set a potential close date, and factor in the sale's probability.

Quotes:

A Quote, also known as a quotation, is a document issued from a business to a customer outlining the price of a sale before the customer has committed to the purchase.

Using Sales Hub, you can create Quotes taking as a startup point any deal unit present on your system, or by manually outlining a new custom quote. When creating a quotation from a Deal Unit, the new quote will be assigned to the same Deal Unit's related contacts, the Quote amounts will be set to the same values as the Deal Unit, and each Deal Unit Item Record will be copied to the new Quote.

Orders:

An order is a stated intention, either spoken or written, to engage in a commercial transaction for specific products or services.

Using Sales Hub, managing orders is not much different from managing Quotes. In fact, Orders can take as a startup point any quotation or deal unit present on the system, or they can be manually outlined.

Linking Contacts to Sales Hub Records (Contact-Scoping)

You can link every Sales Record to any specific Individual/Organization (or both) owned by your acting Business Tenant. This enables Contact-Scoped capabilities such as improved analytics, customer segmentation, opportunity discovery, contact billing & more.

Linking Identities to Sales Hub Records (Identity-Scoping)

Sales Records can also be bound to a specific Account Holder/Business Tenant (or both). When you select an individual or organization on any Sales Record, Sales Hub will search for Identities related to those contacts. When you relate Identities to Sales Records, those records will become available to those users to see and interact with.

For example, if you assign an Account Holder to an Order, that Account Holder will be able to log in to the platform and find that order onto their billing section (if using Alliance Business Studio), generate an invoice to pay, and pay that Invoice using any of your configured Payment Integrations.

Understanding Multi-Currency Support for Sales Records

Sales Hub support's Alliance Business Model's multi-currency specification, meaning that you can manage Sales Records with live & historical multi-currency capabilities.

When adding an amount into Sales Hub, you will be asked to select the currency on which amounts are being provided. This allows Sales Hub to not only present you and your user's information on their favorite currency but also allows your business to manage multi-currency accounting & operations without complications.

Accounting Manager Interoperability

When you create an order using Sales Hub, you are setting the stage for further Invoice(s) & Payment(s). The Alliance Business Model links sales & billing entities through a link between any given order and several Invoices. This means you can create & customize a new invoice taking as a startup point any present Order, and further payment for that Invoice can be requested using any of your configured payment integrations.

When creating Invoices from an Order as a Startup Point, Contact Scoping Records, Identity Scoping Records & Order Item Records will be copied to the new Invoice, and the same process takes place when a new payment for any given Invoice is created or received (trough a Payments Gateway Integration).

Managing Deal Units:

Deal Units are the first step towards managing your business opportunities since they come to life, to their final state. Deal Units allow you to link several Stock Items from which automatically calculates estimated revenues, profits, taxes, totals, and more.

A Deal unit represents a business opportunity, a deal that you want to start tracking. With a Deal Unit, you can forecast sales revenue, set a potential close date, and factor in the sale's probability.

How to Create a Deal Unit

You can create a new deal unit using several ways.

  • From a Cart: You can create a new Deal Unit from an existing Cart. This is useful when you want to start a process of cart abandonment recovery for some carts used in your business applications.
  • From an existing Deal Unit: Using the Sales Hub Module you can create Deal Units by cloning an existing Deal Unit.
  • Using the Outliner: Using the Sales Hub Module you can outline Deal Units directly from the Alliance Business Studio.

Adding Stock Items to Deal Units

When you add a Stock Item to a Deal Unit, you are creating a new Billing Item Record. See Managing Billing Item Records.

Managing Quotes:

A Quote, also known as a quotation, is a document issued from a business to a customer outlining the price of a sale before the customer has committed to the purchase.

Using Sales Hub, you can create Quotes taking as a startup point any deal unit present on your system, or by manually outlining a new custom quote. When creating a quotation from a Deal Unit, the new quote will be assigned to the same Deal Unit's related contacts, the Quote amounts will be set to the same values as the Deal Unit, and each Deal Unit Item Record will be copied to the new Quote.

Managing Orders:

An order is a stated intention, either spoken or written, to engage in a commercial transaction for specific products or services.

Using Sales Hub, managing orders is not much different from managing Quotes. In fact, Orders can take as a startup point any quotation or deal unit present on the system, or they can be manually outlined.

ABS | Content Portals

Through ABS Content Portals, customers can now create a powerful new type of experience: external-facing websites that allow users outside their organizations to sign in with a wide variety of identities, create and view data in the Alliance Business Model, or even browse content anonymously. The full capabilities of the ABS Razor Engine for Content Portals, previously offered only as a Module, are now available right out of the box in every Alliance Business Suite instance.

Content Portals can extend the ABS Modules such as sales, customer service, marketing, service companion, project center, and ABS custom apps to external and internal audiences such as customers, suppliers, partners, and employees.

Customers can use Content Portals to set up an interactive, web-based sales, services, support, and social engagement application platform to connect with the customers, engage with communities, manage multimedia content, and empower your channel partners. Your imagination is the limit!

These capabilities feature a revamped end-to-end experience for technical and non-technical staff to quickly create a website and customize it with pages, layout, and content. Designers can reuse page designs through templates, add forms and views to display key data from the Alliance Business Model and publish it to users with the click of a button.

Content Portal's Tenancy

Content Portals are always owned by one Business Tenant. Interactions from audiences of this portal will always resolve to the scope of the Portal's Owner Tenant. For example, if a customer tries to log in to a portal, Authorization will be attempted against the Business Tenant that owns that portal.

This is incredibly powerful as it allows customers to have more than one portal hosted into the same Alliance Business Suite instance, creating like so a MultiPortal Network.

Workflow Designer Module

Welcome to the Alliance Business Suite | Workflow Designer Module Documentation.

These articles will enable you to work with the module to get the most out of your Alliance Business Suite instance.

The Alliance Business Suite | Workflow Designer is a workflows manager that enables workflow execution in any Alliance Business Suite instance. Workflows, business processes, and enterprise orchestrations can be defined by using code or the visual workflow designer, to integrate your Alliance Business Suite and your data on the Alliance Business Model across cloud and on-premises systems.

Features

  • Create workflows using the Workflow Builder API.
  • Create & manage workflows visually using the Alliance Business Studio Dashboard SPA.
  • Design long-running workflows.
  • REST API Endpoints to manage and integrate with Elsa from external applications.
  • Create higher-level activities using the Composite Activity API.
  • Rich set of activities such as SetVariable, For, ForEach, ParallelForEach, Fork, Join, HttpEndpoint, SendHttpRequest, SendEmail, MessageReceived, and much more.
  • Create custom activities.
  • Workflow Expressions allow you to configure activity properties with expressions that are evaluated at runtime. Supported syntaxes are JavaScript and Liquid.

Why Workflow Designer?

One of the main goals of the Workflow Designer Module is to enable workflows in any Alliance Business Suite instance with minimum effort and maximum extensibility. This means that your Alliance Business Suite is workflow-capable right out of the box.

Azure Logic Apps vs ABS | Workflow Designer?

  • As powerful and as complete as Azure Logic Apps are, it's available only as a managed service in Azure. The Alliance Business Suite, on the other hand, allows you to host it not only on Azure but on any cloud provider that supports .NET Core. And of course, you can host it on-premises.

  • Although you can implement long-running workflows with Logic Apps, you would typically do so by splitting your workflow with multiple Logic Apps where one workflow invokes the other. This can make the logic flow a bit hard to follow. with ABS | Workflow Designer, you simply add triggers anywhere in the workflow, making it easier to have a complete view of your application logic. And if you want, you can still invoke other workflows from one workflow.

ABS | Workflow Designer vs. Windows Workflow Foundation?

I've always liked Windows Workflow Foundation, but unfortunately development appears to have halted. Here are a few reasons to prefer the Workflow Designer Module:

  • The Workflow Designer Module intrinsically supports triggering events that start new workflows and resume halted workflow instances in an easy-to-use manner. E.g. workflow host.TriggerWorkflowAsync("HttpRequestTrigger");" will start and resume all workflows that either start with or are halted on the HttpRequestTrigger.

  • The Workflow Designer Module has an In-Studio (web-based) workflow designer and a REST-based API to manage everything you can manage through the Web Workflow Designer.

ABS | Workflow Designer vs. Orchard Workflows?

Both Orchard and Orchard Core ship with a powerful workflows module, and both are awesome. In fact, the Workflow Designer Module was inspired by Orchard Core's Workflows module.

Although Workflow Designer uses a similar model, here are some differences:

  • The Workflow Designer Module is completely decoupled from the web and relies on the Alliance Business Platform, whereas Orchard Core Workflows is coupled not only to the Orchard Core Framework but to the web itself.
  • The Workflow Designer Module is being built without taking a dependency on any Orchard Core packages.

Working with the Alliance Business Suite Connector (Formerly ABS Self).

The Alliance Business Suite contains several extensibility capabilities, including the ability to host Node.JS Applications, Angular and React interoperability, Workflow Definitions, and a tremendously powerful content management system, but without a doubt, its most extensible feature is the Alliance Business Platform API.

At its most basic level, the ABS Connect Integration is an extension of the Alliance Business Platform API designed to enable customers to set up and manage their integrations without complications. For example, by using the ABS Connector, you could set up Zapier in minutes!

The ABS Connector gives you the greatest extend of control over the integration capabilities of the Alliance Business Platform, enabling customers to create custom integrations that run on their own framework of choosing but still transact data with any given Alliance Business Suite instance.

ABS Connector makes it easy than ever before to configure both internal and external applications to connect to the Alliance Business Platform using industry-standard protocols and it provides an intuitive set of Studio Views to manage them.

Managing Application Credentials

Managing WebHooks

Upload Stock Items from the to a Facebook Commerce Catalog With a Data Feed

The Facebook Integration for the Alliance Business Suite allows you to maintain a data feed to bulk upload Published Stock Items (Store Products) to your catalog using an automatically generated spreadsheet file.

You will need to configure the data feed on the Facebook Commerce Manager by a file once or set up a schedule to update your catalog automatically on a regular basis. Your catalog can hold multiple data feeds, but each data feed must contain different items.

Note: These steps are to set up a new data feed. Depending on the feed configuration, Facebook will automatically retrieve and update published items on a schedule.

Configure a new data feed to a catalog

To upload a new data feed to your catalog:

  1. Go to Commerce Manager and select your catalog.
  2. Open the Catalog tab and go to Data Sources.
  3. Select Data Feed.
  4. Select Scheduled Feed.
  5. Enter the URL on the following form https://your-portal-domain.com/api/v2/Integrations/Facebook/Stores/Catalog ( You can test the URL in your browser to make sure it downloads your file.)
  6. Choose an hourly, daily, or weekly upload schedule for your data feed. Select Next.
  7. Review your data feed’s settings. Select to make any changes. The default currency will only be used if prices in your file don't include a currency code.

Review your data feed’s settings. Select to make any changes. The default currency will only be used if prices in your file don't include a currency code.

Select Save Feed and Upload.

You've uploaded a new data feed from a URL. Your data feed now appears in Data Sources. You can select it to see an overview or manage its settings. To update your items in the future, edit your file and save it again on your hosting website. We'll fetch it from its URL to update your catalog at your scheduled times. You can edit your schedule or request a single upload sooner in your data feed's settings.

Mantaining a Google Merchant Center Data Feed through the Alliance Business Suite

The Alliance Business Suite's Google Merchant Integration can help you upload your product data in Google Merchant Center, it automatically exposes the data to be submitted to your feeds.

To configure this capability, you will need to set up any new feed, and once a feed is registered, it will be updated on a regular basis without having to register it again.

Although feeds are multi-currency, they display the base amount without shipment nor tax data, but we're currently working on multi-country feeds. 🥳

The data endpoint to point Google Merchant Center to can be constructed using the following route:

https://your-portal-domain.com/api/v2/Integrations/Google/Merchant/Catalog?CurrencyID=USD

Configuring survey opt-in

To set up the Google Merchant Survey Opt-In, all you need to do is to plug your Google Merchant ID into the integration configuration page.

To set up your Merchant ID, navigate to the Studio on any Web Portal, head to Integration > Google > Merchant, and place your Google Merchant ID on the form field, then save changes.

Authorization

[[TOC]]

Security Features

If you own an Alliance Business Suite-powered infrastructure or are considering using the Alliance Business Suite as your CMS/CRM/ERP (or any other), you may be concerned about potential Alliance Business Suite security issues. In this post, we’ll outline a few of the most common ABS security vulnerabilities, along with steps you can take to secure and protect your Alliance Business Suite instance.

At Fenix Alliance, we are committed to helping our customers meet their privacy and personal data requirements, as well as General Data Protection Regulation (GDPR). On this page, you will find information and resources to help you understand how the Alliance Business Suite supports protecting and enabling the privacy rights of individuals, and how we provide the information and tools that our customers need in order to define and support their specific obligations. You can read more about the Fenix Alliance commitment to security at the Fenix Alliance Trust Center.

Is the Alliance Business Suite Secure?

The answer to the question “is the Alliance Business Suite secure?” is it depends. The Alliance Business Suite itself is very secure as long as security best practices are followed.

Encryption at rest

All files sent to our applications are automatically encrypted with a 256-bit Advanced Encryption Standard (AES) cipher. SSE automatically encrypts data when writing it to Storage. When you read your files, our storage decrypts the data before returning it. This process incurs no additional charges and doesn't degrade performance. This feature can't be disabled.

Encryption in transit

We keep your data secure by enabling transport-level security between our applications and the client. We ALWAYS use HTTPS to secure communication over the public internet. When you call the REST APIs to access objects in storage accounts or our databases, we enforce the use of HTTPS by requiring secure transfer, and connections that use HTTP will be refused and redirected.

CORS support

We store several website asset types in Storage. These types include images and videos. To secure browser apps, we lock GET requests down to specific domains.

Our storage supports cross-domain access through cross-origin resource sharing (CORS). CORS uses HTTP headers so that a web application at one domain can access resources from a server at a different domain. By using CORS, our web apps ensure that tenants load only authorized content from our sources.

When you create a business application. you will be able to specify your domains in order for us to verify your domains and set CORS flags.

Role-based access control

To access data in an Alliance ID Tenant account, the client makes a request over HTTP or HTTPS. Every request to a secure resource must be authorized. The service ensures that the client has the permissions required to access the data.

Our applications support role-based access control (RBAC) for both resource management and data operations.

White papers, security reports, penetration tests, and risk assessment tools

To find detailed information about privacy and personal data for the Alliance Business Suite applications and services, visit the Alliance Business Suite Website. This site provides white papers, FAQs, security reports, penetration tests, risk assessment tools, and other resources. In particular, the site provides sales/technical guidance about how you should consider enhancing your data protection capabilities and how you might want to think about compliance as a process that has four stages: discover, manage, protect, and report.

Data subject requests

The General Data Protection Regulation (GDPR) is fundamentally about protecting and enabling the privacy rights of individuals. The General Data Protection Regulation (GDPR) took effect on 25 May 2018. For information about the challenges and opportunities that GDPR brings for organizations in the context of their business applications, whether there are any specific risks and measures to be taken in the GDPR context, and any potential impact on how business applications need to be used.

The GDPR grants individuals (or data subjects) certain rights in connection with the processing of their personal data. These rights include the right to correct inaccurate data, erase their data or restrict its processing, receive their data, and fulfill a request to transmit their data to another controller. The resources in this section will help Alliance Business Suite customers respond to data subject requests (DSRs).To find information about what the GDPR requires of controllers (you) and processors (Fenix Alliance) when you respond to DSRs, and how Fenix Alliance enables you to do so, see DSRs on the Service Trust Portal.

Compliance Manager

Alliance Business Suite - Compliance Manager is a modular cloud service solution that is designed to help organizations meet complex compliance obligations like the GDPR. It does real-time risk assessment that reflects your compliance posture against data protection regulations when you use Fenix Alliance's cloud services. It also provides recommended actions and step-by-step guidance.

HTTPS Enforcement in the Alliance Business Suite.

Although no API can prevent a client from sending sensitive data on the first request. the Alliance Business Platform (which serves as a middleware for incoming/outgoing requests, as a rule of thumb, is designed to make sure that:

  • HTTPS is required for all requests.
  • All HTTP requests are redirected to HTTPS.

Note: The Alliance Business platform should not listen on HTTP and will close the connection with status code 400 (Bad Request) and not serve the request.

Preventing Cross-Site Request Forgery (XSRF/CSRF) attacks.

Cross-site request forgery (also known as XSRF or CSRF) is an attack against web-hosted apps whereby a malicious web app can influence the interaction between a client browser and a web app that trusts that browser. These attacks are possible because web browsers send some types of authentication tokens automatically with every request to a website. This form of exploit is also known as a one-click attack or session riding because the attack takes advantage of the user's previously authenticated session.

An example of a CSRF attack:

A user signs into www.good-banking-site.com using forms authentication. The server authenticates the user and issues a response that includes an authentication cookie. The site is vulnerable to attack because it trusts any request that it receives with a valid authentication cookie.

The user visits a malicious site, www.bad-crook-site.com.

The malicious site, www.bad-crook-site.com, contains an HTML form similar to the following:

HTML

<h1>Congratulations! You're a Winner!</h1>
<form action="https://your-abs-instance.com/api/v2/insecure-banking-module/wallet" method="post">
    <input type="hidden" name="Transaction" value="withdraw">
    <input type="hidden" name="Amount" value="1000000">
    <input type="submit" value="Click to collect your prize!">
</form>

Notice that the form's action posts to your Alliance Business Suite instance, not to the malicious site. This is the "cross-site" part of CSRF.

The user selects the submit button. The browser makes the request and automatically includes the authentication cookie for the requested domain, your-abs-instance.com.

Without CSFR protection, the request runs on the your-abs-instance.com server with the user's cookie authentication context and can perform any action that an authenticated user is allowed to perform.

In addition to the scenario where the user selects the button to submit the form, the malicious site could:

  • Run a script that automatically submits the form.
  • Send the form submission as an AJAX request.
  • Hide the form using CSS.

These alternative scenarios don't require any action or input from the user other than initially visiting the malicious site.

Using HTTPS doesn't prevent a CSRF attacks. The malicious site can send an https://your-abs-instance.com/ request just as easily as it can send an insecure request.

Some attacks target endpoints that respond to GET requests, in which case an image tag can be used to perform the action. This form of attack is common on forum sites that permit images but block JavaScript. Apps that change state on GET requests, where variables or resources are altered, are vulnerable to malicious attacks. GET requests that change state are insecure. A best practice is to never change state on a GET request.

CSRF attacks are possible against web apps that use cookies for authentication because:

Browsers store cookies issued by a web app. Stored cookies include session cookies for authenticated users. Browsers send all of the cookies associated with a domain to the web app every request regardless of how the request to app was generated within the browser. However, CSRF attacks aren't limited to exploiting cookies. For example, Basic and Digest authentication are also vulnerable. After a user signs in with Basic or Digest authentication, the browser automatically sends the credentials until the session† ends.

†In this context, session refers to the client-side session during which the user is authenticated. It's unrelated to server-side sessions or ASP.NET Core Session Middleware.

Users can guard against CSRF vulnerabilities by taking precautions:

  • Sign off of web apps when finished using them.
  • Clear browser cookies periodically.
  • However, CSRF vulnerabilities are fundamentally a problem with the web app, not the end user.
<form action="/api/v2/secure-banking-module/wallet" method="post">
    @Html.AntiForgeryToken()
</form>

In each of the preceding cases, ASP.NET Core adds a hidden form field similar to the following:

<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkS ... s2-m9Yw">

Multiple apps hosted at one domain

Shared hosting environments are vulnerable to session hijacking, login CSRF, and other attacks.

Although portal1.my-abs-instance.net and portal2.my-abs-instance.net are different hosts, there's an implicit trust relationship between hosts under the *.my-abs-instance.net domain. This implicit trust relationship allows potentially untrusted hosts to affect each other's cookies (the same-origin policies that govern AJAX requests don't necessarily apply to HTTP cookies).

Attacks that exploit trusted cookies between portals hosted on the same Alliance Business Suite instance can be prevented by not sharing domains. When each instance is hosted on its own domain, there is no implicit cookie trust relationship to exploit.

Require antiforgery validation (Modules only)

ValidateAntiForgeryToken is an action filter that can be applied to individual actions, and controllers. Requests made to actions that have this filter applied are blocked unless the request includes a valid antiforgery token.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
    ManageMessageId? message = ManageMessageId.Error;
    var user = await GetCurrentUserAsync();

    if (user != null)
    {
        var result = 
            await _userManager.RemoveLoginAsync(
                user, account.LoginProvider, account.ProviderKey);

        if (result.Succeeded)
        {
            await _signInManager.SignInAsync(user, isPersistent: false);
            message = ManageMessageId.RemoveLoginSuccess;
        }
    }

    return RedirectToAction(nameof(ManageLogins), new { Message = message });
}

Refresh tokens after authentication

Using JavaScript with AntiForgeryTokens

When you use JavaScript into Dynamic Pages, Components, Templates or any other kind of WebContent, you will be able to access the AntyForgeryToken in several ways. Here's one of them:

function getCookie(cname) {
    var name = cname + "=";
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) === ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) === 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

var csrfToken = getCookie("CSRF-TOKEN");

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
    if (xhttp.readyState === XMLHttpRequest.DONE) {
        if (xhttp.status === 204) {
            alert('Todo item is created successfully.');
        } else {
            alert('There was an error processing the AJAX request.');
        }
    }
};
xhttp.open('POST', '/api/items', true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("X-CSRF-TOKEN", csrfToken);
xhttp.send(JSON.stringify({ "name": "Learn C#" }));

Reporting a Vulnerability

Security issues and bugs should be reported privately to Fenix Alliance either by emailing support@fenix-alliance.com or via the portal at https://fenix-alliance.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

Please do not open issues for anything you think might have a security implication.

Understanding the Alliance Business Suite dependency tree

The Alliance Business Suite is designed as a set of Application Layers dependant upon their service predecessor. Each Layer constitutes a Component for the Alliance Business Suite.

Components can be provisioned as Standalone Applications or used as stand-alone libraries. This means that it is possible to bring the Alliance Business Platform (FenixAlliance.ABP.*) into a new/existing application without having to include any dependency from the Alliance Business Studio (FenixAlliance.ABS.*). The same is true for the Alliance Business Model (FenixAlliance.ABM.*), which can be included without any reference to the Alliance Business Platform namespace (FenixAlliance.ABP.*).

Components rely on their Service Predecessor through abstractions, allowing customers to override almost every functionality through custom implementations.

DependencyTree.1.2.0.jpg

Note: Because other services on the Alliance Business Suite instance might rely on default implementations performing some work, it is imperative for customers who bring their own implementations to make sure their implementations stay compliant with each specification.

Understanding external dependencies

External dependencies required by the Alliance Business Suite are bounded to the Alliance Core Libraries Component, which means that they are available to every dependant Component due to .NET's Waterfall Dependency Resolution mechanism.

This means that Web Contents can make use of already present libraries such as Radzen Blazor, MudBlazor, Newtonsoft.Json, and many more. For a more detailed list of dependencies, please refer to the Core Dependencies.

Fenix Alliance Online Services Overview

Fenix Alliance offers a set of cloud-based services designed to help customers to exceed expectations on their needs for security, reliability, and time-to-market. The Services provided by Fenix Alliance are constantly evolving and the form and nature of such Services (as well as the terms and conditions inherent in each of them) may change from time to time.

This section contains detailed service descriptions, information on how to access the Fenix Alliance Online Services, as well as guides, terms and conditions, and relevant related information.

Online Services Descriptions:

To get started, see the following service descriptions:

APIs

Fenix Alliance exposes a wide set of APIs for interoperability with Online Services. These APIs are divided into Service Endpoint Sets and can be used to create, read, update or delete information from an Online Business Tenant.

REST API

By using standard HTTP Requests customers can perform requests to a wide variety of service endpoints designed to follow the Open API Standard. By default, the Platform generates and exposes Swagger JSON in version 3.0 of the specification—officially called the OpenAPI Specification.

GraphQl API

Alliance Business Cloud

Alliance Pricing Center

Alliance Merchant Center

Alliance Developer Center

Alliance Partner Center

Alliance Support Center

Alliance Business Network

Alliance Pay Platform

Infinity Comex Marketplace

Learn Alliance Academy

Welcome to the Alliance Online Services REST API reference documentation.

Apart from the traditional Web Portals, the AOS APIs expose a set of Representational State Transfer (REST) service endpoints that support sets of HTTP operations (methods), which provide create, retrieve, update, or delete access to the service's resources. This section will walk you through:

  • How to call Alliance Online Services REST APIs with Postman
  • How to register your client application with Alliance Passport Services ("APS") to secure your REST requests.
  • Overviews of creating and sending a REST request, and handling the response.

How to call AOS REST APIs with Postman

The following video will show you how to quickly authenticate with the AOS REST APIs via the client id/secret method. We encourage you to continue reading below to learn about what constitutes a REST operation, but if you need to quickly call the APIs, this video is for you.

{video placeholder}

How to Authenticate and Authorize requests to the AOS Rest API.

Register your client application with APS

Most AOS REST API endpoint sets require your client code to authenticate with valid credentials before you can call the service's API. Authentication is coordinated between the various actors by APS and provides your client with an access token as proof of the authentication. The token is then sent to the AOS service in the HTTP Authorization header of subsequent REST API requests. The token's claims also provide information to the service, allowing it to validate the client and perform any required authorization.

If you are using a REST API that does not use integrated APS authentication, or you've already registered your client, skip to the Create the request section.

Prerequisites

Your client application must make its identity configuration known to APS before run-time by registering it in an Online Business Tenant. Before you register your client with APS, consider the following prerequisites:

  • If you do not have an Online Business Tenant yet, see Set up an Online Business Tenant.

  • In accordance with the OAuth2 Authorization Framework, APS supports two types of clients. Understanding each helps you decide which is most appropriate for your scenario:

    • web/confidential clients run on a web server and can access resources under their own identity (for example, a service or daemon), or obtain delegated authorization to access resources under the identity of a signed-in user (for example, a web app). Only a web client can securely maintain and present its own credentials during APS authentication to acquire an access token.

    • native/public clients are installed and run on a device. They can access resources only under delegated authorization, using the identity of the signed-in user to acquire an access token on behalf of the user.

You are now ready to register your client application with APS.

Client registration

To register a client that accesses an AOS REST API, see Use the Alliance Developer Center portal to create an application that can access resources. The article (also available in PowerShell and CLI versions for automating registration) shows you how to:

  • Register the client application with APS.
  • Set permission requests to allow the client to access the AOS REST APIs.
  • Configure APS IAM Role-Based Access Control (RBAC) settings for authorizing the client.

If your client accesses an API other than the APS IAM API, refer to:

  • Register an application with the Alliance Passport Service
    • Register the client application with APS, in the "Register an application" section.
    • Create a secret key (if you are registering a web client), in the "Add credentials" section.
  • Configure an application to expose a web API
    • Add permissions to your web API, exposing them as scopes
  • Configure a client application to access a web API
    • Add permission requests as required by the scopes defined for the API, in the "Add permissions to access your web API" section.

Now that you've completed the registration of your client application, move on to your client code where you create the REST request and handle the response.

Create the request

This section covers the first three of the five components that we discussed earlier. You first need to acquire the access token from APS, which you use to assemble your request message header.

Acquire an access token

After you have a valid client registration, you have two ways to integrate with APS to acquire an access token:

Platform and language-neutral OAuth2 service endpoints, which we use in this article. The instructions provided in this section assume nothing about your client's platform or language/script when you use the APS OAuth endpoints. The only requirement is that you can send/receive HTTPS requests to/from APS and parse the response message.

The platform- and language-specific Authentication Libraries, which are beyond the scope of this article. The libraries provide asynchronous wrappers for the OAuth2 endpoint requests, and robust token-handling features such as caching and refresh token management. For more information, see the Overview of the ABS SDKs.

The two APS endpoints that you use to authenticate your client and acquire an access token are referred to as the OAuth2 /authorize and /token endpoints. How you use them depends on your application's registration and the type of OAuth2 authorization grant flow you need to support your application at run-time. For the purposes of this article, we assume that your client uses one of the following authorization grant flows: authorization code or client_credentials. To acquire an access token used in the remaining sections, follow the instructions for the flow that best matches your scenario.

Authorization code grant (interactive clients)

This grant is used by both web and native clients, requiring credentials from a signed-in user in order to delegate resource access to the client application. It uses the /authorize endpoint to obtain an authorization code (in response to user sign-in/consent), followed by the /token endpoint to exchange the authorization code for an access token.

  1. First, your client needs to request an authorization code from APS. For details on the format of the HTTPS GET request to the /authorize endpoint, and example request/response messages, see Request an authorization code. The URI contains the following query-string parameters, which are specific to your client application:

    • client_id: A GUID that was assigned to your client application during registration, also known as an application ID.

    • redirect_uri: A URL-encoded version of one of the reply/redirect URIs, specified during registration of your client application. The value you pass must match your registration value exactly.

    • resource: A URL-encoded identifier URI that's specified by the REST API you are calling. Web/REST APIs (also known as resource applications) can expose one or more application ID URIs in their configuration. For example:

The request to the /authorize endpoint first triggers a sign-in prompt to authenticate the user. The response you get back is delivered as a redirect (302) to the URI that you specified in redirect_uri. The response header message contains a location field, containing the redirect URI followed by a code query parameter. The code parameter contains the authorization code that you need for step 2.

Next, your client needs to redeem the authorization code for an access token. For details on the format of the HTTPS POST request to the /token endpoint and request/response examples, see Request an access token. Because this is a POST request, you package your application-specific parameters in the request body. In addition to some of the previously mentioned parameters (along with other new ones), you will pass:

code: This query parameter contains the authorization code that you obtained in step 1.

client_secret: You need this parameter only if your client is configured as a web application. This is the same secret/key value that you generated earlier, in client registration.

Client credentials grant (non-interactive clients)

This grant is used only by web clients, allowing the application to access resources directly (no user delegation) using the client's credentials, which are provided at registration time. The grant is typically used by non-interactive clients (no UI) that run as a service or daemon. It requires only the /token endpoint to acquire an access token.

The client/resource interactions for this grant are similar to step 2 of the authorization code grant. For details on the format of the HTTPS POST request to the /token endpoint and request/response examples, see the "Get a token" section in the Authentication and Authorization and the OAuth 2.0 client credentials flow section.

Assemble the request message

Most programming languages or frameworks and scripting environments make it easy to assemble and send the request message. They typically provide a web/HTTP class or API that abstracts the creation or formatting of the request, making it easier to write the client code. For brevity, and because most of the task is handled for you, this section covers only the important elements of the request.

Request URI

Because sensitive information is being transmitted and received, all REST requests to any AOS Service Endpoint requires the HTTPS protocol for the URI scheme, giving the request and response a secure channel. The information (that is, the APS authorization code, access/bearer token, and sensitive request/response data) is encrypted by a lower transport layer, ensuring the privacy of the messages.

The remainder of your service's request URI (the host, resource path, and any required query-string parameters) are determined by its related REST API specification. For a more detailed reference on each AOS REST Endpoint, please refer to the AOS REST API Interactive Documentation.

Request header

The request URI is bundled in the request message header, along with any additional fields required by your service's REST API specification and the HTTP specification. Your request might require the following common header fields:

  • Authorization: Contains the OAuth2 bearer token to secure the request, as acquired earlier from APS.
  • Content-Type: Typically set to "application/json" (name/value pairs in JSON format), and specifies the MIME type of the request body.
  • Host: The domain name or IP address of the server where the REST service endpoint is hosted.
Request body

As mentioned earlier, the request message body is optional, depending on the specific operation you're requesting and its parameter requirements. If it's required, the API specification for the service you are requesting also specifies the encoding and format.

The request body is separated from the header by an empty line, formatted in accordance with the Content-Type header field. An example of an "application/json" formatted body would appear as follows:

{
  "<name>": "<value>"
}

Send the request

Now that you have the service's request URI and have created the related request message header and body, you are ready to send the request to the AOS REST service endpoint.

For example, you might send an HTTPS GET request method for an AOS REST API endpoint by using request header fields that are similar to the following (note that the request body is empty):

GET /api/v2/subscriptions HTTP/1.1
Authorization: Bearer <bearer-token>
Host: fenix-alliance.com



<no body>

And you might send an HTTPS PUT request method for an AOS REST API endpoint by using request header and body fields similar to the following example:

PUT /api/v2/subscriptions/d0928ef4-84b0-4710-9a8e-e34c82ccc917  HTTP/1.1
Authorization: Bearer <bearer-token>
Content-Length: 29
Content-Type: application/json
Host: fenix-alliance.com

{
  "displayName": "My Subscription"
}

After you make the request, the response message header and optional body are returned.

Process the response message

The process concludes with the final two of the five components.

To process the response, parse the response header and, optionally, the response body (depending on the request). In the HTTPS GET example provided in the preceding section, you used the /API/v2/subscriptions endpoint to retrieve the list of subscriptions for a user. Assuming that the response was successful, you should receive response header fields that are similar to the following example:

HTTP/1.1 200 OK
Content-Length: 303
Content-Type: application/json;

And you should receive a response body that contains a list of subscriptions and their individual properties encoded in JSON format, similar to:

[
    {
        "id":"d0928ef4-84b0-4710-9a8e-e34c82ccc917",
        "subscriptionId":"123cc9dd-09c9-47de-9f2b-2517adfcfd44",
        "displayName":"My Subscription",
        "state":"Enabled",
    }
]

Similarly, for the HTTPS PUT example, you should receive a response header similar to the following, confirming that your PUT operation to add the "ExampleResourceGroup" was successful:

HTTP/1.1 200 OK
Content-Length: 193
Content-Type: application/json;

And you should receive a response body that confirms the content of your newly added resource group encoded in JSON format, similar to:

{
    "id":"123cc9dd-09c9-47de-9f2b-2517adfcfd44",
    "name":"ExampleResourceGroup",
    "location":"westus",
    "properties":
        {
        "provisioningState":"Succeeded"
        }
}

As with the request, most programming languages and frameworks make it easy to process the response message. They typically return this information to your application following the request, allowing you to process it in a typed/structured format. Mainly, you are interested in confirming the HTTP status code in the response header, and parsing the response body according to the API specification (or the Content-Type and Content-Length response header fields).

Authorizing request against the Alliance Online Services

Some apps call the Alliance Online Services ("AOS") APIs with their own identity and not on behalf of an Account Holder. In many cases, these are background services or daemons that run on a server without the presence of a signed-in user. An example of such an app might be a contact information updater service that wakes up and runs overnight. In some cases, apps that have a signed-in user present may also need to call the AOS APIs under their own identity. For example, an app may need to use functionality that requires more elevated privileges in an Online Business Tenant than those granted by the signed-in Account Holder.

Authentication and authorization steps

The basic steps required to configure a service and get a token from the Alliance Passport Services ("APS") API for the endpoint that your service can use to call the AOS under its own identity are:

  1. Register your app.
  2. Configure permissions for AOS on your app.
  3. Get an access token.
  4. Use the access token to call Alliance Online Services.

1. Register your app

To authenticate with the Alliance Passport Service IAM endpoint, you must first register your app at the Alliance Developer Center portal. You need to use a business enrollment with enough privileges to register your app.

For a service that will call AOS under its own identity, you need to register your app for the Web platform and copy the following values:

  • The Application Identifier assigned by the Alliance Developer Center portal.
  • The Public Key assigned by the Alliance Developer Center portal.
  • The Private Key assigned by the Alliance Developer Center portal.
  • A Redirect URL for your service to receive token responses.
  • A Redirect URL for your service to receive admin consent responses if your app implements functionality that requires administrator consent.

For steps on how to configure an app using the Alliance Developer Center portal, see Register your app.

With the OAuth 2.0 client credentials grant flow, your app authenticates directly at the APS IAM endpoint through the API/v2/OAuth/token endpoint using the Application Public Key and Application Secret assigned by the Alliance Developer Center Portal.

2. Configure permissions for Alliance Online Services

For apps that call AOS under their own identity, APS exposes application permissions (APS can also expose delegated permissions for apps that call AOS on behalf of an Account Holder). You pre-configure the application permissions your app needs when you register your app.

By default, application permissions always require administrator consent. An administrator can either consent to these permissions using the Alliance Developer Center portal when your app is installed in their Business Tenant, or you can provide a sign-up experience in your app through which administrators can consent to the permissions you configured. Once administrator consent is recorded by APS, your app can request tokens without having to request consent again. For more detailed information about the permissions available with the Alliance Business Suite, see the Permissions reference.

To configure application permissions for your app in the Alliance Developer Center portal: under an application's API permissions page, choose "Add permission", then choose the permissions your app requires under Application permissions.

The following screenshot shows the Select Permissions page for application permissions. image.png Note: We recommend that you configure the least privileged set of permissions required by your app. This provides a much more comfortable experience for administrators than having to consent to a long list of permissions.

3. Get an access token

In the OAuth 2.0 client credentials grant flow, you use the Application Public Key and Application Secret values that you saved when you registered your app to request an access token directly from the APS /token endpoint.

You specify the pre-configured permissions bypassing the permission ids as a comma-separated list as the value for the requested_scopes parameter in the token request. See the scope parameter description in the token request below for details.

Token request You send a POST request to the APS /token endpoint to acquire an access token:

// Line breaks are for legibility only.

POST https://fenix-allliance.com/api/v2/oauth2/v2.0/token
HTTP/1.1
Host: fenix-allliance.com
Content-Type: application/x-www-form-urlencoded

client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&client_secret=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=assets_read,assets_create,assets_delete
&grant_type=client_credentials

TOKEN REQUEST

ParameterConditionDescription
client_idRequiredThe Application Public Key that the Alliance Developer Center portal assigned when you registered your app.
client_secretRequiredThe Application Private Key that you generated for your app in the Alliance Developer Center portal. ​
grant_typeRequiredMust be client_credentials.
requested_scopesRequiredThe value passed for the scope parameter in this request should be the resource identifier (Permission ID) of the resource you want to work with. For APS IAM, the value default informs the APS endpoint that of all the application permissions you have configured for your app in the app registration portal, although it is highly recommended that you should issue a token for the ones associated with the resource you want to use.
requested_enrollmentoptionalThe Business Profile Record ID that you want to request permission from. This must be a GUID.

Token response A successful response looks like this:

{
 ​"token_type": "Bearer",
 ​"expires_in": 3599,
 ​"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBP..."
}

TOKEN RESPONSE

ParameterDescription
access_tokenThe requested access token. Your app can use this token in calls to AOS.
token_typeIndicates the token type value. The only type that APS supports is Bearer.
expires_inHow long the access token is valid (in seconds).​

4. Use the access token to call Alliance Online Services

After you have an access token, you can use it to call any AOS Web API by including it in the Authorization header of a request. The following request gets the profile of a specific user. Your app must have the User.Read.All permission to call this API.

GET https://fenix-alliance.com/api/v2/me
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw
Host: fenix-alliance.com

A successful response will look similar to this (some response headers have been removed):

HTTP

HTTP/1.1 200 OK
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
request-id: f45d08c0-6901-473a-90f5-7867287de97f
Duration: 309.0273
Date: Wed, 26 Apr 2017 19:53:49 GMT
Content-Length: 407
{
{
  "id": "aa4sg587b-c7f5-44e0-947e-50a5b73f33ed",
  "publicName": "GreatWarrior23",
  "idProvider": "Alliance Passport Services SSO",
  "email": "jhon.doe@contoso.com",
  "coverURL": "data:image/jpeg;base64,/9j/4AAQSkZJsadS..LKSCtz/9k=",
  "avatarURL": "data:image/jpeg;base64,/9j/4AAQSkZJRgA..jACCtz/9k=",
  "followsCount": 2,
  "followersCount": 2,
  "enrollmentsCount": 8,
  "socialProfileID": "s687a1d-dad6-4433-a1d1-83316e9edwed",
  "cartID": "0878e6b6-d25a-481a-ab06-8b76e93e1175",
  "walletID": "1be9de4e-cab1-4044-89f3-a8cc8bf30a8b",
  "currencyID": "COP.COL",
  "currencyISO": "COP",
  "currencyExchange": 3786
}
}

Welcome to the Alliance Online Services GraphQl API reference documentation.

GraphQL was developed by Facebook to facilitate the consultation of information, for example, a mobile application usually contains less information than a web application, so instead of creating 2 services, a service is created to bring only the information that is needed.

The structure of GraphQL is made up of 3 parts

Operation Table and/or data Table fields GraphQL is based on sending requests through queries, there are 3 types:

Query: To consult the information Mutation: To modify information (create, delete, modify) Subscription: For WebSockets (with WebSockets you can for example receive notifications when an event occurs)

Alliance Business Cloud Overview

The Alliance Business Cloud is an HTTP-based service for hosting Alliance Business Suite Instances and other kinds of applications. These can be developed in your favorite language, be it .NET, .NET Core, Java, Ruby, Node.js, PHP, or Python. Applications run and scale with ease on both Windows-based environments.

The Alliance Business Cloud not only adds the power of Microsoft Azure to your Alliance Business Suite instance, such as security, load balancing, autoscaling, and automated management features; You can also take advantages of its DevOps capabilities, such as continuous deployment from Azure DevOps, GitHub, Docker Hub, and other sources, package management, staging environments, custom domain, and free/paid TLS/SSL certificates.

With Alliance Business Cloud, you pay for the Azure compute resources you use. The compute resources you use are determined by the App Service plan that you run your instance on.

Why use Alliance Business Cloud?

  • Centralized Control Panel: Build and manage multiple sites from a single dashboard. You can also run updates, monitor performance, and onboard new portals and applications all from the same place.

  • Certified to hyperscale into the cloud: Certified to run on the largest cloud players such as Amazon AWS, Microsoft Azure, Google Cloud, and all major virtualization & container platforms. Deploy, automate and manage ABS servers in just a few clicks with a selection of virtual machine images with the most popular configurations.

  • Robust Site & Server Security: Broad security levels across OS, network, and instances. Built into the Plesk hosting control panel core and enhanced through our class-leading security partners.

  • Compatible across all platforms and hyper-scale options: You get full root access via SSH on every ABC-powered ABS and dedicated server options are available so you can install any third-party, open-source, or customized application you need.

  • Optimized for the Alliance Business Suite: The Alliance Business Cloud helps customers to be more productive by allowing them to develop, debug, and monitor Alliance Business Suite instances and Alliance Business Cloud Apps locally, and deploy to production using powerful integration tools. Use the range of features and capabilities to quickly and efficiently create highly secure applications optimized for the cloud.

  • API and mobile features: Alliance Business Cloud provides turn-key CORS support for RESTful API scenarios, and simplifies mobile app scenarios by enabling authentication, offline data sync, push notifications, and more.

Limitations

  • Alliance Bussiness Suite on Linux is not supported on Alliance Business Cloud. Please check Computeworks Hosting for an alternative solution.

  • The Alliance Business Cloud shows only features that currently work for Windows apps. As features are enabled, they're activated on the portal.

  • When deployed to built-in images, your code and content are allocated a storage volume for web content, backed by Azure Storage. The disk latency of this volume is higher and more variable than the latency of the container filesystem. Apps that require heavy read-only access to content files may benefit from the custom container option, which places files in the container filesystem instead of on the content volume.

The Alliance Business Cloud is designed to help IT specialists manage Alliance Business Suite instances and their required services such as web, DNS, mail, and other services through a comprehensive and user-friendly GUI called the ABC Portal. The ABC Portal is a hosting control panel built on top of Plesk, an intermediary between system services and ABS instances. For example, when a user creates a website through the ABC Portal GUI, Plesk propagates this request to a web server running IIS, and the latter adds a new virtual host to the system. This method of administering all system services from a single web interface reduces maintenance costs and gives administrators more flexibility and control.

How can I use the ABC Portal?

The ABC Portal is an essential instrument for customers, businesses, Alliance Trusted Advisors. Once an instance is provisioned on a server, the ABC Portal enables customers to organize and quickly provision resources and monitor consumption. The customers are companies and individuals who need a strong suite of LOB applications to support their operations in a digital society but do not have the necessary IT infrastructure.

Quick Start with the Alliance Business Cloud

This chapter is intended for people new to the Alliance Business Cloud and has the need to provision an Alliance Business Suite instance, but don´t wanna have to worry about server and database provisioning, dependency configuration & licensing fees. If this is your first time installing an ABS on the Alliance Business Cloud, start here.

Taking your business online through the Alliance Business Cloud has the following benefits (to name just a few):

  • Reduced IT costs.
  • Increases Scalability.
  • Ensures business continuity
  • Increases Collaboration efficiency
  • Flexibility of work & DevOps and SecOps practices
  • Access to automatic updates
  • Makes it easy for customers to find your business.
  • Advertises your business and provides important information.
  • Acts as a convenient feedback form.
  • Get's you up and running in no time.
  • (New) Free SSL Certificates (Let's Encrypt)

There are a number of ways you can quickly get your company on the Alliance Business Cloud. The Alliance Business Suite can then get your web presence up and running. The Alliance Business Suite may be as simple as a contacts page, or as complex as a large company website with access to an eCommerce+CMS+ERP system on steroids and with superpowers. Getting your business online is as easy as following these three steps:

  • Register a domain name.
  • Get your free ABS license from https://fenix-alliance.com/licensing.
  • Create your ABC Subscription and set your credentials.

These steps are explained in more detail below.

Registering a Domain Name

Think of the domain name as your business digital address. Your customers will use it to find you online, so make sure that it is a good one. The best domain names are short, easy to type, and easy to remember. An example of a domain name is www.example.com. Registering a domain name can be done through one of the many organizations called domain registrars. Your hosting provider will usually be able to assist you in registering a domain name as well. Web hosting services are often bundled with domain name registration offers and vice versa.

Get your free ABS license from https://fenix-alliance.com/licensing.

Create your ABC Subscription and set your credentials.

Viewing Statistics

To view the reports on disk space and traffic usage by your account:

1. Select your subscription.

If you have several subscriptions associated with your account, select the required subscription in the Subscription menu at the top of the screen.

2. Go to Statistics.

The following information is presented in charts:

Disk space used by the following files and directories in the subscription:

  • Websites
  • Mail accounts
  • Databases
  • Logs
  • Backups
  • Chroot directories
  • Configuration files
  • Anonymous FTP directory
  • Traffic used by FTP, web, and mail services during the current month.

FTP field shows the information about the total size of files transferred to and from the subscription over the file transfer protocol.

HTTP field shows the information about the total amount of data transferred from all of your websites over HTTP protocol, that is, retrieved by web browsers.

POP3/IMAP field shows the total amount of data received by all mail accounts under your domains.

SMTP field shows the total amount of data sent by all mail accounts under your domains.

3. Do any of the following:

  • To view a report on the amount of data transferred to and from your sites over FTP, click FTP Statistics.
  • To view a report on the amount of data transferred to and from your FTP directory, which is accessed without authorization, click Anonymous FTP statistics.
  • To view a report on the amount of traffic used by services during a certain month, click Data Transfer Statistics, and select the required month from the menu.

Remember that your subscription can be suspended automatically if you overuse disk space depending on the Provider's policy. Here are some tips that can help you free up some space:

  • Remove any unnecessary and/or obsolete files that are stored in the httpdocs folder.
  • Configure log rotation as described in the Log Files section.
  • Delete outdated emails, or configure your mail client to download email messages from the server by switching to POP3. See the Access Your Mailbox section for more information.
  • Remove outdated backup files as described in the Uploading and Downloading Backup Files section.
  • Remove unnecessary databases. See the Website Databases section for more information.

The Disk space usage by services chart displays how much space is taken up by website content, emails, backups, logs, and databases. It makes sense to pay attention to the services that use the most disk space. If none of the steps above helped, contact your provider to increase the amount of disk space available to your subscription.

view-statistics.png

Depending on your service plan, the following hosting features may be available for your websites (listed at the Account > Hosting Options tab):

SSL/TLS support.

This allows you to secure connections to websites with SSL/TLS encryption.

For information about securing sites with SSL/TLS, refer to the section Securing Connections with SSL/TLS Certificates.

Web statistics.

This allows you to view website visit statistics presented in diagrams and charts.

For information about viewing website visit statistics, refer to the section Viewing Statistics.

Custom error documents.

This allows you to create custom HTML pages and configure a webserver to show them instead of typical error messages, such as 404 Not Found.

For information about setting up custom error documents, refer to the section Setting Up Custom Error Pages.

Support for programming and scripting languages, such as PHP, CGI, Perl, Python, Microsoft ASP, ASP.NET, SSI.

Dedicated IIS application pool.

This option provides isolation and improved stability for web applications working on sites.

Additional write/modify permissions.

This option allows web applications to use a file-based database (like Jet) located in the root of the httpdocs or httpsdocs folder.

Allow web users to use scripts.

This allows scripting at web pages available at URLs like http://example.com/~ /, where refers to a web user. Web users are individuals who do not need their own domain names. This service is popular with educational institutions that host non-commercial personal pages of their students and staff.

Allocated and Consumed Resources

If you are subscribed to a number of service plans at once, then you have several subscriptions. For each subscription, the following types of allocated resources are listed in Plesk at the Account section > Resources:

Disk space.

This is the total amount of disk space allocated to your account with a subscription. This amount includes all data related to your websites, email accounts, applications, backups, and log files.

Traffic.

This is the total amount of data in megabytes that can be transferred monthly from all your websites.

Domains.

This is the number of websites that can have separate second-level domain names, such as, for example, example.com.

For information about setting up websites, refer to the sections Set Up Your First Website and Adding Domains.

Subdomains.

This is the number of additional websites that can have third-level domain names, such as, for example, news.example.com.

For information about setting up subdomains, refer to the section Adding Subdomains.

Domain aliases.

This is the number of additional domain names that can be set up to point to one of your sites. For example, example.fr and example.de can both point to example.com.

For information about setting up domain aliases, refer to the section Adding Domain Aliases.

Mailboxes.

This is the number of mailboxes that can be created under all your websites.

For information about creating mailboxes, refer to the chapter Mail.

Mailbox size.

This is the amount of disk space that can be occupied by a mailbox.

Total mailboxes quota.

This is the total amount of disk space that can be used by all mailboxes under all your domains. This option is available only on Windows-based customer accounts.

Mailing lists.

This is the total number of mailing lists that can be set up under all your websites. Note that there are mailing lists and mail groups, which serve the same purpose, but are slightly different in functionality. Mailing lists support archiving and pre-moderation of messages, while mail groups can only be used for sending one message to a number of recipients at once.

For information about setting up and using mailing lists, refer to the section Using Mailing Lists.

Additional FTP accounts.

This is the number of FTP accounts that can be set up for accessing the subscription, in addition to the main FTP account that was created when your subscription was activated.

For information about setting up FTP accounts, refer to the sections Changing FTP Access Credentials and Adding FTP Accounts.

MySQL databases and MS SQL Server databases.

This is the maximum number of MySQL and Microsoft SQL Server databases respectively that can be created on the Plesk database servers and used by the subscription’s websites.

MySQL databases quota and MS SQL databases quota.

This is the maximum amount of disk space that MySQL and Microsoft SQL Server databases respectively can occupy on a subscription.

MS SQL database file size.

The maximum size of a Microsoft SQL Server database file. Note that if a database consists of more than one file, more disk space might be used than you specify here.

MS SQL database log file size.

The maximum size of a Microsoft SQL Server log file. Note that if a database has more than one log file, more disk space might be used than you specify here.

Java applications.

This is the number of Java applications packaged in WAR format that you can install on your sites.

Sites published with Presence Builder.

This is the number of sites that you can create and publish using Presence Builder if the Presence Builder option is included in your hosting package.

Web users.

This is the number of user accounts that you can create for hosting web pages for other users under your domains.

ODBC DSN connections.

This is the number of connections to external databases that you can create for web applications running on your customer account. This option is available only for Windows-based customer accounts.

Welcome to the Alliance Pay Platform Documentation

By leveraging industry-leading APIs from vendors like MasterCard, Visa, and several payment gateways, Alliance Pay Platform provides multi-channel global payment processing services, advanced fraud prevention, and risk management solutions.

Features

  • Instant activation: our clients can make transactions in minutes. It also allows for fully online incorporation with minimal documentation.
  • Easy integration: through SDKs for several languages, integrate, and start using Alliance Payment Platform in less than an hour.
  • API Driven: Build your business at scale with our full API-based automation that requires no manual intervention.
  • Multiple payment methods: we have at your disposal more than 22 payment methods available. And others will constantly be added.
  • The best support: it is based on tickets, telephone, and chat, which are always available to help you solve each step you take.
  • Admin Dashboard - Refers to real-time data and information in your Alliance Payment Platform dashboard to make informed business decisions.
  • Secure: based on compliant standard PCI DSS Level 1 transactional processing services.

Prerequisites

To receive payments: To receive payments, you must create a Cloud Business Tenant using the Merchant Center. Once created, you'll be able to use the platform in development mode.

Tutorial

###To Pay an order:

Orders allow customers to create recurring payments for customers using pre-built templated orders (also called "proforma invoices").

  • If the order hasn't been confirmed: To pay an order using the Alliance Pay Platform you must confirm it first, either through the REST order confirmation endpoint or the Collection Portal.

    To confirm an order using the Collection Portal, navigate to your Dashboard > Orders, select the order you want to confirm, and click on "Generate Invoice". This will generate an Invoice based on the Order.

To pay an invoice:

  • Pay using credit card: To pay an invoice using the Alliance Pay Platform you can use one of many payment processing methods, such as, either through the REST API endpoint or the Collection Portal.

Test Credit Cards

Accepted

Franchise: Visa
Number: 4575623182290326
Expiration: 12/2025
CVV: 123
Status: Accepted
Response: Accepted

Insufficient Funds

Franchise: Visa
Number: 4151611527583283
Expiration: 12/2025
CVV: 123
Status: Declined
Response: Insufficient Funds

Failed

Franchise: Mastercard
Number: 5170394490379427
Expiration: 12/2025
CVV: 123
Status: Failed
Response: Communication error with the authorization center

Pending

Franchise: American Express
Number: 373118856457642
Expiration: 12/2025
CVV: 123
Estado: Pendiente
Response: Transaction pending for validation

Collection Portals

With our extensive experience in payment processing, collection solves the main needs of your company when you need to receive payments on the issuance of invoices or provision of services. To learn more about these features visit the page fenix-alliance.com/pay/portals

Collection portals are white-labeled web applications that allow small or large companies to control the payments of their invoices or receive collections in a simplified way through different options and rules.

Below you can learn how to manage the collection portal and get the most out of its functionalities:

Managing Collection Portals:

Collections Portals are an opt-in service for the Alliance Pay Platform. Among other functionalities, Collection Portals allow you to:

  • Multiple payment methods
  • Multiple pay currencies
  • Personalization of the website of payments or collections
  • Build and download detailed reports
  • Help or information text
  • Payment confirmation URL
  • Consultation of records online

Franchises

CodeDescription
AMAmex
BABaloto
CRCredencial
DCDiners Club
EFEfecty
GAGana
PRPunto Red
RSRed Servi
MCMastercard
PSEPSE
SPSafetyPay
VSVisa

Refunds, partial refunds, and restocking fees

We do NOT charge restocking fees for returns of defective products if you have received the wrong product, if it doesn't match what was shown on our site or if we have made some other shipping error.

Restocking Fees

If you use the return online portal found here to process your return within the item's return policy period, you will receive a prepaid return label at no charge and a full refund to the original form of payment* for the following items:

You return

  • Defective items (no fault of customer)

  • Unopened items returned in the original condition as shipped

  • Wrong item shipped or item does not match what was shown on the Fenix Alliance S.A.S website

You receive

100% of the item's purchase price AND free shipping label

Partial refunds

You may receive a partial refund to the original form of payment* for the items listed below.

You return

  • Non-defective items that are returned opened and within the item's return policy period.

  • Non-defective special orders or custom-built items within the return policy period.

You receive

85% of the item's purchase price

You may receive a partial refund to the original form of payment* for the items listed below. Returns for these reasons will require Fenix Alliance's Customer Service assistance.

You return

  • Non-defective items that are returned unopened and beyond the return policy period

You receive

85% of the item's purchase price

Returns received in any of the following conditions may be rejected or may receive a partial refund.

You return

  • Items not in original condition, damaged, missing accessories, retail box, UPC code or showing obvious misuse not due to Fenix Alliance S.A.S error

  • Physical user damage

You receive

Up to 50% of the item's purchase price

Rejected items will be returned to the customer

You return

Opened, non-defective notebook and desktop PCs, tablets and TVs in original condition and within the return policy window

You receive

75% of the item's purchase price

You return

Opened physical software, DVDs, games with plastic wrap removed and ALL downloadable software not due to a Fenix Alliance S.A.S' error

You receive

0% of the item's purchase price (non-refundable)

Please note:

  • Marketplace items from 3rd-party sellers follow the individual seller's return policy. See Marketplace FAQs here for more information.

  • Fenix Alliance S.A.S items purchased as gifts are refunded as store credit only.

  • Non-returnable purchases include digital content, prepaid cards, gift packaging, memberships, completed services, consumable items (e.g., batteries, ink and 3D printer filament), and items that are user damaged, unsanitary or missing major contents.

  • If an unopened item purchased from Fenix Alliance S.A.S Global is returned, a restocking fee will be applied.

Return Policy

This Return Policy only applies to products that are listed on any website or mobile application owned or operated by Fenix Alliance S.A.S (the "Site") as "Sold and Shipped by Infinity Comex".

For a Marketplace item, an item that is listed on the Site as "Sold and Shipped" by a third-party seller through Infinity Comex's Marketplace platform and not "Sold and Shipped by Infinity Comex" ("Marketplace Item"), the Marketplace Item is covered by the Marketplace seller's return policy. To learn more about returns for Marketplace Items, please review our Marketplace FAQs

Overall Return Guidelines

These are Fenix Alliance S.A.S' Overall Return Guidelines. All returns must meet the overall guidelines in order for the individual return policy to apply.

  • All product returns require a Return Merchandise Authorization (RMA) number.

  • You can request an RMA number by contacting with a customer service representative or by creating a support ticket on your Alliance ID:

    • If you are an international customer, please contact with a support representative for return instructions.
  • Most products that are new and unopened can be returned to Fenix Alliance S.A.S within 30 days.

  • Products that are received by Fenix Alliance S.A.S in any of the following conditions are not eligible for return and may be rejected:

    • Any product not purchased from the Infinity Comex Platform.

    • Any product that does not exhibit the described reason for the return (i.e., a return initiated for a DOA product that powers on and works properly upon inspection).

    • Any product with a missing, damaged, altered, or otherwise unreadable serial number label, manufacturer model or part number label, and/or warranty label.

    • Any product that is returned without all original packaging and accessories, including the retail box, manuals, cables, and all other items originally included with the product.

    • Any product from which the UPC code has been removed from its packaging.

    • Any product that exhibits physical damage. If you received your product damaged, please read our Report a shipping problem article for guidelines and instructions on how to resolve this issue. This is would not be considered a return.

    • Any product for which you have submitted a mail-in rebate.

    • Any product which appears tampered, customized or altered in any way.

    • Any product that is returned with markings or writing made by the customer on the original box.

Restocking Fees and Return Shipping Labels

Returns are subject to restocking fees and return shipping fees. For products that are eligible for return for replacement, the return shipping labels are free for returns for replacement of the same item within the applicable return policy period. Fenix Alliance S.A.S does NOT charge for restocking fees or return shipping labels for returns of defective products or unopened items that are returned in the original condition as shipped or if you received the wrong product, the product did not match what was shown on the Site or we made some other shipping error, provided the item is returned within its return policy period. In the event a product is returned that is not defective or an incorrect product or where the product does match what was shown on the Site, the product will either be returned to the customer or the return shipping cost initially covered by Fenix Alliance S.A.S will instead be deducted from the refund amount along with any necessary restocking fee that may apply. Please click here to learn more about restocking fees and return shipping fees.

Return Policies

Standard Return Policy

  • Request a return for refund within: 30 days

  • Request a return for replacement within: 30 days

This is our Standard Return Policy. For items covered by this policy (those products for which Fenix Alliance S.A.S states "This item is covered by Fenix Alliance S.A.S' Standard Return Policy"), you must request a return within 30 days from the invoice date for this policy to apply.

Please review the notes specific to your product:

  • Desktop PC, Notebooks, or Tablet PCs:

    • A defective Desktop PC, Notebook, or Tablet PC that is returned for a replacement may be repaired or replaced at Fenix Alliance S.A.S' sole discretion, unless otherwise required by law. While we strive to adhere to our own standard RMA processing times, we cannot guarantee that these times will be met, especially in situations where the item must be sent to the manufacturer for repair. If you have a question regarding returning a Desktop PC, Notebook, or Tablet PC, please contact our customer service Department.

    • Some computer systems will require pre-authorization from the manufacturer technical support in order for an RMA to Fenix Alliance S.A.S to be authorized.

    • For computers that have had an additional operating system(s) installed, we will provide you a replacement or refund as noted in the above policy as long as the original operating system is not corrupted or removed.

  • Televisions:

    • For televisions with a screen size greater than 37 inches: An adult (age 18 or older) is required to sign the shipping courier's release form to complete delivery. It is highly recommended that you inspect the product upon delivery for visible damage. Large item shipments require that shipping damage is reported within 48 HOURS of the product's delivery. To the fullest extent permitted by law, any damage reported more than 48 HOURS after the product delivery will not be accepted by Fenix Alliance S.A.S for replacement or refund. After delivery, please read all included documentation and/or contact the manufacturer directly to determine applicable warranty coverage, if any. If you need to return a product that was shipped via Large Item Delivery, please contact Fenix Alliance S.A.S' customer service department to obtain instructions on how to return the product.
  • Television and Monitor Dead Pixels:

    • Televisions or Monitors with 8 dead pixels or more can be returned for a replacement so long as a return request is submitted within 30 days of the invoice date.

45/1 Return Policy

  • Request a return for refund within: 45 days

  • Request a return for replacement within: 1 year

This is our 45/1 Return Policy. For items covered by this policy (those products for which Fenix Alliance S.A.S states "This item is covered by Fenix Alliance S.A.S' 45/1 Return Policy"), you must request a return for refund within 45 days of the invoice date or request a return for a replacement within 1 year of the invoice date for this policy to apply.

Replacement Only Return Policy

  • Request a return for replacement within: 30 days

This is our Replacement Only Return Policy. For items covered by this policy (those products for which Fenix Alliance S.A.S states "This item is covered by Fenix Alliance S.A.S Replacement Only Return Policy"), you must request a return for replacement within 30 days from the invoice date for this policy to apply. Products covered by this policy may only be returned for a replacement of the same item. If the original item is no longer available, a refund in the amount of the price originally paid will be issued. Products subject to this policy cannot be returned for a refund.

Manufacturer Only Return Policy

This is our Manufacturer Only Return Policy. Items covered by this policy (those products for which Fenix Alliance S.A.S states "This item is covered by Fenix Alliance S.A.S' Manufacturer Only Return Policy") cannot be returned to Fenix Alliance S.A.S. These items are covered by a manufacturer's warranty. For information about the manufacturer's warranty, please refer to the terms and conditions for the manufacturer's warranty or contact the manufacturer.

Consumable Product Return Policy

This is our Consumable Product Return Policy. Items covered by this policy (those products for which Fenix Alliance S.A.S states "This item is covered by Fenix Alliance S.A.S' Consumable Product Return Policy") cannot be returned to Fenix Alliance S.A.S. Consumable products may include, but are not limited to, Printer Ink, Toner Cartridges, CD/DVD Media, Retail Packaged Software, Downloadable Software, Digital Downloads, Paper Products, and etc. that are consumed once they are used.

Retail Packaged Software, Downloadable Software and Digital Downloads

Software may require you to use a computer or other device meeting minimum system requirements, and you are responsible for ensuring that your computer or device meets software system requirements prior to purchase. Generally, software system requirements are available on or from product detail pages. Once you have purchased Retail Packaged Software, Downloadable Software and/or Digital Downloads, we encourage you to install or download it, if applicable, and to access it promptly to ensure that you have received it.

Non-Contract Cell Phone Return Policy

  • Request a return for replacement within: 30 days

This is our Non-Contract Cell Phone Return Policy. For items covered by this policy (those products for which Fenix Alliance S.A.S states "This item is covered by Fenix Alliance S.A.S's Non-Contract Cell Phone Return Policy"), you must request a return within 30 days of the invoice date for this policy to apply. Products covered by this policy may only be returned for a replacement of the same item. If the original item is no longer available, a refund in the amount of the price originally paid will be issued. Products subject to this policy cannot be returned for a refund.

Services and Extended Warranties Return Policy

  • Request a full refund within: 30 days

  • For requests for refunds after 30 days, you may receive a partial refund. A prorated refund may be provided by the warranty provider.

This is our Services and Extended Warranties Return Policy. Items covered by this policy (those products for which Fenix Alliance S.A.S states "This item is covered by Fenix Alliance S.A.S' Services and Extended Warranties Return Policy.") can be returned if the service or warranty has not been used or redeemed. A return must be initiated by Fenix Alliance S.A.S within 30 days of the invoice date for this policy to apply.

International Return Policy

  • Request a return for refund within: 30 days

Items covered by this policy (those products for which Fenix Alliance S.A.S states "This item is covered by Fenix Alliance S.A.S' International Return Policy") must have a return issued through the Fenix Alliance S.A.S Global return portal within 30 days from the invoice date for this policy to apply.

More Information

Product-Specific Return Information

Bundles

Bundles are offered to Fenix Alliance S.A.S shoppers as a way to purchase multiple items together at a discounted price. If you wish to return a Bundle for a refund, you must request a return within the applicable Fenix Alliance S.A.S Return Policy period and you must return the ENTIRE BUNDLE. Items sold as part of a Bundle may be returned individually for replacement if you request a replacement within the applicable Fenix Alliance S.A.S Return Policy period for that individual item.

Combos and Kits

Combos and Kits include two or more items that must be purchased together in order to receive a discount. Items sold as part of a Combo or Kit may be returned individually for replacement within the applicable Fenix Alliance S.A.S Return Policy Period for that individual item.

If an individual Combo or Kit item is returned for a refund, the applicable discount will be voided, and the discounted amount will be deducted from the amount of the refund. If your Combo/Kit discount amount is greater than the individual unit price of the item you wish to return, then the item cannot be returned for a refund by itself; you will need to return all items in the Combo/Kit or return it with other items of value in order to receive a refund. For example, if your Combo/Kit discount was $5, and you return one of the items for a refund, the $5 will be deducted from your refund amount.

Manufacturer Promotional Items and Fenix Alliance S.A.S Gifts

Manufacturers may offer free promotional items with their products. To receive a full refund on a purchase that includes promotional items, all items must be returned. The cost of any promotional items not returned will be deducted from the refund total.

Fenix Alliance S.A.S may also offer gifts to valued customers for their continued support as well as for special giveaways. These gifts are not part of any purchase value and therefore do not have to be returned.

Prepaid card, gift packaging and Memberships

Purchases for prepaid cards, gift packaging and memberships are not eligible for return.

Special Order Products

Special order products are not eligible for return.

Quantity Purchases

While we are more than happy to fill your order for a quantity of ten (10 +) or more of any given item in our inventory on a single purchase order, please understand that an order of that size, once purchase is completed, is automatically non-refundable. All other specific conditions related to the ordered item still apply, including any and all stipulations relative to any available replacement return policies. Please contact our customer service department with any questions you may have.

Additional Return Information

Refunds

Refunds will be credited back to your original payment method. If the original payment method is no longer available, Fenix Alliance S.A.S will mail you a check to the billing address listed on your account.

For returns for refunds for items purchased as discounts, Fenix Alliance S.A.S will issue you a refund in the form of Alliance ID Wallet credit or an Infinity Comex gift card.

Replacements

For products that are eligible for return for replacement, the product may only be returned for a replacement of the same item. We do not allow exchanges or returns for replacements for different items. If you would like to receive a different item, you would need to return the original item for a refund, in accordance with the Return Policy and then purchase the item you would like to receive instead of the original item.

If Fenix Alliance S.A.S no longer carries an item that is sent in for replacement, or if that item is simply out of stock, Fenix Alliance S.A.S will issue you a refund.

###Product Return Procedures

To return a product to Fenix Alliance S.A.S, you must obtain an RMA number within the applicable return period for the product (described above). Fenix Alliance S.A.S will not accept returns without prior authorization and an RMA number. Once issued, RMA numbers are valid for 15 days within which time returned products must be received by Fenix Alliance S.A.S. RMA numbers will not be extended or reissued. Customer should prominently display the RMA number(s) on the shipping label as well as the RMA invoice on the box(s) containing the returned product.

Customer is solely responsible for shipping any returned product to Fenix Alliance S.A.S. Customer agrees to use only reputable carriers capable of providing proof of delivery and insurance for the entire value of the shipment. Customer agrees to bear all shipping and insurance charges and all risk of loss for the return product during shipment. Customer agrees that all returned products will be 100% complete, in re-sealable condition, and will include the original packaging material, manuals, blank warranty cards, and other accessories provided by the manufacturer. If any component of the returned product is missing, Fenix Alliance S.A.S's Return Procedure will be breached and Fenix Alliance S.A.S may in its sole and absolute discretion reject the entire return or choose to impose additional charges against the customer for replacement of the missing component(s). Fenix Alliance S.A.S will not refund the original shipping charges to the Customer. In addition, Fenix Alliance S.A.S may assess a 15% restocking fee against the Customer's account or deduct the fee from the refund amount on all returns, subject to the Return Policy and any product-specific policy. Fenix Alliance S.A.S reserves the right to adjust the value of any item returned for refund to reflect its current market price, in which case the 15% restocking fee will be applied after this adjustment.

Packaging Returns

The return must be properly packaged to protect against damage in transit. Please note that any damage caused by mishandling, improper installation or product defacement will result in your return being denied and the product being returned to you.

Return Processing

Please allow 3-5 business days for your return to process after being received. For returns for laptops, notebooks, desktops, or table PCs, please allow 7-10 business days for your return to process after being received. Due to item availability, some repair/replacement returns may be delayed or changed to refund.

Additional Terms

Title

Fenix Alliance S.A.S does not take title to returned items until the item arrives at the returns address destination. At our discretion, a refund may be issued without requiring a return. In this situation, Fenix Alliance S.A.S does not take title to the refunded item.

Original Shipping Charges

Your original shipping fees are non-refundable. Your original shipping charges are paid for the services provided by and to the original carrier, and will not be refunded to if your item is returned.

Cross-Shipping

We do not cross-ship. Returns must be received, inspected and approved before we ship a replacement.

Refusing Delivery

Refused shipments are treated like regular returns and may be charged a non-refundable 15% restocking fee.

Disclaimer

Nothing in this Return Policy limits your rights and remedies under any law.

Product disclaimers

If you are purchasing any of the following products, please see below for important disclaimers regarding each item type.

Open Box Product

Open Box merchandise are products that have been purchased and delivered to other customers, and then returned to Fenix Alliance S.A.S. Open Box products are sold considerably under cost. Fenix Alliance tests Open Box products for basic functionality only. Due to the varying quality of products returned to Fenix Alliance, Fenix Alliance makes every attempt to supply the original accessories for Open Box products. However, regardless of what the product description says, Fenix Alliance only guarantees that you will receive the product itself, accessories may or may not be included. Bear in mind that your open box product may not contain cables, adaptors, manuals, CDs, drivers, fans, etc. Additionally, the product may exhibit cosmetic imperfections as a result of its having been previously opened. Fenix Alliance will not send you any missing accessory, even if the accessory is required in order to properly make use of all the product's advertised functions. While Fenix Alliance does not like to discourage sales, please purchase open box products only if you know how to deal with potential missing accessories.

Final Sales Product

Sales are final, no refund/exchanges/replacements.

Standalone Service

Proof of Purchase will be required in order to file a claim. Failure to provide proof of purchase will void coverage. Used products or products purchased more than 6 months ago are not eligible for Service Plans. ADH coverage must be purchased within 30 days of product purchase. Service Net reserves the right to cancel contracts (at a full refund to the customer) due to ineligibility.

Downloadable Software

Fenix Alliance Downloadable Software Policy:

  • All sales of Downloadable Software applications are final.

  • Fenix Alliance doesn't accept returns of downloadable software.

  • Please verify purchase quantity before proceeding.

Software may require you to use a computer or other device meeting minimum system requirements, and you are responsible for ensuring that your computer or device meets Software system requirements prior to purchase. Generally, Software system requirements are available on or from product detail pages. Once you have purchased a downloadable product, we encourage you to download it, if applicable, and to access it promptly to ensure that you have received it. You are responsible for downloading and confirming your ability to access software within thirty (30) days after purchase and bear all risk of loss thereafter, including any loss due to a computer or hard drive crashes. We will usually continue to make purchased software available in the Fenix Alliance Order History Page for additional activations or copies even after this thirty (30) day period, but we may, from time to time, remove without notice because of the Software provider's licensing restrictions or for other reasons. Fenix Alliance will not be liable to you if any Software is removed from the Fenix Alliance Order History Page or otherwise becomes unavailable for additional activation or copies. If you are unable to successfully download or access an Application after having reviewed our online help resources, please contact Fenix Alliance customer service.

Digital Deliver Product

Fenix Alliance Digital e-Gift Card/Credit Policy:

  • All sales of Digital Gift Card/Credit are final.

  • Fenix Alliance doesn't accept returns of Digital Gift Card/Credit.

  • Please verify purchase quantity before proceeding.

All sales of Digital E-Gift Card/Credit are final. We do not accept returns of Digital E-Gift Card/Credit. Once you have purchased a Digital E-Gift Card/Credit/Voucher, we encourage you to save the email. Fenix Alliance will not be liable to you for any stolen or misplaced codes. Codes are usually delivered in minutes or, at most, within 48 hours depending on additional order validation required by Fenix Alliance or your Credit Card company. If you are unable to successfully receive your code, please contact Fenix Alliance customer service.

Cell Phone

Please read the product description carefully for all cell phones. Some mobile phones sold by Fenix Alliance that are listed as "Unlocked" may have previously been carrier-specific phones that could still have carrier software, small scratches or carrier badging. By acknowledging this disclaimer, and agreeing to accept the unlocked product, you are acknowledging that you understand this phone may have been unsealed for the purposes of performing this unlock procedure. Mobile phones that are carrier specific are only compatible with the service provider that is listed. No-Contract/Prepaid mobile phones are only compatible with the carrier that is listed. Some No-Contract/Prepaid mobile phones include service airtime. No-Contract/Prepaid service airtime is non-refundable.

Adobe Student Edition Software

Before purchasing this product, please be sure that you (or the person you are buying the product for) are eligible to use the Adobe Student Edition software. Student and Teacher Edition Software Product may be used by:

  • University and college students -- students enrolled at a higher education institution defined as an accredited public or private university or college (including community, junior, or vocational college) that grants degrees requiring not less than the equivalent of two years of full-time study;

  • Primary and secondary school students -- students enrolled at an accredited public private primary or secondary school providing full-time instruction;

  • Faculty and staff -- teachers and staff employed by an accredited primary or secondary school or public or private university or college.

Proof of Eligibility

To receive an authorized serial number, you must provide proof that you are an eligible user of Adobe Student and Teacher Edition Software Product as follows:

  • Students Students must provide a photocopy of a valid, current student ID that includes your name, date, and a photo of yourself. If you do not have such an ID, you must instead provide a photocopy of a valid photo ID and one of the following items:

    • Official, current non-photo student ID with name and date

    • Official, current school transcript indicating name of school and student

    • Official, current school tuition bill indicating name of school and student

    • Official, current report card indicating name of school and student

    • Other official dated proof of enrollment

    Students who are under the age of 18 and do not have a valid photo ID may provide an official letter from their eligible educational institution stating their name and current enrollment status.

  • Teachers, Faculty and Staff Teachers, faculty and staff must provide a photocopy of a valid current school ID that includes your name, date, and a photo. If such end users do not have such an ID, the end user must instead provide a photocopy of a valid photo ID and one of the following items:

    • Faculty or staff paycheck stub

    • An official letter from the registrar of the educational entity

    Formats for Digital Proof of Eligibility The end user must use a digital camera or scanner to create a copy of his/her proof of eligibility. All documents must be clear, legible, and true to size. Acceptable formats include JPEG, GIF, BMP, TIF, and PDF. The file must be no larger than 3MB. Proof of eligibility shall be submitted in accordance with the instructions accompanying the Adobe Student and Teacher Edition Software Product.

Restrictions on Use

A Student and Teacher Edition End User may purchase only one license of any Adobe Student and Teacher Edition product. This license may be used only on your privately owned computer. Student and Teacher Edition Software Products may not be resold by the Student and Teacher End User.

Price matching Policy

With the exception of items that are currently part for our Price Match Guarantee promotion, Fenix Alliance S.A.S does not offer price guarantees.

With the exception of items that are currently part for our Price Match Guarantee promotion, Fenix Alliance S.A.S does not offer price guarantees due to the fact that industry prices change quickly and often. All prices are as posted at the time of purchase. If your order has not been shipped, you can choose to cancel it and re-order to take advantage of any new prices.

Price Match Guarantee

If you find an item advertised at a lower price by an eligible retailer for a product that has a Price Match Guarantee badge on its page, within 5 days of purchase, we will match it after verification

Items with the Price Match Guarantee come with a one-time price match guarantee. If you purchase an item from Fenix Alliance S.A.S which is carrying the Price Match Guarantee badge at the time of purchase, then find the exact same item at a lower price by Fenix Alliance or a major retailer,* within 5 calendar days, just let us know, and we'll send you an Infinity Comex Customer Care Card to cover the difference.

Not valid on exclusive, major-holiday sales event prices offered by Fenix Alliance S.A.S or other retailers

  • This offer applies only to the advertised online price of identical items offered for sale by Fenix Alliance S.A.S and major retailers.*

  • For purposes of comparing prices, the price ("Price") is the total advertised price of the item including shipping costs, but Price shall not include discounts from a "Loyalty" or "Membership" program, and Price shall not include shipping discounts from a membership program such as Amazon Prime.

  • Price Match of a Fenix Alliance item shall include sales tax, if any.

  • Fenix Alliance's and Major retailer's Price must be advertised at the same time the price match is requested.

  • The Price Match Guarantee does not apply to:

    • Auction site prices.

    • Items not displaying the Price Match Guarantee badge at the time of your purchase.

    • Fenix Alliance's or a major retailer's item offered (a) for free or with rebate or coupon or promotional gift card/promotional credit, (b) as part of a bundled offer or financing offer, (c) as a clearance/closeout sale, or (d) for sale for less than 6 hours in a day.

    • Fenix Alliance's or a major retailer's item which is out of stock/not available for immediate shipment or which is offered in limited quantities.

    • A major retailer's item that is advertised below Fenix Alliance's actual cost.

    • Fenix Alliance's or a major retailer's item which is offered as open box or refurbished.

    • Add-on services such as extended warranty or installation.

    • Any item offered by Fenix Alliance or a major retailer which is subject to MAP pricing.

    • Fenix Alliance's or a major retailer's advertised Price which is the result of a typographical error.

  • Limitations: Only one Price Match per customer; only one Price Match per item.

  • Not valid on exclusive, major-holiday sales event prices offered by fenixalliance.com.co/store or other retailers, including:

    • Fantastech Sale

    • Black Friday Sale

    • Cyber Monday Sale

Pricing & Promos

Using a promo code

Promo codes can easily be redeemed in your shopping cart. Once subscribed for at least 24 hours you will be able to use our newsletter promo codes. Some restrictions may apply.

To redeem a promo code, go to your shopping cart, and scroll down to where it says Apply Promo Codes. Enter your email address, wait for the shopping cart to reload, and then enter your promo code.

Important Information: You can only use a promo code once and only one promo code per item. To use a newsletter promo code, you must be subscribed for at least 24 hours. Unless otherwise stated, a promo code will work on up to 5 of the same item if they are all in one order. Promo codes cannot be combined with combo discounts or applied to items with free gifts.

Different price than advertised

You can find more information on the topic of, “different price than advertised” on this page.

Prices and availability of products are subject to change without notice. Errors will be corrected when and where discovered by Fenix Alliance, but we reserve the right to refuse any order, revoke any published offer and correct any errors or inaccuracies, including those discovered subsequent to the submission of an order, and whether or not your credit card has been charged. If your credit card has been charged for the purchase and your order is canceled, Fenix Alliance S.A.S will issue a credit to your credit card account in the amount of the charge.

Please note that the policies of your credit card issuer will determine when this amount is credited to your account. Fenix Alliance S.A.S does not warrant or make any representation about the substance, quality, functionality, accuracy, fitness for a particular purpose, merchantability or any other representation about any third party site or its contents.

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[2.0.0] - 2022-07-26

Added

  • [ABS] In-Studio UI Improvements.
  • [ABS] In-Studio Module Management Engine.
  • [ABS] Business Enrollments Management Engine.
  • [ABS] Business Applications Management Engine.
  • [ABS] Business Security Roles Management Engine.
  • [ABS] Business Security Permissions Management Engine.
  • [ABM] ILicensingService and default implementation (LicensingService).
  • [ABM] ISubscriptionsService and default implementation (LicensingService).
  • [ABM] ISecurityCertificatesService and default implementation (SecurityCertificatesService).
  • [ACL] Adds pt-PT Translations.
  • [ACL] Adds pt-BR Translations.
  • [ACL] Adds de-DE Translations.
  • [ACL] Adds it-IT Translations.
  • [ACL] Adds fr-FR Translations.
  • [ACL] Enables Licensing Engine (ABS Now requires a license).

Fixed

  • [ABM] COA importing capabilities on Accounting Service.
  • [ABS] Error when navigating to the Fiscal Authorities page.
  • [ABS] Virtualize License Types List on Licenses Modal Form.
  • [ABS] Virtualize Subscription Plans List on Subscriptions Modal Form.
  • [ABS] Error when navigating to new created Organization (Contact) details page.

Changed

  • [ABS] Update Studio Base Theme for V2.
  • [ABM] Improve SecurityHelpers class.

[1.9.0] - 2022-07-20

Fixed

  • [ABS] UI Improvements for UI & Core Components.
  • [ABS] Contextual Menu showing when no business is selected.
  • [ABP] Improve DI Tree for most services.

[1.8.0] - 2022-07-04

Added

  • [ABS] Dark Theme Support for Studio.
  • [ABP] OData Support for REST Endpoints.
  • [ABM] ICookiesService and default implementation (CookiesService).
  • [ABM] IDataProtectionService and default implementation (DataProtectionService).
  • [ABM] IBrowserStorageService and default implementation (BrowserStorageService).

Changed

  • [ABS] Update Studio Base Theme for V2.
  • [ABS] Improve Studio Menus & Mobile Layout.

Fixed

  • [APS] NullRedException on SecurityDataService due to DI misconfiguration.

[1.7.2] - 2022-06-04

Added

  • [ABM] IWebUIService and default implementation (WebUIService).
  • [ABM] IDateTimeService and default implementation (DateTimeService).

Changed

  • [ABS] Register Fluent UI & Fast Design Layout Contexts.
  • [ABP] Register IWebUIService default implementation (WebUIService) as Singleton Service.
  • [ABP] Register IDateTimeService default implementation (DateTimeService) as Singleton Service.

[1.7.1] - 2022-06-04

Fixed

  • [ABS] Quick Panels causing UI deadlocks.

[1.7.0] - 2022-06-04

Added

  • [ABS] Studio Static Asset Bundles

Changed

  • [ABS] Improve Country Flag Rendering.
  • [ABS] Improve Country Flag Rendering.
  • [ABS] Improve Studio Rendering Process.
  • [ABM] Improve Curriculum Relations.
  • [ACL] Update dependencies to the latest stable versions.

[1.6.0] - 2022-05-28

Added

  • [ABM] Gig Entity to Database Scheme.
  • [ABM] GigApplication Entity to Database Scheme.

[1.5.9] - 2022-05-27

Fixed

  • [ABM] IContactService's default implementation is now using ICrmDataService.

[1.5.8] - 2022-05-26

Added

  • [ABM] IContactService's default implementation is now using per-operation Data Context instances.

[1.5.7 - 2022-05-25

Added

  • [ABS] ContactSyncronizationStrategy on PortalContext.

[1.5.6] - 2022-05-23

Fixed

  • [ABS] Fix error on Studio Modules Loading Process. More assemblies than necessary used to be passed to the router.
  • [ABM] Adds additional properties to Alliance Business Model for Job Board Applications.
  • [ABM] Adds V1.5.6 ABM Migration for MySQL, MS SQL, and Oracle Data Providers.

[1.5.5] - 2022-05-22

Added

  • [ACL] Brazorize Library Dependency.

Fixed

  • [ABP] Improved ServiceLifetime consistency across default service implementations.
  • [ABS] Improved Studio Rendering Process.

Changed

  • [ACL] Update dependencies to the latest stable versions.
  • [ABS] IAcademyDataService and AcademyDataService are now ILmsDataService and LmsDataService respectively.

[1.5.4] - 2022-05-19

Changed

  • [ABM] Squash migrations for MySQL.
  • [ABP] Update Service Registration Lifetime.
  • [ACL] Update dependencies to the latest stable versions.
  • [ABS] Improve Academy Pages to use new methods on IAcademyService.
  • [ABM] Use new scoped for Scoped Services used over Singleton Services.
  • [ABM] Adds GetStudentCoursesAsync method to IAcademyService and Default Implementation.
  • [ABM] Adds GetStudentProfilesAsync method to IAcademyService and Default Implementation.
  • [ABM] Adds GetCourseEnrollmentAsync method to IAcademyService and Default Implementation.
  • [ABM] Adds GetCourseEnrollmentsAsync method to IAcademyService and Default Implementation.
  • [ABM] Adds GetInstructorCoursesAsync method to IAcademyService and Default Implementation.
  • [ABM] Adds GetInstructorProfilesAsync method to IAcademyService and Default Implementation.
  • [ABM] Adds GetCourseCompletionCertificatesAsync method to IAcademyService and Default Implementation.

Fixed

  • [ABS] Studio wasn't using the SelectedBusinessID for each holder, thus, when reloaded, business selection used to get override with null.

[1.5.3] - 2022-05-15

Changed

  • [ACL] Update dependencies to the latest stable versions.
  • [ABS] Refactor Static Assets to improve package installation time.

[1.5.1] - 2022-05-14

Changed

  • [ACL] Update dependencies to the latest stable versions.
  • [ABS] Improve UI Rendering Process.

[1.5.0] - 2022-05-13

Changed

  • [ACL] Update dependencies to the latest stable versions.
  • [ABS] Improve UI Rendering Process.

[1.4.1] - 2022-05-12

Added

  • [ABM] ICmsDataService.
  • [ABM] ICrmDataService.
  • [ABM] ISocialDataService.
  • [ABM] IMarketplaceDataService.
  • [ABM] ISecurityDataService.
  • [ABM] IGlobalDataService.
  • [ABM] IForexDataService.
  • [ABS] CodeEditorComponent with Monaco Editor.

Fixed

  • [ABS] Fixed Workflows Studio Designer not displaying on production.
  • [ABM] Improve IPricingService implementations to always use the latest data to perform generic/historical/extensible/customizable multi-currency amount calculations.

Changed

  • [ACL] Update dependencies to the latest stable versions.
  • [ABS] Templating Engine now relies on interface services on the Alliance Business Model.
  • [ABS] Templating Engine now relies on default service implementations on the Alliance Business Model.
  • [ABS] PortalContext is now optimized to use DataServices.
  • [ABS] StudioContext is now more efficient through PortalContext Optimization.
  • [ABS] Studio.Core now contains the layout, components, and utilities for the ABS Studio.
  • [ABS] Academy Portal is now an independent dll compatible with Studio.Core.
  • [ABS] Admin Portal is now an independent dll compatible with Studio.Core.
  • [ABS] Wallet Portal is now an independent dll compatible with Studio.Core.
  • [ABS] Holders Portal is now an independent dll compatible with Studio.Core.
  • [ABS] Tenants Portal is now an independent dll compatible with Studio.Core.
  • [ABS] Social Network is now an independent dll compatible with Studio.Core.
  • [ABS] Support Portal is now an independent dll compatible with Studio.Core.
  • [ABS] Developer Portal is now an independent dll compatible with Studio.Core.

Removed

  • [ABM] I

[1.4.0] - 2022-01-12

Added

  • [ACL] .NET 6.0 Support.
  • [ABS] In-Studio Cart.
  • [ABS] In-Studio Store.
  • [ABS] In-Studio Wallet.
  • [ABS] In-Studio Academy.
  • [ABS] In-Studio Networks.
  • [ABS] In-Studio JobBoard.
  • [ABS] Lead Form Component.
  • [ABS] Newsletter Form Component.
  • [ABS] Create Business Modal Form.
  • [ABS] Email Template Editor Pages.
  • [ABS] Token Management Options Page.
  • [ABS] Stock Items Categorizer.
  • [APS] EN-US, ES-CO Localizations.
  • [APS] Account Mgmt. Email Alerts.
  • [APS] Google ReCaptcha Service.
  • [APS] Certificates Manager Service.
  • [APS] OAuth & IODC Service Support.
  • [ABS] Social Feeds & Post Reactions Bar.
  • [ABS] PortalContext Country Selector Form.
  • [ABS] PortalContext Currency Selector Form.
  • [ABS] PortalContext Language Selector Form.
  • [ABS] Monaco Editor Component for WebContent.
  • [ABM] AccountHolder Birthday & Gender Properties
  • [ABM] IPortalContext Interface and default implementation (PortalContext Class)
  • [ABM] ISocialDataService Interface and default implementation (SocialDataService Class)
  • [ABM] IAssembliesService Interface and default implementation (AssembliesService Class)
  • [ABM] IPaymentsService Interface and default implementation (BankTransferPaymentsService Class)
  • [ABM] IStorageService Interface & implementation (FileSystemStorageService, AzureStorageStorageService & AwsS3StorageService Classes)

Changed

  • [ACL] Updated Dependencies to the latest version
  • [ABM] Improved Queries
  • [ABM] Improved MarketplaceData
  • [ABM] Improved Memory Allocation
  • [ABS] Studio Dashboard Icons.

Removed

  • [ACL] Remove deprecated dependencies

Fixed

  • [ABS] Portal & Tenant Selector.
  • [ICX] Duplicated Recently Viewed Product Records.
  • [ABS] Fix Invoice Outliner Glitch.
  • [ABS] Fix Web Installer Versioning Glitch.
  • [ABS] Fix FHIR Server Pooling Glitch.
  • [ABS] Fix Portal Domain Bindings.
  • [ABS] Fix Network Dashboard Deadlock on IP Verification.

[1.3.0] - 2021-07-12

Added

  • [ABM] Oracle Database Provider.
  • [ABM] IOptionsService Interface and default implementation (OptionsService)

Changed

  • [ACL] Updated Dependencies to the latest version.

Removed

  • [ACL] Remove deprecated dependencies.

Fixed

  • [ABS] Fix Workflows Data Provider (LiteSQL)
  • [ABM] Entities Disambiguation

[1.2.1] - 2021-07-13

Added

  • [ABS] View Rendering Cache
  • [ABS] AppDomain Assembly Scoping

[1.2] - 2021-07-12

Added

  • [ABS] Razor Templating Engine
  • [ABS] Custom Options Manager (API)
  • [ABS] Portal Option Manager (UI)
  • [ABS] Custom Portal Option Definitions
  • [ABS] Virtual SPA Support (Angular/React)
  • [ABS] Custom Service Endpoint Definitions

[1.1.9] - 2021-06-30

Added

  • [ABS] Theme Precompilation

[1.1.8] - 2021-06-18

Added

  • [ABS] Workflows Capability

[1.1.7] - 2021-06-06

Added

  • [ABS] Log Viewer
  • [ABS] Template Views
  • [ABS] View Components
  • [ABS] Blog Post Editor
  • [ABS] Drag 'n Drop Live Editor. (Preview)
  • [ABS] Support for Angular and React+Redux SPAs
  • [ABS] Initial Web Content (Editable Pages, Components & Templates)
  • [ABS] Internal Web Content (Sys locked Pages, Components & Templates)
  • [ABS] Frontend Admin Bar
  • [ABS] Invoice Outliner
  • [ABS] Invoice Manager
  • [ABM] Marketing Module Models
  • [ABS] Project Service Models
  • [ABM] LMS Service Models
  • [ABS] Add support for Bootstrap CSS
  • [ABS] Add support for Foundation CSS
  • [ABS] Adds support for Fabric JS and Fluent UI.
  • [ABS] Ensure non-existence of viral licensed libraries. (e.g GNU)
  • [ABS] Adds IViewBuffer, Resx, and Model Resolver to Templating Engine
  • [ABS] Adds Localization String Manager. Initial Localization Capabilities.

Changed

  • [ABS] Fix HTTP context access on IIS making the installation process fail.
  • [ABS] Fix HTTP context access on IIS when trying to create a new view.
  • [ABS] Fix HTTP context access on IIS when trying to edit a new view.
  • [ABS] Fix HTTP context access on IIS when trying to create a new post.
  • [ABS] Fix HTTP context access on IIS when trying to edit a new post.
  • [ABM] Fiscalization document Models
  • [ABM] Project Service document Models
  • [ABM] Pricing engine Models
  • [ABM] Workflow engine Models
  • [ABM] Web Content Records now share a single base class
  • [ABM] ItemPriceList is now a PriceListRecord.
  • [ABS] Fix error when referencing scripts into a Web Content being malformed by templating engine.
  • [ABS] Fix page tree navigation on the live editor.

[1.1.6] - 2021-04-21

Added

  • [ABS] View Precompilation
  • [ABS] Internal Plugin Support+
  • [ABS] Dynamic Portal Metadata
  • [ABS] Google Meta Tags Integration
  • [ABS] Google Analytics Integration
  • [ABS] Google Verification Code Integration
  • [ABS] Bing Verification Code Integration
  • [ABS] Pinterest Verification Code Integration
  • [ABS] Facebook Pixel Verification Code Integration
  • [ABS] ICX Taxonomies Creation Blazor Pages.
  • [ACL] Store Configuration Objects.
  • [APS] External Authentication Provider configuration pages.

Changed

  • [ABP] Fix error while previewing files on File System Explorer.
  • [ICX] Fix error where new users got a 500 when visiting the store.
  • [ICX] Update Swiper to the latest version.
  • [ABS] Monaco editor now lives inside the project instead of as a node module.
  • [ICX] ICX Static Files audit, bundling & minification.
  • [ICX] Fix UI error on cart record addition/deletion.
  • [APS] Fix Auth Error: when users do not belong to any tenant, they used to get an E500 on nested File Retrieval.
  • [ABM] Model Modification to support DB-stored precompiled views.

Removed

  • [ICX] Taxonomies Creation Controllers/Views.

[1.1.4.x] - 2021-04-13

Added

  • [ABS] Extension Updates Page
  • [ABS] Razor Templating Engine
  • [APS] Google Authentication
  • [APS] Facebook Authentication
  • [APS] Microsoft Authentication
  • [APS] Twitter Authentication
  • [APS] LinkedIn Authentication
  • [APS] Instagram Authentication
  • [APS] Github Authentication
  • [SEO] Zift 123 Analytics Script Integration
  • [SEO] Facebook Pixel Integration
  • [SEO] Facebook Chat Widget Integration
  • [SEO] Google Analytics integration
  • [SEO] Google Merchant Center integration
  • [SEO] Google Verification Code Integration
  • [SEO] Google Tag Manager Integration
  • [SEO] Bing Verification code integration
  • [SEO] Pinterest verification code integration
  • [SEO] Dynamic Structured Metadata
  • [UI] Adds Off-Canvas Cart Slider
  • [UI] Dynamic Top Bar content
  • [UI] Logo size customization options
  • [UI] Footer Dynamic Content
  • [UI] Footer/Header Dynamic styling

[1.1.3.x] - 2021-04-09

Added

  • [ACL] Radzen.Blazor is now a project dependency.
  • [ACL] RabbitMQ.Client is now a project dependency.
  • [ACL] Fluid.Core is now a project dependency.
  • [ACL] FluentValidation is now a project dependency.
  • [ACL] NuGet.Packaging is now a project dependency.
  • [ACL] FluentEmail.Core is now a project dependency.
  • [ACL] Flurl.Http is now a project dependency.
  • [ACL] Standard.Licensing is now a project dependency.
  • [ACL] NodaTime is now a project dependency.
  • [ACL] Serilog is now a project dependency.
  • [ACL] Autofac is now a project dependency.
  • [ACL] CsvHelper is now a project dependency.
  • [ACL] Dapper is now a project dependency.
  • [ACL] AngleSharp is now a project dependency.
  • [ACL] IdentityServer4 is now a project dependency.
  • [ACL] DotLiquid is now a project dependency.
  • [ACL] Emitter is now a project dependency.
  • [ACL] MediatR is now a project dependency.
  • [ACL] SixLabors.ImageSharp.Web is now a project dependency.
  • [ACL] RazorLight is now a project dependency.
  • [ACL] MassTransit is now a project dependency.
  • [ACL] ZXing.Net is now a project dependency.
  • [ACL] Z.EntityFramework.Plus.EFCore is now a project dependency.

Changed

  • [ABP] Fix error where plugin assembly paths always returned null (IPluginManager Implementation)

[1.1.2.x] - 2021-02-23

Added

  • Adds ABP Proxy
  • Missing ACL configuration Types
  • ABS Extensions Gallery
  • ABS Extensions Installer
  • ABS Web Installer
  • ABS Admin Portal
  • Dynamic Web Page/Post creation
  • Assembly Explorer
  • Roles and Permissions Explorer
  • Admin Dashboard Initials
  • Added support for SixLabors.ImageSharp.Web
  • Forex service data is now scraped by Fenix Alliance.
  • Data Services are not coded to replaceable interface implementation.
  • ABS.Hub project now contains everything we need to create a new ABS Instance.
  • Added support for IdentityServer4 as a replacement for Alliance Passport Services.
  • ACL.Licensing is now a part of the Alliance Business Suite.

Changed

  • Extracts interface for ACL configuration Types
  • ACS is now ABP.BotEngine
  • Plugin Manager is now loosely coupled to IPluginManager
  • Adds File Manager and FileSystem Service
  • Adds antivirus scanning extension for FileSystem Service (Windows Defender)
  • AccountHolder is now the standard identity class.
  • Fix minor UI glitches and broken links.
  • Fix several bugs on application startup and related extensions.

Removed

  • Data Helpers marked for deprecation.
  • ABS.Nucleus was deprecated and is no longer a part of this project.

[1.1.1.x] - 2021-01-20

Added

  • Adds ABP Proxy
  • Adds Infinity Comex Support
  • Missing ACL configuration Types

Changed

  • Fix Namespaces
  • ABS.Portal.Paperbits is now ABS.Portal.Editor
  • Adds ABS.Portal.UI Components (20+ View Components)

Removed

[1.1.0.x] - 2021-01-12

Added

  • Nuget Packages @1.1.0
  • Initial Portal Admin Blazor Application at route /admin.

Changed

  • Standardize namespace at v1.1.0

Removed

[1.0.0.x] - 2020-12-31

Added

  • Authentication / User Management / Profile Management
  • Authorization / Roles Management / Granular Permissions
  • Blazor Support
  • Cross-Platform Database Support ( MySQL, MSSQL )
  • Dynamic CSS/Lazy Loading
  • Dynamic Page Compositing Model / Site & Page Management
  • Dynamic Routing
  • Dynamic Swagger Specs
  • EF Core Migrations for Database Installation / Upgrade
  • Enabled for Infinity Comex (eCommerce Extension)
  • Event Logging / Audit Trail
  • Extensibility via Custom Modules
  • Extensibility via Custom Themes
  • Folder / File Management (Azure Storage, File System)
  • graphql API with Voyager, GraphiQl y GraphQl Playground
  • Headless API with Swagger Support
  • HealthCheck Rules with UI Support
  • i18n Enabled (Based on GeoAPI and Custom Settings)
  • Improved JavaScript reference support
  • In-App CLI (Studio Commander)
  • Infinity Comex Support (ABS eCommerce Engine)
  • JavaScript Lazy Loading
  • Modular Architecture
  • Multi-Currency Support
  • Multi-Portal ( Monolith & Micro-Service Distributed )
  • Multi-Tenant ( Shared Database & Isolated Database )
  • Notifications / Email Delivery
  • Notifications / SMTP Delivery
  • Progressive Web Application Support
  • Recycle Bin
  • REST API with Swagger Support
  • Scheduled Flows ( Background Processing )
  • Scheduled Jobs ( Background Processing )
  • Seamless Upgrade Experience
  • Slack integration (OAuth)
  • Support For Additional Authentication Providers (OAuth)

Contributing to the Alliance Business Suite and/or its documentation

Woohoo! You've decided to contribute? That's amazing! We want to make contributions to the Alliance Business Suite as easy and frictionless as we can. Contributing requires a GitHub account. If you don't have an account, follow the instructions for the GitHub account setup.

Then, you just need to create an Issue to report bugs, propose APIs, request features and tooling, propose designs and improvements.

All of these contributions will be filled as Issues on the Alliance Business Suite Documentation Repository and they adhere to the following Issue Management Policy.

Issue Management Policy

Because we want to create a world-class product, we spend most of our time coding, designing, and architecting a well-designed solution, so we have adopted the .NET's Issue Management Policy to help us manage incoming Issues. This is a brief summary of some of the policies we have in place and the justification for them.

Commenting on closed issues In general, we recommend you open a new issue if you have a bug, feature request, or question to discuss. If you find a closed issue that is related, open a new issue and link to the closed issue rather than posting on the closed issue. Closed issues don't appear in our triage process, so only the people who have been active on the original thread will be notified of your comment. A new issue will get more attention from the team.

In general, we don't mind getting duplicate issues. It's easier for us to close duplicate issues than to discuss multiple root causes on a single issue! We may close your issue as a duplicate if we determine it has the same root cause as another. Don't worry! It's not a waste of our time!

Needs Author Feedback

If a contributor reviews an issue and determines that more information is needed from the author, they will post a comment requesting that information and apply the Needs: Author Feedback label. This label indicates that the author needs to post a response in order for us to continue investigating the issue.

If the author does not post a response within 7 days, the issue will be automatically closed. If the author responds within 7 days after the issue is closed, the issue will be automatically re-opened. We recognize that you may not be able to respond immediately to our requests, we're happy to hear from you whenever you're able to provide the new information.

PR: pending author input

Similar to the Needs Author Feedback process above, PRs also require author input from time to time. When a member of our team asks for some follow-up changes from the author, we mark these PRs with pr: pending author input label. After doing so, we expect the author to respond within 14 days. If the author does not post a response or updates the PR within 14 days, the issue will be automatically closed. If the author responds within 7 days after the issue is closed, the issue will be automatically re-opened. We recognize that you may not be able to respond immediately to our requests, we're happy to hear from you whenever you're able to provide the new information.

Duplicate issues

If we determine that the issue is a duplicate of another, we will label it with the Resolution: Duplicate label. The issue will be automatically closed in 1 day of inactivity.

Answered questions

If we determine that the issue is a question and have posted an answer, we will label it with the Resolution: Answered label. The issue will be automatically closed in 1 day of inactivity.

Locking closed issues

After an issue has been closed and had no activity for 30 days it will be automatically locked as resolved. This is done in order to reduce confusion as to where to post new comments. If you are still encountering the problem reported in an issue, or have a related question or bug report, feel free to open a new issue and link to the original (now locked) issue!

Reporting a Vulnerability

Security issues and bugs should be reported privately to Fenix Alliance either by emailing support@fenix-alliance.com or via the portal at https://fenix-alliance.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

Please do not open issues for anything you think might have a security implication.

Fenix Alliance's Community & Open Source Code of Conduct.

This code of conduct outlines our expectations for participants within the community, as well as steps to reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all and expect our code of conduct to be honored. Anyone who violates this code of conduct may be banned from the community. Our open source community strives to:

  • Be friendly and patient.
  • Be welcoming: We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
  • Be considerate: Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language.
  • Be respectful: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.
  • Be careful in the words that we choose: we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable.
  • Try to understand why we disagree: Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.

Definitions

Harassment includes, but is not limited to:

  • Offensive comments related to gender, gender identity and expression, sexual orientation, disability, mental illness, neuro(a)typicality, physical appearance, body size, race, age, regional discrimination, political or religious affiliation
  • Unwelcome comments regarding a person’s lifestyle choices and practices, including those related to food, health, parenting, drugs, and employment
  • Deliberate misgendering. This includes deadnaming or persistently using a pronoun that does not correctly reflect a person's gender identity. You must address people by the name they give you when not addressing them by their username or handle
  • Physical contact and simulated physical contact (eg, textual descriptions like “hug” or “backrub”) without consent or after a request to stop
  • Threats of violence, both physical and psychological
  • Incitement of violence towards any individual, including encouraging a person to commit suicide or to engage in self-harm
  • Deliberate intimidation
  • Stalking or following
  • Harassing photography or recording, including logging online activity for harassment purposes
  • Sustained disruption of discussion
  • Unwelcome sexual attention, including gratuitous or off-topic sexual images or behaviour
  • Pattern of inappropriate social contact, such as requesting/assuming inappropriate levels of intimacy with others
  • Continued one-on-one communication after requests to cease
  • Deliberate “outing” of any aspect of a person’s identity without their consent except as necessary to protect others from intentional abuse
  • Publication of non-harassing private communication

Our open source community prioritizes marginalized people’s safety over privileged people’s comfort. We will not act on complaints regarding:

  • ‘Reverse’ -isms, including ‘reverse racism,’ ‘reverse sexism,’ and ‘cisphobia’
  • Reasonable communication of boundaries, such as “leave me alone,” “go away,” or “I’m not discussing this with you”
  • Refusal to explain or debate social justice concepts
  • Communicating in a ‘tone’ you don’t find congenial
  • Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions

Diversity Statement

We encourage everyone to participate and are committed to building a community for all. Although we will fail at times, we seek to treat everyone both as fairly and equally as possible. Whenever a participant has made a mistake, we expect them to take responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and respectfully, and do our best to right the wrong. Although this list cannot be exhaustive, we explicitly honor diversity in age, gender, gender identity or expression, culture, ethnicity, language, national origin, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, and technical ability. We will not tolerate discrimination based on any of the protected characteristics above, including participants with disabilities.

Reporting Issues

If you experience or witness unacceptable behavior—or have any other concerns—please report it by contacting us via support@fenix-alliance.com. All reports will be handled with discretion. In your report please include:

  • Your contact information.
  • Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link.
  • Any additional information that may be helpful.

After filing a report, a representative will contact you personally, review the incident, follow up with any additional questions, and make a decision as to how to respond. If the person who is harassing you is part of the response team, they will recuse themselves from handling your incident. If the complaint originates from a member of the response team, it will be handled by a different member of the response team. We will respect confidentiality requests for the purpose of protecting victims of abuse.

Attribution & Acknowledgements

We all stand on the shoulders of giants across many open source communities. We'd like to thank the communities and projects that established code of conducts and diversity statements as our inspiration:

Third Party Notices

Third-party notices are provided solely for your information and include the original copyright and license which Fenix Alliance received with the third-party software. While Fenix Alliance is not the original author of the third-party materials, Fenix Alliance licenses these third-party materials to you under the terms set forth in the EULA agreement, except that components licensed under open source licenses requiring that such components remain under their original licenses, such as the GNU General Public License (GPL) or the GNU Lesser General Public License (LGPL), are being made available to you by Fenix Alliance under their original licensing terms. Fenix Alliance reserves all rights not expressly granted herein, whether by implication, estoppel, or otherwise.

IdLicenseUrl
AspNetCore.HealthChecks.SqlServerhttps://licenses.nuget.org/Apache-2.0
AspNetCore.HealthChecks.UIhttps://licenses.nuget.org/Apache-2.0
AspNetCore.HealthChecks.UI.Clienthttps://licenses.nuget.org/Apache-2.0
AspNetCore.HealthChecks.UI.InMemory.Storagehttps://licenses.nuget.org/Apache-2.0
AspNetCoreRateLimit
Autofachttps://licenses.nuget.org/MIT
Autofac.Extensions.DependencyInjectionhttps://licenses.nuget.org/MIT
AutoMapperhttps://licenses.nuget.org/MIT
AutoMapper.Collection.EntityFrameworkCorehttps://licenses.nuget.org/MIT
AutoMapper.Extensions.Microsoft.DependencyInjectionhttps://licenses.nuget.org/MIT
Azure.Storage.Blobshttps://licenses.nuget.org/MIT
ByteSize
coverlet.collectorhttps://licenses.nuget.org/MIT
Dapperhttps://licenses.nuget.org/Apache-2.0
FluentEmail.Corehttps://licenses.nuget.org/MIT
FluentEmail.Smtphttps://licenses.nuget.org/MIT
FluentValidationhttps://licenses.nuget.org/Apache-2.0
FluentValidation.AspNetCorehttps://licenses.nuget.org/Apache-2.0
GraphQLhttps://licenses.nuget.org/MIT
GraphQL.Server.Transports.AspNetCorehttps://licenses.nuget.org/MIT
GraphQL.Server.Transports.WebSocketshttps://licenses.nuget.org/MIT
GraphQL.Server.Ui.GraphiQLhttps://licenses.nuget.org/MIT
GraphQL.Server.Ui.Playgroundhttps://licenses.nuget.org/MIT
GraphQL.Server.Ui.Voyagerhttps://licenses.nuget.org/MIT
Humanizerhttps://licenses.nuget.org/MIT
IdentityServer4https://licenses.nuget.org/Apache-2.0
JWT
MailKithttps://licenses.nuget.org/MIT
MassTransithttps://licenses.nuget.org/Apache-2.0
MediatRhttps://licenses.nuget.org/Apache-2.0
MediatR.Extensions.Microsoft.DependencyInjectionhttps://licenses.nuget.org/Apache-2.0
Microsoft.ApplicationInsights.AspNetCorehttps://licenses.nuget.org/MIT
Microsoft.AspNet.WebApi.Clienthttp://www.microsoft.com/web/webpi/eula/net_library_eula_ENU.htm
Microsoft.AspNetCore.Authentication
Microsoft.AspNetCore.Authentication.Abstractions
Microsoft.AspNetCore.Authentication.AzureAD.UIhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Authentication.AzureADB2C.UIhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Authentication.JwtBearerhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Authentication.OpenIdConnecthttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Blazorhttps://raw.githubusercontent.com/aspnet/Home/2.0.0/LICENSE.txt
Microsoft.AspNetCore.Componentshttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Components.Webhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.DataProtectionhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCorehttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Hostinghttps://raw.githubusercontent.com/aspnet/AspNetCore/2.0.0/LICENSE.txt
Microsoft.AspNetCore.Hosting.Server.Abstractions
Microsoft.AspNetCore.Httphttps://raw.githubusercontent.com/aspnet/AspNetCore/2.0.0/LICENSE.txt
Microsoft.AspNetCore.Http.Abstractions
Microsoft.AspNetCore.Http.Featureshttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Identity.EntityFrameworkCorehttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Identity.UIhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Mvc
Microsoft.AspNetCore.Mvc.Corehttps://raw.githubusercontent.com/aspnet/AspNetCore/2.0.0/LICENSE.txt
Microsoft.AspNetCore.Mvc.NewtonsoftJsonhttps://licenses.nuget.org/Apache-2.0
Microsoft.AspNetCore.Mvc.WebApiCompatShimhttps://raw.githubusercontent.com/aspnet/AspNetCore/2.0.0/LICENSE.txt
Microsoft.AspNetCore.SignalR.Core
Microsoft.Azure.KeyVault.Corehttps://licenses.nuget.org/MIT
Microsoft.Bot.Builder.AI.Luishttps://github.com/Microsoft/BotBuilder/blob/master/LICENSE
Microsoft.Bot.Builder.Dialogshttps://github.com/Microsoft/BotBuilder/blob/master/LICENSE
Microsoft.Bot.Builder.integration.AspNet.Corehttps://github.com/Microsoft/BotBuilder/blob/master/LICENSE
Microsoft.CSharphttps://licenses.nuget.org/MIT
Microsoft.EntityFrameworkCorehttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.Designhttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.Proxieshttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.Relationalhttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.SqlServerhttps://licenses.nuget.org/Apache-2.0
Microsoft.EntityFrameworkCore.Toolshttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Caching.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.Caching.Memoryhttps://licenses.nuget.org/MIT
Microsoft.Extensions.Caching.SqlServerhttps://licenses.nuget.org/MIT
Microsoft.Extensions.Configuration.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.DependencyInjectionhttps://licenses.nuget.org/MIT
Microsoft.Extensions.DependencyInjection.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.Diagnostics.HealthChecks.Abstractionshttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCorehttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Hostinghttps://licenses.nuget.org/MIT
Microsoft.Extensions.Hosting.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.Httphttps://licenses.nuget.org/MIT
Microsoft.Extensions.Localizationhttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Localization.Abstractionshttps://licenses.nuget.org/Apache-2.0
Microsoft.Extensions.Logginghttps://licenses.nuget.org/MIT
Microsoft.Extensions.Logging.Abstractionshttps://licenses.nuget.org/MIT
Microsoft.Extensions.Logging.Consolehttps://licenses.nuget.org/MIT
Microsoft.Extensions.Logging.Debughttps://licenses.nuget.org/MIT
Microsoft.Extensions.Primitiveshttps://licenses.nuget.org/MIT
Microsoft.Graphhttps://aka.ms/deprecateLicenseUrl
Microsoft.Identity.Clienthttps://licenses.nuget.org/MIT
Microsoft.IdentityModel.Tokenshttps://licenses.nuget.org/MIT
Microsoft.NET.Test.Sdkhttp://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm
Microsoft.OpenApihttps://raw.githubusercontent.com/Microsoft/OpenAPI.NET/master/LICENSE
Microsoft.Rest.ClientRuntime.Azure.Authenticationhttps://raw.githubusercontent.com/Microsoft/dotnet/master/LICENSE
Microsoft.TestPlatformhttps://www.visualstudio.com/microsoft-visual-studio-test-platform
Microsoft.VisualStudio.Web.BrowserLink
MongoDB.Bsonhttps://aka.ms/deprecateLicenseUrl
MongoDB.Driverhttps://aka.ms/deprecateLicenseUrl
MSTest.TestAdapterhttps://aka.ms/deprecateLicenseUrl
MSTest.TestFrameworkhttps://aka.ms/deprecateLicenseUrl
Newtonsoft.Jsonhttps://licenses.nuget.org/MIT
NodaTimehttps://licenses.nuget.org/Apache-2.0
NodaTime.Serialization.JsonNethttps://licenses.nuget.org/Apache-2.0
NUnit
NUnit3TestAdapterhttps://aka.ms/deprecateLicenseUrl
Pollyhttps://licenses.nuget.org/BSD-3-Clause
Polly.Caching.Memoryhttps://licenses.nuget.org/BSD-3-Clause
Pomelo.EntityFrameworkCore.MySqlhttps://licenses.nuget.org/MIT
reCAPTCHA.AspNetCorehttps://aka.ms/deprecateLicenseUrl
Sendgridhttps://licenses.nuget.org/MIT
Seq.Extensions.Logginghttps://licenses.nuget.org/Apache-2.0
Seriloghttps://licenses.nuget.org/Apache-2.0
Serilog.AspNetCorehttps://licenses.nuget.org/Apache-2.0
Serilog.Enrichers.Environmenthttp://www.apache.org/licenses/LICENSE-2.0
Serilog.Enrichers.Processhttp://www.apache.org/licenses/LICENSE-2.0
Serilog.Enrichers.Threadhttp://www.apache.org/licenses/LICENSE-2.0
Serilog.Settings.Configurationhttps://licenses.nuget.org/Apache-2.0
Serilog.Sinks.AzureBlobStoragehttps://aka.ms/deprecateLicenseUrl
StackifyMiddleware
Swashbuckle.AspNetCore.Swaggerhttps://licenses.nuget.org/MIT
Swashbuckle.AspNetCore.SwaggerGenhttps://licenses.nuget.org/MIT
Swashbuckle.AspNetCore.SwaggerUIhttps://licenses.nuget.org/MIT
System.ComponentModel.Annotationshttps://licenses.nuget.org/MIT
System.IdentityModel.Tokens.Jwthttps://licenses.nuget.org/MIT
WindowsAzure.Storagehttps://github.com/Azure/azure-storage-net/blob/master/LICENSE.txt
xunithttps://raw.githubusercontent.com/xunit/xunit/master/license.txt
xunit.runner.visualstudiohttps://licenses.nuget.org/MIT

About licensing

Our Community Edition was released to help you make your life easier while increasing your odds for success through the right tools and support required for your path for digitalization.

The Community Edition License is not a demo license. You’ll get access to the entire ABS. Either if you are an individual or an organization.

In a nutshell, You’ll only pay for core licensing fees if you use the ABS on behalf of an Enterprise, who’s an organization and its affiliates who collectively have either (a) more than 250 PCs or users or (b) more than one million U.S. dollars (or the equivalent in other currencies) in annual revenues.

Logo and Trademark

The brand name Alliance Business Suite and its logos are trademarks of Fenix Alliance S.A.S in Colombia and Fenix Alliance Inc in other countries ("Fenix Alliance").

Fenix Alliance owns and oversees the trademarks for the ABS name and logos. We have developed this trademark usage policy with the following goals in mind:

  • We’d like to make it easy for anyone to use the ABS name or logo for community-oriented efforts that help spread and improve ABS.
  • We’d like to make it clear how ABS-related businesses and projects can (and cannot) use the ABS name and logo.
  • We’d like to make it hard for anyone to use the ABS name and logo to unfairly profit from, trick, or confuse people who are looking for official ABS resources.

Licensing and Contributions

Your access to and use of the Alliance Business Suite's source code is governed by the Fenix Alliance's End User License Agreement "EULA". If you don't agree to those terms, as amended from time to time, you are not permitted to access or use the Alliance Business Suite.

We welcome any contributions to the Alliance Business Suite development through pull requests on GitHub. Most of our active development is in the develop branch, so we prefer to take pull requests there (particularly for new features). We try to make sure that all new code adheres to the Fenix Alliance coding standards. All contributions are governed by the terms of the EULA.

A note about your account and the privacy of your information.

The Alliance Passport Services engine is built on top of a highly compliant service to keep your identity private. This engine supports Facebook, Microsoft Accounts, Google+, LinkedIn, and many other identity providers, but you can also integrate your own.

We think that it's also worth pointing out that we DO NOT store any identity information into our databases; instead, that data is always encrypted and sent to the same systems that governments and enterprises worldwide are using to keep your data safe, and then we access that data by using industry-standard protocols so that you can rest assured that your sensitive information is protected through various security controls in addition to multi-factor authentication.

To learn more about our privacy policy, please visit: https://fenixalliance.com.co/legal/policies/privacypolicy