Public pages

Introduction

This option can either create completely public pages or pages that can be accessed via registration. On the pages that require registration the user accounts are created as customers.

Permission

Public pages are protected by 3 different methods.

  1. Erply user group permissions - on installation two user groups per app are created app-public-{app_name} and app-b2b-{app_name}, all data fetches to erply api’s will use the rights on these groups.
  2. Dynamic api request whitelist - a list of calls that are allowed with the dynamic api feature.
  3. Parameter whitelist - a list of parameters that we allow to be used.

Dynamic api request whitelist

The whitelist is under the ‘Publish settings’ tab in the editor view.

Publish settings Publish settings

When enabled the dynamic requests would need to be added to the page

Request whitelist Request whitelist

As of 1.234.5+ disabling of these features is not recommended and will be disabled for new templates.

Parameters whitelist

Note

This feature used to be connected to the Alias list (v1.188.5), from v1.189.0 this is now separated from it.

The following error is given when on public pages we send a parameter that is not added to the whitelist.

Parameter whitelist error Parameter whitelist error

The whitelist can be accessed under the ‘Publish settings’ in the editor view. The parameter whitelist counts in presets and request the whitelist (when used) so the values there do not need to be duplicated here.

Publish settings Publish settings

When enabled the used parameters need to be filled to the list of the page.

Parameter whitelist Parameter whitelist

If the permissions were previously set to the aliases then we can also use the ‘Import from alias’ button to automatically fill them based on the alias settings.

As of 1.234.5+ disabling of these features is not recommended and will be disabled for new templates.

Pattern matching rules for parameter whitelist

The whitelist supports pattern matching for the parameters. That would be very helpful when working with the json that contains or generates arrays. At the moment pattern matching is supported for digits <%d%> and string <%s%>.

To define a placeholder just put a <%d%> in the place where actual parameter name may have a number. Can be defined as many placeholders per parameter as needed.

For example, this rule:

KvsApi.Api.Json.saveData.string.entries.<%d%>.value.products.<%d%>.code

will much any of the following parameters:

KvsApi.Api.Json.saveData.string.entries.1.value.products.1.code
KvsApi.Api.Json.saveData.string.entries.2.value.products.1.code
KvsApi.Api.Json.saveData.string.entries.1.value.products.2.code
KvsApi.Api.Json.saveData.string.entries.2.value.products.2.code

Subsections of Public pages

Protected

Introduction

Protected pages can only be accessed with a special customer session

Setup

In order to use the protected features we need a page that that is set up to allow B2B access.

This can be configured in the template editor mode under the ‘Publish setting’ right menu.

Note

As of version 1.248.0 its also possible to set an optional expiration date to the page (UTC unix value) after this timestamp has passed on the server the will no longer be accessible using the b2b endpoint. Use authentication config input set the value.

Also note that this setting is based on applications or auth domains.

Add protected configuration Add protected configuration

  1. Every customer that is registered can only access the same application, the same login cannot be used for another app on the account.
  2. If auth domain is provided then all the applications that share it will also share the customers.

Optionally the redirect field can be used to redirect requests that are not authenticated to a specific page (public login page for example).

Registration

Create a public page that implements the automat api’s registration form. Use the Session.Customer.ID to detect if the user is already logged in.

Optionally, the AutomatApi.B2BLoginRegisterInput.LoginOnSuccess can be used to automatically login newly created user and AutomatApi.B2BLoginRegisterInput.Redirect to redirect the user to a specific page after successful login.

Check the automat api B2BLoginRegisterInput data source docs for additional available fields.

<!-- Read registration errors -->
<div class="my-error-container">
    {{ range .Data.Errors }}
    <span class="my-error-message">{{ . }}</span>
    {{ end }}
</div>

{{ if .Session.Customer.ID }}
    <h1>Already registered</h1>
{{ else }}
    <h1>Register a new user</h1>
    <form method="post">
        <input type="hidden" name="postActionEntity" value="B2BLoginRegisterInput">
        <input type="hidden" name="postActionRedirect" value="b2b-login-demo-page">

        <!-- Configure autologin and redirect -->
        <input type="hidden" name="AutomatApi.B2BLoginRegisterInput.LoginOnSuccess" value="1">
        <input type="hidden" name="AutomatApi.B2BLoginRegisterInput.Redirect" value="b2b-2-members-page">

        <br>
        <label for="firstName">First name</label>
        <input type="text" id="firstName" name="AutomatApi.B2BLoginRegisterInput.Firstname">

        <br>
        <label for="lastName">Last name</label>
        <input type="text" id="lastName" name="AutomatApi.B2BLoginRegisterInput.Lastname">

        <br>
        <label for="email">Email</label>
        <input type="text" id="email" name="AutomatApi.B2BLoginRegisterInput.Username">

        <br>
        <label for="password">Password</label>
        <input type="password" id="password" name="AutomatApi.B2BLoginRegisterInput.Password">

        <br>
        <button type="submit">Register</button>
    </form>
{{ end }}

Login

Create a public page that implements the automat api’s login form. Use the Session.Customer.ID to detect if the user is already logged in.

Optionally the AutomatApi.B2BLoginInput.Redirect can be used to redirect the user to a specific page after successful login

<!-- Read login errors -->
<div class="my-error-container">
    {{ range .Data.Errors }}
    <span class="my-error-message">{{ . }}</span>
    {{ end }}
</div>

{{ if .Session.Customer.ID }}
    <p>Welcome {{ .Session.Customer.FirstName }}</p>
{{ else }}
    <form method="post">
        <label for="username">Email</label>
        <input type="text" id="username" name="AutomatApi.B2BLoginInput.Username"/>

        <br>

        <label for="password">Password</label>
        <input type="password" id="password" name="AutomatApi.B2BLoginInput.Password"/>

        <br>
        <button type="submit">Login</button>
    </form>
{{ end }}

Public

Introduction

Public pages are accessible to all users.

Setup

This can be added in the template edit view and enabling the “Allow B2B and public access” setting.

Note

As of version 1.248.0 its also possible to set an optional expiration date to the page (UTC unix value) after this timestamp has passed on the server the will no longer be accessible using the public endpoint. Use authentication config input set the value.

Add public configuration Add public configuration

These routes can be accessed by prefixing the routes with /public/

Example:

  1. automat-eu.erply.com/104146/en/my-test-page
  2. automat-eu.erply.com/public/104146/en/my-test-page

Using dynamics

Starting from version 1.246.0, GoErp allows to use dynamic api features while creating register, login and others b2b authentication calls. This allows to create multiple requests and chain data between them, including authorization calls.

Note

Those API calls works properly only inside GoErp templates, because b2b (public) authentication depends on the template configuration, therefore all b2b API endpoints requires b2bKey to be sent in the request header. This key is available inside session and could be chained to the API request header.

More about b2b API calls read in the Automat API documentation.

Registration page

A simple registration page using API and dynamics. All page configuration steps remains same as for model based b2b authentication.

<h1>Register page</h1>
<form method="post">
   <input type="hidden" name="AutomatApi.Api.Post.register" value="v1/b2b/register-user">
   <!-- Use chaining to pass b2b key to the header -->
   <input type="hidden" name="AutomatApi.Api.Header.register.<-b2bKey" value="Session.key">
   <!-- Use .Tools.B2bAuthDomain to get the domain -->
   <input type="hidden" name="AutomatApi.Api.Json.register.string.domain" value="{{ .Tools.B2bAuthDomain }}">
   <!--  Setup redirect on succeed, if needed. It will be triggered only if all calls in this 
   template are successful. So, if registration fails, we stay on this page, very useful. -->
   <input type="hidden" name="Form.Redirect" value="10-b2b-in-page">
   
   <fieldset>
      <label for="firstname">Firstname:</label>
      <input id="firstname" name="AutomatApi.Api.Json.register.string.firstname" value="">
      <label for="lastname">Lastname:</label>
      <input id="lastname" name="AutomatApi.Api.Json.register.string.lastname" value="">
   </fieldset>
   <fieldset>
      <label for="username">Username:</label>
      <input id="username" name="AutomatApi.Api.Json.register.string.username" value="">
      <label for="password">Password:</label>
      <input id="password" name="AutomatApi.Api.Json.register.string.password" value="">
   </fieldset>
    <!-- Login would be performed automatically only if this parameter set to 1 -->
   <input type="hidden" name="AutomatApi.Api.Json.register.string.triggerLoginAfterRegister" value="1">
   <button type="submit">Register</button>
</form>
Note

Please note that if the triggerLoginAfterRegister parameter is not passed or set to 0, the user will be registered but not logged in. Although, Form.Redirect will be triggered anyway and try to access the protected area (10-b2b-in-page in this case). Therefore, while user not logged in, the 10-b2b-in-page page configuration will redirect to the login page (if configured). So, this could be confusing.

Login page

Here we will just use the username and password, and redirect to the protected area when successful.

<h1>Login page</h1>
<form method="post">
   <input type="hidden" name="AutomatApi.Api.Post.login" value="v1/b2b/login">
   <!-- Use chaining to pass b2b key to the header -->
   <input type="hidden" name="AutomatApi.Api.Header.login.<-b2bKey" value="Session.key">
   <!-- Use .Tools.B2bAuthDomain to get the domain -->
   <input type="hidden" name="AutomatApi.Api.Json.login.string.domain" value="{{ .Tools.B2bAuthDomain }}">
   <!--  Setup redirect on succeed, if needed. It will be triggered only if all calls in this 
   template are successful. So, if login fails, we stay on this page, very useful. -->
   <input type="hidden" name="Form.Redirect" value="10-b2b-in-page">
   <fieldset>
      <label for="username">Username:</label>
      <input id="username" name="AutomatApi.Api.Json.login.string.username" value="">
      <label for="password">Password:</label>
      <input id="password" name="AutomatApi.Api.Json.login.string.password" value="">
   </fieldset>
   <button type="submit">Login</button>
</form>

Samples

In the following sample we have a registration, login and a members area. This shows how we restrict the members area to only read results for the logged in customer.

Page setup

Note

The public features only work if the registration, login and any members pages belong to the same application or auth domain.

Registration page

A simple registration page with minimal inputs.

<!DOCTYPE html>
<html>
<body>
    <h2>Register a new user</h2>
    <form method="post">
        <input type="hidden" name="postActionEntity" value="B2BLoginRegisterInput">
        <input type="hidden" name="postActionRedirect" value="b2b-2-login-page">

        <div class="user-box">
            <input type="text" name="AutomatApi.B2BLoginRegisterInput.Firstname" required="">
            <label>Firstname</label>
        </div>
        <div class="user-box">
            <input type="text" name="AutomatApi.B2BLoginRegisterInput.Lastname" required="">
            <label>Lastname</label>
        </div>
        <div class="user-box">
            <input type="text" name="AutomatApi.B2BLoginRegisterInput.Username" required="">
            <label>Email</label>
        </div>
        <div class="user-box">
            <input type="password" name="AutomatApi.B2BLoginRegisterInput.Password" required="">
            <label>Password</label>
        </div>

        <!-- Read possible registration errors -->
        <div>
            {{ range .Data.Errors }}
                <span>{{ . }}</span>
            {{ end }}
        </div>

        <button type="submit">Register</button>
    </form>
</body>
</html>

For publish settings we enable the ‘Allow B2B and public access’ checkbox

Also since registration allows more fields to be used we also need to fill in the parameter whitelist of the value we will allow to be used, in this case we will fill the ones we have defined in the form.

Add public configuration Add public configuration

Login page

Here we will just use the username and password, and redirect to the members area when successful.

<!DOCTYPE html>
<html>
<body>
    {{ if .Session.Customer.ID }}
        <h2>Already logged on!</h2>
    {{ else }}
    <h2>Login</h2>
    <form method="post">
        <input type="hidden" name="AutomatApi.B2BLoginInput.Redirect" value="b2b-2-members-page">

        <div class="user-box">
            <input type="text" name="AutomatApi.B2BLoginInput.Username" required="">
            <label>Username</label>
        </div>
        <div class="user-box">
            <input type="password" name="AutomatApi.B2BLoginInput.Password" required="">
            <label>Password</label>
        </div>
        
        <div class="my-error-container">
            {{ range .Data.Errors }}
            <span class="my-error-message">{{ . }}</span>
            {{ end }}
        </div>
        
        <button type="submit">Login</button>
    </form>
    {{ end }}
</body>
</html>

For publish settings we enable the ‘Allow B2B and public access’ checkbox.

Login model parameters are automatically whitelisted, so we should not need to fill them here.

Members page

On the members page we will generate a simple list of documents for the currently logged on member. We use the preset to read session id to the request and prevent it from being adjusted via any parameters.

<!DOCTYPE html>
<html>
<body>
    <h1>Members page</h1>
    <form method="post">
        <input type="hidden" name="AutomatApi.B2BLogoutInput.Logout" value="1">
        <button type="submit">Logout</button>
    </form>
    <h2>Welcome {{ .Session.Customer.FirstName }} to the members area</h2>

    <!-- Erply api response data in the 'records' field -->
    <h2>My orders</h2>
    <form method="POST">
        <!-- Request definition -->
        <input type="hidden" name="ErplyApi.Api.Post.getDocs" value="getSalesDocuments" data-preset-val="getSalesDocuments">
        <button type="submit">Reload orders</button>
    </form>

    <ul>
        {{ $salesDocs := (.Data.ErplyApi.Api.Requests.getDocs.Response.Get "records").Array }}
    
        {{ if $salesDocs }}
            {{ range $salesDocs }}
            <li>{{ .Get "id" }} / {{ .Get "type" }} / {{ .Get "clientName" }}</li>
            {{ end }}
        {{ else }}
            <li>You currently have no orders!</li>
        {{ end }}
    </ul>
</body>
</html>
Note

By default all public access groups do not have access to read documents. This right needs to be given under the public user groups (starting with ‘app_public’ and ‘app_b2b’) by the account administrator in the backoffice.

Every application or authentication domain will have a separate user group with rights assigned to them.

For publish settings we enable the ‘Allow B2B access’ checkbox as we will only want logged in members to access it.

We also set the redirection to the name of the login page, so whenever its being accessed without a proper session it will be automatically redirected.

Add permissions Add permissions

We are also using dynamic api here, so we will add the ErplyApi.Api.Post.getDocs -> getSalesDocuments to the request whitelist.

Under URl configuration we add the preset ErplyApi.Api.PostParam.getDocs.<-clientID : Session.customer.ID This will write the current session customer id to the request when it is being done, since we do not allow the parameter to be adjusted in the parameters list then it cannot be changed to anything else.

Add preset chain Add preset chain

Workflow

To test it:

  1. Register a new user
  2. Login with the created customer
  3. The members area only displays the members sales documents (use backoffice to create them or create a new page that creates the documents for the member using the same method)