sharepoint online – Can we move/copy a customized list forms (using power app) from one tenant to another

Yes, we can do this using the export and import of the powerapps package. We need to follow the below steps to do that:

  1. Export the app from the source environment
  2. Import the app into the target environment

Export Process

Step 1:

Open the PowerApps form in the browser. Go to the Apps tab. Right-click on the Application which you want to move. You will get the context menu Click on the “Export-Package“.

Step 2:

In the Export package page enter the Name and Description and click on Export.

Step 3:

Now we will get our PowerApps form in our local system.

Import Process:

Step 1:

Open the new tenant in the browser. Go the Apps tab. Click on the “Import-Package” from the top.

Step 2:

Click on the “Upload” in the Import-Package.

Step 3:

Select on the Zip file from the local system which you want to import.

Step 4:

Click on the Update. In the Setup option click on the “Create as new” option.

Step 5:

Click on save. When we have clicked on the Create as new the save button will be enabled.

Step 6:

Click on the Import in the Review Package Content Page.

Step 7:

We will get our imported App in the Apps tab.

For complete details steps, you may refer the below MSDN article:

Environment and tenant app migration through Packaging

Export PowerApps from one Tenant to another Tenant

Note:

After importing the package in the target environment, open the form verify the data connection.

azure – “error_description”:”AADSTS500011: The resource principal named .database.windows.net was not found in the tenant named

I am trying to establish communication between an Azure Linux VM (source) and a Azure SQL Server ( Target) via Managed Identity. I have followed steps in the article

https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-windows-vm-access-sql

until the step where we do a “InvokeWebRequest” (tried “curl” too) to get the Access Token for the SQL Server. I am getting below error message upon hitting the “curl” command

“error_description”:”AADSTS500011: The resource principal named .database.windows.net was not found in the tenant named . This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant

Could anybody please help in resolving this?

Thanks.

sql server – Join to get most specific record for tenant without PIVOT

I have a Settings table and a Tenant table.
There is a hierarchy for that an Account can have 1 or many Companies and a Company can have 1 or many `Facilities’.

Account 1
   ---> Company 1
          ---> Facility 1   
          ---> Facility 2
   ---> Company 2
          ---> Facility 3   
          ---> Facility 4

They may have a default setting that applies to their entire account….

| FacilityId | CompanyId | AccountId | SettingValue |
|------------|-----------|-----------|--------------|
|     (null) |    (null) |         1 |            5 |

…except they have one override for Facility 3 that only applies to Facility 3, all other facilities will use the default setting value at the account level.

| FacilityId | CompanyId | AccountId | SettingValue |
|------------|-----------|-----------|--------------|
|          3 |    (null) |         1 |            6 |
   

I want to create a join between them to get the most specific setting for each tenant. Most specific is defined as the Setting record that matches the Tenant‘s FacilityId is more specific than a match on CompanyId which is more specific than a match on AccountId and finally, if no match is found, use the setting that has NULL for all 3 values.

I do not want to use the PIVOT feature as the code uses Entity Framework and LINQ and there is no LINQ to SQL for PIVOT.

SQLFiddle

Table: Settings

| FacilityId | CompanyId | AccountId | SettingValue |
|------------|-----------|-----------|--------------|
|          1 |         1 |         1 |            5 |
|     (null) |         2 |         2 |            7 |
|     (null) |         1 |         1 |            4 |
|     (null) |    (null) |         2 |            6 |
|     (null) |    (null) |         1 |            3 |
|     (null) |    (null) |    (null) |            2 |

Table: Tenants

| FacilityId | CompanyId | AccountId |
|------------|-----------|-----------|
|          1 |         1 |         1 |
|          2 |         2 |         2 |
|          3 |         3 |         3 |

So join on these would have this desired output:

| FacilityId | CompanyId | AccountId | SettingValue |
|------------|-----------|-----------|--------------|
|          1 |         1 |         1 |            5 |
|          2 |         2 |         2 |            7 | --> this account would match to a setting value of 6 or 7, but the 7 value matches more specifically
|          3 |         3 |         3 |            2 | --> there is no match on Facility, Company, or Account so match to all nulls.

In code, I am doing the following to get the most specific Setting for a given Tenant, but I now need to do this for a large set of Tenant data and hence want to do it by a SQL Join. For those unfamiliar with LINQ the double pipe (||) is equivalent to OR.

private SettingViewModel GetSettingBy(string strKey)
{
    var allSettings = GetAllSettings();
    var settingQuery = allSettings.Where(x => x.SettingKey == strKey);

    if (_accountCompanyFacilityViewModel.AccountId.HasValue)
    {
        settingQuery = settingQuery.Where(x => (x.AccountId == _accountCompanyFacilityViewModel.AccountId || x.AccountId == null));
    }

    if (_accountCompanyFacilityViewModel.CompanyId.HasValue)
    {
        settingQuery = settingQuery.Where(x => (x.CompanyId == _accountCompanyFacilityViewModel.CompanyId || x.CompanyId == null));
    }

    if (_accountCompanyFacilityViewModel.FacilityId.HasValue)
    {
        settingQuery = settingQuery.Where(x => (x.FacilityId == _accountCompanyFacilityViewModel.FacilityId || x.FacilityId == null));
    }

    var setting = settingQuery
            .OrderByDescending(x => x.FacilityId)
            .ThenByDescending(x => x.CompanyId)
            .ThenByDescending(x => x.AccountId)
            .FirstOrDefault();
            
    return setting;
}

sharepoint online – How does updating SPFx webparts/extensions work between tenant wide/non-tenant wide deployment models?

I am trying to understand the difference between deploying spfx customizations between tenant wide and non tenant wide (and differences when updating/not updating the version number). Per my current knowledge, I understand this so far

Tenant Wide:

Once you overwrite the solution, it updates everywhere automatically. This is true when keeping the version number the same.

If version number is increased, what happens here?

Non Tenant Wide:

If you overwrite the solution, it updates everywhere. This is true when keeping the version number the same. However for some webparts like listview command sets, it requires the app to be deleted from each site and its recycle bin, and needs an increase version number when adding to app catalogue.

If version number is increased, then apps will get a message on each site saying there is an update, and requires a manual update to fully update. While this is not done, only the static resources portion of the app will get the update automatically. Any manifest config-like changes won’t take effect until it is manually updated.

Can anyone confirm if these details are correct, or if there is anything more to be added?

Thanks

sharepoint online – How to set up SPFx customizations on a shared tenant?

I have a tenant thats shared with multiple regions from the same company. Lets say region A, B, C. Each one is doing their own customizations but its all on the same tenant. And we are following the best practice of making hubs and then 1 level of sites inside them (no further subsites). And some hubs will be assigned to each region.

Lets say I am developing for region A. How can I best deploy my spfx customizations that could be scoped to region A? If I do tenant wide, then it would be available to other regions which I don’t want. Though I could just code it so if its part of a site not based off of A then display a message saying its blocked. If I do that, what’s the best way to detect this? Or can I deploy to some sites?

If I don’t deploy tenant wide, then that means I have to manually add the app to the site which is time consuming. And then for updating apps, I need to remove apps and re-add them back again, per site which is really painful.

Does anyone know?

Thanks

sharepoint online – How to update SPFx extension instances tenant wide automatically?

In SPFx, I deployed a listviewcommandset extension to add a context menu option to list items. After adding to app catalogue, I had to manually add the app to the site. And then to update it, I had to delete the app from the site and recycle bin, increase the version number, re deploy the app to the catalogue and then add the app to the site again. Is there a way I can simplify the process and have it so that once I deploy, all sites just get the update automatically?

mysql – Should I in general partition tables by tenant IDs in a multi-tenant system?

We’re building a system where the data in 10 tables is associated with Accounts. A typical table looks like this:

create table Things(
    accountId varchar(64) not null,
    internalId varchar(64) not null,
    externalId varchar(256) as (concat(accountId, '-', internalId)) stored,
    ...
    primary key (accountId, sourcedId),
    unique (externalId),
    foreign key (accountId) references Accounts (id)
);

All queries either have an accountId in the where clause, or they use externalId. There are no cross-account queries.

We’re expecting to have a total of 200 accounts. The sizes of the other tables (like Things) vary from 5 rows per account for some tables (1000 rows total) to 225K rows per account for some other tables (45M rows total). (These are the numbers we use for performance testing – they’re the max numbers)

The DB size is ~150 GB. 95% of the scenarios are reads.

The RDBMS is Mysql 8.0.16 (AWS RDS).

We don’t have any performance issues at the moment and we’re not trying to make anything work faster. But I’m wondering if NOT partitioning the tables like Things by accountId is a “premature pessimization”?

Patterns for multi tenant systems

What you need is a core and modules.

The core will contain all of the functionality that is common to every tenant.

Modules will also contain common functionality, but can be customized to each tenant, and there will be modules that are specific to particular tenants.

Hence, you need a “modular” system.

There are several technical solutions for modularity, in particular plugin systems. Most modern programming languages use interfaces. I suggest you begin by researching those.

Making a database multi-tenant can be as simple as adding a TenantID field to each table.

ruby – Is Devise enough to make multi tenant app

I’m currently using Devise (with a RoR app) to handle multiple users in a SAAS app built for a client.

The user owns Posts. URLs are scoped to the user, user/posts. And the Controller CRUDs the posts through the user, user.post.new etc.. For the most part that is the gist of the app. BUT, there does need to be some logic based around ALL of the posts, most liked posts across all users, searching post tagged with x — across all users.

It was brought to my attention that I need a more robust multi tenancy and was introduced the Apartment Gem. I don’t need subdomains, and as far as I can tell it’ll make the actions that need to done across all users much harder. On the plus side, queries might be faster, and there is less managing data access at controller level.

Are there any heuristics around multi tenancy, that makes a using Devise alone a bad choice? Is it necessary to sequester users data in separate tables? Is Devise alone enough to make a multi tenant app?

security – Securing React SPA with Azure AD B2C Tenant using MSAL

I am securing my React Apps and I want to use the wrapper function below to insure that the app only gets rendered when there is a successful login. I am separating the Login from future MSAL token requests because I perceive Login to be a boolean in that you are logged in or you are not logged in. If a later MSAL request requires my user to “re-login” I will call this function to reload the app:

window.location.reload(true);

This code is for React Apps only. I am only securing the app not the endpoints. This code may be used in apps that only access public endpoints.

Sample Usage:

import { WrapWithMSAL } from './MSAL_Utils'

// Will handle Auth and then render App
WrapWithMSAL(() =>
  ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root'))
);

This is the Wrapper function:

    import { Configuration, UserAgentApplication, AuthenticationParameters,
    AuthResponse, Logger, LogLevel, } from 'msal'

    // Hold the render CBR while Authenticating
    let appRender:CallableFunction = ()=>{}

    // Wrapper function to secure the Rendering of the React App
    export const WrapWithMSAL = (callbackRtn:CallableFunction) => {
      appRender = callbackRtn;
      if (!MSALAuthAgent.getAccount())
      {
        // Set the MSAL CBR specifically to Login Handler
        MSALAuthAgent.handleRedirectCallback(msalLoginResultCallback);
        const msalAuthParams: AuthenticationParameters = {
          scopes: regScopes
        };
        // Popup AD B2C Login, 
        MSALAuthAgent.loginRedirect(msalAuthParams);
      }
      else // Login was retrieved from Session Cache
      {
        appRender(); // Start the app
      }
    }
    // Callbacks passed to MSAL
    /**
    * Called when the user has successfully logged in
    * (the account object is created at the time of successful login)
    * or null when no state is found
    * @returns {@link Account} - the account object stored in MSAL
    */
    const msalLoginResultCallback = (error: any, response: any) => {
      if (error) {
        alert(error.toString());
      }
      else {
        appRender(); // Start the app
      }
    }

    // MSAL Specifications
    const configuration: Configuration = {
      auth: {
        clientId: "AZURE_APPLICATION_ID",
        authority:"AZURE_USER_FLOW",
        redirectUri: "https://myspa.mysite.com",
        validateAuthority: false,
      },
      cache: {
        cacheLocation: "sessionStorage",
        storeAuthStateInCookie: true,
      },
      system: {
        logger: new Logger((logLevel, message, containsPii) => {
          console.log("(MSAL): ", message)
        }, {
          level: LogLevel.Verbose,
          piiLoggingEnabled: false
        })
     }
   }

   const regScopes : ('read.scope');
   const MSALAuthAgent = new UserAgentApplication(configuration);
   export default MSALAuthAgent;

My question is does this approach secure my app?