
package com.smartgwt.client.docs;

/**
 * <h3>Transparent Multi-Tenancy</h3>
 * A multi-tenant application is one where multiple customers experience the same application
 *  but with their data segregated - the different customers are not aware of each other.
 *  <p>
 *  Smart GWT provides a "transparent" multi-tenant system, in which a Smart GWT application
 *  can be quickly converted to support multi-tenancy, with only a handful of very simple
 *  changes required.
 *  <p>
 *  In short, you designate a set of DataSources as multi-tenant, and those DataSources are then
 *  available to you in tenant-specific forms, which can store data in different databases,
 *  automatically.
 *  <p>
 *  Specifically:<ol>
 *  <li>database configurations become a template where <i>tenantId</i> can appear in the
 *  settings<p>
 *  You can use <code>$tenantId</code> in your DB settings so that you can put different tenants
 *  in different schemas or even entirely different DB hosts.<p>
 *  There are also APIs for providing entirely different database settings on a per-tenant
 *  basis, or for specific tenants that are special.</li>
 *  <li>when loading DataSources into the browser, you pass a <i>tenantId</i> (to
 *  DataSourceLoader, or in JSP tags)<p>
 *  This means that tenant-specific DataSources are returned, with a naming convention that
 *  defaults to <code>mt_<i>tenantId</i>_<i>originalDataSourceID</i></code>.<p>
 *  However, for client-side logic, the DataSources are still available under the original name.
 *  So, your ListGrid that is bound to the "orders" DataSource still works as expected, and code
 *  such as <code>DataSource.get("orders").fetchData(...)</code> also works, unchanged.</li>
 *  <li>for server-side logic, you just tell us the authenticated <i>tenantId</i>, and
 *  server-side APIs transparently work without code changes<p>
 *  You provide the authenticated <i>tenantId</i> to the server-side RPCManager object via the
 *  <code>setTenantId()</code> API. From then on, if you ask the RPCManager for a DataSource
 *  (<code>getDataSource()</code> API), you get tenant-specific DataSources.<p>
 *  Likewise, if you create a <code>new DSRequest(...)</code> and pass the RPCManager into the
 *  constructor, the operation is scoped to the current tenant.</li></ol>
 *  <p><hr><p>
 *  Taken together, these features mean that a typical Smart GWT app can be converted to
 *  multi-tenancy by just:<ol>
 *  <li>moving multi-tenant DataSources to the designated directory, by default
 *  <code>$webRoot/shared/ds</code></li>
 *  <li>adding the <i>tenantId</i> to the DataSourceLoader &lt;script&gt; tag in your bootstrap
 *  .html file</li>
 *  <li>securely providing the authenticated <i>tenantId</i> to Smart GWT: a call to
 *  <code>RPCManager.setTenantId()</code>, or setting the servlet attribute
 *  <code>isc_tenantId</code></li>
 *  <li>adding <code>$tenantId</code> in your database config (and of course provisioning the
 *  databases!)</li></ol>
 *  All the rest is handled for you, by Smart GWT.
 * 
 *  <h2>Smart GWT multi-tenancy</h2>
 * {@link com.smartgwt.client.data.DataSource DataSources} in Smart GWT support the Bridge model
 * and Silo model for
 *  multi-tenancy. as described in the section below titled, "Multi-tenancy models."
 * 
 *  <h3>Multi-tenant DataSource loading</h3>
 *  By default multi-tenant DataSources in Smart GWT are named
 *  <code>mt_&lt;tenantId&gt;_&lt;baseId&gt;</code>, where <code>baseId</code> is the filename
 *  prefix of the XML DS definition file (e.g. <code>supplyItem</code> for
 *  <code>supplyItem.ds.xml</code>), but when loaded by the client an alias is automatically
 * created so that it's accessible simply as <code>baseId</code> via {@link
 * com.smartgwt.client.data.DataSource#get DataSource.get()}.
 *  The server looks for the definitions under the <code>tenants</code> subdirectory of each of
 *  your <code>project.datasources</code> paths, so if that property is just the directory
 *  <code>$webRoot/shared/ds</code>, for example, then we'll look in
 *  <code>$webRoot/shared/ds/tenants</code>.
 *  <p>
 *  When loading a DataSource via the
 * <a href='../../../../../server/javadoc/com/isomorphic/servlet/DataSourceLoader.html'
 * target='_blank'>DataSourceLoader</a> servlet, you
 *  should supply the baseId(s) of any multi-tenant DataSources.  If a <code>tenantId</code>
 *  parameter is included in the request, and is authorized, the multi-tenant directories are
 *  searched first, falling back to the normal DataSource filesystem location(s) if the DS isn't
 *  found.  Conversely, if no <code>tenantId</code> parameter is included, the server will
 *  search the normal DS location(s) first, and then fall back to the multi-tenant directories
 *  (assuming authorization is present).
 *  <p>
 *  You can designate specific multi-tenant DataSources as "test" DataSources that should be
 *  loaded from the normal DS filesystem location(s) by declaring them in the config property
 *  <code>tenant.testDataSources</code>, and you can limit the allowed tenants by listing
 *  them in the config property <code>mt.tenants</code>.
 *  <p>
 *  <b>Note:</b> See the server.properties table at the end of this topic for how to customize
 *  the attribute name and other multi-tenant configuration.
 * 
 *  <h3>Converting app to use multi-tenancy</h3>
 *  To convert an existing Smart GWT app to use multi-tenancy you just need to make a few
 *  changes outlined as follows.  There's no need to rewrite the client app since an alias is
 *  created for the multi-tenant DataSource under its "base" ID.
 * 
 * <h4>Define a database template in your {@link com.smartgwt.client.docs.Server_properties
 * server.properties} file</h4>
 *  When encountering a new tenant for the first time, the Smart GWT server will automatically
 *  add a database definition for the tenant to the global config, using the database template.
 *  The template consists of a number of separate config properties that are each Velocity
 *  templates, so they can reference <code>tenandId</code> and standard Velocity variables, but
 *  also existing server.properties variables.
 *  <p>
 *  For example, the template used by the multi-tenant sample in the SDK is:
 *  <pre>
 *  tenant.dbTemplate.driver: $sql.HSQLDB.driver
 *  tenant.dbTemplate.driver.databaseName: mt_\$tenantId
 *  tenant.dbTemplate.driver.url: jdbc:hsqldb:file:$sql.HSQLDB.database.baseDir/mt_\$tenantId
 *  tenant.dbTemplate.database.type: $sql.HSQLDB.database.type
 *  tenant.dbTemplate.interface.type: $sql.HSQLDB.interface.type
 *  tenant.dbTemplate.driver.user: SA
 *  tenant.dbTemplate.driver.password:</pre>
 *  Note that references to Velocity variables must be escaped by putting a backslash before the
 *  <code>$</code> symbol; otherwise it will be interpreted as a reference to another config
 *  property.
 * 
 *  <h4>Add an authorization mechanism</h4>
 *  In a multi-tenant system, one tenant's data should not be accessible by other tenants, so
 *  you will need to add a means of authenticating the current tenant.  There are several ways
 *  to do this securely in a production system.  We support two approaches:<ul>
 *  <li><b>By Servlet Request.</b> Set an attribute on the servlet request via a web.xml
 *  filter or other server code.
 *  <li><b>By RPCManager.</b> Call
 * <a href='../../../../../server/javadoc/com/isomorphic/rpc/RPCManager.html#setTenantId'
 * target='_blank'>RPCManager.setTenantId()</a> from a
 *  user override of
 * <a
 * href='../../../../../server/javadoc/com/isomorphic/servlet/IDACall.html#prepareRPCTransaction'
 * target='_blank'>IDACall.prepareRPCTransaction()</a>
 *  </ul>
 *  In the first approach, your filter will need to intercept servlet traffic to the IDACall
 *  and DataSourceLoader servlets, adding authorization by setting the
 *  <code>isc_tenantId</code> attribute on the servlet request.  For proper security, your
 *  solution should avoid just checking for certain query params, at least if their values can
 *  be easily guessed, since that would allow any client to gain access.
 *  <p>
 *  Under this approach, when loading DataSources with a <code>&lt;isomorphic:loadDS&gt;</code>
 *  tag, there's no need to set the <code>tenantId</code> attribute as it's assumed to be
 *  whatever your servlet filter authorizes, though you can set the attribute to
 *  <code>"none"</code> to avoid unintentionally picking up a multi-tenant DS if you have one by
 *  the same name that's both multi-tenant and a normal DataSource.
 *  <p>
 *  As an alternate approach, you can subclass the
 * <a href='../../../../../server/javadoc/com/isomorphic/servlet/IDACall.html'
 * target='_blank'>IDACall</a> servlet, and override 
 * <a
 * href='../../../../../server/javadoc/com/isomorphic/servlet/IDACall.html#prepareRPCTransaction'
 * target='_blank'>IDACall.prepareRPCTransaction()</a>
 *  like so:
 *  <pre>
 *  public void prepareRPCTransaction (RPCManager rpc, RequestContext context) {
 *      String tenantId = null;
 *      // ... code here that analyzes context and sets (authorizes) tenantid ...
 *      rpc.setTenantId(tenantId);
 *  }</pre>
 * which also requires setting {@link com.smartgwt.client.rpc.RPCManager#actionURL actionURL} to
 * "[ISOMORPHIC]/AuthedIDACall",
 *  assuming your subclass is named <code>AuthedIDACall</code>.
 *  <p>
 *  Under this approach, you can load the DataSource either by providing a servlet filter to
 *  auth DataSourceLoader, or by launching your app with a JSP so that the JSP sets the
 *  authorized tenant into the <code>tenantId</code> attribute of the
 *  <code>&lt;isomorphic:loadDS&gt;</code> tag.
 * 
 *  <h3>Multi-tenant demo app</h3>
 *  The Order Management App has been included in the Smart GWT SDK as a demo of
 *  multi-tenancy.  A few shortcuts have been taken adding multi-tenancy to this app, leveraging
 *  the fact that we are not worried about a client gaining unauthorized access to the demo
 *  tenant data:<ul>
 *  <li>To enable tenant authorization for the <code>&lt;isomorphic:loadDS&gt;</code> JSP tag,
 *  we've just added the built-in
 * <a href='../../../../../server/javadoc/com/isomorphic/servlet/ParamMapperFilter.html'
 * target='_blank'>ParamMapperFilter</a> filter to
 *  the SDK's web.xml to apply the <code>isc_tenantId</code> servlet request parameter to the
 *  <code>isc_tenantId</code> servlet request attribute.
 *  <li>To support multi-tenant IDACall requests, we've added the config property
 * <code>tenant.testOnlyURLParam</code> to {@link com.smartgwt.client.docs.Server_properties
 * server.properties}.  This
 *  causes any <code>isc_tenantId</code> query param in the page URL to be sent to the server as
 *  a request parameter for IDACall requests, and ultimately set into the
 *  <code>isc_tenantId</code> servlet request attribute, authorizing the tenant</ul>
 *  The end result is that for the demo, you can choose (authorize) one of the two supported
 *  tenants, "biginc" and "worldship," by simply setting the tenant's ID as the value of the
 *  <code>isc_tenantId</code> query param in the demo URL.
 *  <p>
 *  So, for example, you can hit<p>
 * <a href='/examples/multi_tenant/orderManagementJS.jsp?isc_tenantId=biginc'
 * target='_blank'>/examples/multi_tenant/orderManagementJS.jsp?isc_tenantId=biginc</a><p>
 *  to use the app as tenant "biginc", and<p>
 * <a href='/examples/multi_tenant/orderManagementJS.jsp?isc_tenantId=worldship'
 * target='_blank'>/examples/multi_tenant/orderManagementJS.jsp?isc_tenantId=worldship</a><p>
 *  to use it as "worldship."  Obviously, having the tenant ID query param on the client
 *  authorize access is only suitable for a demo, and not a real production setup.
 * 
 *  <h3>Custom configuration</h3>
 *  Much of Smart GWT's multi-tenant behavior can be customized via server.properties
 *  configuration:<table border=1 class="normal">
 *  <tr>
 *      <td>Property Name</td>
 *      <td width="250">Default value</td>
 *      <td>Description</td>
 *  </tr>
 *  <tr>
 *      <td>datasources.poolTenantDataSources</td>
 *      <td>true</td>
 *      <td>Whether to pool multi-tenant DataSources</td>
 *  </tr>
 *  <tr>
 *      <td>mt.tenants</td>
 *      <td><i>empty list</i></td>
 *      <td>If defined, limits tenants to those listed.  Other tenants will be treated as
 *      unauthorized even if the normal auth process has been followed.</td>
 *  </tr>
 *  <tr>
 *      <td>tenant.datasources</td>
 *      <td><i>list of directories formed from project.datasources by adding the subdirectory
 *      /tenants to each directory entry</i></td>
 *      <td>List of directories in which to look for the multi-tenant DS XML definition files
 *      (files of the form &lt;baseId&gt;.ds.xml).
 *     </td>
 *  </tr>
 *  <tr>
 *      <td>tenant.datasources.nameTemplate</td>
 *      <td>mt_$&#123;tenantId&#125;_$baseId</td>
 *      <td>The multi-tenant name for the DataSource with the base DS ID <code>baseId</code>
 *      and tenant <code>tenantId</code>.  This property is used by the DataSourceLoader servlet
 *      to generate a multi-tenant DataSource ID
 *      </td>
 *  </tr>
 *  <tr>
 *      <td>tenant.datasources.namingPattern</td>
 *      <td>mt_([A-Za-z0-9]+)_([A-Za-z0-9_$]+)</td>
 *      <td>Pattern used by the Multi-tenant Dynamic DataSource Generator to recognize the name
 *      of a valid multi-tenant DataSource.  The first regex group will be assumed to be the
 *      tenant ID and the second to be the base DS ID.</td>
 *  </tr>
 *  <tr>
 *      <td>tenant.dbNameTemplate</td>
 *      <td>mt_$tenantId</td>
 *      <td>Database name for tenant <code>tenantId</code></td>
 *  </tr>
 *  <tr>
 *      <td>tenant.servletReqAttribute</td>
 *      <td>isc_tenantId</td>
 *      <td>Attribute to look for on the servlet request that holds the authorized tenant ID.
 *      Note that currently, the URL query param name read by the client framework and sent to
 *      the server as the request param when <code>tenant.testOnlyURLParam</code> is true is
 *      hardcoded to <code>isc_tenantId</code>, and is thus unaffected by this config setting.
 *      </td>
 *  </tr>
 *  <tr>
 *      <td>tenant.testDataSources</td>
 *      <td><i>empty list</i></td>
 *      <td>List of DataSource base IDs that should be picked up from the normal DS filesystem
 *      location(s) (typically defined by <code>project.datasources</code>) instead of from
 *      the multi-tenant directories defined by <code>tenant.datasources</code>.</td>
 *  </tr>
 *  <tr>
 *      <td>tenant.testOnlyURLParam</td>
 *      <td>false</td>
 *      <td>If true, when the client URL query parameter <code>isc_tenantId</code> is present
 *      and forwarded to the server as a servlet request parameter, it will be set into the
 *      servlet request attribute defined by <code>tenant.servletReqAttribute</code>, thus
 *      authorizing the tenant specified on the client.  This is insecure, and so for testing
 *      or demo purposes only.</td>
 *  </tr>
 *  </table>
 * 
 *  <h2>Multi-tenancy models</h2>
 *  Multi-tenancy refers to the ability of a single database system to serve multiple tenants,
 *  where each tenant represents a distinct entity, such as a customer, user, or organization.
 *  These tenants share the same underlying database infrastructure, but their data is logically
 *  isolated and segregated to ensure privacy, security, and performance.
 *  <p>
 *  For consistency, we define the following terms before continuing:<ul>
 *  <li><b>Database Process:</b> means a separate OS-level database process - what results when
 *  you run the mariaDB binary, for example
 *  <li><b>Database Server:</b> means a distinct OS install that is dedicated to one database
 *  process, with no other database processes running on that OS. Does not necessarily mean
 *  separate physical hardware. Does not necessarily mean that the database server is running
 *  only a database process and nothing else (there could also be an application server, for
 *  example)
 *  <li><b>Database (without other qualifiers):</b> a container for tables, views, etc, where
 *  there might be many "databases" within a given database process . This is what you get when
 *  you run "create database" in MariaDB, for example. Sometimes also called a "schema" but
 *  we won't use that term, because in Smart GWT we have Component Schema et al and a set of
 *  DataSource fields is also commonly referred to as a "schema".
 *  </ul>
 *  Given these terms, we can describe three different approaches to multi-tenancy.
 * 
 *  <h3>Pool Model</h3>
 *  In the pool model, tenants share and their data coexists within a single database and
 *  database process.  This is cost efficient, as resources are shared among multiple tenants,
 *  and easily scalable to provision for a larger or smaller number of tenants.  it's also
 *  easily managed, as only a single database process is required.
 *  <p>
 *  However, sharing resources with other tenants can raise security risks if not properly
 *  managed, and there can be performance issues from resource contention among multiple
 *  tenants.
 * 
 *  <h3>Silo Model</h3>
 *  In the silo model, each tenant's data is stored within a dedicated database process,
 *  completely isolated from other tenants.  In this model, isolating resources for each tenant
 *  reduces the risk of security vulnerabilities.  Moreover, tenants have more control over
 *  their individual resource allocations and configurations.  Resource contention between
 *  the separate database processes of different tenants  may be eliminated, as there's no
 *  requirement that the separate processes even be on the same physical hardware.
 *  <p>
 *  However, these advantages come with higher costs due to maintaining per-tenant resources.
 *  Also, managing the separate database processes or servers can require more effort, and more
 *  expertise if different database server products are used.  If the separate database
 *  processes must run on a single machine, scalability may be an issue as each process may
 *  require significant resources.
 * 
 *  <h3>Bridge Model</h3>
 *  The bridge model is a compromise in which data for separate tenants is stored in separate
 *  databases within the same database process.  This offers better cross-tenant data security
 *  than the pool model, while not consuming as many machine resources as having separate
 *  database processes per tenant.  It can be more easily scaled to a larger number of tenants
 *  than a silo implementation, but the separate tenant databases may make management more
 *  challenging than a pool implementation.
 */
public interface MultiTenancy {
}
