Monday, February 21, 2022
Front End Development Basic Tools
Npm is your toolbox, including tools such as bower and gulp
Bower is a package manager. It pulls down the javascript libraries you want locally. We (generally) don’t want to keep these in source control, as the gulp optimized ones are kept in source control instead.
Gulp is run over the top of your source files to minimize, optimize, and otherwise process CSS, JS, and Images for production use.
SASS
Sass is a stylesheet language that’s compiled to CSS. It allows you to use variables, nested rules, mixins, functions, and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized and makes it easy to share design within and across projects.
https://sass-lang.com/
https://sass-lang.com/guide
https://css-tricks.com/the-sass-ampersand/
BEM
BEM (Block Element Modifier) is a styling methodology that helps you to create reusable components and code sharing in front-end development.
Block: Standalone entity that is meaningful on its own.
Element: A part of a block that has no standalone meaning and is semantically tied to its block.
Modifier: A flag on a block or element. Use them to change appearance or behavior.
Official Website: http://getbem.com/
Quick Start: http://getbem.com/introduction/
NPM
npm makes it easy for JavaScript developers to share and reuse code, and makes it easy to update the code that you’re sharing, so you can build amazing things.
Official Website: https://www.npmjs.com/get-npm
Gulp
Gulp is a task runner.
Modern web development has many repetitive tasks like running a local server, minifying code, optimizing images, preprocessing CSS and more. This text discusses gulp, a build tool for automating these tasks. Gulp is a cross-platform, streaming task runner that lets developers automate many development tasks. At a high level, gulp reads files as streams and pipes the streams to different tasks. These tasks are code-based and use plugins. The tasks modify the files, building source files into production files.
Official Website: https://gulpjs.com/
Quick Start: https://gulpjs.com/docs/en/getting-started/quick-start
Also see:
https://developers.google.com/web/ilt/pwa/introduction-to-gulp
Bower
Bower is a package manager. It works by fetching, downloading, and installing packages as needed.
Official Website: https://bower.io/
.NET Core
.NET Core is an open-source, general-purpose development platform maintained by Microsoft and the .NET community on GitHub. It’s cross-platform (supporting Windows, macOS, and Linux) and can be used to build device, cloud, and IoT applications.
Official Website: https://dotnet.microsoft.com/
Also see:
https://docs.microsoft.com/en-us/dotnet/core/
Razor Pages
Razor is a server-side markup language that lets you embed server-based code (Visual Basic and C#) into web pages.
See:
https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-2.2&tabs=visual-studio
https://www.w3schools.com/asp/razor_intro.asp
Nuget
NuGet is the package manager for .NET. The NuGet client tools provide the ability to produce and consume packages. The NuGet Gallery is the central package repository used by all package authors and consumers.
Official Website: https://www.nuget.org/
Moving or pointing a SQL Server database to a new disk location
From:
C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA
To:
D:\SQLData
– Check SSISDB settings and they should point to the From files paths
use master
ALTER DATABASE SSISDB SET SINGLE_USER WITH Rollback Immediate
ALTER DATABASE SSISDB SET OFFLINE WITH ROLLBACK IMMEDIATE
ALTER DATABASE SSISDB MODIFY FILE ( NAME = data, FILENAME = ‘D:\SQLData\SSISDB.mdf’)
ALTER DATABASE SSISDB MODIFY FILE ( NAME = log, FILENAME = ‘D:\SQLData\SSISDB.ldf’)
ALTER DATABASE SSISDB set online
ALTER DATABASE SSISDB set multi_user
– Check SSISDB settings and they should point to D:\SQLData
Further docs
See: https://www.sqlshack.com/move-sql-database-files-mdf-ldf-another-location/
Microsoft Doc covering all scenarios:
https://docs.microsoft.com/en-us/sql/relational-databases/databases/move-user-databases?view=sql-server-2017
Moving System Databases:
https://docs.microsoft.com/en-us/sql/relational-databases/databases/move-system-databases?view=sql-server-2017
SSL Cert No Private Key Issue
Import and Export Business Central General Journal Entries
Sunday, February 20, 2022
OAuth Bearer Token Business Central
Problem Description
The current Microsoft implementation of Web Services authorization is a giant security hole. Anyone who knows the current NON-expiring user id and the access key should be able to read and tamper with the accounting data. Moreover, anyone with sufficient access in user card could generate a new access key.
Microsoft has deprecated the feature and in future releases will not make it available to the Cloud installations of Business Central. (On-premise installation could still use it though for the foreseeable future.)
The OAuth token has a limited lifetime and needs to be constantly refreshed. We could automatically refresh the token - forever. (Only generating the first token requires Azure active directory login.)
(Should we go to prod before Microsoft totally removes the current Web service Access Key method, we need to wipe out any existing web access keys used by the consultants or internal users.)
Register Azure app as described here in detail:
https://www.youtube.com/watch?v=lCzqg2N0vbA
( Microsoft’s documentation is absurdly insufficient in implementing the plumbing - in this article they the general road map is listed:
The already-registered app is shown below. Note that you don’t need to ever create the actual app. The registration is sufficient - the registration is a proxy to get the access and refresh tokens.
https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade
In Prod you may have to either alter the registered app’s parameters to point to the Prod URLs or create a new registered app with the new Prod URLs.
Get the first token from PostMan:
Set the parameters and click on “Get New Access Token”. (I could provide you the Postman parameters on Teams. Basically they are derived from the registered app.)
Active Directory login will pop up and you need to supply your credentials.
Copy and paste the access token. and then scroll down and copy and paste the refresh token.
You will put the tokens into a SQL server database. But before executing the SQL, stop the instance of the PDP OAuth Token refresher scheduled task shown below.
update [dbo].[BusinessCentralOAuthToken] set [access_token]=‘YourNewAccessToken’,
[refresh_token]=‘yournewRefreshToken’
Token Refresher Micro Service
// refresh token and the acces stoken are sent as params in a custom object instance of type BusinessCentralOAuthToken_Result
private static void UpdateNewTokenFromRefreshToken(BusinessCentralOAuthToken_Result oInputModel)
{
// https://docs.microsoft.com/en-us/linkedin/shared/authentication/programmatic-refresh-tokens
HttpResponseMessage responseMessage;
using (HttpClient client = new HttpClient())
{
// Before it expires, refresh the close-to-expiration token using the latest refresh token
HttpRequestMessage tokenRequest = new HttpRequestMessage(HttpMethod.Post, oInputModel.AccessTokenURL);
HttpContent httpContent = new FormUrlEncodedContent(
new[]
{
new KeyValuePair<string, string>("grant_type", "refresh_token"),
new KeyValuePair<string, string>("refresh_token", oInputModel.refresh_token),
new KeyValuePair<string, string>("client_id",oInputModel.ClientID),
new KeyValuePair<string, string>("client_secret",oInputModel.ClientSecret),
});
// let the app server provide the date, in case the clocks do NOT match
tokenRequest.Content = httpContent;
responseMessage = client.SendAsync(tokenRequest).Result;
}
string oJsonReponse = responseMessage.Content.ReadAsStringAsync().Result;
ResponseModel oModel = JsonConvert.DeserializeObject<ResponseModel>(oJsonReponse);
if (string.IsNullOrEmpty(oModel.access_token))
{
ReportError(new Exception("access_token and refresh_token is no longer valid. Update [dbo].[PDPBusinessCentralOAuthToken] set access_token, refresh_token"), "manually (PostMan) generate a new access and refresh token");
}
else
{
// write the Model to DB with the new acsess token and the new refresh token
// this database write code is not shown. Create a table to store the token url, access token, and refresh token and last update time
// this is a verification method to read the latest access token
BCOAuthBearerToken(oModel.access_token);
}
OAuthMicroService
All apps get the latest token from the database through a call to OAuthMicroService project which writes the latest refreshed token into the database
private static string GetOAuthAccessToken()
{
var client = new HttpClient();
Task<string> resultOrder = client.GetStringAsync(ConfigurationManager.AppSettings["OAuthMicroService"]);
return resultOrder.Result;
// or get it from the database:
/*IntegrationEntities model = new IntegrationEntities();
var lst = model.usp_GetBusinessCentralOAuthToken().ToList();
return lst[0].access_token;*/
}
Since the token expires every hour or so by Microsoft, we have to get the common token from DB, and NOT form config file(s), and refresh it 24/7 .
(Extending the expiration period of the access token was not possible with an Azure cmdlet. Also the refresh token has a much longer expiration period than the access token. However since we are constantly refreshing with the BusinessCentralOAtuhTokenRefresher
task, our taken would be up-to-date indefinitely. I’ve tested this for days running though automation. )
Backup of logs failed in SQL Server
Can’t backup in RECOVERY SIMPLE mode. Insure RECOVERY FULL Mode is set:
-- to check recovery ode
SELECT name, recovery_model_desc
FROM sys.databases
WHERE name = 'Forecast' ;
GO
use Forecast;
ALTER DATABASE forecast SET RECOVERY FULL ;
USE Operations
GO
ALTER DATABASE Operations SET RECOVERY FULL;
USE CreditRequest
GO
ALTER DATABASE CreditRequest SET RECOVERY FULL;
USE FortKnox
GO
ALTER DATABASE FortKnox SET RECOVERY FULL;
Use Model
GO
ALTER DATABASE FortKnox SET RECOVERY FULL;
Also need to do a full backup so that you could do incremental backup of log again:
Solution: BACKUP LOG cannot be performed because there is no current database backup. So run the FULL backup jobs again and should be good.
DBCC ShrinkFile. Transaction Log Full on SQL Server database.
Backup and log full errors are handled as follows:
Tran log full:
https://blog.devoworx.net/2016/04/26/the-transaction-log-for-database-sharepoint_config-is-full-due-to-log_backup/
If you are unable to perform any of the previous alternative solutions. In this case, you can perform a shrink operation to reduce the physical file size. By running the following below commands.
-- This example is for a database named
sharepoint_config. Substitue your database here
use sharepoint_config
go
alter database sharepoint_config set recovery simple
go
dbcc shrinkfile('SharePoint_Config_log',100)
go
alter database sharepoint_config set recovery FULL
go
Sample SQL Server RESTORE DATABASE script from backup
-- Sample restore script for a database named "Sample" whose back up is on Disk at ’C:\YOUR_PATH\Sample_Monday.bak’
ALTER DATABASE [Sample] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE [Sample] SET SINGLE_USER WITH NO_WAIT
USE master
RESTORE DATABASE [Sample] FROM DISK=’C:\YOUR_PATH\Sample_Monday.bak’ WITH REPLACE;
--- After the restore completes
ALTER DATABASE [Sample] SET MULTI_USER